2 * Dumb driver for gta01 battery
4 * Copyright 2009 Openmoko, Inc
5 * Balaji Rao <balajirrao@openmoko.org>
8 #include <linux/module.h>
9 #include <linux/param.h>
10 #include <linux/delay.h>
11 #include <linux/workqueue.h>
12 #include <linux/platform_device.h>
13 #include <linux/power_supply.h>
14 #include <linux/gta01_battery.h>
16 struct gta01_battery {
17 struct power_supply psy;
18 struct gta01_bat_platform_data *pdata;
21 static enum power_supply_property gta01_bat_props[] = {
22 POWER_SUPPLY_PROP_PRESENT,
23 POWER_SUPPLY_PROP_STATUS,
24 POWER_SUPPLY_PROP_VOLTAGE_NOW,
25 POWER_SUPPLY_PROP_CURRENT_NOW,
26 POWER_SUPPLY_PROP_CAPACITY,
27 POWER_SUPPLY_PROP_CHARGE_FULL,
28 POWER_SUPPLY_PROP_CHARGE_NOW,
31 /* Capacity of typical BL-5C dumb battery */
32 #define GTA01_BAT_CHARGE_FULL 850000
34 static int gta01_bat_voltscale(int volt)
36 /* This table is suggested by SpeedEvil based on analysis of
37 * experimental data */
38 static const int lut[][2] = {
49 for (i = 0; lut[i][1]; i++) {
50 if (volt <= lut[i][0] && volt >= lut[i+1][0]) {
51 res = lut[i][1] - (lut[i][0]-volt)*
52 (lut[i][1]-lut[i+1][1])/
53 (lut[i][0]-lut[i+1][0]);
60 static int gta01_bat_get_property(struct power_supply *psy,
61 enum power_supply_property psp,
62 union power_supply_propval *val)
64 struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
67 case POWER_SUPPLY_PROP_STATUS:
68 if (bat->pdata->get_charging_status)
69 if (bat->pdata->get_charging_status())
70 val->intval = POWER_SUPPLY_STATUS_CHARGING;
72 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
74 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
76 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
77 if (bat->pdata->get_voltage)
78 val->intval = bat->pdata->get_voltage();
82 case POWER_SUPPLY_PROP_CURRENT_NOW:
83 if (bat->pdata->get_current)
84 val->intval = bat->pdata->get_current();
88 case POWER_SUPPLY_PROP_PRESENT:
89 val->intval = 1; /* You must never run GTA01 without battery. */
91 case POWER_SUPPLY_PROP_CHARGE_NOW:
92 if (bat->pdata->get_voltage) {
93 int perc = gta01_bat_voltscale(
94 bat->pdata->get_voltage()/1000);
95 val->intval = perc * GTA01_BAT_CHARGE_FULL / 100;
99 case POWER_SUPPLY_PROP_CAPACITY:
100 if (bat->pdata->get_voltage)
101 val->intval = gta01_bat_voltscale(
102 bat->pdata->get_voltage()/1000);
106 case POWER_SUPPLY_PROP_CHARGE_FULL:
107 val->intval = GTA01_BAT_CHARGE_FULL;
117 static void gta01_bat_ext_changed(struct power_supply *psy)
119 struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
120 power_supply_changed(&bat->psy);
123 static int gta01_battery_probe(struct platform_device *pdev)
125 struct gta01_battery *gta01_bat;
127 gta01_bat = kzalloc(sizeof(*gta01_bat), GFP_KERNEL);
131 gta01_bat->psy.name = "battery";
132 gta01_bat->psy.type = POWER_SUPPLY_TYPE_BATTERY;
133 gta01_bat->psy.properties = gta01_bat_props;
134 gta01_bat->psy.num_properties = ARRAY_SIZE(gta01_bat_props);
135 gta01_bat->psy.get_property = gta01_bat_get_property;
136 gta01_bat->psy.external_power_changed = gta01_bat_ext_changed;
138 gta01_bat->pdata = pdev->dev.platform_data;
139 platform_set_drvdata(pdev, gta01_bat);
140 power_supply_register(&pdev->dev, >a01_bat->psy);
145 static int gta01_battery_remove(struct platform_device *pdev)
147 struct gta01_battery *bat = platform_get_drvdata(pdev);
149 power_supply_unregister(&bat->psy);
155 static struct platform_driver gta01_battery_driver = {
157 .name = "gta01_battery",
159 .probe = gta01_battery_probe,
160 .remove = gta01_battery_remove,
163 static int __init gta01_battery_init(void)
165 return platform_driver_register(>a01_battery_driver);
168 static void __exit gta01_battery_exit(void)
170 platform_driver_unregister(>a01_battery_driver);
173 module_init(gta01_battery_init);
174 module_exit(gta01_battery_exit);
176 MODULE_LICENSE("GPL");
177 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
178 MODULE_DESCRIPTION("gta01 battery driver");