This is interesting. What kernel is this patch for and, more important, did you test it a bit?
O originally hacked GNUstep's battery monitor batmon.app to work on the original 2.4 kernel, using the APM interface, but the values were close to bogus essentially. http://gap.nongnu.org/batmon/index.html I got no continuous voltage and charge information and even the information about the system being plugged in or not were bogus sometimes, wondering if the hardware was actually limited/faulty to just 4 "charge levels". Can you tell us more? Riccardo On Sat, Apr 4, 2015 at 6:43 PM, Daniel Glöckner <daniel...@gmx.net> wrote: > The Letux 400 MIPS netbook contains an LPC915 microcontroller to measure > the battery voltage, detect the presence of a charger, and to power the > device off. It is controlled via I2C address 0x28. > > Signed-off-by: Daniel Glöckner <daniel...@gmx.net> > --- > drivers/power/minipc-mcu.c | 167 > +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 167 insertions(+) > create mode 100644 drivers/power/minipc-mcu.c > > diff --git a/drivers/power/minipc-mcu.c b/drivers/power/minipc-mcu.c > new file mode 100644 > index 0000000..29d779a > --- /dev/null > +++ b/drivers/power/minipc-mcu.c > @@ -0,0 +1,167 @@ > +/* > + * An I2C driver for the MCU used on the Letux 400 > + * Copyright 2012 Daniel Gloeckner > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/i2c.h> > +#include <linux/power_supply.h> > +#include <linux/pm.h> > + > +#define DRV_VERSION "1.0" > + > +static struct i2c_client *mcu; > + > +static int minipc_battery_get_properties(struct power_supply *psy, > + enum power_supply_property psp, > + union power_supply_propval *val) > +{ > + int ret = 0; > + switch (psp) { > + case POWER_SUPPLY_PROP_TECHNOLOGY: > + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; > + break; > + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: > + val->intval = 7000000; > + break; > + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: > + val->intval = 8400000; > + break; > + case POWER_SUPPLY_PROP_VOLTAGE_NOW: > + ret = i2c_smbus_read_byte_data(mcu, 0xdb); > + if (ret >= 0) { > + /* resistor divider scales 8.4V to 3V */ > + /* lpc915 is powered from 3.3V */ > + /* ergo voltage = value * 2.8 * 3.3 / 255 */ > + val->intval = ret * 616000 / 17; > + ret = 0; > + } > + break; > + default: > + ret = -EINVAL; > + } > + return ret; > +} > + > +static enum power_supply_property minipc_battery_properties[] = { > + POWER_SUPPLY_PROP_TECHNOLOGY, > + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, > + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, > + POWER_SUPPLY_PROP_VOLTAGE_NOW, > +}; > + > +static struct power_supply minipc_battery = { > + .name = "battery", > + .type = POWER_SUPPLY_TYPE_BATTERY, > + .properties = minipc_battery_properties, > + .num_properties = ARRAY_SIZE(minipc_battery_properties), > + .get_property = minipc_battery_get_properties, > +}; > + > +static int minipc_psu_get_properties(struct power_supply *psy, > + enum power_supply_property psp, > + union power_supply_propval *val) > +{ > + int ret = 0; > + switch (psp) { > + case POWER_SUPPLY_PROP_ONLINE: > + val->intval = i2c_smbus_read_byte_data(mcu, 0xd9) & 1; > + if (val->intval < 0) > + ret = val->intval; > + break; > + default: > + ret = -EINVAL; > + } > + return ret; > +} > + > +static enum power_supply_property minipc_psu_properties[] = { > + POWER_SUPPLY_PROP_ONLINE, > +}; > + > +static struct power_supply minipc_psu = { > + .name = "psu", > + .type = POWER_SUPPLY_TYPE_MAINS, > + .properties = minipc_psu_properties, > + .num_properties = ARRAY_SIZE(minipc_psu_properties), > + .get_property = minipc_psu_get_properties, > +}; > + > +static void minipc_mcu_power_off(void) > +{ > + i2c_smbus_write_byte_data(mcu, 0xd8, 0x01); > +} > + > +static int minipc_mcu_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + dev_dbg(&client->dev, "%s\n", __func__); > + > + if (mcu) > + return -EBUSY; > + > + if (!i2c_check_functionality(client->adapter, > I2C_FUNC_SMBUS_BYTE_DATA)) > + return -ENODEV; > + > + dev_info(&client->dev, "chip found, driver version " DRV_VERSION > "\n"); > + > + minipc_battery.use_for_apm = power_supply_register(&client->dev, > + > &minipc_battery); > + minipc_psu.use_for_apm = power_supply_register(&client->dev, > + &minipc_psu); > + > + mcu = client; > + pm_power_off = minipc_mcu_power_off; > + > + return 0; > +} > + > +static int minipc_mcu_remove(struct i2c_client *client) > +{ > + if (!mcu) > + return 0; > + if (!minipc_battery.use_for_apm) > + power_supply_unregister(&minipc_battery); > + if (!minipc_psu.use_for_apm) > + power_supply_unregister(&minipc_psu); > + pm_power_off = NULL; > + mcu = NULL; > + > + return 0; > +} > + > +static const struct i2c_device_id minipc_mcu_id[] = { > + { "minipc-mcu", 0 }, > + { } > +}; > +MODULE_DEVICE_TABLE(i2c, minipc_mcu_id); > + > +static struct i2c_driver minipc_mcu_driver = { > + .driver = { > + .name = "minipc-mcu", > + }, > + .probe = minipc_mcu_probe, > + .remove = minipc_mcu_remove, > + .id_table = minipc_mcu_id, > +}; > + > +static int __init minipc_mcu_init(void) > +{ > + return i2c_add_driver(&minipc_mcu_driver); > +} > + > +static void __exit minipc_mcu_exit(void) > +{ > + i2c_del_driver(&minipc_mcu_driver); > +} > + > +MODULE_AUTHOR("Daniel Gloeckner <daniel...@gmx.net>"); > +MODULE_DESCRIPTION("Letux 400 LPC915 MCU driver"); > +MODULE_LICENSE("GPL"); > +MODULE_VERSION(DRV_VERSION); > + > +module_init(minipc_mcu_init); > +module_exit(minipc_mcu_exit); > -- > 1.8.3.4 > > > _______________________________________________ > Mipsbook-devel mailing list > Mipsbook-devel@linuxtogo.org > http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel >
_______________________________________________ Mipsbook-devel mailing list Mipsbook-devel@linuxtogo.org http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel