brcmfmac: remove unnecessary EXPORT_SYMBOL() usage
[deliverable/linux.git] / drivers / power / rx51_battery.c
CommitLineData
04930baf
PR
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
8e2747f0
MB
28/* RX51 specific channels */
29#define TWL4030_MADC_BTEMP_RX51 TWL4030_MADC_ADCIN0
30#define TWL4030_MADC_BCI_RX51 TWL4030_MADC_ADCIN4
31
04930baf
PR
32struct 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 */
40static int rx51_battery_read_adc(int channel)
41{
42 struct twl4030_madc_request req;
43
8e2747f0 44 req.channels = channel;
04930baf
PR
45 req.do_avg = 1;
46 req.method = TWL4030_MADC_SW1;
47 req.func_cb = NULL;
48 req.type = TWL4030_MADC_WAIT;
8059c1c6 49 req.raw = true;
04930baf
PR
50
51 if (twl4030_madc_conversion(&req) <= 0)
52 return -ENODATA;
53
db15e631 54 return req.rbuf[ffs(channel) - 1];
04930baf
PR
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 */
61static int rx51_battery_read_voltage(struct rx51_device_info *di)
62{
8e2747f0 63 int voltage = rx51_battery_read_adc(TWL4030_MADC_VBAT);
04930baf
PR
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 */
85static 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
97static 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 */
111static int rx51_battery_read_temperature(struct rx51_device_info *di)
112{
113 int min = 0;
114 int max = ARRAY_SIZE(rx51_temp_table2) - 1;
8e2747f0 115 int raw = rx51_battery_read_adc(TWL4030_MADC_BTEMP_RX51);
04930baf
PR
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))
59584857 127 return rx51_temp_table1[raw] * 10;
04930baf
PR
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
59584857 140 return (rx51_temp_table2_first - min) * 10;
04930baf
PR
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 */
147static int rx51_battery_read_capacity(struct rx51_device_info *di)
148{
8e2747f0 149 int capacity = rx51_battery_read_adc(TWL4030_MADC_BCI_RX51);
04930baf
PR
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 */
160static 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
196static 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
6d2cea4f 205static int rx51_battery_probe(struct platform_device *pdev)
04930baf
PR
206{
207 struct rx51_device_info *di;
208 int ret;
209
b852ac51 210 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
04930baf
PR
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);
f70d739a 223 if (ret)
04930baf 224 return ret;
04930baf
PR
225
226 return 0;
227}
228
6d2cea4f 229static int rx51_battery_remove(struct platform_device *pdev)
04930baf
PR
230{
231 struct rx51_device_info *di = platform_get_drvdata(pdev);
232
233 power_supply_unregister(&di->bat);
04930baf
PR
234
235 return 0;
236}
237
238static struct platform_driver rx51_battery_driver = {
239 .probe = rx51_battery_probe,
6d2cea4f 240 .remove = rx51_battery_remove,
04930baf
PR
241 .driver = {
242 .name = "rx51-battery",
243 .owner = THIS_MODULE,
244 },
245};
246module_platform_driver(rx51_battery_driver);
247
248MODULE_ALIAS("platform:rx51-battery");
249MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
250MODULE_DESCRIPTION("Nokia RX-51 battery driver");
251MODULE_LICENSE("GPL");
This page took 0.07747 seconds and 5 git commands to generate.