Merge remote-tracking branch 'spi/fix/dspi' into spi-linus
[deliverable/linux.git] / drivers / power / rx51_battery.c
1 /*
2 * Nokia RX-51 battery driver
3 *
4 * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <linux/module.h>
22 #include <linux/param.h>
23 #include <linux/platform_device.h>
24 #include <linux/power_supply.h>
25 #include <linux/slab.h>
26 #include <linux/i2c/twl4030-madc.h>
27
28 /* RX51 specific channels */
29 #define TWL4030_MADC_BTEMP_RX51 TWL4030_MADC_ADCIN0
30 #define TWL4030_MADC_BCI_RX51 TWL4030_MADC_ADCIN4
31
32 struct rx51_device_info {
33 struct device *dev;
34 struct power_supply bat;
35 };
36
37 /*
38 * Read ADCIN channel value, code copied from maemo kernel
39 */
40 static int rx51_battery_read_adc(int channel)
41 {
42 struct twl4030_madc_request req;
43
44 req.channels = channel;
45 req.do_avg = 1;
46 req.method = TWL4030_MADC_SW1;
47 req.func_cb = NULL;
48 req.type = TWL4030_MADC_WAIT;
49 req.raw = true;
50
51 if (twl4030_madc_conversion(&req) <= 0)
52 return -ENODATA;
53
54 return req.rbuf[ffs(channel) - 1];
55 }
56
57 /*
58 * Read ADCIN channel 12 (voltage) and convert RAW value to micro voltage
59 * This conversion formula was extracted from maemo program bsi-read
60 */
61 static int rx51_battery_read_voltage(struct rx51_device_info *di)
62 {
63 int voltage = rx51_battery_read_adc(TWL4030_MADC_VBAT);
64
65 if (voltage < 0)
66 return voltage;
67
68 return 1000 * (10000 * voltage / 1705);
69 }
70
71 /*
72 * Temperature look-up tables
73 * TEMP = (1/(t1 + 1/298) - 273.15)
74 * Where t1 = (1/B) * ln((RAW_ADC_U * 2.5)/(R * I * 255))
75 * Formula is based on experimental data, RX-51 CAL data, maemo program bme
76 * and formula from da9052 driver with values R = 100, B = 3380, I = 0.00671
77 */
78
79 /*
80 * Table1 (temperature for first 25 RAW values)
81 * Usage: TEMP = rx51_temp_table1[RAW]
82 * RAW is between 1 and 24
83 * TEMP is between 201 C and 55 C
84 */
85 static u8 rx51_temp_table1[] = {
86 255, 201, 159, 138, 124, 114, 106, 99, 94, 89, 85, 82, 78, 75,
87 73, 70, 68, 66, 64, 62, 61, 59, 57, 56, 55
88 };
89
90 /*
91 * Table2 (lowest RAW value for temperature)
92 * Usage: RAW = rx51_temp_table2[TEMP-rx51_temp_table2_first]
93 * TEMP is between 53 C and -32 C
94 * RAW is between 25 and 993
95 */
96 #define rx51_temp_table2_first 53
97 static u16 rx51_temp_table2[] = {
98 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39,
99 40, 41, 43, 44, 46, 48, 49, 51, 53, 55, 57, 59, 61, 64,
100 66, 69, 71, 74, 77, 80, 83, 86, 90, 94, 97, 101, 106, 110,
101 115, 119, 125, 130, 136, 141, 148, 154, 161, 168, 176, 184, 202, 211,
102 221, 231, 242, 254, 266, 279, 293, 308, 323, 340, 357, 375, 395, 415,
103 437, 460, 485, 511, 539, 568, 600, 633, 669, 706, 747, 790, 836, 885,
104 937, 993, 1024
105 };
106
107 /*
108 * Read ADCIN channel 0 (battery temp) and convert value to tenths of Celsius
109 * Use Temperature look-up tables for conversation
110 */
111 static int rx51_battery_read_temperature(struct rx51_device_info *di)
112 {
113 int min = 0;
114 int max = ARRAY_SIZE(rx51_temp_table2) - 1;
115 int raw = rx51_battery_read_adc(TWL4030_MADC_BTEMP_RX51);
116
117 /* Zero and negative values are undefined */
118 if (raw <= 0)
119 return INT_MAX;
120
121 /* ADC channels are 10 bit, higher value are undefined */
122 if (raw >= (1 << 10))
123 return INT_MIN;
124
125 /* First check for temperature in first direct table */
126 if (raw < ARRAY_SIZE(rx51_temp_table1))
127 return rx51_temp_table1[raw] * 10;
128
129 /* Binary search RAW value in second inverse table */
130 while (max - min > 1) {
131 int mid = (max + min) / 2;
132 if (rx51_temp_table2[mid] <= raw)
133 min = mid;
134 else if (rx51_temp_table2[mid] > raw)
135 max = mid;
136 if (rx51_temp_table2[mid] == raw)
137 break;
138 }
139
140 return (rx51_temp_table2_first - min) * 10;
141 }
142
143 /*
144 * Read ADCIN channel 4 (BSI) and convert RAW value to micro Ah
145 * This conversion formula was extracted from maemo program bsi-read
146 */
147 static int rx51_battery_read_capacity(struct rx51_device_info *di)
148 {
149 int capacity = rx51_battery_read_adc(TWL4030_MADC_BCI_RX51);
150
151 if (capacity < 0)
152 return capacity;
153
154 return 1280 * (1200 * capacity)/(1024 - capacity);
155 }
156
157 /*
158 * Return power_supply property
159 */
160 static int rx51_battery_get_property(struct power_supply *psy,
161 enum power_supply_property psp,
162 union power_supply_propval *val)
163 {
164 struct rx51_device_info *di = container_of((psy),
165 struct rx51_device_info, bat);
166
167 switch (psp) {
168 case POWER_SUPPLY_PROP_TECHNOLOGY:
169 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
170 break;
171 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
172 val->intval = 4200000;
173 break;
174 case POWER_SUPPLY_PROP_PRESENT:
175 val->intval = rx51_battery_read_voltage(di) ? 1 : 0;
176 break;
177 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
178 val->intval = rx51_battery_read_voltage(di);
179 break;
180 case POWER_SUPPLY_PROP_TEMP:
181 val->intval = rx51_battery_read_temperature(di);
182 break;
183 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
184 val->intval = rx51_battery_read_capacity(di);
185 break;
186 default:
187 return -EINVAL;
188 }
189
190 if (val->intval == INT_MAX || val->intval == INT_MIN)
191 return -EINVAL;
192
193 return 0;
194 }
195
196 static enum power_supply_property rx51_battery_props[] = {
197 POWER_SUPPLY_PROP_TECHNOLOGY,
198 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
199 POWER_SUPPLY_PROP_PRESENT,
200 POWER_SUPPLY_PROP_VOLTAGE_NOW,
201 POWER_SUPPLY_PROP_TEMP,
202 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
203 };
204
205 static int rx51_battery_probe(struct platform_device *pdev)
206 {
207 struct rx51_device_info *di;
208 int ret;
209
210 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
211 if (!di)
212 return -ENOMEM;
213
214 platform_set_drvdata(pdev, di);
215
216 di->bat.name = dev_name(&pdev->dev);
217 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
218 di->bat.properties = rx51_battery_props;
219 di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
220 di->bat.get_property = rx51_battery_get_property;
221
222 ret = power_supply_register(di->dev, &di->bat);
223 if (ret)
224 return ret;
225
226 return 0;
227 }
228
229 static int rx51_battery_remove(struct platform_device *pdev)
230 {
231 struct rx51_device_info *di = platform_get_drvdata(pdev);
232
233 power_supply_unregister(&di->bat);
234
235 return 0;
236 }
237
238 static struct platform_driver rx51_battery_driver = {
239 .probe = rx51_battery_probe,
240 .remove = rx51_battery_remove,
241 .driver = {
242 .name = "rx51-battery",
243 .owner = THIS_MODULE,
244 },
245 };
246 module_platform_driver(rx51_battery_driver);
247
248 MODULE_ALIAS("platform:rx51-battery");
249 MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
250 MODULE_DESCRIPTION("Nokia RX-51 battery driver");
251 MODULE_LICENSE("GPL");
This page took 0.036145 seconds and 6 git commands to generate.