aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/axp20x.c
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@linux.intel.com>2014-10-07 00:17:14 -0400
committerLee Jones <lee.jones@linaro.org>2014-10-07 04:30:05 -0400
commitaf7e9069543aabd415d7c543f3f89b143ac1a932 (patch)
tree40e00e77c9aef5b83dab704575330e27cc6beed7 /drivers/mfd/axp20x.c
parentbfe01a5ba2490f299e1d2d5508cbbbadd897bbe9 (diff)
mfd: axp20x: Extend axp20x to support axp288 pmic
X-Powers AXP288 is a customized PMIC for Intel Baytrail-CR platforms. Similar to AXP202/209, AXP288 comes with USB charger, more LDO and BUCK channels, and AD converters. It also provides extended status and interrupt reporting capabilities than the devices currently supported in axp20x.c. In addition to feature extension, this patch also adds ACPI binding for enumeration. This consolidated driver should support more X-Powers' PMICs in both device tree and ACPI enumerated platforms. Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Reviewed-by: Maxime Ripard <maxime.ripard@free-electrons.com> Reviewed-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/axp20x.c')
-rw-r--r--drivers/mfd/axp20x.c361
1 files changed, 306 insertions, 55 deletions
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index dee653989e3a..b2fb7f492c86 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209 2 * axp20x.c - MFD core driver for the X-Powers' Power Management ICs
3 * 3 *
4 * AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC 4 * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
5 * converters, 5 LDOs, multiple 12-bit ADCs of voltage, current and temperature 5 * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
6 * as well as 4 configurable GPIOs. 6 * as well as configurable GPIOs.
7 * 7 *
8 * Author: Carlo Caione <carlo@caione.org> 8 * Author: Carlo Caione <carlo@caione.org>
9 * 9 *
@@ -25,9 +25,16 @@
25#include <linux/mfd/core.h> 25#include <linux/mfd/core.h>
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/of_irq.h> 27#include <linux/of_irq.h>
28#include <linux/acpi.h>
28 29
29#define AXP20X_OFF 0x80 30#define AXP20X_OFF 0x80
30 31
32static const char const *axp20x_model_names[] = {
33 "AXP202",
34 "AXP209",
35 "AXP288",
36};
37
31static const struct regmap_range axp20x_writeable_ranges[] = { 38static const struct regmap_range axp20x_writeable_ranges[] = {
32 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), 39 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
33 regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES), 40 regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
@@ -47,6 +54,25 @@ static const struct regmap_access_table axp20x_volatile_table = {
47 .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), 54 .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
48}; 55};
49 56
57static const struct regmap_range axp288_writeable_ranges[] = {
58 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
59 regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
60};
61
62static const struct regmap_range axp288_volatile_ranges[] = {
63 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
64};
65
66static const struct regmap_access_table axp288_writeable_table = {
67 .yes_ranges = axp288_writeable_ranges,
68 .n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges),
69};
70
71static const struct regmap_access_table axp288_volatile_table = {
72 .yes_ranges = axp288_volatile_ranges,
73 .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges),
74};
75
50static struct resource axp20x_pek_resources[] = { 76static struct resource axp20x_pek_resources[] = {
51 { 77 {
52 .name = "PEK_DBR", 78 .name = "PEK_DBR",
@@ -61,6 +87,39 @@ static struct resource axp20x_pek_resources[] = {
61 }, 87 },
62}; 88};
63 89
90static struct resource axp288_battery_resources[] = {
91 {
92 .start = AXP288_IRQ_QWBTU,
93 .end = AXP288_IRQ_QWBTU,
94 .flags = IORESOURCE_IRQ,
95 },
96 {
97 .start = AXP288_IRQ_WBTU,
98 .end = AXP288_IRQ_WBTU,
99 .flags = IORESOURCE_IRQ,
100 },
101 {
102 .start = AXP288_IRQ_QWBTO,
103 .end = AXP288_IRQ_QWBTO,
104 .flags = IORESOURCE_IRQ,
105 },
106 {
107 .start = AXP288_IRQ_WBTO,
108 .end = AXP288_IRQ_WBTO,
109 .flags = IORESOURCE_IRQ,
110 },
111 {
112 .start = AXP288_IRQ_WL2,
113 .end = AXP288_IRQ_WL2,
114 .flags = IORESOURCE_IRQ,
115 },
116 {
117 .start = AXP288_IRQ_WL1,
118 .end = AXP288_IRQ_WL1,
119 .flags = IORESOURCE_IRQ,
120 },
121};
122
64static const struct regmap_config axp20x_regmap_config = { 123static const struct regmap_config axp20x_regmap_config = {
65 .reg_bits = 8, 124 .reg_bits = 8,
66 .val_bits = 8, 125 .val_bits = 8,
@@ -70,47 +129,96 @@ static const struct regmap_config axp20x_regmap_config = {
70 .cache_type = REGCACHE_RBTREE, 129 .cache_type = REGCACHE_RBTREE,
71}; 130};
72 131
73#define AXP20X_IRQ(_irq, _off, _mask) \ 132static const struct regmap_config axp288_regmap_config = {
74 [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } 133 .reg_bits = 8,
134 .val_bits = 8,
135 .wr_table = &axp288_writeable_table,
136 .volatile_table = &axp288_volatile_table,
137 .max_register = AXP288_FG_TUNE5,
138 .cache_type = REGCACHE_RBTREE,
139};
140
141#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
142 [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
75 143
76static const struct regmap_irq axp20x_regmap_irqs[] = { 144static const struct regmap_irq axp20x_regmap_irqs[] = {
77 AXP20X_IRQ(ACIN_OVER_V, 0, 7), 145 INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7),
78 AXP20X_IRQ(ACIN_PLUGIN, 0, 6), 146 INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6),
79 AXP20X_IRQ(ACIN_REMOVAL, 0, 5), 147 INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5),
80 AXP20X_IRQ(VBUS_OVER_V, 0, 4), 148 INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4),
81 AXP20X_IRQ(VBUS_PLUGIN, 0, 3), 149 INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3),
82 AXP20X_IRQ(VBUS_REMOVAL, 0, 2), 150 INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2),
83 AXP20X_IRQ(VBUS_V_LOW, 0, 1), 151 INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1),
84 AXP20X_IRQ(BATT_PLUGIN, 1, 7), 152 INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7),
85 AXP20X_IRQ(BATT_REMOVAL, 1, 6), 153 INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6),
86 AXP20X_IRQ(BATT_ENT_ACT_MODE, 1, 5), 154 INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5),
87 AXP20X_IRQ(BATT_EXIT_ACT_MODE, 1, 4), 155 INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4),
88 AXP20X_IRQ(CHARG, 1, 3), 156 INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3),
89 AXP20X_IRQ(CHARG_DONE, 1, 2), 157 INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2),
90 AXP20X_IRQ(BATT_TEMP_HIGH, 1, 1), 158 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1),
91 AXP20X_IRQ(BATT_TEMP_LOW, 1, 0), 159 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0),
92 AXP20X_IRQ(DIE_TEMP_HIGH, 2, 7), 160 INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7),
93 AXP20X_IRQ(CHARG_I_LOW, 2, 6), 161 INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6),
94 AXP20X_IRQ(DCDC1_V_LONG, 2, 5), 162 INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5),
95 AXP20X_IRQ(DCDC2_V_LONG, 2, 4), 163 INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4),
96 AXP20X_IRQ(DCDC3_V_LONG, 2, 3), 164 INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3),
97 AXP20X_IRQ(PEK_SHORT, 2, 1), 165 INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1),
98 AXP20X_IRQ(PEK_LONG, 2, 0), 166 INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0),
99 AXP20X_IRQ(N_OE_PWR_ON, 3, 7), 167 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7),
100 AXP20X_IRQ(N_OE_PWR_OFF, 3, 6), 168 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6),
101 AXP20X_IRQ(VBUS_VALID, 3, 5), 169 INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5),
102 AXP20X_IRQ(VBUS_NOT_VALID, 3, 4), 170 INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4),
103 AXP20X_IRQ(VBUS_SESS_VALID, 3, 3), 171 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3),
104 AXP20X_IRQ(VBUS_SESS_END, 3, 2), 172 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2),
105 AXP20X_IRQ(LOW_PWR_LVL1, 3, 1), 173 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1),
106 AXP20X_IRQ(LOW_PWR_LVL2, 3, 0), 174 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0),
107 AXP20X_IRQ(TIMER, 4, 7), 175 INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7),
108 AXP20X_IRQ(PEK_RIS_EDGE, 4, 6), 176 INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6),
109 AXP20X_IRQ(PEK_FAL_EDGE, 4, 5), 177 INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5),
110 AXP20X_IRQ(GPIO3_INPUT, 4, 3), 178 INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3),
111 AXP20X_IRQ(GPIO2_INPUT, 4, 2), 179 INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2),
112 AXP20X_IRQ(GPIO1_INPUT, 4, 1), 180 INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1),
113 AXP20X_IRQ(GPIO0_INPUT, 4, 0), 181 INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0),
182};
183
184/* some IRQs are compatible with axp20x models */
185static const struct regmap_irq axp288_regmap_irqs[] = {
186 INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2),
187 INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3),
188 INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4),
189
190 INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2),
191 INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3),
192 INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4),
193 INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5),
194 INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6),
195 INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7),
196
197 INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0),
198 INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1),
199 INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2),
200 INIT_REGMAP_IRQ(AXP288, WBTU, 2, 3),
201 INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4),
202 INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5),
203 INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6),
204 INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7),
205
206 INIT_REGMAP_IRQ(AXP288, WL2, 3, 0),
207 INIT_REGMAP_IRQ(AXP288, WL1, 3, 1),
208 INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2),
209 INIT_REGMAP_IRQ(AXP288, OT, 3, 7),
210
211 INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0),
212 INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1),
213 INIT_REGMAP_IRQ(AXP288, POKO, 4, 2),
214 INIT_REGMAP_IRQ(AXP288, POKL, 4, 3),
215 INIT_REGMAP_IRQ(AXP288, POKS, 4, 4),
216 INIT_REGMAP_IRQ(AXP288, POKN, 4, 5),
217 INIT_REGMAP_IRQ(AXP288, POKP, 4, 6),
218 INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7),
219
220 INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0),
221 INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
114}; 222};
115 223
116static const struct of_device_id axp20x_of_match[] = { 224static const struct of_device_id axp20x_of_match[] = {
@@ -128,16 +236,39 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
128}; 236};
129MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); 237MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
130 238
239static struct acpi_device_id axp20x_acpi_match[] = {
240 {
241 .id = "INT33F4",
242 .driver_data = AXP288_ID,
243 },
244 { },
245};
246MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match);
247
131static const struct regmap_irq_chip axp20x_regmap_irq_chip = { 248static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
132 .name = "axp20x_irq_chip", 249 .name = "axp20x_irq_chip",
133 .status_base = AXP20X_IRQ1_STATE, 250 .status_base = AXP20X_IRQ1_STATE,
134 .ack_base = AXP20X_IRQ1_STATE, 251 .ack_base = AXP20X_IRQ1_STATE,
135 .mask_base = AXP20X_IRQ1_EN, 252 .mask_base = AXP20X_IRQ1_EN,
136 .num_regs = 5, 253 .mask_invert = true,
254 .init_ack_masked = true,
137 .irqs = axp20x_regmap_irqs, 255 .irqs = axp20x_regmap_irqs,
138 .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), 256 .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
257 .num_regs = 5,
258
259};
260
261static const struct regmap_irq_chip axp288_regmap_irq_chip = {
262 .name = "axp288_irq_chip",
263 .status_base = AXP20X_IRQ1_STATE,
264 .ack_base = AXP20X_IRQ1_STATE,
265 .mask_base = AXP20X_IRQ1_EN,
139 .mask_invert = true, 266 .mask_invert = true,
140 .init_ack_masked = true, 267 .init_ack_masked = true,
268 .irqs = axp288_regmap_irqs,
269 .num_irqs = ARRAY_SIZE(axp288_regmap_irqs),
270 .num_regs = 6,
271
141}; 272};
142 273
143static const char * const axp20x_supplies[] = { 274static const char * const axp20x_supplies[] = {
@@ -161,36 +292,155 @@ static struct mfd_cell axp20x_cells[] = {
161 }, 292 },
162}; 293};
163 294
295static struct resource axp288_adc_resources[] = {
296 {
297 .name = "GPADC",
298 .start = AXP288_IRQ_GPADC,
299 .end = AXP288_IRQ_GPADC,
300 .flags = IORESOURCE_IRQ,
301 },
302};
303
304static struct resource axp288_charger_resources[] = {
305 {
306 .start = AXP288_IRQ_OV,
307 .end = AXP288_IRQ_OV,
308 .flags = IORESOURCE_IRQ,
309 },
310 {
311 .start = AXP288_IRQ_DONE,
312 .end = AXP288_IRQ_DONE,
313 .flags = IORESOURCE_IRQ,
314 },
315 {
316 .start = AXP288_IRQ_CHARGING,
317 .end = AXP288_IRQ_CHARGING,
318 .flags = IORESOURCE_IRQ,
319 },
320 {
321 .start = AXP288_IRQ_SAFE_QUIT,
322 .end = AXP288_IRQ_SAFE_QUIT,
323 .flags = IORESOURCE_IRQ,
324 },
325 {
326 .start = AXP288_IRQ_SAFE_ENTER,
327 .end = AXP288_IRQ_SAFE_ENTER,
328 .flags = IORESOURCE_IRQ,
329 },
330 {
331 .start = AXP288_IRQ_QCBTU,
332 .end = AXP288_IRQ_QCBTU,
333 .flags = IORESOURCE_IRQ,
334 },
335 {
336 .start = AXP288_IRQ_CBTU,
337 .end = AXP288_IRQ_CBTU,
338 .flags = IORESOURCE_IRQ,
339 },
340 {
341 .start = AXP288_IRQ_QCBTO,
342 .end = AXP288_IRQ_QCBTO,
343 .flags = IORESOURCE_IRQ,
344 },
345 {
346 .start = AXP288_IRQ_CBTO,
347 .end = AXP288_IRQ_CBTO,
348 .flags = IORESOURCE_IRQ,
349 },
350};
351
352static struct mfd_cell axp288_cells[] = {
353 {
354 .name = "axp288_adc",
355 .num_resources = ARRAY_SIZE(axp288_adc_resources),
356 .resources = axp288_adc_resources,
357 },
358 {
359 .name = "axp288_charger",
360 .num_resources = ARRAY_SIZE(axp288_charger_resources),
361 .resources = axp288_charger_resources,
362 },
363 {
364 .name = "axp288_battery",
365 .num_resources = ARRAY_SIZE(axp288_battery_resources),
366 .resources = axp288_battery_resources,
367 },
368};
369
164static struct axp20x_dev *axp20x_pm_power_off; 370static struct axp20x_dev *axp20x_pm_power_off;
165static void axp20x_power_off(void) 371static void axp20x_power_off(void)
166{ 372{
373 if (axp20x_pm_power_off->variant == AXP288_ID)
374 return;
375
167 regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, 376 regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
168 AXP20X_OFF); 377 AXP20X_OFF);
169} 378}
170 379
380static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
381{
382 const struct acpi_device_id *acpi_id;
383 const struct of_device_id *of_id;
384
385 if (dev->of_node) {
386 of_id = of_match_device(axp20x_of_match, dev);
387 if (!of_id) {
388 dev_err(dev, "Unable to match OF ID\n");
389 return -ENODEV;
390 }
391 axp20x->variant = (long) of_id->data;
392 } else {
393 acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
394 if (!acpi_id || !acpi_id->driver_data) {
395 dev_err(dev, "Unable to match ACPI ID and data\n");
396 return -ENODEV;
397 }
398 axp20x->variant = (long) acpi_id->driver_data;
399 }
400
401 switch (axp20x->variant) {
402 case AXP202_ID:
403 case AXP209_ID:
404 axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
405 axp20x->cells = axp20x_cells;
406 axp20x->regmap_cfg = &axp20x_regmap_config;
407 axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
408 break;
409 case AXP288_ID:
410 axp20x->cells = axp288_cells;
411 axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
412 axp20x->regmap_cfg = &axp288_regmap_config;
413 axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
414 break;
415 default:
416 dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
417 return -EINVAL;
418 }
419 dev_info(dev, "AXP20x variant %s found\n",
420 axp20x_model_names[axp20x->variant]);
421
422 return 0;
423}
424
171static int axp20x_i2c_probe(struct i2c_client *i2c, 425static int axp20x_i2c_probe(struct i2c_client *i2c,
172 const struct i2c_device_id *id) 426 const struct i2c_device_id *id)
173{ 427{
174 struct axp20x_dev *axp20x; 428 struct axp20x_dev *axp20x;
175 const struct of_device_id *of_id;
176 int ret; 429 int ret;
177 430
178 axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL); 431 axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
179 if (!axp20x) 432 if (!axp20x)
180 return -ENOMEM; 433 return -ENOMEM;
181 434
182 of_id = of_match_device(axp20x_of_match, &i2c->dev); 435 ret = axp20x_match_device(axp20x, &i2c->dev);
183 if (!of_id) { 436 if (ret)
184 dev_err(&i2c->dev, "Unable to setup AXP20X data\n"); 437 return ret;
185 return -ENODEV;
186 }
187 axp20x->variant = (long) of_id->data;
188 438
189 axp20x->i2c_client = i2c; 439 axp20x->i2c_client = i2c;
190 axp20x->dev = &i2c->dev; 440 axp20x->dev = &i2c->dev;
191 dev_set_drvdata(axp20x->dev, axp20x); 441 dev_set_drvdata(axp20x->dev, axp20x);
192 442
193 axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config); 443 axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
194 if (IS_ERR(axp20x->regmap)) { 444 if (IS_ERR(axp20x->regmap)) {
195 ret = PTR_ERR(axp20x->regmap); 445 ret = PTR_ERR(axp20x->regmap);
196 dev_err(&i2c->dev, "regmap init failed: %d\n", ret); 446 dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
@@ -199,15 +449,15 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
199 449
200 ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq, 450 ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
201 IRQF_ONESHOT | IRQF_SHARED, -1, 451 IRQF_ONESHOT | IRQF_SHARED, -1,
202 &axp20x_regmap_irq_chip, 452 axp20x->regmap_irq_chip,
203 &axp20x->regmap_irqc); 453 &axp20x->regmap_irqc);
204 if (ret) { 454 if (ret) {
205 dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret); 455 dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
206 return ret; 456 return ret;
207 } 457 }
208 458
209 ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells, 459 ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
210 ARRAY_SIZE(axp20x_cells), NULL, 0, NULL); 460 axp20x->nr_cells, NULL, 0, NULL);
211 461
212 if (ret) { 462 if (ret) {
213 dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); 463 dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
@@ -245,6 +495,7 @@ static struct i2c_driver axp20x_i2c_driver = {
245 .name = "axp20x", 495 .name = "axp20x",
246 .owner = THIS_MODULE, 496 .owner = THIS_MODULE,
247 .of_match_table = of_match_ptr(axp20x_of_match), 497 .of_match_table = of_match_ptr(axp20x_of_match),
498 .acpi_match_table = ACPI_PTR(axp20x_acpi_match),
248 }, 499 },
249 .probe = axp20x_i2c_probe, 500 .probe = axp20x_i2c_probe,
250 .remove = axp20x_i2c_remove, 501 .remove = axp20x_i2c_remove,