4 * Copyright 2011-2012 Texas Instruments Inc.
6 * Author: Graeme Gregory <gg@slimlogic.co.uk>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/init.h>
18 #include <linux/slab.h>
19 #include <linux/i2c.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/regmap.h>
23 #include <linux/err.h>
24 #include <linux/mfd/core.h>
25 #include <linux/mfd/palmas.h>
27 static const struct resource gpadc_resource
[] = {
30 .start
= PALMAS_GPADC_EOC_SW_IRQ
,
31 .end
= PALMAS_GPADC_EOC_SW_IRQ
,
32 .flags
= IORESOURCE_IRQ
,
36 static const struct resource usb_resource
[] = {
39 .start
= PALMAS_ID_OTG_IRQ
,
40 .end
= PALMAS_ID_OTG_IRQ
,
41 .flags
= IORESOURCE_IRQ
,
45 .start
= PALMAS_ID_IRQ
,
47 .flags
= IORESOURCE_IRQ
,
51 .start
= PALMAS_VBUS_OTG_IRQ
,
52 .end
= PALMAS_VBUS_OTG_IRQ
,
53 .flags
= IORESOURCE_IRQ
,
56 .name
= "VBUS_WAKEUP",
57 .start
= PALMAS_VBUS_IRQ
,
58 .end
= PALMAS_VBUS_IRQ
,
59 .flags
= IORESOURCE_IRQ
,
63 static const struct resource rtc_resource
[] = {
66 .start
= PALMAS_RTC_ALARM_IRQ
,
67 .end
= PALMAS_RTC_ALARM_IRQ
,
68 .flags
= IORESOURCE_IRQ
,
72 static const struct resource pwron_resource
[] = {
74 .name
= "PWRON_BUTTON",
75 .start
= PALMAS_PWRON_IRQ
,
76 .end
= PALMAS_PWRON_IRQ
,
77 .flags
= IORESOURCE_IRQ
,
95 static const struct mfd_cell palmas_children
[] = {
97 .name
= "palmas-pmic",
101 .name
= "palmas-gpio",
102 .id
= PALMAS_GPIO_ID
,
105 .name
= "palmas-leds",
106 .id
= PALMAS_LEDS_ID
,
109 .name
= "palmas-wdt",
113 .name
= "palmas-rtc",
114 .num_resources
= ARRAY_SIZE(rtc_resource
),
115 .resources
= rtc_resource
,
119 .name
= "palmas-pwrbutton",
120 .num_resources
= ARRAY_SIZE(pwron_resource
),
121 .resources
= pwron_resource
,
122 .id
= PALMAS_PWRBUTTON_ID
,
125 .name
= "palmas-gpadc",
126 .num_resources
= ARRAY_SIZE(gpadc_resource
),
127 .resources
= gpadc_resource
,
128 .id
= PALMAS_GPADC_ID
,
131 .name
= "palmas-resource",
132 .id
= PALMAS_RESOURCE_ID
,
135 .name
= "palmas-clk",
139 .name
= "palmas-pwm",
143 .name
= "palmas-usb",
144 .num_resources
= ARRAY_SIZE(usb_resource
),
145 .resources
= usb_resource
,
150 static const struct regmap_config palmas_regmap_config
[PALMAS_NUM_CLIENTS
] = {
154 .max_register
= PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE
,
155 PALMAS_PRIMARY_SECONDARY_PAD3
),
160 .max_register
= PALMAS_BASE_TO_REG(PALMAS_GPADC_BASE
,
161 PALMAS_GPADC_SMPS_VSEL_MONITORING
),
166 .max_register
= PALMAS_BASE_TO_REG(PALMAS_TRIM_GPADC_BASE
,
167 PALMAS_GPADC_TRIM16
),
171 static const struct regmap_irq palmas_irqs
[] = {
173 [PALMAS_CHARG_DET_N_VBUS_OVV_IRQ
] = {
174 .mask
= PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV
,
176 [PALMAS_PWRON_IRQ
] = {
177 .mask
= PALMAS_INT1_STATUS_PWRON
,
179 [PALMAS_LONG_PRESS_KEY_IRQ
] = {
180 .mask
= PALMAS_INT1_STATUS_LONG_PRESS_KEY
,
182 [PALMAS_RPWRON_IRQ
] = {
183 .mask
= PALMAS_INT1_STATUS_RPWRON
,
185 [PALMAS_PWRDOWN_IRQ
] = {
186 .mask
= PALMAS_INT1_STATUS_PWRDOWN
,
188 [PALMAS_HOTDIE_IRQ
] = {
189 .mask
= PALMAS_INT1_STATUS_HOTDIE
,
191 [PALMAS_VSYS_MON_IRQ
] = {
192 .mask
= PALMAS_INT1_STATUS_VSYS_MON
,
194 [PALMAS_VBAT_MON_IRQ
] = {
195 .mask
= PALMAS_INT1_STATUS_VBAT_MON
,
198 [PALMAS_RTC_ALARM_IRQ
] = {
199 .mask
= PALMAS_INT2_STATUS_RTC_ALARM
,
202 [PALMAS_RTC_TIMER_IRQ
] = {
203 .mask
= PALMAS_INT2_STATUS_RTC_TIMER
,
207 .mask
= PALMAS_INT2_STATUS_WDT
,
210 [PALMAS_BATREMOVAL_IRQ
] = {
211 .mask
= PALMAS_INT2_STATUS_BATREMOVAL
,
214 [PALMAS_RESET_IN_IRQ
] = {
215 .mask
= PALMAS_INT2_STATUS_RESET_IN
,
218 [PALMAS_FBI_BB_IRQ
] = {
219 .mask
= PALMAS_INT2_STATUS_FBI_BB
,
222 [PALMAS_SHORT_IRQ
] = {
223 .mask
= PALMAS_INT2_STATUS_SHORT
,
226 [PALMAS_VAC_ACOK_IRQ
] = {
227 .mask
= PALMAS_INT2_STATUS_VAC_ACOK
,
231 [PALMAS_GPADC_AUTO_0_IRQ
] = {
232 .mask
= PALMAS_INT3_STATUS_GPADC_AUTO_0
,
235 [PALMAS_GPADC_AUTO_1_IRQ
] = {
236 .mask
= PALMAS_INT3_STATUS_GPADC_AUTO_1
,
239 [PALMAS_GPADC_EOC_SW_IRQ
] = {
240 .mask
= PALMAS_INT3_STATUS_GPADC_EOC_SW
,
243 [PALMAS_GPADC_EOC_RT_IRQ
] = {
244 .mask
= PALMAS_INT3_STATUS_GPADC_EOC_RT
,
247 [PALMAS_ID_OTG_IRQ
] = {
248 .mask
= PALMAS_INT3_STATUS_ID_OTG
,
252 .mask
= PALMAS_INT3_STATUS_ID
,
255 [PALMAS_VBUS_OTG_IRQ
] = {
256 .mask
= PALMAS_INT3_STATUS_VBUS_OTG
,
259 [PALMAS_VBUS_IRQ
] = {
260 .mask
= PALMAS_INT3_STATUS_VBUS
,
264 [PALMAS_GPIO_0_IRQ
] = {
265 .mask
= PALMAS_INT4_STATUS_GPIO_0
,
268 [PALMAS_GPIO_1_IRQ
] = {
269 .mask
= PALMAS_INT4_STATUS_GPIO_1
,
272 [PALMAS_GPIO_2_IRQ
] = {
273 .mask
= PALMAS_INT4_STATUS_GPIO_2
,
276 [PALMAS_GPIO_3_IRQ
] = {
277 .mask
= PALMAS_INT4_STATUS_GPIO_3
,
280 [PALMAS_GPIO_4_IRQ
] = {
281 .mask
= PALMAS_INT4_STATUS_GPIO_4
,
284 [PALMAS_GPIO_5_IRQ
] = {
285 .mask
= PALMAS_INT4_STATUS_GPIO_5
,
288 [PALMAS_GPIO_6_IRQ
] = {
289 .mask
= PALMAS_INT4_STATUS_GPIO_6
,
292 [PALMAS_GPIO_7_IRQ
] = {
293 .mask
= PALMAS_INT4_STATUS_GPIO_7
,
298 static struct regmap_irq_chip palmas_irq_chip
= {
301 .num_irqs
= ARRAY_SIZE(palmas_irqs
),
305 .status_base
= PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE
,
307 .mask_base
= PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE
,
311 static int __devinit
palmas_i2c_probe(struct i2c_client
*i2c
,
312 const struct i2c_device_id
*id
)
314 struct palmas
*palmas
;
315 struct palmas_platform_data
*pdata
;
317 unsigned int reg
, addr
;
319 struct mfd_cell
*children
;
321 pdata
= dev_get_platdata(&i2c
->dev
);
325 palmas
= devm_kzalloc(&i2c
->dev
, sizeof(struct palmas
), GFP_KERNEL
);
329 i2c_set_clientdata(i2c
, palmas
);
330 palmas
->dev
= &i2c
->dev
;
331 palmas
->id
= id
->driver_data
;
332 palmas
->irq
= i2c
->irq
;
334 for (i
= 0; i
< PALMAS_NUM_CLIENTS
; i
++) {
336 palmas
->i2c_clients
[i
] = i2c
;
338 palmas
->i2c_clients
[i
] =
339 i2c_new_dummy(i2c
->adapter
,
341 if (!palmas
->i2c_clients
[i
]) {
343 "can't attach client %d\n", i
);
348 palmas
->regmap
[i
] = devm_regmap_init_i2c(palmas
->i2c_clients
[i
],
349 &palmas_regmap_config
[i
]);
350 if (IS_ERR(palmas
->regmap
[i
])) {
351 ret
= PTR_ERR(palmas
->regmap
[i
]);
353 "Failed to allocate regmap %d, err: %d\n",
359 /* Change IRQ into clear on read mode for efficiency */
360 slave
= PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE
);
361 addr
= PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE
, PALMAS_INT_CTRL
);
362 reg
= PALMAS_INT_CTRL_INT_CLEAR
;
364 regmap_write(palmas
->regmap
[slave
], addr
, reg
);
366 ret
= regmap_add_irq_chip(palmas
->regmap
[slave
], palmas
->irq
,
367 IRQF_ONESHOT
| IRQF_TRIGGER_LOW
, -1, &palmas_irq_chip
,
372 slave
= PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE
);
373 addr
= PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE
,
374 PALMAS_PRIMARY_SECONDARY_PAD1
);
376 if (pdata
->mux_from_pdata
) {
378 ret
= regmap_write(palmas
->regmap
[slave
], addr
, reg
);
382 ret
= regmap_read(palmas
->regmap
[slave
], addr
, ®
);
387 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0
))
388 palmas
->gpio_muxed
|= PALMAS_GPIO_0_MUXED
;
389 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK
))
390 palmas
->gpio_muxed
|= PALMAS_GPIO_1_MUXED
;
391 else if ((reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK
) ==
392 (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT
))
393 palmas
->led_muxed
|= PALMAS_LED1_MUXED
;
394 else if ((reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK
) ==
395 (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT
))
396 palmas
->pwm_muxed
|= PALMAS_PWM1_MUXED
;
397 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK
))
398 palmas
->gpio_muxed
|= PALMAS_GPIO_2_MUXED
;
399 else if ((reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK
) ==
400 (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT
))
401 palmas
->led_muxed
|= PALMAS_LED2_MUXED
;
402 else if ((reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK
) ==
403 (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT
))
404 palmas
->pwm_muxed
|= PALMAS_PWM2_MUXED
;
405 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3
))
406 palmas
->gpio_muxed
|= PALMAS_GPIO_3_MUXED
;
408 addr
= PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE
,
409 PALMAS_PRIMARY_SECONDARY_PAD2
);
411 if (pdata
->mux_from_pdata
) {
413 ret
= regmap_write(palmas
->regmap
[slave
], addr
, reg
);
417 ret
= regmap_read(palmas
->regmap
[slave
], addr
, ®
);
422 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4
))
423 palmas
->gpio_muxed
|= PALMAS_GPIO_4_MUXED
;
424 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK
))
425 palmas
->gpio_muxed
|= PALMAS_GPIO_5_MUXED
;
426 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6
))
427 palmas
->gpio_muxed
|= PALMAS_GPIO_6_MUXED
;
428 if (!(reg
& PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK
))
429 palmas
->gpio_muxed
|= PALMAS_GPIO_7_MUXED
;
431 dev_info(palmas
->dev
, "Muxing GPIO %x, PWM %x, LED %x\n",
432 palmas
->gpio_muxed
, palmas
->pwm_muxed
,
435 reg
= pdata
->power_ctrl
;
437 slave
= PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE
);
438 addr
= PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE
, PALMAS_POWER_CTRL
);
440 ret
= regmap_write(palmas
->regmap
[slave
], addr
, reg
);
444 children
= kmemdup(palmas_children
, sizeof(palmas_children
),
451 children
[PALMAS_PMIC_ID
].platform_data
= pdata
->pmic_pdata
;
452 children
[PALMAS_PMIC_ID
].pdata_size
= sizeof(*pdata
->pmic_pdata
);
454 ret
= mfd_add_devices(palmas
->dev
, -1,
455 children
, ARRAY_SIZE(palmas_children
),
456 NULL
, regmap_irq_chip_get_base(palmas
->irq_data
));
465 mfd_remove_devices(palmas
->dev
);
470 static int palmas_i2c_remove(struct i2c_client
*i2c
)
472 struct palmas
*palmas
= i2c_get_clientdata(i2c
);
474 mfd_remove_devices(palmas
->dev
);
475 regmap_del_irq_chip(palmas
->irq
, palmas
->irq_data
);
480 static const struct i2c_device_id palmas_i2c_id
[] = {
487 MODULE_DEVICE_TABLE(i2c
, palmas_i2c_id
);
489 static struct of_device_id __devinitdata of_palmas_match_tbl
[] = {
490 { .compatible
= "ti,palmas", },
494 static struct i2c_driver palmas_i2c_driver
= {
497 .of_match_table
= of_palmas_match_tbl
,
498 .owner
= THIS_MODULE
,
500 .probe
= palmas_i2c_probe
,
501 .remove
= palmas_i2c_remove
,
502 .id_table
= palmas_i2c_id
,
505 static int __init
palmas_i2c_init(void)
507 return i2c_add_driver(&palmas_i2c_driver
);
509 /* init early so consumer devices can complete system boot */
510 subsys_initcall(palmas_i2c_init
);
512 static void __exit
palmas_i2c_exit(void)
514 i2c_del_driver(&palmas_i2c_driver
);
516 module_exit(palmas_i2c_exit
);
518 MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
519 MODULE_DESCRIPTION("Palmas chip family multi-function driver");
520 MODULE_LICENSE("GPL");