aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/lp8788-irq.c198
-rw-r--r--drivers/mfd/lp8788.c245
-rw-r--r--include/linux/mfd/lp8788-isink.h52
-rw-r--r--include/linux/mfd/lp8788.h364
6 files changed, 871 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b9282cafa978..84d6ea2d74f4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -440,6 +440,16 @@ config PMIC_ADP5520
440 individual components like LCD backlight, LEDs, GPIOs and Kepad 440 individual components like LCD backlight, LEDs, GPIOs and Kepad
441 under the corresponding menus. 441 under the corresponding menus.
442 442
443config MFD_LP8788
444 bool "Texas Instruments LP8788 Power Management Unit Driver"
445 depends on I2C=y
446 select MFD_CORE
447 select REGMAP_I2C
448 select IRQ_DOMAIN
449 help
450 TI LP8788 PMU supports regulators, battery charger, RTC,
451 ADC, backlight driver and current sinks.
452
443config MFD_MAX77686 453config MFD_MAX77686
444 bool "Maxim Semiconductor MAX77686 PMIC Support" 454 bool "Maxim Semiconductor MAX77686 PMIC Support"
445 depends on I2C=y && GENERIC_HARDIRQS 455 depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d16bc0220e1f..083acf97af26 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -89,6 +89,8 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
89obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o 89obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
90obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o 90obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
91 91
92obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
93
92obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o 94obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
93obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o 95obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
94obj-$(CONFIG_MFD_MAX8907) += max8907.o 96obj-$(CONFIG_MFD_MAX8907) += max8907.o
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
new file mode 100644
index 000000000000..c84ded5f8ece
--- /dev/null
+++ b/drivers/mfd/lp8788-irq.c
@@ -0,0 +1,198 @@
1/*
2 * TI LP8788 MFD - interrupt handler
3 *
4 * Copyright 2012 Texas Instruments
5 *
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7 *
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.
11 *
12 */
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18#include <linux/irqdomain.h>
19#include <linux/device.h>
20#include <linux/mfd/lp8788.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23
24/* register address */
25#define LP8788_INT_1 0x00
26#define LP8788_INTEN_1 0x03
27
28#define BASE_INTEN_ADDR LP8788_INTEN_1
29#define SIZE_REG 8
30#define NUM_REGS 3
31
32/*
33 * struct lp8788_irq_data
34 * @lp : used for accessing to lp8788 registers
35 * @irq_lock : mutex for enabling/disabling the interrupt
36 * @domain : IRQ domain for handling nested interrupt
37 * @enabled : status of enabled interrupt
38 */
39struct lp8788_irq_data {
40 struct lp8788 *lp;
41 struct mutex irq_lock;
42 struct irq_domain *domain;
43 int enabled[LP8788_INT_MAX];
44};
45
46static inline u8 _irq_to_addr(enum lp8788_int_id id)
47{
48 return id / SIZE_REG;
49}
50
51static inline u8 _irq_to_enable_addr(enum lp8788_int_id id)
52{
53 return _irq_to_addr(id) + BASE_INTEN_ADDR;
54}
55
56static inline u8 _irq_to_mask(enum lp8788_int_id id)
57{
58 return 1 << (id % SIZE_REG);
59}
60
61static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
62{
63 return enable << (id % SIZE_REG);
64}
65
66static void lp8788_irq_enable(struct irq_data *data)
67{
68 struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
69 irqd->enabled[data->hwirq] = 1;
70}
71
72static void lp8788_irq_disable(struct irq_data *data)
73{
74 struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
75 irqd->enabled[data->hwirq] = 0;
76}
77
78static void lp8788_irq_bus_lock(struct irq_data *data)
79{
80 struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
81
82 mutex_lock(&irqd->irq_lock);
83}
84
85static void lp8788_irq_bus_sync_unlock(struct irq_data *data)
86{
87 struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
88 enum lp8788_int_id irq = data->hwirq;
89 u8 addr, mask, val;
90
91 addr = _irq_to_enable_addr(irq);
92 mask = _irq_to_mask(irq);
93 val = _irq_to_val(irq, irqd->enabled[irq]);
94
95 lp8788_update_bits(irqd->lp, addr, mask, val);
96
97 mutex_unlock(&irqd->irq_lock);
98}
99
100static struct irq_chip lp8788_irq_chip = {
101 .name = "lp8788",
102 .irq_enable = lp8788_irq_enable,
103 .irq_disable = lp8788_irq_disable,
104 .irq_bus_lock = lp8788_irq_bus_lock,
105 .irq_bus_sync_unlock = lp8788_irq_bus_sync_unlock,
106};
107
108static irqreturn_t lp8788_irq_handler(int irq, void *ptr)
109{
110 struct lp8788_irq_data *irqd = ptr;
111 struct lp8788 *lp = irqd->lp;
112 u8 status[NUM_REGS], addr, mask;
113 bool handled;
114 int i;
115
116 if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS))
117 return IRQ_NONE;
118
119 for (i = 0 ; i < LP8788_INT_MAX ; i++) {
120 addr = _irq_to_addr(i);
121 mask = _irq_to_mask(i);
122
123 /* reporting only if the irq is enabled */
124 if (status[addr] & mask) {
125 handle_nested_irq(irq_find_mapping(irqd->domain, i));
126 handled = true;
127 }
128 }
129
130 return handled ? IRQ_HANDLED : IRQ_NONE;
131}
132
133static int lp8788_irq_map(struct irq_domain *d, unsigned int virq,
134 irq_hw_number_t hwirq)
135{
136 struct lp8788_irq_data *irqd = d->host_data;
137 struct irq_chip *chip = &lp8788_irq_chip;
138
139 irq_set_chip_data(virq, irqd);
140 irq_set_chip_and_handler(virq, chip, handle_edge_irq);
141 irq_set_nested_thread(virq, 1);
142
143#ifdef CONFIG_ARM
144 set_irq_flags(virq, IRQF_VALID);
145#else
146 irq_set_noprobe(virq);
147#endif
148
149 return 0;
150}
151
152static struct irq_domain_ops lp8788_domain_ops = {
153 .map = lp8788_irq_map,
154};
155
156int lp8788_irq_init(struct lp8788 *lp, int irq)
157{
158 struct lp8788_irq_data *irqd;
159 int ret;
160
161 if (irq <= 0) {
162 dev_warn(lp->dev, "invalid irq number: %d\n", irq);
163 return 0;
164 }
165
166 irqd = devm_kzalloc(lp->dev, sizeof(*irqd), GFP_KERNEL);
167 if (!irqd)
168 return -ENOMEM;
169
170 irqd->lp = lp;
171 irqd->domain = irq_domain_add_linear(lp->dev->of_node, LP8788_INT_MAX,
172 &lp8788_domain_ops, irqd);
173 if (!irqd->domain) {
174 dev_err(lp->dev, "failed to add irq domain err\n");
175 return -EINVAL;
176 }
177
178 lp->irqdm = irqd->domain;
179 mutex_init(&irqd->irq_lock);
180
181 ret = request_threaded_irq(irq, NULL, lp8788_irq_handler,
182 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
183 "lp8788-irq", irqd);
184 if (ret) {
185 dev_err(lp->dev, "failed to create a thread for IRQ_N\n");
186 return ret;
187 }
188
189 lp->irq = irq;
190
191 return 0;
192}
193
194void lp8788_irq_exit(struct lp8788 *lp)
195{
196 if (lp->irq)
197 free_irq(lp->irq, lp->irqdm);
198}
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
new file mode 100644
index 000000000000..3e94a699833c
--- /dev/null
+++ b/drivers/mfd/lp8788.c
@@ -0,0 +1,245 @@
1/*
2 * TI LP8788 MFD - core interface
3 *
4 * Copyright 2012 Texas Instruments
5 *
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7 *
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.
11 *
12 */
13
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>
20
21#define MAX_LP8788_REGISTERS 0xA2
22
23#define MFD_DEV_SIMPLE(_name) \
24{ \
25 .name = LP8788_DEV_##_name, \
26}
27
28#define MFD_DEV_WITH_ID(_name, _id) \
29{ \
30 .name = LP8788_DEV_##_name, \
31 .id = _id, \
32}
33
34#define MFD_DEV_WITH_RESOURCE(_name, _resource, num_resource) \
35{ \
36 .name = LP8788_DEV_##_name, \
37 .resources = _resource, \
38 .num_resources = num_resource, \
39}
40
41static struct resource chg_irqs[] = {
42 /* Charger Interrupts */
43 {
44 .start = LP8788_INT_CHG_INPUT_STATE,
45 .end = LP8788_INT_PRECHG_TIMEOUT,
46 .name = LP8788_CHG_IRQ,
47 .flags = IORESOURCE_IRQ,
48 },
49 /* Power Routing Switch Interrupts */
50 {
51 .start = LP8788_INT_ENTER_SYS_SUPPORT,
52 .end = LP8788_INT_EXIT_SYS_SUPPORT,
53 .name = LP8788_PRSW_IRQ,
54 .flags = IORESOURCE_IRQ,
55 },
56 /* Battery Interrupts */
57 {
58 .start = LP8788_INT_BATT_LOW,
59 .end = LP8788_INT_NO_BATT,
60 .name = LP8788_BATT_IRQ,
61 .flags = IORESOURCE_IRQ,
62 },
63};
64
65static struct resource rtc_irqs[] = {
66 {
67 .start = LP8788_INT_RTC_ALARM1,
68 .end = LP8788_INT_RTC_ALARM2,
69 .name = LP8788_ALM_IRQ,
70 .flags = IORESOURCE_IRQ,
71 },
72};
73
74static struct mfd_cell lp8788_devs[] = {
75 /* 4 bucks */
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),
80
81 /* 12 digital ldos */
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),
94
95 /* 10 analog ldos */
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),
106
107 /* ADC */
108 MFD_DEV_SIMPLE(ADC),
109
110 /* battery charger */
111 MFD_DEV_WITH_RESOURCE(CHARGER, chg_irqs, ARRAY_SIZE(chg_irqs)),
112
113 /* rtc */
114 MFD_DEV_WITH_RESOURCE(RTC, rtc_irqs, ARRAY_SIZE(rtc_irqs)),
115
116 /* backlight */
117 MFD_DEV_SIMPLE(BACKLIGHT),
118
119 /* current sink for vibrator */
120 MFD_DEV_SIMPLE(VIBRATOR),
121
122 /* current sink for keypad LED */
123 MFD_DEV_SIMPLE(KEYLED),
124};
125
126int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data)
127{
128 int ret;
129 unsigned int val;
130
131 ret = regmap_read(lp->regmap, reg, &val);
132 if (ret < 0) {
133 dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
134 return ret;
135 }
136
137 *data = (u8)val;
138 return 0;
139}
140EXPORT_SYMBOL_GPL(lp8788_read_byte);
141
142int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count)
143{
144 return regmap_bulk_read(lp->regmap, reg, data, count);
145}
146EXPORT_SYMBOL_GPL(lp8788_read_multi_bytes);
147
148int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data)
149{
150 return regmap_write(lp->regmap, reg, data);
151}
152EXPORT_SYMBOL_GPL(lp8788_write_byte);
153
154int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data)
155{
156 return regmap_update_bits(lp->regmap, reg, mask, data);
157}
158EXPORT_SYMBOL_GPL(lp8788_update_bits);
159
160static int lp8788_platform_init(struct lp8788 *lp)
161{
162 struct lp8788_platform_data *pdata = lp->pdata;
163
164 return (pdata && pdata->init_func) ? pdata->init_func(lp) : 0;
165}
166
167static const struct regmap_config lp8788_regmap_config = {
168 .reg_bits = 8,
169 .val_bits = 8,
170 .max_register = MAX_LP8788_REGISTERS,
171};
172
173static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
174{
175 struct lp8788 *lp;
176 struct lp8788_platform_data *pdata = cl->dev.platform_data;
177 int ret;
178
179 lp = devm_kzalloc(&cl->dev, sizeof(struct lp8788), GFP_KERNEL);
180 if (!lp)
181 return -ENOMEM;
182
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);
187 return ret;
188 }
189
190 lp->pdata = pdata;
191 lp->dev = &cl->dev;
192 i2c_set_clientdata(cl, lp);
193
194 ret = lp8788_platform_init(lp);
195 if (ret)
196 return ret;
197
198 ret = lp8788_irq_init(lp, cl->irq);
199 if (ret)
200 return ret;
201
202 return mfd_add_devices(lp->dev, -1, lp8788_devs,
203 ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
204}
205
206static int __devexit lp8788_remove(struct i2c_client *cl)
207{
208 struct lp8788 *lp = i2c_get_clientdata(cl);
209
210 mfd_remove_devices(lp->dev);
211 lp8788_irq_exit(lp);
212 return 0;
213}
214
215static const struct i2c_device_id lp8788_ids[] = {
216 {"lp8788", 0},
217 { }
218};
219MODULE_DEVICE_TABLE(i2c, lp8788_ids);
220
221static struct i2c_driver lp8788_driver = {
222 .driver = {
223 .name = "lp8788",
224 .owner = THIS_MODULE,
225 },
226 .probe = lp8788_probe,
227 .remove = __devexit_p(lp8788_remove),
228 .id_table = lp8788_ids,
229};
230
231static int __init lp8788_init(void)
232{
233 return i2c_add_driver(&lp8788_driver);
234}
235subsys_initcall(lp8788_init);
236
237static void __exit lp8788_exit(void)
238{
239 i2c_del_driver(&lp8788_driver);
240}
241module_exit(lp8788_exit);
242
243MODULE_DESCRIPTION("TI LP8788 MFD Driver");
244MODULE_AUTHOR("Milo Kim");
245MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/lp8788-isink.h b/include/linux/mfd/lp8788-isink.h
new file mode 100644
index 000000000000..f38262d21ff1
--- /dev/null
+++ b/include/linux/mfd/lp8788-isink.h
@@ -0,0 +1,52 @@
1/*
2 * TI LP8788 MFD - common definitions for current sinks
3 *
4 * Copyright 2012 Texas Instruments
5 *
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7 *
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.
11 *
12 */
13
14#ifndef __ISINK_LP8788_H__
15#define __ISINK_LP8788_H__
16
17/* register address */
18#define LP8788_ISINK_CTRL 0x99
19#define LP8788_ISINK12_IOUT 0x9A
20#define LP8788_ISINK3_IOUT 0x9B
21#define LP8788_ISINK1_PWM 0x9C
22#define LP8788_ISINK2_PWM 0x9D
23#define LP8788_ISINK3_PWM 0x9E
24
25/* mask bits */
26#define LP8788_ISINK1_IOUT_M 0x0F /* Addr 9Ah */
27#define LP8788_ISINK2_IOUT_M 0xF0
28#define LP8788_ISINK3_IOUT_M 0x0F /* Addr 9Bh */
29
30/* 6 bits used for PWM code : Addr 9C ~ 9Eh */
31#define LP8788_ISINK_MAX_PWM 63
32#define LP8788_ISINK_SCALE_OFFSET 3
33
34static const u8 lp8788_iout_addr[] = {
35 LP8788_ISINK12_IOUT,
36 LP8788_ISINK12_IOUT,
37 LP8788_ISINK3_IOUT,
38};
39
40static const u8 lp8788_iout_mask[] = {
41 LP8788_ISINK1_IOUT_M,
42 LP8788_ISINK2_IOUT_M,
43 LP8788_ISINK3_IOUT_M,
44};
45
46static const u8 lp8788_pwm_addr[] = {
47 LP8788_ISINK1_PWM,
48 LP8788_ISINK2_PWM,
49 LP8788_ISINK3_PWM,
50};
51
52#endif
diff --git a/include/linux/mfd/lp8788.h b/include/linux/mfd/lp8788.h
new file mode 100644
index 000000000000..cec364bdccfa
--- /dev/null
+++ b/include/linux/mfd/lp8788.h
@@ -0,0 +1,364 @@
1/*
2 * TI LP8788 MFD Device
3 *
4 * Copyright 2012 Texas Instruments
5 *
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7 *
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.
11 *
12 */
13
14#ifndef __MFD_LP8788_H__
15#define __MFD_LP8788_H__
16
17#include <linux/gpio.h>
18#include <linux/irqdomain.h>
19#include <linux/regmap.h>
20
21#define LP8788_DEV_BUCK "lp8788-buck"
22#define LP8788_DEV_DLDO "lp8788-dldo"
23#define LP8788_DEV_ALDO "lp8788-aldo"
24#define LP8788_DEV_CHARGER "lp8788-charger"
25#define LP8788_DEV_RTC "lp8788-rtc"
26#define LP8788_DEV_BACKLIGHT "lp8788-backlight"
27#define LP8788_DEV_VIBRATOR "lp8788-vibrator"
28#define LP8788_DEV_KEYLED "lp8788-keyled"
29#define LP8788_DEV_ADC "lp8788-adc"
30
31#define LP8788_NUM_BUCKS 4
32#define LP8788_NUM_DLDOS 12
33#define LP8788_NUM_ALDOS 10
34#define LP8788_NUM_BUCK2_DVS 2
35
36#define LP8788_CHG_IRQ "CHG_IRQ"
37#define LP8788_PRSW_IRQ "PRSW_IRQ"
38#define LP8788_BATT_IRQ "BATT_IRQ"
39#define LP8788_ALM_IRQ "ALARM_IRQ"
40
41enum lp8788_int_id {
42 /* interrup register 1 : Addr 00h */
43 LP8788_INT_TSDL,
44 LP8788_INT_TSDH,
45 LP8788_INT_UVLO,
46 LP8788_INT_FLAGMON,
47 LP8788_INT_PWRON_TIME,
48 LP8788_INT_PWRON,
49 LP8788_INT_COMP1,
50 LP8788_INT_COMP2,
51
52 /* interrupt register 2 : Addr 01h */
53 LP8788_INT_CHG_INPUT_STATE,
54 LP8788_INT_CHG_STATE,
55 LP8788_INT_EOC,
56 LP8788_INT_CHG_RESTART,
57 LP8788_INT_RESTART_TIMEOUT,
58 LP8788_INT_FULLCHG_TIMEOUT,
59 LP8788_INT_PRECHG_TIMEOUT,
60
61 /* interrupt register 3 : Addr 02h */
62 LP8788_INT_RTC_ALARM1 = 17,
63 LP8788_INT_RTC_ALARM2,
64 LP8788_INT_ENTER_SYS_SUPPORT,
65 LP8788_INT_EXIT_SYS_SUPPORT,
66 LP8788_INT_BATT_LOW,
67 LP8788_INT_NO_BATT,
68
69 LP8788_INT_MAX = 24,
70};
71
72enum lp8788_dvs_sel {
73 DVS_SEL_V0,
74 DVS_SEL_V1,
75 DVS_SEL_V2,
76 DVS_SEL_V3,
77};
78
79enum lp8788_ext_ldo_en_id {
80 EN_ALDO1,
81 EN_ALDO234,
82 EN_ALDO5,
83 EN_ALDO7,
84 EN_DLDO7,
85 EN_DLDO911,
86 EN_LDOS_MAX,
87};
88
89enum lp8788_charger_event {
90 NO_CHARGER,
91 CHARGER_DETECTED,
92};
93
94enum lp8788_bl_ctrl_mode {
95 LP8788_BL_REGISTER_ONLY,
96 LP8788_BL_COMB_PWM_BASED, /* PWM + I2C, changed by PWM input */
97 LP8788_BL_COMB_REGISTER_BASED, /* PWM + I2C, changed by I2C */
98};
99
100enum lp8788_bl_dim_mode {
101 LP8788_DIM_EXPONENTIAL,
102 LP8788_DIM_LINEAR,
103};
104
105enum lp8788_bl_full_scale_current {
106 LP8788_FULLSCALE_5000uA,
107 LP8788_FULLSCALE_8500uA,
108 LP8788_FULLSCALE_1200uA,
109 LP8788_FULLSCALE_1550uA,
110 LP8788_FULLSCALE_1900uA,
111 LP8788_FULLSCALE_2250uA,
112 LP8788_FULLSCALE_2600uA,
113 LP8788_FULLSCALE_2950uA,
114};
115
116enum lp8788_bl_ramp_step {
117 LP8788_RAMP_8us,
118 LP8788_RAMP_1024us,
119 LP8788_RAMP_2048us,
120 LP8788_RAMP_4096us,
121 LP8788_RAMP_8192us,
122 LP8788_RAMP_16384us,
123 LP8788_RAMP_32768us,
124 LP8788_RAMP_65538us,
125};
126
127enum lp8788_bl_pwm_polarity {
128 LP8788_PWM_ACTIVE_HIGH,
129 LP8788_PWM_ACTIVE_LOW,
130};
131
132enum lp8788_isink_scale {
133 LP8788_ISINK_SCALE_100mA,
134 LP8788_ISINK_SCALE_120mA,
135};
136
137enum lp8788_isink_number {
138 LP8788_ISINK_1,
139 LP8788_ISINK_2,
140 LP8788_ISINK_3,
141};
142
143enum lp8788_alarm_sel {
144 LP8788_ALARM_1,
145 LP8788_ALARM_2,
146 LP8788_ALARM_MAX,
147};
148
149enum lp8788_adc_id {
150 LPADC_VBATT_5P5,
151 LPADC_VIN_CHG,
152 LPADC_IBATT,
153 LPADC_IC_TEMP,
154 LPADC_VBATT_6P0,
155 LPADC_VBATT_5P0,
156 LPADC_ADC1,
157 LPADC_ADC2,
158 LPADC_VDD,
159 LPADC_VCOIN,
160 LPADC_VDD_LDO,
161 LPADC_ADC3,
162 LPADC_ADC4,
163 LPADC_MAX,
164};
165
166struct lp8788;
167
168/*
169 * lp8788_buck1_dvs
170 * @gpio : gpio pin number for dvs control
171 * @vsel : dvs selector for buck v1 register
172 */
173struct lp8788_buck1_dvs {
174 int gpio;
175 enum lp8788_dvs_sel vsel;
176};
177
178/*
179 * lp8788_buck2_dvs
180 * @gpio : two gpio pin numbers are used for dvs
181 * @vsel : dvs selector for buck v2 register
182 */
183struct lp8788_buck2_dvs {
184 int gpio[LP8788_NUM_BUCK2_DVS];
185 enum lp8788_dvs_sel vsel;
186};
187
188/*
189 * struct lp8788_ldo_enable_pin
190 *
191 * Basically, all LDOs are enabled through the I2C commands.
192 * But ALDO 1 ~ 5, 7, DLDO 7, 9, 11 can be enabled by external gpio pins.
193 *
194 * @gpio : gpio number which is used for enabling ldos
195 * @init_state : initial gpio state (ex. GPIOF_OUT_INIT_LOW)
196 */
197struct lp8788_ldo_enable_pin {
198 int gpio;
199 int init_state;
200};
201
202/*
203 * struct lp8788_chg_param
204 * @addr : charging control register address (range : 0x11 ~ 0x1C)
205 * @val : charging parameter value
206 */
207struct lp8788_chg_param {
208 u8 addr;
209 u8 val;
210};
211
212/*
213 * struct lp8788_charger_platform_data
214 * @vbatt_adc : adc selection id for battery voltage
215 * @batt_temp_adc : adc selection id for battery temperature
216 * @max_vbatt_mv : used for calculating battery capacity
217 * @chg_params : initial charging parameters
218 * @num_chg_params : numbers of charging parameters
219 * @charger_event : the charger event can be reported to the platform side
220 */
221struct lp8788_charger_platform_data {
222 enum lp8788_adc_id vbatt_adc;
223 enum lp8788_adc_id batt_temp_adc;
224 unsigned int max_vbatt_mv;
225 struct lp8788_chg_param *chg_params;
226 int num_chg_params;
227 void (*charger_event) (struct lp8788 *lp,
228 enum lp8788_charger_event event);
229};
230
231/*
232 * struct lp8788_bl_pwm_data
233 * @pwm_set_intensity : set duty of pwm
234 * @pwm_get_intensity : get current duty of pwm
235 */
236struct lp8788_bl_pwm_data {
237 void (*pwm_set_intensity) (int brightness, int max_brightness);
238 int (*pwm_get_intensity) (int max_brightness);
239};
240
241/*
242 * struct lp8788_backlight_platform_data
243 * @name : backlight driver name. (default: "lcd-backlight")
244 * @initial_brightness : initial value of backlight brightness
245 * @bl_mode : brightness control by pwm or lp8788 register
246 * @dim_mode : dimming mode selection
247 * @full_scale : full scale current setting
248 * @rise_time : brightness ramp up step time
249 * @fall_time : brightness ramp down step time
250 * @pwm_pol : pwm polarity setting when bl_mode is pwm based
251 * @pwm_data : platform specific pwm generation functions
252 * only valid when bl_mode is pwm based
253 */
254struct lp8788_backlight_platform_data {
255 char *name;
256 int initial_brightness;
257 enum lp8788_bl_ctrl_mode bl_mode;
258 enum lp8788_bl_dim_mode dim_mode;
259 enum lp8788_bl_full_scale_current full_scale;
260 enum lp8788_bl_ramp_step rise_time;
261 enum lp8788_bl_ramp_step fall_time;
262 enum lp8788_bl_pwm_polarity pwm_pol;
263 struct lp8788_bl_pwm_data pwm_data;
264};
265
266/*
267 * struct lp8788_led_platform_data
268 * @name : led driver name. (default: "keyboard-backlight")
269 * @scale : current scale
270 * @num : current sink number
271 * @iout_code : current output value (Addr 9Ah ~ 9Bh)
272 */
273struct lp8788_led_platform_data {
274 char *name;
275 enum lp8788_isink_scale scale;
276 enum lp8788_isink_number num;
277 int iout_code;
278};
279
280/*
281 * struct lp8788_vib_platform_data
282 * @name : vibrator driver name
283 * @scale : current scale
284 * @num : current sink number
285 * @iout_code : current output value (Addr 9Ah ~ 9Bh)
286 * @pwm_code : PWM code value (Addr 9Ch ~ 9Eh)
287 */
288struct lp8788_vib_platform_data {
289 char *name;
290 enum lp8788_isink_scale scale;
291 enum lp8788_isink_number num;
292 int iout_code;
293 int pwm_code;
294};
295
296/*
297 * struct lp8788_platform_data
298 * @init_func : used for initializing registers
299 * before mfd driver is registered
300 * @buck_data : regulator initial data for buck
301 * @dldo_data : regulator initial data for digital ldo
302 * @aldo_data : regulator initial data for analog ldo
303 * @buck1_dvs : gpio configurations for buck1 dvs
304 * @buck2_dvs : gpio configurations for buck2 dvs
305 * @ldo_pin : gpio configurations for enabling LDOs
306 * @chg_pdata : platform data for charger driver
307 * @alarm_sel : rtc alarm selection (1 or 2)
308 * @bl_pdata : configurable data for backlight driver
309 * @led_pdata : configurable data for led driver
310 * @vib_pdata : configurable data for vibrator driver
311 * @adc_pdata : iio map data for adc driver
312 */
313struct lp8788_platform_data {
314 /* general system information */
315 int (*init_func) (struct lp8788 *lp);
316
317 /* regulators */
318 struct regulator_init_data *buck_data[LP8788_NUM_BUCKS];
319 struct regulator_init_data *dldo_data[LP8788_NUM_DLDOS];
320 struct regulator_init_data *aldo_data[LP8788_NUM_ALDOS];
321 struct lp8788_buck1_dvs *buck1_dvs;
322 struct lp8788_buck2_dvs *buck2_dvs;
323 struct lp8788_ldo_enable_pin *ldo_pin[EN_LDOS_MAX];
324
325 /* charger */
326 struct lp8788_charger_platform_data *chg_pdata;
327
328 /* rtc alarm */
329 enum lp8788_alarm_sel alarm_sel;
330
331 /* backlight */
332 struct lp8788_backlight_platform_data *bl_pdata;
333
334 /* current sinks */
335 struct lp8788_led_platform_data *led_pdata;
336 struct lp8788_vib_platform_data *vib_pdata;
337
338 /* adc iio map data */
339 struct iio_map *adc_pdata;
340};
341
342/*
343 * struct lp8788
344 * @dev : parent device pointer
345 * @regmap : used for i2c communcation on accessing registers
346 * @irqdm : interrupt domain for handling nested interrupt
347 * @irq : pin number of IRQ_N
348 * @pdata : lp8788 platform specific data
349 */
350struct lp8788 {
351 struct device *dev;
352 struct regmap *regmap;
353 struct irq_domain *irqdm;
354 int irq;
355 struct lp8788_platform_data *pdata;
356};
357
358int lp8788_irq_init(struct lp8788 *lp, int chip_irq);
359void lp8788_irq_exit(struct lp8788 *lp);
360int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data);
361int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count);
362int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data);
363int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data);
364#endif