Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
da9055-core.c
Go to the documentation of this file.
1 /*
2  * Device access for Dialog DA9055 PMICs.
3  *
4  * Copyright(c) 2012 Dialog Semiconductor Ltd.
5  *
6  * Author: David Dajun Chen <[email protected]>
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/module.h>
15 #include <linux/device.h>
16 #include <linux/input.h>
17 #include <linux/irq.h>
18 #include <linux/mutex.h>
19 
20 #include <linux/mfd/core.h>
21 #include <linux/mfd/da9055/core.h>
22 #include <linux/mfd/da9055/pdata.h>
23 #include <linux/mfd/da9055/reg.h>
24 
25 #define DA9055_IRQ_NONKEY_MASK 0x01
26 #define DA9055_IRQ_ALM_MASK 0x02
27 #define DA9055_IRQ_TICK_MASK 0x04
28 #define DA9055_IRQ_ADC_MASK 0x08
29 #define DA9055_IRQ_BUCK_ILIM_MASK 0x08
30 
31 static bool da9055_register_readable(struct device *dev, unsigned int reg)
32 {
33  switch (reg) {
36  case DA9055_REG_EVENT_A:
37  case DA9055_REG_EVENT_B:
38  case DA9055_REG_EVENT_C:
42 
48 
49  case DA9055_REG_ADC_MAN:
58 
59  case DA9055_REG_COUNT_S:
61  case DA9055_REG_COUNT_H:
62  case DA9055_REG_COUNT_D:
64  case DA9055_REG_COUNT_Y:
65  case DA9055_REG_ALARM_H:
66  case DA9055_REG_ALARM_D:
69  case DA9055_REG_ALARM_Y:
70 
71  case DA9055_REG_GPIO0_1:
72  case DA9055_REG_GPIO2:
74 
86  case DA9055_REG_VBMEM_A:
87  case DA9055_REG_VLDO1_A:
88  case DA9055_REG_VLDO2_A:
89  case DA9055_REG_VLDO3_A:
90  case DA9055_REG_VLDO4_A:
91  case DA9055_REG_VLDO5_A:
92  case DA9055_REG_VLDO6_A:
94  case DA9055_REG_VBMEM_B:
95  case DA9055_REG_VLDO1_B:
96  case DA9055_REG_VLDO2_B:
97  case DA9055_REG_VLDO3_B:
98  case DA9055_REG_VLDO4_B:
99  case DA9055_REG_VLDO5_B:
100  case DA9055_REG_VLDO6_B:
101  return true;
102  default:
103  return false;
104  }
105 }
106 
107 static bool da9055_register_writeable(struct device *dev, unsigned int reg)
108 {
109  switch (reg) {
110  case DA9055_REG_STATUS_A:
111  case DA9055_REG_STATUS_B:
112  case DA9055_REG_EVENT_A:
113  case DA9055_REG_EVENT_B:
114  case DA9055_REG_EVENT_C:
118 
124 
125  case DA9055_REG_ADC_MAN:
126  case DA9055_REG_ADC_CONT:
127  case DA9055_REG_VSYS_MON:
130  case DA9055_REG_VSYS_RES:
134 
135  case DA9055_REG_COUNT_S:
136  case DA9055_REG_COUNT_MI:
137  case DA9055_REG_COUNT_H:
138  case DA9055_REG_COUNT_D:
139  case DA9055_REG_COUNT_MO:
140  case DA9055_REG_COUNT_Y:
141  case DA9055_REG_ALARM_H:
142  case DA9055_REG_ALARM_D:
143  case DA9055_REG_ALARM_MI:
144  case DA9055_REG_ALARM_MO:
145  case DA9055_REG_ALARM_Y:
146 
147  case DA9055_REG_GPIO0_1:
148  case DA9055_REG_GPIO2:
150 
159  case DA9055_REG_BUCK_LIM:
161  case DA9055_REG_VBCORE_A:
162  case DA9055_REG_VBMEM_A:
163  case DA9055_REG_VLDO1_A:
164  case DA9055_REG_VLDO2_A:
165  case DA9055_REG_VLDO3_A:
166  case DA9055_REG_VLDO4_A:
167  case DA9055_REG_VLDO5_A:
168  case DA9055_REG_VLDO6_A:
169  case DA9055_REG_VBCORE_B:
170  case DA9055_REG_VBMEM_B:
171  case DA9055_REG_VLDO1_B:
172  case DA9055_REG_VLDO2_B:
173  case DA9055_REG_VLDO3_B:
174  case DA9055_REG_VLDO4_B:
175  case DA9055_REG_VLDO5_B:
176  case DA9055_REG_VLDO6_B:
177  return true;
178  default:
179  return false;
180  }
181 }
182 
183 static bool da9055_register_volatile(struct device *dev, unsigned int reg)
184 {
185  switch (reg) {
186  case DA9055_REG_STATUS_A:
187  case DA9055_REG_STATUS_B:
188  case DA9055_REG_EVENT_A:
189  case DA9055_REG_EVENT_B:
190  case DA9055_REG_EVENT_C:
191 
194 
195  case DA9055_REG_ADC_MAN:
198  case DA9055_REG_VSYS_RES:
202 
203  case DA9055_REG_COUNT_S:
204  case DA9055_REG_COUNT_MI:
205  case DA9055_REG_COUNT_H:
206  case DA9055_REG_COUNT_D:
207  case DA9055_REG_COUNT_MO:
208  case DA9055_REG_COUNT_Y:
209  case DA9055_REG_ALARM_MI:
210 
219  return true;
220  default:
221  return false;
222  }
223 }
224 
225 static struct regmap_irq da9055_irqs[] = {
226  [DA9055_IRQ_NONKEY] = {
227  .reg_offset = 0,
228  .mask = DA9055_IRQ_NONKEY_MASK,
229  },
230  [DA9055_IRQ_ALARM] = {
231  .reg_offset = 0,
232  .mask = DA9055_IRQ_ALM_MASK,
233  },
234  [DA9055_IRQ_TICK] = {
235  .reg_offset = 0,
236  .mask = DA9055_IRQ_TICK_MASK,
237  },
238  [DA9055_IRQ_HWMON] = {
239  .reg_offset = 0,
240  .mask = DA9055_IRQ_ADC_MASK,
241  },
243  .reg_offset = 1,
245  },
246 };
247 
248 struct regmap_config da9055_regmap_config = {
249  .reg_bits = 8,
250  .val_bits = 8,
251 
252  .cache_type = REGCACHE_RBTREE,
253 
254  .max_register = DA9055_MAX_REGISTER_CNT,
255  .readable_reg = da9055_register_readable,
256  .writeable_reg = da9055_register_writeable,
257  .volatile_reg = da9055_register_volatile,
258 };
259 EXPORT_SYMBOL_GPL(da9055_regmap_config);
260 
261 static struct resource da9055_onkey_resource = {
262  .name = "ONKEY",
263  .start = DA9055_IRQ_NONKEY,
264  .end = DA9055_IRQ_NONKEY,
265  .flags = IORESOURCE_IRQ,
266 };
267 
268 static struct resource da9055_rtc_resource[] = {
269  {
270  .name = "ALM",
271  .start = DA9055_IRQ_ALARM,
272  .end = DA9055_IRQ_ALARM,
273  .flags = IORESOURCE_IRQ,
274  },
275  {
276  .name = "TICK",
277  .start = DA9055_IRQ_TICK,
278  .end = DA9055_IRQ_TICK,
279  .flags = IORESOURCE_IRQ,
280  },
281 };
282 
283 static struct resource da9055_hwmon_resource = {
284  .name = "HWMON",
285  .start = DA9055_IRQ_HWMON,
286  .end = DA9055_IRQ_HWMON,
287  .flags = IORESOURCE_IRQ,
288 };
289 
290 static struct resource da9055_ld05_6_resource = {
291  .name = "REGULATOR",
292  .start = DA9055_IRQ_REGULATOR,
293  .end = DA9055_IRQ_REGULATOR,
294  .flags = IORESOURCE_IRQ,
295 };
296 
297 static struct mfd_cell da9055_devs[] = {
298  {
299  .of_compatible = "dialog,da9055-gpio",
300  .name = "da9055-gpio",
301  },
302  {
303  .of_compatible = "dialog,da9055-regulator",
304  .name = "da9055-regulator",
305  .id = 1,
306  },
307  {
308  .of_compatible = "dialog,da9055-regulator",
309  .name = "da9055-regulator",
310  .id = 2,
311  },
312  {
313  .of_compatible = "dialog,da9055-regulator",
314  .name = "da9055-regulator",
315  .id = 3,
316  },
317  {
318  .of_compatible = "dialog,da9055-regulator",
319  .name = "da9055-regulator",
320  .id = 4,
321  },
322  {
323  .of_compatible = "dialog,da9055-regulator",
324  .name = "da9055-regulator",
325  .id = 5,
326  },
327  {
328  .of_compatible = "dialog,da9055-regulator",
329  .name = "da9055-regulator",
330  .id = 6,
331  },
332  {
333  .of_compatible = "dialog,da9055-regulator",
334  .name = "da9055-regulator",
335  .id = 7,
336  .resources = &da9055_ld05_6_resource,
337  .num_resources = 1,
338  },
339  {
340  .of_compatible = "dialog,da9055-regulator",
341  .name = "da9055-regulator",
342  .resources = &da9055_ld05_6_resource,
343  .num_resources = 1,
344  .id = 8,
345  },
346  {
347  .of_compatible = "dialog,da9055-onkey",
348  .name = "da9055-onkey",
349  .resources = &da9055_onkey_resource,
350  .num_resources = 1,
351  },
352  {
353  .of_compatible = "dialog,da9055-rtc",
354  .name = "da9055-rtc",
355  .resources = da9055_rtc_resource,
356  .num_resources = ARRAY_SIZE(da9055_rtc_resource),
357  },
358  {
359  .of_compatible = "dialog,da9055-hwmon",
360  .name = "da9055-hwmon",
361  .resources = &da9055_hwmon_resource,
362  .num_resources = 1,
363  },
364  {
365  .of_compatible = "dialog,da9055-watchdog",
366  .name = "da9055-watchdog",
367  },
368 };
369 
370 static struct regmap_irq_chip da9055_regmap_irq_chip = {
371  .name = "da9055_irq",
372  .status_base = DA9055_REG_EVENT_A,
373  .mask_base = DA9055_REG_IRQ_MASK_A,
374  .ack_base = DA9055_REG_EVENT_A,
375  .num_regs = 3,
376  .irqs = da9055_irqs,
377  .num_irqs = ARRAY_SIZE(da9055_irqs),
378 };
379 
381 {
382  struct da9055_pdata *pdata = da9055->dev->platform_data;
383  int ret;
384 
385  if (pdata && pdata->init != NULL)
386  pdata->init(da9055);
387 
388  if (!pdata || !pdata->irq_base)
389  da9055->irq_base = -1;
390  else
391  da9055->irq_base = pdata->irq_base;
392 
393  ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
395  da9055->irq_base, &da9055_regmap_irq_chip,
396  &da9055->irq_data);
397  if (ret < 0)
398  return ret;
399 
400  da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
401 
402  ret = mfd_add_devices(da9055->dev, -1,
403  da9055_devs, ARRAY_SIZE(da9055_devs),
404  NULL, da9055->irq_base, NULL);
405  if (ret)
406  goto err;
407 
408  return 0;
409 
410 err:
411  mfd_remove_devices(da9055->dev);
412  return ret;
413 }
414 
416 {
417  regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
418  mfd_remove_devices(da9055->dev);
419 }
420 
421 MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
422 MODULE_LICENSE("GPL");
423 MODULE_AUTHOR("David Dajun Chen <[email protected]>");