Hi Riccardo,
I have merged Daniel’s patch into the 4.0-rc7 kernel (and added some Kconfig + 
Makefile) [1] but it does not yet work of course.

I think it will provide the standard /sys/class/power_supply interface. There 
might be wrappers for older PM APIs but I do not know.

BR,
Nikolaus

[1]: 
http://git.goldelico.com/?p=gta04-kernel.git;a=shortlog;h=refs/heads/wip/letux400


Am 07.04.2015 um 08:58 schrieb Riccardo Mottola <mul...@gmail.com>:

> 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
> 
> _______________________________________________
> Lenny400 mailing list
> lenny...@goldelico.com
> http://lists.goldelico.com/mailman/listinfo.cgi/lenny400

_______________________________________________
Mipsbook-devel mailing list
Mipsbook-devel@linuxtogo.org
http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/mipsbook-devel

Reply via email to