aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/max14577.c
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-04-14 05:17:18 -0400
committerLee Jones <lee.jones@linaro.org>2014-04-23 09:08:54 -0400
commitaee2a57c7482c712052b877218aa2c5bc0fe8626 (patch)
tree875184a014f637ddc88637ec85012be9f2131f6b /drivers/mfd/max14577.c
parentc7846852ec8f304c629963202fa565452e8fe34c (diff)
mfd: max77836: Add MAX77836 support to max14577 driver
Add Maxim 77836 support to max14577 driver. The chipsets have same MUIC component so the extcon, charger and regulators are almost the same. The MAX77836 however has also PMIC and Fuel Gauge. The MAX77836 uses three I2C slave addresses and has additional interrupts (related to PMIC and Fuel Gauge). It has also Interrupt Source register, just like MAX77686 and MAX77693. The MAX77836 PMIC's TOPSYS and INTSRC interrupts are reported in the PMIC block. The PMIC block has different I2C slave address and uses own regmap so another regmap_irq_chip is needed. Since we have two regmap_irq_chip, use shared interrupts on MAX77836. This patch adds additional defines and functions to the max14577 MFD core driver so the driver will handle both chipsets. Also this patch replaces "0x1 << N" with BIT(N) in defines for register masks. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/max14577.c')
-rw-r--r--drivers/mfd/max14577.c217
1 files changed, 209 insertions, 8 deletions
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 6f39dec9dfdf..20e3b2d81bf0 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * max14577.c - mfd core driver for the Maxim 14577 2 * max14577.c - mfd core driver for the Maxim 14577/77836
3 * 3 *
4 * Copyright (C) 2013 Samsung Electrnoics 4 * Copyright (C) 2014 Samsung Electrnoics
5 * Chanwoo Choi <cw00.choi@samsung.com> 5 * Chanwoo Choi <cw00.choi@samsung.com>
6 * Krzysztof Kozlowski <k.kozlowski@samsung.com> 6 * Krzysztof Kozlowski <k.kozlowski@samsung.com>
7 * 7 *
@@ -38,11 +38,34 @@ static struct mfd_cell max14577_devs[] = {
38 { .name = "max14577-charger", }, 38 { .name = "max14577-charger", },
39}; 39};
40 40
41static struct mfd_cell max77836_devs[] = {
42 {
43 .name = "max77836-muic",
44 .of_compatible = "maxim,max77836-muic",
45 },
46 {
47 .name = "max77836-regulator",
48 .of_compatible = "maxim,max77836-regulator",
49 },
50 {
51 .name = "max77836-charger",
52 .of_compatible = "maxim,max77836-charger",
53 },
54 {
55 .name = "max77836-battery",
56 .of_compatible = "maxim,max77836-battery",
57 },
58};
59
41static struct of_device_id max14577_dt_match[] = { 60static struct of_device_id max14577_dt_match[] = {
42 { 61 {
43 .compatible = "maxim,max14577", 62 .compatible = "maxim,max14577",
44 .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, 63 .data = (void *)MAXIM_DEVICE_TYPE_MAX14577,
45 }, 64 },
65 {
66 .compatible = "maxim,max77836",
67 .data = (void *)MAXIM_DEVICE_TYPE_MAX77836,
68 },
46 {}, 69 {},
47}; 70};
48 71
@@ -57,6 +80,26 @@ static bool max14577_muic_volatile_reg(struct device *dev, unsigned int reg)
57 return false; 80 return false;
58} 81}
59 82
83static bool max77836_muic_volatile_reg(struct device *dev, unsigned int reg)
84{
85 /* Any max14577 volatile registers are also max77836 volatile. */
86 if (max14577_muic_volatile_reg(dev, reg))
87 return true;
88
89 switch (reg) {
90 case MAX77836_FG_REG_VCELL_MSB ... MAX77836_FG_REG_SOC_LSB:
91 case MAX77836_FG_REG_CRATE_MSB ... MAX77836_FG_REG_CRATE_LSB:
92 case MAX77836_FG_REG_STATUS_H ... MAX77836_FG_REG_STATUS_L:
93 case MAX77836_PMIC_REG_INTSRC:
94 case MAX77836_PMIC_REG_TOPSYS_INT:
95 case MAX77836_PMIC_REG_TOPSYS_STAT:
96 return true;
97 default:
98 break;
99 }
100 return false;
101}
102
60static const struct regmap_config max14577_muic_regmap_config = { 103static const struct regmap_config max14577_muic_regmap_config = {
61 .reg_bits = 8, 104 .reg_bits = 8,
62 .val_bits = 8, 105 .val_bits = 8,
@@ -64,6 +107,13 @@ static const struct regmap_config max14577_muic_regmap_config = {
64 .max_register = MAX14577_REG_END, 107 .max_register = MAX14577_REG_END,
65}; 108};
66 109
110static const struct regmap_config max77836_pmic_regmap_config = {
111 .reg_bits = 8,
112 .val_bits = 8,
113 .volatile_reg = max77836_muic_volatile_reg,
114 .max_register = MAX77836_PMIC_REG_END,
115};
116
67static const struct regmap_irq max14577_irqs[] = { 117static const struct regmap_irq max14577_irqs[] = {
68 /* INT1 interrupts */ 118 /* INT1 interrupts */
69 { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, 119 { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, },
@@ -86,12 +136,56 @@ static const struct regmap_irq_chip max14577_irq_chip = {
86 .name = "max14577", 136 .name = "max14577",
87 .status_base = MAX14577_REG_INT1, 137 .status_base = MAX14577_REG_INT1,
88 .mask_base = MAX14577_REG_INTMASK1, 138 .mask_base = MAX14577_REG_INTMASK1,
89 .mask_invert = 1, 139 .mask_invert = true,
90 .num_regs = 3, 140 .num_regs = 3,
91 .irqs = max14577_irqs, 141 .irqs = max14577_irqs,
92 .num_irqs = ARRAY_SIZE(max14577_irqs), 142 .num_irqs = ARRAY_SIZE(max14577_irqs),
93}; 143};
94 144
145static const struct regmap_irq max77836_muic_irqs[] = {
146 /* INT1 interrupts */
147 { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, },
148 { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, },
149 { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, },
150 /* INT2 interrupts */
151 { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, },
152 { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, },
153 { .reg_offset = 1, .mask = MAX14577_INT2_DCDTMR_MASK, },
154 { .reg_offset = 1, .mask = MAX14577_INT2_DBCHG_MASK, },
155 { .reg_offset = 1, .mask = MAX14577_INT2_VBVOLT_MASK, },
156 { .reg_offset = 1, .mask = MAX77836_INT2_VIDRM_MASK, },
157 /* INT3 interrupts */
158 { .reg_offset = 2, .mask = MAX14577_INT3_EOC_MASK, },
159 { .reg_offset = 2, .mask = MAX14577_INT3_CGMBC_MASK, },
160 { .reg_offset = 2, .mask = MAX14577_INT3_OVP_MASK, },
161 { .reg_offset = 2, .mask = MAX14577_INT3_MBCCHGERR_MASK, },
162};
163
164static const struct regmap_irq_chip max77836_muic_irq_chip = {
165 .name = "max77836-muic",
166 .status_base = MAX14577_REG_INT1,
167 .mask_base = MAX14577_REG_INTMASK1,
168 .mask_invert = true,
169 .num_regs = 3,
170 .irqs = max77836_muic_irqs,
171 .num_irqs = ARRAY_SIZE(max77836_muic_irqs),
172};
173
174static const struct regmap_irq max77836_pmic_irqs[] = {
175 { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T120C_MASK, },
176 { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T140C_MASK, },
177};
178
179static const struct regmap_irq_chip max77836_pmic_irq_chip = {
180 .name = "max77836-pmic",
181 .status_base = MAX77836_PMIC_REG_TOPSYS_INT,
182 .mask_base = MAX77836_PMIC_REG_TOPSYS_INT_MASK,
183 .mask_invert = false,
184 .num_regs = 1,
185 .irqs = max77836_pmic_irqs,
186 .num_irqs = ARRAY_SIZE(max77836_pmic_irqs),
187};
188
95static void max14577_print_dev_type(struct max14577 *max14577) 189static void max14577_print_dev_type(struct max14577 *max14577)
96{ 190{
97 u8 reg_data, vendor_id, device_id; 191 u8 reg_data, vendor_id, device_id;
@@ -114,6 +208,81 @@ static void max14577_print_dev_type(struct max14577 *max14577)
114 max14577->dev_type, device_id, vendor_id); 208 max14577->dev_type, device_id, vendor_id);
115} 209}
116 210
211/*
212 * Max77836 specific initialization code for driver probe.
213 * Adds new I2C dummy device, regmap and regmap IRQ chip.
214 * Unmasks Interrupt Source register.
215 *
216 * On success returns 0.
217 * On failure returns errno and reverts any changes done so far (e.g. remove
218 * I2C dummy device), except masking the INT SRC register.
219 */
220static int max77836_init(struct max14577 *max14577)
221{
222 int ret;
223 u8 intsrc_mask;
224
225 max14577->i2c_pmic = i2c_new_dummy(max14577->i2c->adapter,
226 I2C_ADDR_PMIC);
227 if (!max14577->i2c_pmic) {
228 dev_err(max14577->dev, "Failed to register PMIC I2C device\n");
229 return -ENODEV;
230 }
231 i2c_set_clientdata(max14577->i2c_pmic, max14577);
232
233 max14577->regmap_pmic = devm_regmap_init_i2c(max14577->i2c_pmic,
234 &max77836_pmic_regmap_config);
235 if (IS_ERR(max14577->regmap_pmic)) {
236 ret = PTR_ERR(max14577->regmap_pmic);
237 dev_err(max14577->dev, "Failed to allocate PMIC register map: %d\n",
238 ret);
239 goto err;
240 }
241
242 /* Un-mask MAX77836 Interrupt Source register */
243 ret = max14577_read_reg(max14577->regmap_pmic,
244 MAX77836_PMIC_REG_INTSRC_MASK, &intsrc_mask);
245 if (ret < 0) {
246 dev_err(max14577->dev, "Failed to read PMIC register\n");
247 goto err;
248 }
249
250 intsrc_mask &= ~(MAX77836_INTSRC_MASK_TOP_INT_MASK);
251 intsrc_mask &= ~(MAX77836_INTSRC_MASK_MUIC_CHG_INT_MASK);
252 ret = max14577_write_reg(max14577->regmap_pmic,
253 MAX77836_PMIC_REG_INTSRC_MASK, intsrc_mask);
254 if (ret < 0) {
255 dev_err(max14577->dev, "Failed to write PMIC register\n");
256 goto err;
257 }
258
259 ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq,
260 IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,
261 0, &max77836_pmic_irq_chip,
262 &max14577->irq_data_pmic);
263 if (ret != 0) {
264 dev_err(max14577->dev, "Failed to request PMIC IRQ %d: %d\n",
265 max14577->irq, ret);
266 goto err;
267 }
268
269 return 0;
270
271err:
272 i2c_unregister_device(max14577->i2c_pmic);
273
274 return ret;
275}
276
277/*
278 * Max77836 specific de-initialization code for driver remove.
279 */
280static void max77836_remove(struct max14577 *max14577)
281{
282 regmap_del_irq_chip(max14577->irq, max14577->irq_data_pmic);
283 i2c_unregister_device(max14577->i2c_pmic);
284}
285
117static int max14577_i2c_probe(struct i2c_client *i2c, 286static int max14577_i2c_probe(struct i2c_client *i2c,
118 const struct i2c_device_id *id) 287 const struct i2c_device_id *id)
119{ 288{
@@ -121,6 +290,10 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
121 struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); 290 struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev);
122 struct device_node *np = i2c->dev.of_node; 291 struct device_node *np = i2c->dev.of_node;
123 int ret = 0; 292 int ret = 0;
293 const struct regmap_irq_chip *irq_chip;
294 struct mfd_cell *mfd_devs;
295 unsigned int mfd_devs_size;
296 int irq_flags;
124 297
125 if (np) { 298 if (np) {
126 pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); 299 pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
@@ -164,9 +337,24 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
164 337
165 max14577_print_dev_type(max14577); 338 max14577_print_dev_type(max14577);
166 339
340 switch (max14577->dev_type) {
341 case MAXIM_DEVICE_TYPE_MAX77836:
342 irq_chip = &max77836_muic_irq_chip;
343 mfd_devs = max77836_devs;
344 mfd_devs_size = ARRAY_SIZE(max77836_devs);
345 irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
346 break;
347 case MAXIM_DEVICE_TYPE_MAX14577:
348 default:
349 irq_chip = &max14577_irq_chip;
350 mfd_devs = max14577_devs;
351 mfd_devs_size = ARRAY_SIZE(max14577_devs);
352 irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
353 break;
354 }
355
167 ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, 356 ret = regmap_add_irq_chip(max14577->regmap, max14577->irq,
168 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, 357 irq_flags, 0, irq_chip,
169 &max14577_irq_chip,
170 &max14577->irq_data); 358 &max14577->irq_data);
171 if (ret != 0) { 359 if (ret != 0) {
172 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", 360 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
@@ -174,8 +362,15 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
174 return ret; 362 return ret;
175 } 363 }
176 364
177 ret = mfd_add_devices(max14577->dev, -1, max14577_devs, 365 /* Max77836 specific initialization code (additional regmap) */
178 ARRAY_SIZE(max14577_devs), NULL, 0, 366 if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) {
367 ret = max77836_init(max14577);
368 if (ret < 0)
369 goto err_max77836;
370 }
371
372 ret = mfd_add_devices(max14577->dev, -1, mfd_devs,
373 mfd_devs_size, NULL, 0,
179 regmap_irq_get_domain(max14577->irq_data)); 374 regmap_irq_get_domain(max14577->irq_data));
180 if (ret < 0) 375 if (ret < 0)
181 goto err_mfd; 376 goto err_mfd;
@@ -185,6 +380,9 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
185 return 0; 380 return 0;
186 381
187err_mfd: 382err_mfd:
383 if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836)
384 max77836_remove(max14577);
385err_max77836:
188 regmap_del_irq_chip(max14577->irq, max14577->irq_data); 386 regmap_del_irq_chip(max14577->irq, max14577->irq_data);
189 387
190 return ret; 388 return ret;
@@ -196,12 +394,15 @@ static int max14577_i2c_remove(struct i2c_client *i2c)
196 394
197 mfd_remove_devices(max14577->dev); 395 mfd_remove_devices(max14577->dev);
198 regmap_del_irq_chip(max14577->irq, max14577->irq_data); 396 regmap_del_irq_chip(max14577->irq, max14577->irq_data);
397 if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836)
398 max77836_remove(max14577);
199 399
200 return 0; 400 return 0;
201} 401}
202 402
203static const struct i2c_device_id max14577_i2c_id[] = { 403static const struct i2c_device_id max14577_i2c_id[] = {
204 { "max14577", MAXIM_DEVICE_TYPE_MAX14577, }, 404 { "max14577", MAXIM_DEVICE_TYPE_MAX14577, },
405 { "max77836", MAXIM_DEVICE_TYPE_MAX77836, },
205 { } 406 { }
206}; 407};
207MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); 408MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
@@ -274,5 +475,5 @@ static void __exit max14577_i2c_exit(void)
274module_exit(max14577_i2c_exit); 475module_exit(max14577_i2c_exit);
275 476
276MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); 477MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
277MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver"); 478MODULE_DESCRIPTION("Maxim 14577/77836 multi-function core driver");
278MODULE_LICENSE("GPL"); 479MODULE_LICENSE("GPL");