diff --git a/pisugar-module/.clang-format b/pisugar-module/pisugar-2/.clang-format
similarity index 100%
rename from pisugar-module/.clang-format
rename to pisugar-module/pisugar-2/.clang-format
diff --git a/pisugar-module/.gitignore b/pisugar-module/pisugar-2/.gitignore
similarity index 100%
rename from pisugar-module/.gitignore
rename to pisugar-module/pisugar-2/.gitignore
diff --git a/pisugar-module/pisugar-2/Makefile b/pisugar-module/pisugar-2/Makefile
new file mode 100644
index 0000000..4f62eef
--- /dev/null
+++ b/pisugar-module/pisugar-2/Makefile
@@ -0,0 +1,31 @@
+TARGET = pisugar_2_battery
+
+obj-m += pisugar_2_battery.o
+
+KERN_VER = $(shell uname -r)
+
+SOURCEDIR = $(shell pwd)
+BUILDDIR = $(shell pwd)/build
+
+I2C_BUS ?= 0x01
+I2C_ADDR ?= 0x75
+BAT_MODEL ?= 0
+
+all:
+ make -C /lib/modules/$(KERN_VER)/build M=$(SOURCEDIR) modules
+
+clean:
+ rm -f *.cmd *.ko *.o Module.symvers modules.order *.mod.c .pisugar_2_battery.* .modules.* .Module.symvers.* pisugar_2_battery.mod
+
+install: all
+ cp -f pisugar_2_battery.ko /lib/modules/$(KERN_VER)/kernel/drivers/power/supply
+ grep -q pisugar_2_battery /etc/modules || sed -i '$$a pisugar_2_battery' /etc/modules
+ echo "options pisugar_2_battery i2c_bus=$(I2C_BUS) i2c_addr=$(I2C_ADDR) bat_model=$(BAT_MODEL)" > /etc/modprobe.d/pisugar_2_battery.conf
+ depmod -a
+ modprobe pisugar_2_battery
+
+uninstall:
+ rmmod pisugar_2_battery || true
+ rm -f /lib/modules/$(KERN_VER)/kernel/drivers/power/supply/pisugar_2_battery.ko
+ sed -i '/pisugar_2_battery/d' /etc/modules
+ rm -f /etc/modprobe.d/pisugar_2_battery.conf
diff --git a/pisugar-module/pisugar-2/README.md b/pisugar-module/pisugar-2/README.md
new file mode 100644
index 0000000..d1e1550
--- /dev/null
+++ b/pisugar-module/pisugar-2/README.md
@@ -0,0 +1,93 @@
+# PiSugar Linux kernel modules
+
+Linux kernel modules for PiSugar 2.
+
+## Preparing for building RPI kernel module
+
+### Linux distributions with kernel symbols
+
+Congratulations if your PI is running a linux distribution that has `/lib/modules/$(uname -r)/build/` directory, e.g. ubuntu-server or latest pi os, you don't need to manually build RPI kernel, and that will save a lot of time.
+
+Install `build-essential` and `linux-headers`
+```shell
+sudo apt install -y build-essential linux-headers-$(uname -r)
+```
+
+Running 32bit OS in a 64bit machine, see [this](https://forums.raspberrypi.com/viewtopic.php?t=367669).
+
+### Old raspberry Pi OS
+
+As kernel symbols is not included in Raspberry Pi OS (no `/lib/modules/$(uname -r)/build`), so you need to compile the kernel and generate the kernel symbols by yourself.
+
+To build the kernel, see official doc: https://www.raspberrypi.com/documentation/computers/linux_kernel.html
+
+## Compile/install/uninstall kernel module
+
+Clone this repository, make kernel modules:
+```shell
+make
+```
+
+Install:
+```shell
+sudo make install
+```
+
+Module params:
+```
+i2c_bus i2c bus, default 0x01
+i2c_addr i2c addr, default 0x75
+bat_model PiSugar2 model, 0 (for pi zero) or 1 (pro for pi 3/4)
+```
+
+Install with parameters:
+```shell
+sudo make install i2c_bus=0x01 i2c_addr=0x75 bat_model=0
+```
+
+Uninstall:
+```shell
+sudo make uninstall
+```
+
+## Manually load kernel module
+
+Load module:
+```shell
+sudo insmod pisugar_2_battery.ko
+# or
+sudo insmod pisugar_2_battery.ko i2c_bus=1 i2c_addr=0x75 bat_model=0
+```
+
+Now, it is loaded:
+```shell
+lsmod | grep battery
+```
+
+And you will see extra device files in `/sys/class/power_supply`
+```shell
+ls /sys/class/power_supply
+```
+
+Remove module:
+```shell
+sudo rmmod pisugar_2_battery.ko
+```
+
+Now, you can enable a battery monitor plugin that reads battery status from power supply subsystem (OS battery monitor plugin or a 3rd party plugin).
+
+If you want to load kernel module at boot time, copy it to `/lib/modules/$(uname -r)/kernel/drivers/power/supply`
+```shell
+sudo cp -f pisugar_2_battery.ko /lib/modules/$(uname -r)/kernel/drivers/power/supply
+sudo echo pisugar_2_battery >> /etc/modules
+sudo depmod -a
+```
+
+You may want to change module parameters:
+```shell
+echo "options pisugar_2_battery i2c_bus=0x01 i2c_addr=0x75 bat_model=0" | sudo tee /etc/modprobe.d/pisugar_2_battery.conf
+```
+
+## License
+
+GPL
\ No newline at end of file
diff --git a/pisugar-module/pisugar-2/pisugar_2_battery.c b/pisugar-module/pisugar-2/pisugar_2_battery.c
new file mode 100644
index 0000000..1f88c8d
--- /dev/null
+++ b/pisugar-module/pisugar-2/pisugar_2_battery.c
@@ -0,0 +1,499 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/* Based heavily on
+ * https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/drivers/power/test_power.c?id=refs/tags/v4.2.6
+ */
+/*
+ * Fork from https://github.com/hoelzro/linux-fake-battery-module
+ * https://docs.kernel.org/power/power_supply_class.html
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define BAT_I2C_BUS 0x01
+#define IP5209_I2C_ADDR 0x75
+#define IP5312_I2C_ADDR 0x75
+
+#define TOTAL_LIFE_SECONDS (3 * 60 * 60)
+#define TOTAL_CHARGE (2000 * 1000) // uAH
+#define TOTAL_CHARGE_FULL_SECONDS (60 * 60)
+
+const float IP5209_CURVE[][] = {
+ {4.16, 100.0},
+ {4.05, 95.0},
+ {4.00, 80.0},
+ {3.92, 65.0},
+ {3.86, 40.0},
+ {3.79, 25.5},
+ {3.66, 10.0},
+ {3.52, 6.5},
+ {3.49, 3.2},
+ {3.1, 0.0},
+};
+
+const float IP5312_CURVE[][] = {
+ {4.10, 100.0},
+ {4.05, 95.0},
+ {3.90, 88.0},
+ {3.80, 77.0},
+ {3.70, 65.0},
+ {3.62, 55.0},
+ {3.58, 49.0},
+ {3.49, 25.6},
+ {3.32, 4.5},
+ {3.1, 0.0},
+};
+
+enum BAT_MODEL {
+ STANDARD = 0, // ip5209, for pi zero
+ PRO = 1, // ip5312, for pi 3/4
+}
+
+enum pisugar_2_bat_reg {
+ pisugar_2_VER = 0x00,
+ pisugar_2_MOD = 0x01,
+ pisugar_2_CTL1 = 0x02,
+ pisugar_2_TEMP = 0x04,
+ pisugar_2_CAP = 0x2A,
+ pisugar_2_VOL_H = 0x22,
+ PISGUAR_3_VOL_L = 0x23,
+};
+
+#define pisugar_2_VER_3 3
+#define pisugar_2_MOD_APP 0x0F
+
+#define pisugar_2_MSK_CTR1_USB (1 << 7)
+#define pisugar_2_MSK_CTR1_CH_EN (1 << 6)
+
+#define BAT_HIS_LEN 30
+float bat_voltage_his[BAT_HIS_LEN] = {0}; // mV
+
+static short int i2c_bus = BAT_I2C_BUS;
+static short int i2c_addr = IP5209_I2C_ADDR;
+static short int bat_module = STANDARD;
+
+module_param(i2c_bus, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(i2c_bus, "I2C bus default 0x01");
+
+module_param(i2c_addr, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(i2c_addr, "I2C addr default 0x75");
+
+module_param(bat_module, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(bat_module, "PiSugar 2 model, 0 standard (pi zero), 1 pro (pi 3/4)");
+
+static int pisugar_2_battery_get_property1(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
+
+static int pisugar_2_ac_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
+
+static struct task_struct *pisugar_2_monitor_task = NULL;
+
+static struct battery_status {
+ int status;
+ int capacity_level;
+ int capacity; // %
+ int time_left; // seconds
+ int voltage; // uV
+ int temperature;
+} pisugar_2_battery_statuses[1] = {{.status = POWER_SUPPLY_STATUS_FULL,
+ .capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+ .capacity = 100,
+ .time_left = TOTAL_LIFE_SECONDS,
+ .voltage = 4200 * 1000, // uV
+ .temperature = 30}};
+
+static int ac_status = 1;
+
+static char *pisugar_2_ac_supplies[] = {
+ "BAT0",
+};
+
+static enum power_supply_property pisugar_2_battery_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_SERIAL_NUMBER,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static enum power_supply_property pisugar_2_ac_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply_desc descriptions[] = {
+ {
+ .name = "BAT0",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = pisugar_2_battery_properties,
+ .num_properties = ARRAY_SIZE(pisugar_2_battery_properties),
+ .get_property = pisugar_2_battery_get_property1,
+ },
+
+ {
+ .name = "AC0",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = pisugar_2_ac_properties,
+ .num_properties = ARRAY_SIZE(pisugar_2_ac_properties),
+ .get_property = pisugar_2_ac_get_property,
+ },
+};
+
+static struct power_supply_config configs[] = {
+ {},
+ {},
+ {
+ .supplied_to = pisugar_2_ac_supplies,
+ .num_supplicants = ARRAY_SIZE(pisugar_2_ac_supplies),
+ },
+};
+
+static struct power_supply *supplies[sizeof(descriptions) / sizeof(descriptions[0])];
+
+#define prefixed(s, prefix) (!strncmp((s), (prefix), sizeof(prefix) - 1))
+
+static int pisugar_2_battery_generic_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val,
+ struct battery_status *status)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = "PiSugar";
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = status->status;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = status->capacity;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ val->intval = status->capacity_level;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = status->capacity * TOTAL_CHARGE / 100;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = TOTAL_CHARGE;
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ val->intval = status->time_left;
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+ val->intval = (100 - status->capacity) * TOTAL_CHARGE_FULL_SECONDS / 100;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = status->temperature;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = status->voltage;
+ break;
+ default:
+ pr_info("%s: some properties deliberately report errors.\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+};
+
+static int pisugar_2_battery_get_property1(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = "PiSugar battery 0";
+ break;
+ case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+ val->strval = "";
+ break;
+ default:
+ return pisugar_2_battery_generic_get_property(psy, psp, val, &pisugar_2_battery_statuses[0]);
+ }
+ return 0;
+}
+
+static int pisugar_2_ac_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = ac_status;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#define CHECK_VALID(val) ((val) >= 0 && (val) <= 255)
+
+static void push_bat_voltage(float vol)
+{
+ for (int i = 0; i < BAT_HIS_LEN - 1; i++) {
+ bat_voltage_his[i] = bat_voltage_his[i + 1];
+ }
+ bat_voltage_his[BAT_HIS_LEN - 1] = vol;
+}
+
+static float get_bat_avg_voltage()
+{
+ double vol_sum = 0;
+ for (int i = 0; i < BAT_HIS_LEN; i++) {
+ vol_sum += bat_voltage_his[i];
+ }
+ return (float)(vol_sum / BAT_HIS_LEN);
+}
+
+static void update_bat_capacity_level_and_status()
+{
+ // capacity level
+ int cap = pisugar_2_battery_statuses->capacity;
+ if (cap > 95) {
+ pisugar_2_battery_statuses->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ } else if (cap > 85) {
+ pisugar_2_battery_statuses->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
+ } else if (cap > 40) {
+ pisugar_2_battery_statuses->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ } else if (cap > 30) {
+ pisugar_2_battery_statuses->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ } else {
+ pisugar_2_battery_statuses->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ }
+
+ // bat status
+ if (ac_status) {
+ if (cap > 95) {
+ pisugar_2_battery_statuses->status = POWER_SUPPLY_STATUS_FULL;
+ } else {
+ pisugar_2_battery_statuses->status = POWER_SUPPLY_STATUS_CHARGING;
+ }
+ } else {
+ pisugar_2_battery_statuses->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+
+}
+
+static void ip5209_monitor_once(struct i2c_client *pisugar_2_client)
+{
+ // read voltage
+ int vol_low = i2c_smbus_read_byte_data(pisugar_2_client, 0xa2);
+ int vol_high = i2c_smbus_read_byte_data(pisugar_2_client, 0xa3);
+ float vol = 0; // mv
+ if (!CHECK_VALID(vol_high) || !CHECK_VALID(vol_low)) {
+ return;
+ }
+ if ((vol_high & 0x20) == 0x20) {
+ vol = 2600.0 - (float)((~vol_low) + (~(vol_high & 0x1F)) * 256 + 1) * 0.26855;
+ } else {
+ vol = 2600.0 + (float)(vol_low + vol_high * 256) * 0.26855;
+ }
+ push_bat_voltage(vol);
+ float vol_avg = get_bat_avg_voltage(); // mV
+ pisugar_2_battery_statuses->voltage = vol_avg * 1000; // uV
+
+ // capacity
+ int cap = 0;
+ float vol_avg_v = vol_avg / 1000;
+ for (int i=0; i= IP5209_CURVE[i][0]) {
+ cap = IP5209_CURVE[i][1];
+ }
+ if (i > 0) {
+ float vol_diff_v = vol_avg_v - IP5209_CURVE[i];
+ float k = (IP5209_CURVE[i-1][1] - IP5209_CURVE[i][1]) / (IP5209_CURVE[i-1][0] - IP5209_CURVE[i][0]);
+ cap += (int)(k * vol_diff_v);
+ }
+ }
+ pisugar_2_battery_statuses->capacity = cap;
+
+ // charging status
+ int charging_flags = i2c_smbus_read_byte_data(pisugar_2_client, 0x71);
+ ac_status = charging_flags > 0 ? 1: 0;
+
+ update_bat_capacity_level_and_status();
+}
+
+static void ip5312_monitor_once() {
+ // read voltage
+ int vol_low = i2c_smbus_read_byte_data(pisugar_2_client, 0xd0);
+ int vol_high = i2c_smbus_read_byte_data(pisugar_2_client, 0xd1);
+ float vol = 0; // mv
+ if (!CHECK_VALID(vol_high) || !CHECK_VALID(vol_low)) {
+ return;
+ }
+ vol = 2600.0 + (float)(vol_low + (vol_high & (0x1F)) * 256) * 0.26855;}
+ push_bat_voltage(vol);
+ float vol_avg = get_bat_avg_voltage(); // mV
+ pisugar_2_battery_statuses->voltage = vol_avg * 1000; // uV
+
+ // capacity
+ int cap = 0;
+ float vol_avg_v = vol_avg / 1000;
+ for (int i=0; i= IP5312_CURVE[i][0]) {
+ cap = IP5312_CURVE[i][1];
+ }
+ if (i > 0) {
+ float vol_diff_v = vol_avg_v - IP5312_CURVE[i];
+ float k = (IP5312_CURVE[i-1][1] - IP5312_CURVE[i][1]) / (IP5312_CURVE[i-1][0] - IP5312_CURVE[i][0]);
+ cap += (int)(k * vol_diff_v);
+ }
+ }
+ pisugar_2_battery_statuses->capacity = cap;
+
+ // charging status
+ int charging_flags = i2c_smbus_read_byte_data(pisugar_2_client, 0x79);
+ ac_status = (charging_flags >> 6) > 0 ? 1: 0;
+
+ update_bat_capacity_level_and_status();
+}
+
+static int pisugar_2_monitor(void *args)
+{
+ struct i2c_client *pisugar_2_client = NULL;
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_board_info board_info = {I2C_BOARD_INFO("pisugar_2_battery", i2c_addr)};
+
+ // create i2c pisugar_2_client
+ adapter = i2c_get_adapter(i2c_bus);
+ if (adapter == NULL) {
+ printk(KERN_ERR "Unable to get i2c adapter!");
+ return -1;
+ }
+ pisugar_2_client = i2c_new_client_device(adapter, &board_info);
+ if (pisugar_2_client == NULL) {
+ printk(KERN_ERR "Unable to create i2c client!");
+ return -1;
+ }
+
+ while (true) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (kthread_should_stop()) break;
+
+ if (bat_module == STANDARD) {
+ ip5209_monitor_once(pisugar_2_client);
+ }
+ if (bat_module == PRO) {
+ ip5312_monitor_once(pisugar_2_client);
+ }
+
+ sleep:
+ set_current_state(TASK_RUNNING);
+ schedule_timeout(HZ);
+ }
+
+ i2c_unregister_device(pisugar_2_client);
+ pisugar_2_client = NULL;
+
+ return 0;
+}
+
+static int __init pisugar_2_battery_init(void)
+{
+ int result;
+ int i;
+
+ // create a monitor kthread
+ pisugar_2_monitor_task = kthread_run(pisugar_2_monitor, NULL, "pisugar_2_monitor");
+ if (pisugar_2_monitor_task == NULL) {
+ goto error;
+ }
+
+ // register power supply
+ for (i = 0; i < ARRAY_SIZE(descriptions); i++) {
+ supplies[i] = power_supply_register(NULL, &descriptions[i], &configs[i]);
+ if (IS_ERR(supplies[i])) {
+ printk(KERN_ERR "Unable to register power supply %d in pisugar_2_battery\n", i);
+ goto error;
+ }
+ }
+
+ printk(KERN_INFO "loaded pisugar_2_battery module\n");
+ return 0;
+
+error:
+ if (pisugar_2_monitor_task) {
+ kthread_stop(pisugar_2_monitor_task);
+ pisugar_2_monitor_task = NULL;
+ }
+ while (--i >= 0) {
+ power_supply_unregister(supplies[i]);
+ }
+ return -1;
+}
+
+static void __exit pisugar_2_battery_exit(void)
+{
+ int i;
+
+ if (pisugar_2_monitor_task) {
+ kthread_stop(pisugar_2_monitor_task);
+ pisugar_2_monitor_task = NULL;
+ }
+
+ for (i = ARRAY_SIZE(descriptions) - 1; i >= 0; i--) {
+ power_supply_unregister(supplies[i]);
+ }
+
+ printk(KERN_INFO "unloaded pisugar_2_battery module\n");
+}
+
+module_init(pisugar_2_battery_init);
+module_exit(pisugar_2_battery_exit);
+
+MODULE_AUTHOR("The PiSugar Team ");
+MODULE_DESCRIPTION("PiSugar 2 battery driver");
+MODULE_LICENSE("GPL");
diff --git a/pisugar-module/pisugar-3/.clang-format b/pisugar-module/pisugar-3/.clang-format
new file mode 100644
index 0000000..1c3d514
--- /dev/null
+++ b/pisugar-module/pisugar-3/.clang-format
@@ -0,0 +1,26 @@
+BasedOnStyle: Google
+IndentWidth: 4
+---
+Language: Cpp
+AllowShortBlocksOnASingleLine: Never
+ColumnLimit: 120
+AlignTrailingComments: true
+AllowShortFunctionsOnASingleLine: Empty
+AlignConsecutiveMacros: true
+MaxEmptyLinesToKeep: 1
+UseTab: Never
+SortIncludes: true
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: "^<.*>"
+ Priority: -99
+ - Regex: ".*"
+ Priority: 0
+ReflowComments: true
+TabWidth: 4
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterFunction: true
+BinPackArguments: false
+BinPackParameters: false
+AlignEscapedNewlinesLeft: false
\ No newline at end of file
diff --git a/pisugar-module/pisugar-3/.gitignore b/pisugar-module/pisugar-3/.gitignore
new file mode 100644
index 0000000..d163863
--- /dev/null
+++ b/pisugar-module/pisugar-3/.gitignore
@@ -0,0 +1 @@
+build/
\ No newline at end of file
diff --git a/pisugar-module/Makefile b/pisugar-module/pisugar-3/Makefile
similarity index 100%
rename from pisugar-module/Makefile
rename to pisugar-module/pisugar-3/Makefile
diff --git a/pisugar-module/README.md b/pisugar-module/pisugar-3/README.md
similarity index 100%
rename from pisugar-module/README.md
rename to pisugar-module/pisugar-3/README.md
diff --git a/pisugar-module/pisugar_3_battery.c b/pisugar-module/pisugar-3/pisugar_3_battery.c
similarity index 100%
rename from pisugar-module/pisugar_3_battery.c
rename to pisugar-module/pisugar-3/pisugar_3_battery.c