]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/mfd/da9150-core.c
Merge remote-tracking branch 'md/for-next'
[karo-tx-linux.git] / drivers / mfd / da9150-core.c
1 /*
2  * DA9150 Core MFD Driver
3  *
4  * Copyright (c) 2014 Dialog Semiconductor
5  *
6  * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
7  *
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.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/i2c.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20 #include <linux/irq.h>
21 #include <linux/interrupt.h>
22 #include <linux/mfd/core.h>
23 #include <linux/mfd/da9150/core.h>
24 #include <linux/mfd/da9150/registers.h>
25
26 static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
27 {
28         switch (reg) {
29         case DA9150_PAGE_CON:
30         case DA9150_STATUS_A:
31         case DA9150_STATUS_B:
32         case DA9150_STATUS_C:
33         case DA9150_STATUS_D:
34         case DA9150_STATUS_E:
35         case DA9150_STATUS_F:
36         case DA9150_STATUS_G:
37         case DA9150_STATUS_H:
38         case DA9150_STATUS_I:
39         case DA9150_STATUS_J:
40         case DA9150_STATUS_K:
41         case DA9150_STATUS_L:
42         case DA9150_STATUS_N:
43         case DA9150_FAULT_LOG_A:
44         case DA9150_FAULT_LOG_B:
45         case DA9150_EVENT_E:
46         case DA9150_EVENT_F:
47         case DA9150_EVENT_G:
48         case DA9150_EVENT_H:
49         case DA9150_CONTROL_B:
50         case DA9150_CONTROL_C:
51         case DA9150_GPADC_MAN:
52         case DA9150_GPADC_RES_A:
53         case DA9150_GPADC_RES_B:
54         case DA9150_ADETVB_CFG_C:
55         case DA9150_ADETD_STAT:
56         case DA9150_ADET_CMPSTAT:
57         case DA9150_ADET_CTRL_A:
58         case DA9150_PPR_TCTR_B:
59         case DA9150_COREBTLD_STAT_A:
60         case DA9150_CORE_DATA_A:
61         case DA9150_CORE_DATA_B:
62         case DA9150_CORE_DATA_C:
63         case DA9150_CORE_DATA_D:
64         case DA9150_CORE2WIRE_STAT_A:
65         case DA9150_FW_CTRL_C:
66         case DA9150_FG_CTRL_B:
67         case DA9150_FW_CTRL_B:
68         case DA9150_GPADC_CMAN:
69         case DA9150_GPADC_CRES_A:
70         case DA9150_GPADC_CRES_B:
71         case DA9150_CC_ICHG_RES_A:
72         case DA9150_CC_ICHG_RES_B:
73         case DA9150_CC_IAVG_RES_A:
74         case DA9150_CC_IAVG_RES_B:
75         case DA9150_TAUX_CTRL_A:
76         case DA9150_TAUX_VALUE_H:
77         case DA9150_TAUX_VALUE_L:
78         case DA9150_TBAT_RES_A:
79         case DA9150_TBAT_RES_B:
80                 return true;
81         default:
82                 return false;
83         }
84 }
85
86 static const struct regmap_range_cfg da9150_range_cfg[] = {
87         {
88                 .range_min = DA9150_PAGE_CON,
89                 .range_max = DA9150_TBAT_RES_B,
90                 .selector_reg = DA9150_PAGE_CON,
91                 .selector_mask = DA9150_I2C_PAGE_MASK,
92                 .selector_shift = DA9150_I2C_PAGE_SHIFT,
93                 .window_start = 0,
94                 .window_len = 256,
95         },
96 };
97
98 static const struct regmap_config da9150_regmap_config = {
99         .reg_bits = 8,
100         .val_bits = 8,
101         .ranges = da9150_range_cfg,
102         .num_ranges = ARRAY_SIZE(da9150_range_cfg),
103         .max_register = DA9150_TBAT_RES_B,
104
105         .cache_type = REGCACHE_RBTREE,
106
107         .volatile_reg = da9150_volatile_reg,
108 };
109
110 u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
111 {
112         int val, ret;
113
114         ret = regmap_read(da9150->regmap, reg, &val);
115         if (ret)
116                 dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
117                         reg, ret);
118
119         return (u8) val;
120 }
121 EXPORT_SYMBOL_GPL(da9150_reg_read);
122
123 void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
124 {
125         int ret;
126
127         ret = regmap_write(da9150->regmap, reg, val);
128         if (ret)
129                 dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
130                         reg, ret);
131 }
132 EXPORT_SYMBOL_GPL(da9150_reg_write);
133
134 void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val)
135 {
136         int ret;
137
138         ret = regmap_update_bits(da9150->regmap, reg, mask, val);
139         if (ret)
140                 dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
141                         reg, ret);
142 }
143 EXPORT_SYMBOL_GPL(da9150_set_bits);
144
145 void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf)
146 {
147         int ret;
148
149         ret = regmap_bulk_read(da9150->regmap, reg, buf, count);
150         if (ret)
151                 dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
152                         reg, ret);
153 }
154 EXPORT_SYMBOL_GPL(da9150_bulk_read);
155
156 void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf)
157 {
158         int ret;
159
160         ret = regmap_raw_write(da9150->regmap, reg, buf, count);
161         if (ret)
162                 dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
163                         reg, ret);
164 }
165 EXPORT_SYMBOL_GPL(da9150_bulk_write);
166
167 static const struct regmap_irq da9150_irqs[] = {
168         [DA9150_IRQ_VBUS] = {
169                 .reg_offset = 0,
170                 .mask = DA9150_E_VBUS_MASK,
171         },
172         [DA9150_IRQ_CHG] = {
173                 .reg_offset = 0,
174                 .mask = DA9150_E_CHG_MASK,
175         },
176         [DA9150_IRQ_TCLASS] = {
177                 .reg_offset = 0,
178                 .mask = DA9150_E_TCLASS_MASK,
179         },
180         [DA9150_IRQ_TJUNC] = {
181                 .reg_offset = 0,
182                 .mask = DA9150_E_TJUNC_MASK,
183         },
184         [DA9150_IRQ_VFAULT] = {
185                 .reg_offset = 0,
186                 .mask = DA9150_E_VFAULT_MASK,
187         },
188         [DA9150_IRQ_CONF] = {
189                 .reg_offset = 1,
190                 .mask = DA9150_E_CONF_MASK,
191         },
192         [DA9150_IRQ_DAT] = {
193                 .reg_offset = 1,
194                 .mask = DA9150_E_DAT_MASK,
195         },
196         [DA9150_IRQ_DTYPE] = {
197                 .reg_offset = 1,
198                 .mask = DA9150_E_DTYPE_MASK,
199         },
200         [DA9150_IRQ_ID] = {
201                 .reg_offset = 1,
202                 .mask = DA9150_E_ID_MASK,
203         },
204         [DA9150_IRQ_ADP] = {
205                 .reg_offset = 1,
206                 .mask = DA9150_E_ADP_MASK,
207         },
208         [DA9150_IRQ_SESS_END] = {
209                 .reg_offset = 1,
210                 .mask = DA9150_E_SESS_END_MASK,
211         },
212         [DA9150_IRQ_SESS_VLD] = {
213                 .reg_offset = 1,
214                 .mask = DA9150_E_SESS_VLD_MASK,
215         },
216         [DA9150_IRQ_FG] = {
217                 .reg_offset = 2,
218                 .mask = DA9150_E_FG_MASK,
219         },
220         [DA9150_IRQ_GP] = {
221                 .reg_offset = 2,
222                 .mask = DA9150_E_GP_MASK,
223         },
224         [DA9150_IRQ_TBAT] = {
225                 .reg_offset = 2,
226                 .mask = DA9150_E_TBAT_MASK,
227         },
228         [DA9150_IRQ_GPIOA] = {
229                 .reg_offset = 2,
230                 .mask = DA9150_E_GPIOA_MASK,
231         },
232         [DA9150_IRQ_GPIOB] = {
233                 .reg_offset = 2,
234                 .mask = DA9150_E_GPIOB_MASK,
235         },
236         [DA9150_IRQ_GPIOC] = {
237                 .reg_offset = 2,
238                 .mask = DA9150_E_GPIOC_MASK,
239         },
240         [DA9150_IRQ_GPIOD] = {
241                 .reg_offset = 2,
242                 .mask = DA9150_E_GPIOD_MASK,
243         },
244         [DA9150_IRQ_GPADC] = {
245                 .reg_offset = 2,
246                 .mask = DA9150_E_GPADC_MASK,
247         },
248         [DA9150_IRQ_WKUP] = {
249                 .reg_offset = 3,
250                 .mask = DA9150_E_WKUP_MASK,
251         },
252 };
253
254 static const struct regmap_irq_chip da9150_regmap_irq_chip = {
255         .name = "da9150_irq",
256         .status_base = DA9150_EVENT_E,
257         .mask_base = DA9150_IRQ_MASK_E,
258         .ack_base = DA9150_EVENT_E,
259         .num_regs = DA9150_NUM_IRQ_REGS,
260         .irqs = da9150_irqs,
261         .num_irqs = ARRAY_SIZE(da9150_irqs),
262 };
263
264 static struct resource da9150_gpadc_resources[] = {
265         {
266                 .name = "GPADC",
267                 .start = DA9150_IRQ_GPADC,
268                 .end = DA9150_IRQ_GPADC,
269                 .flags = IORESOURCE_IRQ,
270         },
271 };
272
273 static struct resource da9150_charger_resources[] = {
274         {
275                 .name = "CHG_STATUS",
276                 .start = DA9150_IRQ_CHG,
277                 .end = DA9150_IRQ_CHG,
278                 .flags = IORESOURCE_IRQ,
279         },
280         {
281                 .name = "CHG_TJUNC",
282                 .start = DA9150_IRQ_TJUNC,
283                 .end = DA9150_IRQ_TJUNC,
284                 .flags = IORESOURCE_IRQ,
285         },
286         {
287                 .name = "CHG_VFAULT",
288                 .start = DA9150_IRQ_VFAULT,
289                 .end = DA9150_IRQ_VFAULT,
290                 .flags = IORESOURCE_IRQ,
291         },
292         {
293                 .name = "CHG_VBUS",
294                 .start = DA9150_IRQ_VBUS,
295                 .end = DA9150_IRQ_VBUS,
296                 .flags = IORESOURCE_IRQ,
297         },
298 };
299
300 static struct mfd_cell da9150_devs[] = {
301         {
302                 .name = "da9150-gpadc",
303                 .of_compatible = "dlg,da9150-gpadc",
304                 .resources = da9150_gpadc_resources,
305                 .num_resources = ARRAY_SIZE(da9150_gpadc_resources),
306         },
307         {
308                 .name = "da9150-charger",
309                 .of_compatible = "dlg,da9150-charger",
310                 .resources = da9150_charger_resources,
311                 .num_resources = ARRAY_SIZE(da9150_charger_resources),
312         },
313 };
314
315 static int da9150_probe(struct i2c_client *client,
316                         const struct i2c_device_id *id)
317 {
318         struct da9150 *da9150;
319         struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
320         int ret;
321
322         da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
323         if (!da9150)
324                 return -ENOMEM;
325
326         da9150->dev = &client->dev;
327         da9150->irq = client->irq;
328         i2c_set_clientdata(client, da9150);
329
330         da9150->regmap = devm_regmap_init_i2c(client, &da9150_regmap_config);
331         if (IS_ERR(da9150->regmap)) {
332                 ret = PTR_ERR(da9150->regmap);
333                 dev_err(da9150->dev, "Failed to allocate register map: %d\n",
334                         ret);
335                 return ret;
336         }
337
338         da9150->irq_base = pdata ? pdata->irq_base : -1;
339
340         ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
341                                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
342                                   da9150->irq_base, &da9150_regmap_irq_chip,
343                                   &da9150->regmap_irq_data);
344         if (ret)
345                 return ret;
346
347         da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
348         enable_irq_wake(da9150->irq);
349
350         ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
351                               ARRAY_SIZE(da9150_devs), NULL,
352                               da9150->irq_base, NULL);
353         if (ret) {
354                 dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
355                 regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
356                 return ret;
357         }
358
359         return 0;
360 }
361
362 static int da9150_remove(struct i2c_client *client)
363 {
364         struct da9150 *da9150 = i2c_get_clientdata(client);
365
366         regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
367         mfd_remove_devices(da9150->dev);
368
369         return 0;
370 }
371
372 static void da9150_shutdown(struct i2c_client *client)
373 {
374         struct da9150 *da9150 = i2c_get_clientdata(client);
375
376         /* Make sure we have a wakup source for the device */
377         da9150_set_bits(da9150, DA9150_CONFIG_D,
378                         DA9150_WKUP_PM_EN_MASK,
379                         DA9150_WKUP_PM_EN_MASK);
380
381         /* Set device to DISABLED mode */
382         da9150_set_bits(da9150, DA9150_CONTROL_C,
383                         DA9150_DISABLE_MASK, DA9150_DISABLE_MASK);
384 }
385
386 static const struct i2c_device_id da9150_i2c_id[] = {
387         { "da9150", },
388         { }
389 };
390 MODULE_DEVICE_TABLE(i2c, da9150_i2c_id);
391
392 static const struct of_device_id da9150_of_match[] = {
393         { .compatible = "dlg,da9150", },
394         { }
395 };
396 MODULE_DEVICE_TABLE(of, da9150_of_match);
397
398 static struct i2c_driver da9150_driver = {
399         .driver = {
400                 .name   = "da9150",
401                 .of_match_table = of_match_ptr(da9150_of_match),
402         },
403         .probe          = da9150_probe,
404         .remove         = da9150_remove,
405         .shutdown       = da9150_shutdown,
406         .id_table       = da9150_i2c_id,
407 };
408
409 module_i2c_driver(da9150_driver);
410
411 MODULE_DESCRIPTION("MFD Core Driver for DA9150");
412 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
413 MODULE_LICENSE("GPL");