reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

commit 14f62fd6287ec340ce99c8eb0c68d00970d98684
parent dd72b52f7253ea4ad1e0070985709272435a9a99
Author: nanocodebug <nanocodebug@gmail.com>
Date:   Tue, 21 Jun 2022 23:21:09 -0700

cleanup and fixes

Diffstat:
Mreform2-lpc-driver/src/reform2-lpc.c | 155+++++++++++++++++++++++++++++++++++++++++++------------------------------------
1 file changed, 84 insertions(+), 71 deletions(-)

diff --git a/reform2-lpc-driver/src/reform2-lpc.c b/reform2-lpc-driver/src/reform2-lpc.c @@ -5,22 +5,22 @@ #include <linux/delay.h> #include <linux/power_supply.h> -static int spiProbe(struct spi_device *spi); -static void spiRemove(struct spi_device *spi); +static int lpcProbe(struct spi_device *spi); +static void lpcRemove(struct spi_device *spi); static ssize_t showStatus(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t showCells(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t showFirmware(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t showCapacity(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_t *response); -static int bat_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); +static int getBatProperty(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); -typedef struct t_private_data +typedef struct lpc_driver_data { struct spi_device *spi; struct power_supply *bat; struct mutex lock; -} T_PRIVATE_DATA; +} lpc_driver_data; static DEVICE_ATTR(status, 0444, showStatus, NULL); static DEVICE_ATTR(cells, 0444, showCells, NULL); @@ -37,28 +37,29 @@ static struct spi_board_info g_spi_board_info = { static enum power_supply_property bat_props[] = { POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_TECHNOLOGY, // lifepo4 - POWER_SUPPLY_PROP_VOLTAGE_NOW, // uV - POWER_SUPPLY_PROP_CURRENT_NOW, // uA - POWER_SUPPLY_PROP_CAPACITY, // percent - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, //uAh hardcoded to 1800 atm, param 2 - POWER_SUPPLY_PROP_CHARGE_NOW, //uAh capacity_accu_ampsecs param 0 - POWER_SUPPLY_PROP_CHARGE_EMPTY, // uAh param 1 + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_EMPTY, }; static struct power_supply_desc bat_desc = { .name = "8xlifepo4", .properties = bat_props, .num_properties = ARRAY_SIZE(bat_props), - .get_property = bat_get_property, + .get_property = getBatProperty, .type = POWER_SUPPLY_TYPE_BATTERY, }; -static int spiProbe(struct spi_device *spi) +static int lpcProbe(struct spi_device *spi) { - T_PRIVATE_DATA *data; - int ret; + struct lpc_driver_data *data; struct power_supply_config psy_cfg = {}; + int ret; printk(KERN_INFO "%s: probing ...\n", "reform2-lpc"); @@ -73,7 +74,7 @@ static int spiProbe(struct spi_device *spi) return -ENODEV; } - data = kzalloc(sizeof(T_PRIVATE_DATA), GFP_KERNEL); + data = kzalloc(sizeof(struct lpc_driver_data), GFP_KERNEL); if (data == NULL) { printk(KERN_ERR "%s: kzalloc failed\n", __func__); @@ -118,12 +119,12 @@ static int spiProbe(struct spi_device *spi) return PTR_ERR(data->bat); } - return 0; + return ret; } -static void spiRemove(struct spi_device *spi) +static void lpcRemove(struct spi_device *spi) { - T_PRIVATE_DATA *data = (T_PRIVATE_DATA *)spi_get_drvdata(spi); + struct lpc_driver_data *data = (struct lpc_driver_data *)spi_get_drvdata(spi); printk(KERN_INFO "%s: removing ... \n", "reform2-lpc"); @@ -139,36 +140,38 @@ static void spiRemove(struct spi_device *spi) static ssize_t showStatus(struct device *dev, struct device_attribute *attr, char *buf) { - uint8_t statusResult[8]; - int ret = 0; + uint8_t buffer[8]; int16_t voltage; int16_t amps; uint8_t percentage; uint8_t status; + int ret = 0; - ret = lpcCommand(dev, 'q', 0, statusResult); + ret = lpcCommand(dev, 'q', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); } - voltage = (int16_t)statusResult[0] | ((int16_t)statusResult[1] << 8); - amps = (int16_t)statusResult[2] | ((int16_t)statusResult[3] << 8); - percentage = statusResult[4]; - status = statusResult[5]; + voltage = (int16_t)buffer[0] | ((int16_t)buffer[1] << 8); + amps = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); + percentage = buffer[4]; + status = buffer[5]; return snprintf(buf, PAGE_SIZE, "%d.%d %d.%d %2d%% %d", - voltage / 1000, voltage % 1000, amps / 1000, abs(amps % 1000), percentage, status); + voltage / 1000, voltage % 1000, + amps / 1000, abs(amps % 1000), + percentage, status); } static ssize_t showCells(struct device *dev, struct device_attribute *attr, char *buf) { - uint8_t statusResult[8]; + uint8_t buffer[8]; uint16_t cells[8]; - int ret = 0; ssize_t wroteChars = 0; - - ret = lpcCommand(dev, 'v', 0, statusResult); + int ret = 0; + + ret = lpcCommand(dev, 'v', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); @@ -176,10 +179,10 @@ static ssize_t showCells(struct device *dev, struct device_attribute *attr, char for(uint8_t s = 0; s < 4; s++) { - cells[s] = statusResult[s*2] | statusResult[(s*2)+1] << 8; + cells[s] = buffer[s*2] | buffer[(s*2)+1] << 8; } - ret = lpcCommand(dev, 'v', 1, statusResult); + ret = lpcCommand(dev, 'v', 1, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); @@ -187,7 +190,7 @@ static ssize_t showCells(struct device *dev, struct device_attribute *attr, char for(uint8_t s = 0; s < 4; s++) { - cells[s+4] = statusResult[s*2] | statusResult[(s*2)+1] << 8; + cells[s+4] = buffer[s*2] | buffer[(s*2)+1] << 8; } for(uint8_t s = 0; s < 8; s++) @@ -215,7 +218,6 @@ static ssize_t showFirmware(struct device *dev, struct device_attribute *attr, c uint8_t str3[9]; int ret = 0; - ret = lpcCommand(dev, 'f', 0, str1); if (ret) { @@ -245,24 +247,23 @@ static ssize_t showCapacity(struct device *dev, struct device_attribute *attr, c { uint8_t buffer[8]; int ret = 0; - uint16_t cap_accu, cap_min, cap_max; + uint16_t cap_accu_mah, cap_min_mah, cap_max_mah; ret = lpcCommand(dev, 'c', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); } - // units in mAh - cap_accu = buffer[0] | (buffer[1] << 8); - cap_min = buffer[2] | (buffer[3] << 8); - cap_max = buffer[4] | (buffer[5] << 8); + cap_accu_mah = buffer[0] | (buffer[1] << 8); + cap_min_mah = buffer[2] | (buffer[3] << 8); + cap_max_mah = buffer[4] | (buffer[5] << 8); - return snprintf(buf, PAGE_SIZE, "%d %d %d", cap_accu, cap_min, cap_max); + return snprintf(buf, PAGE_SIZE, "%d %d %d", cap_accu_mah, cap_min_mah, cap_max_mah); } static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_t *responseBuffer) { - T_PRIVATE_DATA *data = (T_PRIVATE_DATA *)dev_get_drvdata(dev); + struct lpc_driver_data *data = (struct lpc_driver_data *)dev_get_drvdata(dev); uint8_t commandBuffer[4] = {0xB5, command, arg1, 0x0}; int ret = 0; @@ -273,6 +274,7 @@ static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_ { printk(KERN_INFO "%s: spi_write failed\n", __func__); } + // todo, replace with wait timer? mdelay(70); ret = spi_read(data->spi, responseBuffer, 8); @@ -280,26 +282,28 @@ static ssize_t lpcCommand(struct device *dev, char command, uint8_t arg1, uint8_ { printk(KERN_INFO "%s: spi_read failed\n", __func__); } + // todo, replace with wait timer? mdelay(70); mutex_unlock(&data->lock); return ret; } -static int bat_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) +static int getBatProperty(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) { int ret = 0; uint8_t buffer[8]; - T_PRIVATE_DATA *data; + struct lpc_driver_data *data; struct device *dev; - int16_t temp = 0; + int16_t amp; - data = (T_PRIVATE_DATA *)power_supply_get_drvdata(psy); + data = (struct lpc_driver_data *)power_supply_get_drvdata(psy); dev = &(data->spi->dev); - switch (psp) { + switch (psp) + { case POWER_SUPPLY_PROP_STATUS: val->intval = POWER_SUPPLY_STATUS_UNKNOWN; ret = lpcCommand(dev, 'q', 0, buffer); @@ -307,14 +311,14 @@ static int bat_get_property(struct power_supply *psy, { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); } - temp = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); - if(temp < 0) + amp = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); + if (amp < 0) { val->intval = POWER_SUPPLY_STATUS_CHARGING; } - else if(temp == 0) + else if (amp == 0) { - if(buffer[4] == 100) + if (buffer[4] == 100) { val->intval = POWER_SUPPLY_STATUS_FULL; } @@ -325,60 +329,82 @@ static int bat_get_property(struct power_supply *psy, } else { - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; } break; + case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe; break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: ret = lpcCommand(dev, 'q', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } val->intval = (buffer[0] | buffer[1] << 8) * 1000; break; + case POWER_SUPPLY_PROP_CURRENT_NOW: ret = lpcCommand(dev, 'q', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } - val->intval = (buffer[2] | buffer[3] << 8) * 1000; + amp = (int16_t)buffer[2] | ((int16_t)buffer[3] << 8); + // negative current, battery is charging + // reporting a negative value is out of spec + if(amp < 0) + { + amp = 0; + } + val->intval = amp * 1000; break; + case POWER_SUPPLY_PROP_CAPACITY: ret = lpcCommand(dev, 'q', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } val->intval = buffer[4]; break; + + case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: ret = lpcCommand(dev, 'c', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } val->intval = (buffer[4] | buffer[5] << 8) * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: ret = lpcCommand(dev, 'c', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } val->intval = (buffer[0] | buffer[1] << 8) * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_EMPTY: ret = lpcCommand(dev, 'c', 0, buffer); if (ret) { printk(KERN_INFO "%s: lpcCommand failed\n", __func__); + ret = -EINVAL; } val->intval = (buffer[2] | buffer[3] << 8) * 1000; break; + default: val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; ret = -EINVAL; @@ -387,33 +413,20 @@ static int bat_get_property(struct power_supply *psy, return ret; } -// enum state_t { -// ST_CHARGE, -- charging -// ST_OVERVOLTED, -- charging? full? balancing -// ST_COOLDOWN, -- charging? full? balancing -// ST_UNDERVOLTED, -- cells under voltage, discharging? -// ST_MISSING, -- cells missing -// ST_FULLY_CHARGED, -- full charged -// ST_POWERSAVE -- deep sleep of lpc -// }; - static const struct of_device_id of_tis_spi_match[] = { {.compatible = "mntre,lpc11u24", .data = 0}, - {.compatible = "mntre,lpc-reform2", .data = 0}, {}}; MODULE_DEVICE_TABLE(of, of_tis_spi_match); static struct spi_device_id g_spi_dev_id_list[] = { - /* device name, device id */ { "lpc11u24", 0 }, - { "lpc-reform2", 0 }, { }, }; MODULE_DEVICE_TABLE(spi, g_spi_dev_id_list); static struct spi_driver g_spi_driver = { - .probe = spiProbe, - .remove = spiRemove, + .probe = lpcProbe, + .remove = lpcRemove, .driver = { .of_match_table = of_match_ptr(of_tis_spi_match), .owner = THIS_MODULE,