diff options
author | Donggeun Kim <dg77.kim@samsung.com> | 2011-06-22 06:40:06 -0400 |
---|---|---|
committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2011-07-08 08:58:59 -0400 |
commit | 149c077b4bd746eca2eeb241e55456eb4882b259 (patch) | |
tree | 037b7d498326eb667ae6d14e45d01d89378a0c63 /drivers/power/max8997_charger.c | |
parent | 7c4509b4cd1d99a1ea22ee4c1da4d3dbb9771c95 (diff) |
power_supply: Add charger driver for MAX8997/8966
MAX8997/8966 chip is a multi-function device which includes
PMIC, RTC, Fuel Gauge, MUIC, Haptic, Flash control, and
Battery charging control.
The driver for it is located at drivers/mfd.
This patch supports battery charging control of MAX8997/8966 chip and
provides power supply class information to userspace.
Signed-off-by: Donggeun Kim <dg77.kim@samsung.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: KyungMin Park <kyungmin.park@samsung.com>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power/max8997_charger.c')
-rw-r--r-- | drivers/power/max8997_charger.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c new file mode 100644 index 000000000000..7106b49b26e4 --- /dev/null +++ b/drivers/power/max8997_charger.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966 | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/err.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/power_supply.h> | ||
26 | #include <linux/mfd/max8997.h> | ||
27 | #include <linux/mfd/max8997-private.h> | ||
28 | |||
29 | struct charger_data { | ||
30 | struct device *dev; | ||
31 | struct max8997_dev *iodev; | ||
32 | struct power_supply battery; | ||
33 | }; | ||
34 | |||
35 | static enum power_supply_property max8997_battery_props[] = { | ||
36 | POWER_SUPPLY_PROP_STATUS, /* "FULL" or "NOT FULL" only. */ | ||
37 | POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */ | ||
38 | POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */ | ||
39 | }; | ||
40 | |||
41 | /* Note that the charger control is done by a current regulator "CHARGER" */ | ||
42 | static int max8997_battery_get_property(struct power_supply *psy, | ||
43 | enum power_supply_property psp, | ||
44 | union power_supply_propval *val) | ||
45 | { | ||
46 | struct charger_data *charger = container_of(psy, | ||
47 | struct charger_data, battery); | ||
48 | struct i2c_client *i2c = charger->iodev->i2c; | ||
49 | int ret; | ||
50 | u8 reg; | ||
51 | |||
52 | switch (psp) { | ||
53 | case POWER_SUPPLY_PROP_STATUS: | ||
54 | val->intval = 0; | ||
55 | ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®); | ||
56 | if (ret) | ||
57 | return ret; | ||
58 | if ((reg & (1 << 0)) == 0x1) | ||
59 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
60 | |||
61 | break; | ||
62 | case POWER_SUPPLY_PROP_PRESENT: | ||
63 | val->intval = 0; | ||
64 | ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®); | ||
65 | if (ret) | ||
66 | return ret; | ||
67 | if ((reg & (1 << 2)) == 0x0) | ||
68 | val->intval = 1; | ||
69 | |||
70 | break; | ||
71 | case POWER_SUPPLY_PROP_ONLINE: | ||
72 | val->intval = 0; | ||
73 | ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | /* DCINOK */ | ||
77 | if (reg & (1 << 1)) | ||
78 | val->intval = 1; | ||
79 | |||
80 | break; | ||
81 | default: | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static __devinit int max8997_battery_probe(struct platform_device *pdev) | ||
89 | { | ||
90 | int ret = 0; | ||
91 | struct charger_data *charger; | ||
92 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
93 | struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); | ||
94 | |||
95 | if (!pdata) | ||
96 | return -EINVAL; | ||
97 | |||
98 | if (pdata->eoc_mA) { | ||
99 | u8 val = (pdata->eoc_mA - 50) / 10; | ||
100 | if (val < 0) | ||
101 | val = 0; | ||
102 | if (val > 0xf) | ||
103 | val = 0xf; | ||
104 | |||
105 | ret = max8997_update_reg(iodev->i2c, | ||
106 | MAX8997_REG_MBCCTRL5, val, 0xf); | ||
107 | if (ret < 0) { | ||
108 | dev_err(&pdev->dev, "Cannot use i2c bus.\n"); | ||
109 | return ret; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | switch (pdata->timeout) { | ||
114 | case 5: | ||
115 | ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, | ||
116 | 0x2 << 4, 0x7 << 4); | ||
117 | break; | ||
118 | case 6: | ||
119 | ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, | ||
120 | 0x3 << 4, 0x7 << 4); | ||
121 | break; | ||
122 | case 7: | ||
123 | ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, | ||
124 | 0x4 << 4, 0x7 << 4); | ||
125 | break; | ||
126 | case 0: | ||
127 | ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, | ||
128 | 0x7 << 4, 0x7 << 4); | ||
129 | break; | ||
130 | default: | ||
131 | dev_err(&pdev->dev, "incorrect timeout value (%d)\n", | ||
132 | pdata->timeout); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | if (ret < 0) { | ||
136 | dev_err(&pdev->dev, "Cannot use i2c bus.\n"); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | charger = kzalloc(sizeof(struct charger_data), GFP_KERNEL); | ||
141 | if (charger == NULL) { | ||
142 | dev_err(&pdev->dev, "Cannot allocate memory.\n"); | ||
143 | return -ENOMEM; | ||
144 | } | ||
145 | |||
146 | platform_set_drvdata(pdev, charger); | ||
147 | |||
148 | charger->battery.name = "max8997_pmic"; | ||
149 | charger->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
150 | charger->battery.get_property = max8997_battery_get_property; | ||
151 | charger->battery.properties = max8997_battery_props; | ||
152 | charger->battery.num_properties = ARRAY_SIZE(max8997_battery_props); | ||
153 | |||
154 | charger->dev = &pdev->dev; | ||
155 | charger->iodev = iodev; | ||
156 | |||
157 | ret = power_supply_register(&pdev->dev, &charger->battery); | ||
158 | if (ret) { | ||
159 | dev_err(&pdev->dev, "failed: power supply register\n"); | ||
160 | goto err; | ||
161 | } | ||
162 | |||
163 | return 0; | ||
164 | err: | ||
165 | kfree(charger); | ||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | static int __devexit max8997_battery_remove(struct platform_device *pdev) | ||
170 | { | ||
171 | struct charger_data *charger = platform_get_drvdata(pdev); | ||
172 | |||
173 | power_supply_unregister(&charger->battery); | ||
174 | kfree(charger); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static const struct platform_device_id max8997_battery_id[] = { | ||
179 | { "max8997-battery", 0 }, | ||
180 | }; | ||
181 | |||
182 | static struct platform_driver max8997_battery_driver = { | ||
183 | .driver = { | ||
184 | .name = "max8997-battery", | ||
185 | .owner = THIS_MODULE, | ||
186 | }, | ||
187 | .probe = max8997_battery_probe, | ||
188 | .remove = __devexit_p(max8997_battery_remove), | ||
189 | .id_table = max8997_battery_id, | ||
190 | }; | ||
191 | |||
192 | static int __init max8997_battery_init(void) | ||
193 | { | ||
194 | return platform_driver_register(&max8997_battery_driver); | ||
195 | } | ||
196 | subsys_initcall(max8997_battery_init); | ||
197 | |||
198 | static void __exit max8997_battery_cleanup(void) | ||
199 | { | ||
200 | platform_driver_unregister(&max8997_battery_driver); | ||
201 | } | ||
202 | module_exit(max8997_battery_cleanup); | ||
203 | |||
204 | MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver"); | ||
205 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
206 | MODULE_LICENSE("GPL"); | ||