aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajanikanth H.V <rajanikanth.hv@stericsson.com>2012-11-18 21:45:41 -0500
committerAnton Vorontsov <anton.vorontsov@linaro.org>2012-11-18 22:37:04 -0500
commite0f1abeba5c2d8a2183566717d99294fd1a29c2e (patch)
treebf4b3582791d3e4baa298f4268cf2bbad8169b74
parente9f14c18b83ccf3ab291b83a1d6c640113ecf545 (diff)
ab8500: Add devicetree support for fuelgauge
- This patch adds device tree support for fuelgauge driver - optimize bm devices platform_data usage and of_probe(...) Note: of_probe() routine for battery managed devices is made common across all bm drivers. - test status: - interrupt numbers assigned differs between legacy and FDT mode. Signed-off-by: Rajanikanth H.V <rajanikanth.hv@stericsson.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/mfd/ab8500.txt7
-rw-r--r--Documentation/devicetree/bindings/power_supply/ab8500/fg.txt58
-rw-r--r--arch/arm/boot/dts/dbx5x0.dtsi12
-rw-r--r--drivers/mfd/ab8500-core.c5
-rw-r--r--drivers/power/Makefile2
-rw-r--r--drivers/power/ab8500_bmdata.c521
-rw-r--r--drivers/power/ab8500_btemp.c16
-rw-r--r--drivers/power/ab8500_charger.c16
-rw-r--r--drivers/power/ab8500_fg.c82
-rw-r--r--drivers/power/abx500_chargalg.c8
-rw-r--r--include/linux/mfd/abx500.h36
11 files changed, 667 insertions, 96 deletions
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt
index ce83c8d3c00e..6ca8d817ef92 100644
--- a/Documentation/devicetree/bindings/mfd/ab8500.txt
+++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
@@ -24,7 +24,12 @@ ab8500-bm : : : Battery Manager
24ab8500-btemp : : : Battery Temperature 24ab8500-btemp : : : Battery Temperature
25ab8500-charger : : : Battery Charger 25ab8500-charger : : : Battery Charger
26ab8500-codec : : : Audio Codec 26ab8500-codec : : : Audio Codec
27ab8500-fg : : : Fuel Gauge 27ab8500-fg : : vddadc : Fuel Gauge
28 : NCONV_ACCU : : Accumulate N Sample Conversion
29 : BATT_OVV : : Battery Over Voltage
30 : LOW_BAT_F : : LOW threshold battery voltage
31 : CC_INT_CALIB : : Coulomb Counter Internal Calibration
32 : CCEOC : : Coulomb Counter End of Conversion
28ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter 33ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter
29 SW_CONV_END : : 34 SW_CONV_END : :
30ab8500-gpio : : : GPIO Controller 35ab8500-gpio : : : GPIO Controller
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
new file mode 100644
index 000000000000..ccafcb9112fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,58 @@
1=== AB8500 Fuel Gauge Driver ===
2
3AB8500 is a mixed signal multimedia and power management
4device comprising: power and energy-management-module,
5wall-charger, usb-charger, audio codec, general purpose adc,
6tvout, clock management and sim card interface.
7
8Fuelgauge support is part of energy-management-modules, other
9components of this module are:
10main-charger, usb-combo-charger and battery-temperature-monitoring.
11
12The properties below describes the node for fuelgauge driver.
13
14Required Properties:
15- compatible = This shall be: "stericsson,ab8500-fg"
16- battery = Shall be battery specific information
17 Example:
18 ab8500_fg {
19 compatible = "stericsson,ab8500-fg";
20 battery = <&ab8500_battery>;
21 };
22
23dependent node:
24 ab8500_battery: ab8500_battery {
25 };
26 This node will provide information on 'thermistor interface' and
27 'battery technology type' used.
28
29Properties of this node are:
30thermistor-on-batctrl:
31 A boolean value indicating thermistor interface to battery
32
33 Note:
34 'btemp' and 'batctrl' are the pins interfaced for battery temperature
35 measurement, 'btemp' signal is used when NTC(negative temperature
36 coefficient) resister is interfaced external to battery whereas
37 'batctrl' pin is used when NTC resister is internal to battery.
38
39 Example:
40 ab8500_battery: ab8500_battery {
41 thermistor-on-batctrl;
42 };
43 indicates: NTC resister is internal to battery, 'batctrl' is used
44 for thermal measurement.
45
46 The absence of property 'thermal-on-batctrl' indicates
47 NTC resister is external to battery and 'btemp' signal is used
48 for thermal measurement.
49
50battery-type:
51 This shall be the battery manufacturing technology type,
52 allowed types are:
53 "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
54 Example:
55 ab8500_battery: ab8500_battery {
56 stericsson,battery-type = "LIPO";
57 }
58
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 4b0e0ca08f40..0c81986904c5 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -352,7 +352,17 @@
352 vddadc-supply = <&ab8500_ldo_tvout_reg>; 352 vddadc-supply = <&ab8500_ldo_tvout_reg>;
353 }; 353 };
354 354
355 ab8500-usb { 355 ab8500_battery: ab8500_battery {
356 stericsson,battery-type = "LIPO";
357 thermistor-on-batctrl;
358 };
359
360 ab8500_fg {
361 compatible = "stericsson,ab8500-fg";
362 battery = <&ab8500_battery>;
363 };
364
365 ab8500_usb {
356 compatible = "stericsson,ab8500-usb"; 366 compatible = "stericsson,ab8500-usb";
357 interrupts = < 90 0x4 367 interrupts = < 90 0x4
358 96 0x4 368 96 0x4
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77b5cde..7c3017ba73e4 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1051,8 +1051,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
1051 }, 1051 },
1052 { 1052 {
1053 .name = "ab8500-fg", 1053 .name = "ab8500-fg",
1054 .of_compatible = "stericsson,ab8500-fg",
1054 .num_resources = ARRAY_SIZE(ab8500_fg_resources), 1055 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
1055 .resources = ab8500_fg_resources, 1056 .resources = ab8500_fg_resources,
1057#ifndef CONFIG_OF
1058 .platform_data = &ab8500_bm_data,
1059 .pdata_size = sizeof(ab8500_bm_data),
1060#endif
1056 }, 1061 },
1057 { 1062 {
1058 .name = "ab8500-chargalg", 1063 .name = "ab8500-chargalg",
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 74dfd9570154..696e3a960b3e 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -38,7 +38,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
38obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o 38obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
39obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o 39obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
40obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o 40obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
41obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o 41obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
42obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o 42obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
43obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o 43obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
44obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o 44obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
new file mode 100644
index 000000000000..e7639b6659f7
--- /dev/null
+++ b/drivers/power/ab8500_bmdata.c
@@ -0,0 +1,521 @@
1#include <linux/export.h>
2#include <linux/power_supply.h>
3#include <linux/of.h>
4#include <linux/mfd/abx500.h>
5#include <linux/mfd/abx500/ab8500.h>
6#include <linux/mfd/abx500/ab8500-bm.h>
7
8/*
9 * These are the defined batteries that uses a NTC and ID resistor placed
10 * inside of the battery pack.
11 * Note that the res_to_temp table must be strictly sorted by falling resistance
12 * values to work.
13 */
14static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
15 {-5, 53407},
16 { 0, 48594},
17 { 5, 43804},
18 {10, 39188},
19 {15, 34870},
20 {20, 30933},
21 {25, 27422},
22 {30, 24347},
23 {35, 21694},
24 {40, 19431},
25 {45, 17517},
26 {50, 15908},
27 {55, 14561},
28 {60, 13437},
29 {65, 12500},
30};
31
32static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
33 {-5, 165418},
34 { 0, 159024},
35 { 5, 151921},
36 {10, 144300},
37 {15, 136424},
38 {20, 128565},
39 {25, 120978},
40 {30, 113875},
41 {35, 107397},
42 {40, 101629},
43 {45, 96592},
44 {50, 92253},
45 {55, 88569},
46 {60, 85461},
47 {65, 82869},
48};
49
50static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
51 {4171, 100},
52 {4114, 95},
53 {4009, 83},
54 {3947, 74},
55 {3907, 67},
56 {3863, 59},
57 {3830, 56},
58 {3813, 53},
59 {3791, 46},
60 {3771, 33},
61 {3754, 25},
62 {3735, 20},
63 {3717, 17},
64 {3681, 13},
65 {3664, 8},
66 {3651, 6},
67 {3635, 5},
68 {3560, 3},
69 {3408, 1},
70 {3247, 0},
71};
72
73static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
74 {4161, 100},
75 {4124, 98},
76 {4044, 90},
77 {4003, 85},
78 {3966, 80},
79 {3933, 75},
80 {3888, 67},
81 {3849, 60},
82 {3813, 55},
83 {3787, 47},
84 {3772, 30},
85 {3751, 25},
86 {3718, 20},
87 {3681, 16},
88 {3660, 14},
89 {3589, 10},
90 {3546, 7},
91 {3495, 4},
92 {3404, 2},
93 {3250, 0},
94};
95
96static struct abx500_v_to_cap cap_tbl[] = {
97 {4186, 100},
98 {4163, 99},
99 {4114, 95},
100 {4068, 90},
101 {3990, 80},
102 {3926, 70},
103 {3898, 65},
104 {3866, 60},
105 {3833, 55},
106 {3812, 50},
107 {3787, 40},
108 {3768, 30},
109 {3747, 25},
110 {3730, 20},
111 {3705, 15},
112 {3699, 14},
113 {3684, 12},
114 {3672, 9},
115 {3657, 7},
116 {3638, 6},
117 {3556, 4},
118 {3424, 2},
119 {3317, 1},
120 {3094, 0},
121};
122
123/*
124 * Note that the res_to_temp table must be strictly sorted by falling
125 * resistance values to work.
126 */
127static struct abx500_res_to_temp temp_tbl[] = {
128 {-5, 214834},
129 { 0, 162943},
130 { 5, 124820},
131 {10, 96520},
132 {15, 75306},
133 {20, 59254},
134 {25, 47000},
135 {30, 37566},
136 {35, 30245},
137 {40, 24520},
138 {45, 20010},
139 {50, 16432},
140 {55, 13576},
141 {60, 11280},
142 {65, 9425},
143};
144
145/*
146 * Note that the batres_vs_temp table must be strictly sorted by falling
147 * temperature values to work.
148 */
149static struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
150 { 40, 120},
151 { 30, 135},
152 { 20, 165},
153 { 10, 230},
154 { 00, 325},
155 {-10, 445},
156 {-20, 595},
157};
158
159/*
160 * Note that the batres_vs_temp table must be strictly sorted by falling
161 * temperature values to work.
162 */
163static struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
164 { 60, 300},
165 { 30, 300},
166 { 20, 300},
167 { 10, 300},
168 { 00, 300},
169 {-10, 300},
170 {-20, 300},
171};
172
173/* battery resistance table for LI ION 9100 battery */
174static struct batres_vs_temp temp_to_batres_tbl_9100[] = {
175 { 60, 180},
176 { 30, 180},
177 { 20, 180},
178 { 10, 180},
179 { 00, 180},
180 {-10, 180},
181 {-20, 180},
182};
183
184static struct abx500_battery_type bat_type_thermistor[] = {
185[BATTERY_UNKNOWN] = {
186 /* First element always represent the UNKNOWN battery */
187 .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
188 .resis_high = 0,
189 .resis_low = 0,
190 .battery_resistance = 300,
191 .charge_full_design = 612,
192 .nominal_voltage = 3700,
193 .termination_vol = 4050,
194 .termination_curr = 200,
195 .recharge_vol = 3990,
196 .normal_cur_lvl = 400,
197 .normal_vol_lvl = 4100,
198 .maint_a_cur_lvl = 400,
199 .maint_a_vol_lvl = 4050,
200 .maint_a_chg_timer_h = 60,
201 .maint_b_cur_lvl = 400,
202 .maint_b_vol_lvl = 4000,
203 .maint_b_chg_timer_h = 200,
204 .low_high_cur_lvl = 300,
205 .low_high_vol_lvl = 4000,
206 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
207 .r_to_t_tbl = temp_tbl,
208 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
209 .v_to_cap_tbl = cap_tbl,
210 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
211 .batres_tbl = temp_to_batres_tbl_thermistor,
212},
213{
214 .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
215 .resis_high = 53407,
216 .resis_low = 12500,
217 .battery_resistance = 300,
218 .charge_full_design = 900,
219 .nominal_voltage = 3600,
220 .termination_vol = 4150,
221 .termination_curr = 80,
222 .recharge_vol = 4130,
223 .normal_cur_lvl = 700,
224 .normal_vol_lvl = 4200,
225 .maint_a_cur_lvl = 600,
226 .maint_a_vol_lvl = 4150,
227 .maint_a_chg_timer_h = 60,
228 .maint_b_cur_lvl = 600,
229 .maint_b_vol_lvl = 4100,
230 .maint_b_chg_timer_h = 200,
231 .low_high_cur_lvl = 300,
232 .low_high_vol_lvl = 4000,
233 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
234 .r_to_t_tbl = temp_tbl_A_thermistor,
235 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
236 .v_to_cap_tbl = cap_tbl_A_thermistor,
237 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
238 .batres_tbl = temp_to_batres_tbl_thermistor,
239
240},
241{
242 .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
243 .resis_high = 165418,
244 .resis_low = 82869,
245 .battery_resistance = 300,
246 .charge_full_design = 900,
247 .nominal_voltage = 3600,
248 .termination_vol = 4150,
249 .termination_curr = 80,
250 .recharge_vol = 4130,
251 .normal_cur_lvl = 700,
252 .normal_vol_lvl = 4200,
253 .maint_a_cur_lvl = 600,
254 .maint_a_vol_lvl = 4150,
255 .maint_a_chg_timer_h = 60,
256 .maint_b_cur_lvl = 600,
257 .maint_b_vol_lvl = 4100,
258 .maint_b_chg_timer_h = 200,
259 .low_high_cur_lvl = 300,
260 .low_high_vol_lvl = 4000,
261 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
262 .r_to_t_tbl = temp_tbl_B_thermistor,
263 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
264 .v_to_cap_tbl = cap_tbl_B_thermistor,
265 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
266 .batres_tbl = temp_to_batres_tbl_thermistor,
267},
268};
269
270static struct abx500_battery_type bat_type_ext_thermistor[] = {
271[BATTERY_UNKNOWN] = {
272 /* First element always represent the UNKNOWN battery */
273 .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
274 .resis_high = 0,
275 .resis_low = 0,
276 .battery_resistance = 300,
277 .charge_full_design = 612,
278 .nominal_voltage = 3700,
279 .termination_vol = 4050,
280 .termination_curr = 200,
281 .recharge_vol = 3990,
282 .normal_cur_lvl = 400,
283 .normal_vol_lvl = 4100,
284 .maint_a_cur_lvl = 400,
285 .maint_a_vol_lvl = 4050,
286 .maint_a_chg_timer_h = 60,
287 .maint_b_cur_lvl = 400,
288 .maint_b_vol_lvl = 4000,
289 .maint_b_chg_timer_h = 200,
290 .low_high_cur_lvl = 300,
291 .low_high_vol_lvl = 4000,
292 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
293 .r_to_t_tbl = temp_tbl,
294 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
295 .v_to_cap_tbl = cap_tbl,
296 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
297 .batres_tbl = temp_to_batres_tbl_thermistor,
298},
299/*
300 * These are the batteries that doesn't have an internal NTC resistor to measure
301 * its temperature. The temperature in this case is measure with a NTC placed
302 * near the battery but on the PCB.
303 */
304{
305 .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
306 .resis_high = 76000,
307 .resis_low = 53000,
308 .battery_resistance = 300,
309 .charge_full_design = 900,
310 .nominal_voltage = 3700,
311 .termination_vol = 4150,
312 .termination_curr = 100,
313 .recharge_vol = 4130,
314 .normal_cur_lvl = 700,
315 .normal_vol_lvl = 4200,
316 .maint_a_cur_lvl = 600,
317 .maint_a_vol_lvl = 4150,
318 .maint_a_chg_timer_h = 60,
319 .maint_b_cur_lvl = 600,
320 .maint_b_vol_lvl = 4100,
321 .maint_b_chg_timer_h = 200,
322 .low_high_cur_lvl = 300,
323 .low_high_vol_lvl = 4000,
324 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
325 .r_to_t_tbl = temp_tbl,
326 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
327 .v_to_cap_tbl = cap_tbl,
328 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
329 .batres_tbl = temp_to_batres_tbl_thermistor,
330},
331{
332 .name = POWER_SUPPLY_TECHNOLOGY_LION,
333 .resis_high = 30000,
334 .resis_low = 10000,
335 .battery_resistance = 300,
336 .charge_full_design = 950,
337 .nominal_voltage = 3700,
338 .termination_vol = 4150,
339 .termination_curr = 100,
340 .recharge_vol = 4130,
341 .normal_cur_lvl = 700,
342 .normal_vol_lvl = 4200,
343 .maint_a_cur_lvl = 600,
344 .maint_a_vol_lvl = 4150,
345 .maint_a_chg_timer_h = 60,
346 .maint_b_cur_lvl = 600,
347 .maint_b_vol_lvl = 4100,
348 .maint_b_chg_timer_h = 200,
349 .low_high_cur_lvl = 300,
350 .low_high_vol_lvl = 4000,
351 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
352 .r_to_t_tbl = temp_tbl,
353 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
354 .v_to_cap_tbl = cap_tbl,
355 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
356 .batres_tbl = temp_to_batres_tbl_thermistor,
357},
358{
359 .name = POWER_SUPPLY_TECHNOLOGY_LION,
360 .resis_high = 95000,
361 .resis_low = 76001,
362 .battery_resistance = 300,
363 .charge_full_design = 950,
364 .nominal_voltage = 3700,
365 .termination_vol = 4150,
366 .termination_curr = 100,
367 .recharge_vol = 4130,
368 .normal_cur_lvl = 700,
369 .normal_vol_lvl = 4200,
370 .maint_a_cur_lvl = 600,
371 .maint_a_vol_lvl = 4150,
372 .maint_a_chg_timer_h = 60,
373 .maint_b_cur_lvl = 600,
374 .maint_b_vol_lvl = 4100,
375 .maint_b_chg_timer_h = 200,
376 .low_high_cur_lvl = 300,
377 .low_high_vol_lvl = 4000,
378 .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
379 .r_to_t_tbl = temp_tbl,
380 .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
381 .v_to_cap_tbl = cap_tbl,
382 .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
383 .batres_tbl = temp_to_batres_tbl_thermistor,
384},
385};
386
387static const struct abx500_bm_capacity_levels cap_levels = {
388 .critical = 2,
389 .low = 10,
390 .normal = 70,
391 .high = 95,
392 .full = 100,
393};
394
395static const struct abx500_fg_parameters fg = {
396 .recovery_sleep_timer = 10,
397 .recovery_total_time = 100,
398 .init_timer = 1,
399 .init_discard_time = 5,
400 .init_total_time = 40,
401 .high_curr_time = 60,
402 .accu_charging = 30,
403 .accu_high_curr = 30,
404 .high_curr_threshold = 50,
405 .lowbat_threshold = 3100,
406 .battok_falling_th_sel0 = 2860,
407 .battok_raising_th_sel1 = 2860,
408 .user_cap_limit = 15,
409 .maint_thres = 97,
410};
411
412static const struct abx500_maxim_parameters maxi_params = {
413 .ena_maxi = true,
414 .chg_curr = 910,
415 .wait_cycles = 10,
416 .charger_curr_step = 100,
417};
418
419static const struct abx500_bm_charger_parameters chg = {
420 .usb_volt_max = 5500,
421 .usb_curr_max = 1500,
422 .ac_volt_max = 7500,
423 .ac_curr_max = 1500,
424};
425
426struct abx500_bm_data ab8500_bm_data = {
427 .temp_under = 3,
428 .temp_low = 8,
429 .temp_high = 43,
430 .temp_over = 48,
431 .main_safety_tmr_h = 4,
432 .temp_interval_chg = 20,
433 .temp_interval_nochg = 120,
434 .usb_safety_tmr_h = 4,
435 .bkup_bat_v = BUP_VCH_SEL_2P6V,
436 .bkup_bat_i = BUP_ICH_SEL_150UA,
437 .no_maintenance = false,
438 .adc_therm = ABx500_ADC_THERM_BATCTRL,
439 .chg_unknown_bat = false,
440 .enable_overshoot = false,
441 .fg_res = 100,
442 .cap_levels = &cap_levels,
443 .bat_type = bat_type_thermistor,
444 .n_btypes = 3,
445 .batt_id = 0,
446 .interval_charging = 5,
447 .interval_not_charging = 120,
448 .temp_hysteresis = 3,
449 .gnd_lift_resistance = 34,
450 .maxi = &maxi_params,
451 .chg_params = &chg,
452 .fg_params = &fg,
453};
454
455int __devinit
456bmdevs_of_probe(struct device *dev,
457 struct device_node *np,
458 struct abx500_bm_data **battery)
459{
460 struct abx500_battery_type *btype;
461 struct device_node *np_bat_supply;
462 struct abx500_bm_data *bat;
463 const char *btech;
464 char bat_tech[8];
465 int i, thermistor;
466
467 *battery = &ab8500_bm_data;
468
469 /* get phandle to 'battery-info' node */
470 np_bat_supply = of_parse_phandle(np, "battery", 0);
471 if (!np_bat_supply) {
472 dev_err(dev, "missing property battery\n");
473 return -EINVAL;
474 }
475 if (of_property_read_bool(np_bat_supply,
476 "thermistor-on-batctrl"))
477 thermistor = NTC_INTERNAL;
478 else
479 thermistor = NTC_EXTERNAL;
480
481 bat = *battery;
482 if (thermistor == NTC_EXTERNAL) {
483 bat->n_btypes = 4;
484 bat->bat_type = bat_type_ext_thermistor;
485 bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
486 }
487 btech = of_get_property(np_bat_supply,
488 "stericsson,battery-type", NULL);
489 if (!btech) {
490 dev_warn(dev, "missing property battery-name/type\n");
491 strcpy(bat_tech, "UNKNOWN");
492 } else {
493 strcpy(bat_tech, btech);
494 }
495
496 if (strncmp(bat_tech, "LION", 4) == 0) {
497 bat->no_maintenance = true;
498 bat->chg_unknown_bat = true;
499 bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
500 bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150;
501 bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130;
502 bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520;
503 bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200;
504 }
505 /* select the battery resolution table */
506 for (i = 0; i < bat->n_btypes; ++i) {
507 btype = (bat->bat_type + i);
508 if (thermistor == NTC_EXTERNAL) {
509 btype->batres_tbl =
510 temp_to_batres_tbl_ext_thermistor;
511 } else if (strncmp(bat_tech, "LION", 4) == 0) {
512 btype->batres_tbl =
513 temp_to_batres_tbl_9100;
514 } else {
515 btype->batres_tbl =
516 temp_to_batres_tbl_thermistor;
517 }
518 }
519 of_node_put(np_bat_supply);
520 return 0;
521}
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index e3b6395b20dd..abc2abc16a5d 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -93,7 +93,7 @@ struct ab8500_btemp {
93 struct ab8500 *parent; 93 struct ab8500 *parent;
94 struct ab8500_gpadc *gpadc; 94 struct ab8500_gpadc *gpadc;
95 struct ab8500_fg *fg; 95 struct ab8500_fg *fg;
96 struct abx500_btemp_platform_data *pdata; 96 struct abx500_bmdevs_plat_data *pdata;
97 struct abx500_bm_data *bat; 97 struct abx500_bm_data *bat;
98 struct power_supply btemp_psy; 98 struct power_supply btemp_psy;
99 struct ab8500_btemp_events events; 99 struct ab8500_btemp_events events;
@@ -962,10 +962,10 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
962 962
963static int __devinit ab8500_btemp_probe(struct platform_device *pdev) 963static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
964{ 964{
965 struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data;
966 struct ab8500_btemp *di;
965 int irq, i, ret = 0; 967 int irq, i, ret = 0;
966 u8 val; 968 u8 val;
967 struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
968 struct ab8500_btemp *di;
969 969
970 if (!plat_data) { 970 if (!plat_data) {
971 dev_err(&pdev->dev, "No platform data\n"); 971 dev_err(&pdev->dev, "No platform data\n");
@@ -982,21 +982,13 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
982 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 982 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
983 983
984 /* get btemp specific platform data */ 984 /* get btemp specific platform data */
985 di->pdata = plat_data->btemp; 985 di->pdata = plat_data;
986 if (!di->pdata) { 986 if (!di->pdata) {
987 dev_err(di->dev, "no btemp platform data supplied\n"); 987 dev_err(di->dev, "no btemp platform data supplied\n");
988 ret = -EINVAL; 988 ret = -EINVAL;
989 goto free_device_info; 989 goto free_device_info;
990 } 990 }
991 991
992 /* get battery specific platform data */
993 di->bat = plat_data->battery;
994 if (!di->bat) {
995 dev_err(di->dev, "no battery platform data supplied\n");
996 ret = -EINVAL;
997 goto free_device_info;
998 }
999
1000 /* BTEMP supply */ 992 /* BTEMP supply */
1001 di->btemp_psy.name = "ab8500_btemp"; 993 di->btemp_psy.name = "ab8500_btemp";
1002 di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; 994 di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 26ff759e2220..723edb47b1d8 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -220,7 +220,7 @@ struct ab8500_charger {
220 bool autopower; 220 bool autopower;
221 struct ab8500 *parent; 221 struct ab8500 *parent;
222 struct ab8500_gpadc *gpadc; 222 struct ab8500_gpadc *gpadc;
223 struct abx500_charger_platform_data *pdata; 223 struct abx500_bmdevs_plat_data *pdata;
224 struct abx500_bm_data *bat; 224 struct abx500_bm_data *bat;
225 struct ab8500_charger_event_flags flags; 225 struct ab8500_charger_event_flags flags;
226 struct ab8500_charger_usb_state usb_state; 226 struct ab8500_charger_usb_state usb_state;
@@ -2533,9 +2533,9 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
2533 2533
2534static int __devinit ab8500_charger_probe(struct platform_device *pdev) 2534static int __devinit ab8500_charger_probe(struct platform_device *pdev)
2535{ 2535{
2536 int irq, i, charger_status, ret = 0; 2536 struct abx500_bmdevs_plat_data *plat_data = pdev->dev.platform_data;
2537 struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
2538 struct ab8500_charger *di; 2537 struct ab8500_charger *di;
2538 int irq, i, charger_status, ret = 0;
2539 2539
2540 if (!plat_data) { 2540 if (!plat_data) {
2541 dev_err(&pdev->dev, "No platform data\n"); 2541 dev_err(&pdev->dev, "No platform data\n");
@@ -2555,21 +2555,13 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
2555 spin_lock_init(&di->usb_state.usb_lock); 2555 spin_lock_init(&di->usb_state.usb_lock);
2556 2556
2557 /* get charger specific platform data */ 2557 /* get charger specific platform data */
2558 di->pdata = plat_data->charger; 2558 di->pdata = plat_data;
2559 if (!di->pdata) { 2559 if (!di->pdata) {
2560 dev_err(di->dev, "no charger platform data supplied\n"); 2560 dev_err(di->dev, "no charger platform data supplied\n");
2561 ret = -EINVAL; 2561 ret = -EINVAL;
2562 goto free_device_info; 2562 goto free_device_info;
2563 } 2563 }
2564 2564
2565 /* get battery specific platform data */
2566 di->bat = plat_data->battery;
2567 if (!di->bat) {
2568 dev_err(di->dev, "no battery platform data supplied\n");
2569 ret = -EINVAL;
2570 goto free_device_info;
2571 }
2572
2573 di->autopower = false; 2565 di->autopower = false;
2574 2566
2575 /* AC supply */ 2567 /* AC supply */
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 2db8cc254399..ed62ef788eb5 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -22,15 +22,16 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/power_supply.h> 23#include <linux/power_supply.h>
24#include <linux/kobject.h> 24#include <linux/kobject.h>
25#include <linux/mfd/abx500/ab8500.h>
26#include <linux/mfd/abx500.h>
27#include <linux/slab.h> 25#include <linux/slab.h>
28#include <linux/mfd/abx500/ab8500-bm.h>
29#include <linux/delay.h> 26#include <linux/delay.h>
30#include <linux/mfd/abx500/ab8500-gpadc.h>
31#include <linux/mfd/abx500.h>
32#include <linux/time.h> 27#include <linux/time.h>
28#include <linux/of.h>
33#include <linux/completion.h> 29#include <linux/completion.h>
30#include <linux/mfd/core.h>
31#include <linux/mfd/abx500.h>
32#include <linux/mfd/abx500/ab8500.h>
33#include <linux/mfd/abx500/ab8500-bm.h>
34#include <linux/mfd/abx500/ab8500-gpadc.h>
34 35
35#define MILLI_TO_MICRO 1000 36#define MILLI_TO_MICRO 1000
36#define FG_LSB_IN_MA 1627 37#define FG_LSB_IN_MA 1627
@@ -172,7 +173,6 @@ struct inst_curr_result_list {
172 * @avg_cap: Average capacity filter 173 * @avg_cap: Average capacity filter
173 * @parent: Pointer to the struct ab8500 174 * @parent: Pointer to the struct ab8500
174 * @gpadc: Pointer to the struct gpadc 175 * @gpadc: Pointer to the struct gpadc
175 * @pdata: Pointer to the abx500_fg platform data
176 * @bat: Pointer to the abx500_bm platform data 176 * @bat: Pointer to the abx500_bm platform data
177 * @fg_psy: Structure that holds the FG specific battery properties 177 * @fg_psy: Structure that holds the FG specific battery properties
178 * @fg_wq: Work queue for running the FG algorithm 178 * @fg_wq: Work queue for running the FG algorithm
@@ -212,7 +212,6 @@ struct ab8500_fg {
212 struct ab8500_fg_avg_cap avg_cap; 212 struct ab8500_fg_avg_cap avg_cap;
213 struct ab8500 *parent; 213 struct ab8500 *parent;
214 struct ab8500_gpadc *gpadc; 214 struct ab8500_gpadc *gpadc;
215 struct abx500_fg_platform_data *pdata;
216 struct abx500_bm_data *bat; 215 struct abx500_bm_data *bat;
217 struct power_supply fg_psy; 216 struct power_supply fg_psy;
218 struct workqueue_struct *fg_wq; 217 struct workqueue_struct *fg_wq;
@@ -2429,7 +2428,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev)
2429 flush_scheduled_work(); 2428 flush_scheduled_work();
2430 power_supply_unregister(&di->fg_psy); 2429 power_supply_unregister(&di->fg_psy);
2431 platform_set_drvdata(pdev, NULL); 2430 platform_set_drvdata(pdev, NULL);
2432 kfree(di);
2433 return ret; 2431 return ret;
2434} 2432}
2435 2433
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
2442 {"CCEOC", ab8500_fg_cc_data_end_handler}, 2440 {"CCEOC", ab8500_fg_cc_data_end_handler},
2443}; 2441};
2444 2442
2443static char *supply_interface[] = {
2444 "ab8500_chargalg",
2445 "ab8500_usb",
2446};
2447
2445static int __devinit ab8500_fg_probe(struct platform_device *pdev) 2448static int __devinit ab8500_fg_probe(struct platform_device *pdev)
2446{ 2449{
2450 struct device_node *np = pdev->dev.of_node;
2451 struct ab8500_fg *di;
2447 int i, irq; 2452 int i, irq;
2448 int ret = 0; 2453 int ret = 0;
2449 struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
2450 struct ab8500_fg *di;
2451
2452 if (!plat_data) {
2453 dev_err(&pdev->dev, "No platform data\n");
2454 return -EINVAL;
2455 }
2456 2454
2457 di = kzalloc(sizeof(*di), GFP_KERNEL); 2455 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
2458 if (!di) 2456 if (!di) {
2457 dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
2459 return -ENOMEM; 2458 return -ENOMEM;
2459 }
2460 di->bat = pdev->mfd_cell->platform_data;
2461 if (!di->bat) {
2462 if (np) {
2463 ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
2464 if (ret) {
2465 dev_err(&pdev->dev,
2466 "failed to get battery information\n");
2467 return ret;
2468 }
2469 } else {
2470 dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
2471 return -EINVAL;
2472 }
2473 } else {
2474 dev_info(&pdev->dev, "falling back to legacy platform data\n");
2475 }
2460 2476
2461 mutex_init(&di->cc_lock); 2477 mutex_init(&di->cc_lock);
2462 2478
@@ -2465,29 +2481,13 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
2465 di->parent = dev_get_drvdata(pdev->dev.parent); 2481 di->parent = dev_get_drvdata(pdev->dev.parent);
2466 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 2482 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
2467 2483
2468 /* get fg specific platform data */
2469 di->pdata = plat_data->fg;
2470 if (!di->pdata) {
2471 dev_err(di->dev, "no fg platform data supplied\n");
2472 ret = -EINVAL;
2473 goto free_device_info;
2474 }
2475
2476 /* get battery specific platform data */
2477 di->bat = plat_data->battery;
2478 if (!di->bat) {
2479 dev_err(di->dev, "no battery platform data supplied\n");
2480 ret = -EINVAL;
2481 goto free_device_info;
2482 }
2483
2484 di->fg_psy.name = "ab8500_fg"; 2484 di->fg_psy.name = "ab8500_fg";
2485 di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; 2485 di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
2486 di->fg_psy.properties = ab8500_fg_props; 2486 di->fg_psy.properties = ab8500_fg_props;
2487 di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); 2487 di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
2488 di->fg_psy.get_property = ab8500_fg_get_property; 2488 di->fg_psy.get_property = ab8500_fg_get_property;
2489 di->fg_psy.supplied_to = di->pdata->supplied_to; 2489 di->fg_psy.supplied_to = supply_interface;
2490 di->fg_psy.num_supplicants = di->pdata->num_supplicants; 2490 di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
2491 di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; 2491 di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
2492 2492
2493 di->bat_cap.max_mah_design = MILLI_TO_MICRO * 2493 di->bat_cap.max_mah_design = MILLI_TO_MICRO *
@@ -2506,8 +2506,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
2506 di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); 2506 di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
2507 if (di->fg_wq == NULL) { 2507 if (di->fg_wq == NULL) {
2508 dev_err(di->dev, "failed to create work queue\n"); 2508 dev_err(di->dev, "failed to create work queue\n");
2509 ret = -ENOMEM; 2509 return -ENOMEM;
2510 goto free_device_info;
2511 } 2510 }
2512 2511
2513 /* Init work for running the fg algorithm instantly */ 2512 /* Init work for running the fg algorithm instantly */
@@ -2606,12 +2605,14 @@ free_irq:
2606 } 2605 }
2607free_inst_curr_wq: 2606free_inst_curr_wq:
2608 destroy_workqueue(di->fg_wq); 2607 destroy_workqueue(di->fg_wq);
2609free_device_info:
2610 kfree(di);
2611
2612 return ret; 2608 return ret;
2613} 2609}
2614 2610
2611static const struct of_device_id ab8500_fg_match[] = {
2612 { .compatible = "stericsson,ab8500-fg", },
2613 { },
2614};
2615
2615static struct platform_driver ab8500_fg_driver = { 2616static struct platform_driver ab8500_fg_driver = {
2616 .probe = ab8500_fg_probe, 2617 .probe = ab8500_fg_probe,
2617 .remove = __devexit_p(ab8500_fg_remove), 2618 .remove = __devexit_p(ab8500_fg_remove),
@@ -2620,6 +2621,7 @@ static struct platform_driver ab8500_fg_driver = {
2620 .driver = { 2621 .driver = {
2621 .name = "ab8500-fg", 2622 .name = "ab8500-fg",
2622 .owner = THIS_MODULE, 2623 .owner = THIS_MODULE,
2624 .of_match_table = ab8500_fg_match,
2623 }, 2625 },
2624}; 2626};
2625 2627
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 4d302803ffcc..758ea76de2f8 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -231,7 +231,7 @@ struct abx500_chargalg {
231 struct abx500_chargalg_charger_info chg_info; 231 struct abx500_chargalg_charger_info chg_info;
232 struct abx500_chargalg_battery_data batt_data; 232 struct abx500_chargalg_battery_data batt_data;
233 struct abx500_chargalg_suspension_status susp_status; 233 struct abx500_chargalg_suspension_status susp_status;
234 struct abx500_chargalg_platform_data *pdata; 234 struct abx500_bmdevs_plat_data *pdata;
235 struct abx500_bm_data *bat; 235 struct abx500_bm_data *bat;
236 struct power_supply chargalg_psy; 236 struct power_supply chargalg_psy;
237 struct ux500_charger *ac_chg; 237 struct ux500_charger *ac_chg;
@@ -1802,7 +1802,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
1802 1802
1803static int __devinit abx500_chargalg_probe(struct platform_device *pdev) 1803static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
1804{ 1804{
1805 struct abx500_bm_plat_data *plat_data; 1805 struct abx500_bmdevs_plat_data *plat_data;
1806 int ret = 0; 1806 int ret = 0;
1807 1807
1808 struct abx500_chargalg *di = 1808 struct abx500_chargalg *di =
@@ -1812,10 +1812,8 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
1812 1812
1813 /* get device struct */ 1813 /* get device struct */
1814 di->dev = &pdev->dev; 1814 di->dev = &pdev->dev;
1815
1816 plat_data = pdev->dev.platform_data; 1815 plat_data = pdev->dev.platform_data;
1817 di->pdata = plat_data->chargalg; 1816 di->pdata = plat_data;
1818 di->bat = plat_data->battery;
1819 1817
1820 /* chargalg supply */ 1818 /* chargalg supply */
1821 di->chargalg_psy.name = "abx500_chargalg"; 1819 di->chargalg_psy.name = "abx500_chargalg";
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 5d5298d56026..33f2c58554f4 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -267,39 +267,27 @@ struct abx500_bm_data {
267 int gnd_lift_resistance; 267 int gnd_lift_resistance;
268 const struct abx500_maxim_parameters *maxi; 268 const struct abx500_maxim_parameters *maxi;
269 const struct abx500_bm_capacity_levels *cap_levels; 269 const struct abx500_bm_capacity_levels *cap_levels;
270 const struct abx500_battery_type *bat_type; 270 struct abx500_battery_type *bat_type;
271 const struct abx500_bm_charger_parameters *chg_params; 271 const struct abx500_bm_charger_parameters *chg_params;
272 const struct abx500_fg_parameters *fg_params; 272 const struct abx500_fg_parameters *fg_params;
273}; 273};
274 274
275struct abx500_chargalg_platform_data { 275extern struct abx500_bm_data ab8500_bm_data;
276 char **supplied_to;
277 size_t num_supplicants;
278};
279
280struct abx500_charger_platform_data {
281 char **supplied_to;
282 size_t num_supplicants;
283 bool autopower_cfg;
284};
285 276
286struct abx500_btemp_platform_data { 277struct abx500_bmdevs_plat_data {
287 char **supplied_to; 278 char **supplied_to;
288 size_t num_supplicants; 279 size_t num_supplicants;
280 bool autopower_cfg;
289}; 281};
290 282
291struct abx500_fg_platform_data { 283enum {
292 char **supplied_to; 284 NTC_EXTERNAL = 0,
293 size_t num_supplicants; 285 NTC_INTERNAL,
294}; 286};
295 287
296struct abx500_bm_plat_data { 288int bmdevs_of_probe(struct device *dev,
297 struct abx500_bm_data *battery; 289 struct device_node *np,
298 struct abx500_charger_platform_data *charger; 290 struct abx500_bm_data **battery);
299 struct abx500_btemp_platform_data *btemp;
300 struct abx500_fg_platform_data *fg;
301 struct abx500_chargalg_platform_data *chargalg;
302};
303 291
304int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, 292int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
305 u8 value); 293 u8 value);