2 * TI LP8788 MFD - core interface
4 * Copyright 2012 Texas Instruments
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/err.h>
15 #include <linux/i2c.h>
16 #include <linux/mfd/core.h>
17 #include <linux/mfd/lp8788.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
21 #define MAX_LP8788_REGISTERS 0xA2
23 #define MFD_DEV_SIMPLE(_name) \
25 .name = LP8788_DEV_##_name, \
28 #define MFD_DEV_WITH_ID(_name, _id) \
30 .name = LP8788_DEV_##_name, \
34 #define MFD_DEV_WITH_RESOURCE(_name, _resource, num_resource) \
36 .name = LP8788_DEV_##_name, \
37 .resources = _resource, \
38 .num_resources = num_resource, \
41 static struct resource chg_irqs
[] = {
42 /* Charger Interrupts */
44 .start
= LP8788_INT_CHG_INPUT_STATE
,
45 .end
= LP8788_INT_PRECHG_TIMEOUT
,
46 .name
= LP8788_CHG_IRQ
,
47 .flags
= IORESOURCE_IRQ
,
49 /* Power Routing Switch Interrupts */
51 .start
= LP8788_INT_ENTER_SYS_SUPPORT
,
52 .end
= LP8788_INT_EXIT_SYS_SUPPORT
,
53 .name
= LP8788_PRSW_IRQ
,
54 .flags
= IORESOURCE_IRQ
,
56 /* Battery Interrupts */
58 .start
= LP8788_INT_BATT_LOW
,
59 .end
= LP8788_INT_NO_BATT
,
60 .name
= LP8788_BATT_IRQ
,
61 .flags
= IORESOURCE_IRQ
,
65 static struct resource rtc_irqs
[] = {
67 .start
= LP8788_INT_RTC_ALARM1
,
68 .end
= LP8788_INT_RTC_ALARM2
,
69 .name
= LP8788_ALM_IRQ
,
70 .flags
= IORESOURCE_IRQ
,
74 static const struct mfd_cell lp8788_devs
[] = {
76 MFD_DEV_WITH_ID(BUCK
, 1),
77 MFD_DEV_WITH_ID(BUCK
, 2),
78 MFD_DEV_WITH_ID(BUCK
, 3),
79 MFD_DEV_WITH_ID(BUCK
, 4),
82 MFD_DEV_WITH_ID(DLDO
, 1),
83 MFD_DEV_WITH_ID(DLDO
, 2),
84 MFD_DEV_WITH_ID(DLDO
, 3),
85 MFD_DEV_WITH_ID(DLDO
, 4),
86 MFD_DEV_WITH_ID(DLDO
, 5),
87 MFD_DEV_WITH_ID(DLDO
, 6),
88 MFD_DEV_WITH_ID(DLDO
, 7),
89 MFD_DEV_WITH_ID(DLDO
, 8),
90 MFD_DEV_WITH_ID(DLDO
, 9),
91 MFD_DEV_WITH_ID(DLDO
, 10),
92 MFD_DEV_WITH_ID(DLDO
, 11),
93 MFD_DEV_WITH_ID(DLDO
, 12),
96 MFD_DEV_WITH_ID(ALDO
, 1),
97 MFD_DEV_WITH_ID(ALDO
, 2),
98 MFD_DEV_WITH_ID(ALDO
, 3),
99 MFD_DEV_WITH_ID(ALDO
, 4),
100 MFD_DEV_WITH_ID(ALDO
, 5),
101 MFD_DEV_WITH_ID(ALDO
, 6),
102 MFD_DEV_WITH_ID(ALDO
, 7),
103 MFD_DEV_WITH_ID(ALDO
, 8),
104 MFD_DEV_WITH_ID(ALDO
, 9),
105 MFD_DEV_WITH_ID(ALDO
, 10),
110 /* battery charger */
111 MFD_DEV_WITH_RESOURCE(CHARGER
, chg_irqs
, ARRAY_SIZE(chg_irqs
)),
114 MFD_DEV_WITH_RESOURCE(RTC
, rtc_irqs
, ARRAY_SIZE(rtc_irqs
)),
117 MFD_DEV_SIMPLE(BACKLIGHT
),
119 /* current sink for vibrator */
120 MFD_DEV_SIMPLE(VIBRATOR
),
122 /* current sink for keypad LED */
123 MFD_DEV_SIMPLE(KEYLED
),
126 int lp8788_read_byte(struct lp8788
*lp
, u8 reg
, u8
*data
)
131 ret
= regmap_read(lp
->regmap
, reg
, &val
);
133 dev_err(lp
->dev
, "failed to read 0x%.2x\n", reg
);
140 EXPORT_SYMBOL_GPL(lp8788_read_byte
);
142 int lp8788_read_multi_bytes(struct lp8788
*lp
, u8 reg
, u8
*data
, size_t count
)
144 return regmap_bulk_read(lp
->regmap
, reg
, data
, count
);
146 EXPORT_SYMBOL_GPL(lp8788_read_multi_bytes
);
148 int lp8788_write_byte(struct lp8788
*lp
, u8 reg
, u8 data
)
150 return regmap_write(lp
->regmap
, reg
, data
);
152 EXPORT_SYMBOL_GPL(lp8788_write_byte
);
154 int lp8788_update_bits(struct lp8788
*lp
, u8 reg
, u8 mask
, u8 data
)
156 return regmap_update_bits(lp
->regmap
, reg
, mask
, data
);
158 EXPORT_SYMBOL_GPL(lp8788_update_bits
);
160 static int lp8788_platform_init(struct lp8788
*lp
)
162 struct lp8788_platform_data
*pdata
= lp
->pdata
;
164 return (pdata
&& pdata
->init_func
) ? pdata
->init_func(lp
) : 0;
167 static const struct regmap_config lp8788_regmap_config
= {
170 .max_register
= MAX_LP8788_REGISTERS
,
173 static int lp8788_probe(struct i2c_client
*cl
, const struct i2c_device_id
*id
)
176 struct lp8788_platform_data
*pdata
= dev_get_platdata(&cl
->dev
);
179 lp
= devm_kzalloc(&cl
->dev
, sizeof(struct lp8788
), GFP_KERNEL
);
183 lp
->regmap
= devm_regmap_init_i2c(cl
, &lp8788_regmap_config
);
184 if (IS_ERR(lp
->regmap
)) {
185 ret
= PTR_ERR(lp
->regmap
);
186 dev_err(&cl
->dev
, "regmap init i2c err: %d\n", ret
);
192 i2c_set_clientdata(cl
, lp
);
194 ret
= lp8788_platform_init(lp
);
198 ret
= lp8788_irq_init(lp
, cl
->irq
);
202 return mfd_add_devices(lp
->dev
, -1, lp8788_devs
,
203 ARRAY_SIZE(lp8788_devs
), NULL
, 0, NULL
);
206 static int lp8788_remove(struct i2c_client
*cl
)
208 struct lp8788
*lp
= i2c_get_clientdata(cl
);
210 mfd_remove_devices(lp
->dev
);
215 static const struct i2c_device_id lp8788_ids
[] = {
219 MODULE_DEVICE_TABLE(i2c
, lp8788_ids
);
221 static struct i2c_driver lp8788_driver
= {
224 .owner
= THIS_MODULE
,
226 .probe
= lp8788_probe
,
227 .remove
= lp8788_remove
,
228 .id_table
= lp8788_ids
,
231 static int __init
lp8788_init(void)
233 return i2c_add_driver(&lp8788_driver
);
235 subsys_initcall(lp8788_init
);
237 static void __exit
lp8788_exit(void)
239 i2c_del_driver(&lp8788_driver
);
241 module_exit(lp8788_exit
);
243 MODULE_DESCRIPTION("TI LP8788 MFD Driver");
244 MODULE_AUTHOR("Milo Kim");
245 MODULE_LICENSE("GPL");