Commit a0e08b8606f3c0722b235a09b537264e5b14f748

Authored by Krystian Garbaciak
Committed by Samuel Ortiz
1 parent 8e685483b0

mfd: da9063: Add IRQ support

This patch adds a regmap irqchip for DA9063 IRQs. It depends on

  git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git tags/regmap-irq-ack-mask

Signed-off-by: Krystian Garbaciak <krystian.garbaciak@diasemi.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Mark Brown <broonie@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

Showing 4 changed files with 288 additions and 1 deletions Side-by-side Diff

drivers/mfd/Makefile
... ... @@ -107,7 +107,7 @@
107 107 da9055-objs := da9055-core.o da9055-i2c.o
108 108 obj-$(CONFIG_MFD_DA9055) += da9055.o
109 109  
110   -da9063-objs := da9063-core.o da9063-i2c.o
  110 +da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o
111 111 obj-$(CONFIG_MFD_DA9063) += da9063.o
112 112  
113 113 obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
drivers/mfd/da9063-core.c
... ... @@ -34,9 +34,52 @@
34 34 #include <linux/uaccess.h>
35 35  
36 36  
  37 +static struct resource da9063_regulators_resources[] = {
  38 + {
  39 + .name = "LDO_LIM",
  40 + .start = DA9063_IRQ_LDO_LIM,
  41 + .end = DA9063_IRQ_LDO_LIM,
  42 + .flags = IORESOURCE_IRQ,
  43 + },
  44 +};
  45 +
  46 +static struct resource da9063_rtc_resources[] = {
  47 + {
  48 + .name = "ALARM",
  49 + .start = DA9063_IRQ_ALARM,
  50 + .end = DA9063_IRQ_ALARM,
  51 + .flags = IORESOURCE_IRQ,
  52 + },
  53 + {
  54 + .name = "TICK",
  55 + .start = DA9063_IRQ_TICK,
  56 + .end = DA9063_IRQ_TICK,
  57 + .flags = IORESOURCE_IRQ,
  58 + }
  59 +};
  60 +
  61 +static struct resource da9063_onkey_resources[] = {
  62 + {
  63 + .start = DA9063_IRQ_ONKEY,
  64 + .end = DA9063_IRQ_ONKEY,
  65 + .flags = IORESOURCE_IRQ,
  66 + },
  67 +};
  68 +
  69 +static struct resource da9063_hwmon_resources[] = {
  70 + {
  71 + .start = DA9063_IRQ_ADC_RDY,
  72 + .end = DA9063_IRQ_ADC_RDY,
  73 + .flags = IORESOURCE_IRQ,
  74 + },
  75 +};
  76 +
  77 +
37 78 static struct mfd_cell da9063_devs[] = {
38 79 {
39 80 .name = DA9063_DRVNAME_REGULATORS,
  81 + .num_resources = ARRAY_SIZE(da9063_regulators_resources),
  82 + .resources = da9063_regulators_resources,
40 83 },
41 84 {
42 85 .name = DA9063_DRVNAME_LEDS,
43 86  
44 87  
... ... @@ -46,12 +89,18 @@
46 89 },
47 90 {
48 91 .name = DA9063_DRVNAME_HWMON,
  92 + .num_resources = ARRAY_SIZE(da9063_hwmon_resources),
  93 + .resources = da9063_hwmon_resources,
49 94 },
50 95 {
51 96 .name = DA9063_DRVNAME_ONKEY,
  97 + .num_resources = ARRAY_SIZE(da9063_onkey_resources),
  98 + .resources = da9063_onkey_resources,
52 99 },
53 100 {
54 101 .name = DA9063_DRVNAME_RTC,
  102 + .num_resources = ARRAY_SIZE(da9063_rtc_resources),
  103 + .resources = da9063_rtc_resources,
55 104 },
56 105 {
57 106 .name = DA9063_DRVNAME_VIBRATION,
... ... @@ -110,6 +159,12 @@
110 159 "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n",
111 160 model, revision);
112 161  
  162 + ret = da9063_irq_init(da9063);
  163 + if (ret) {
  164 + dev_err(da9063->dev, "Cannot initialize interrupts.\n");
  165 + return ret;
  166 + }
  167 +
113 168 ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
114 169 ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
115 170 NULL);
... ... @@ -122,6 +177,7 @@
122 177 void da9063_device_exit(struct da9063 *da9063)
123 178 {
124 179 mfd_remove_devices(da9063->dev);
  180 + da9063_irq_exit(da9063);
125 181 }
126 182  
127 183 MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
drivers/mfd/da9063-irq.c
  1 +/* da9063-irq.c: Interrupts support for Dialog DA9063
  2 + *
  3 + * Copyright 2012 Dialog Semiconductor Ltd.
  4 + * Copyright 2013 Philipp Zabel, Pengutronix
  5 + *
  6 + * Author: Michal Hajduk <michal.hajduk@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 +
  15 +#include <linux/kernel.h>
  16 +#include <linux/module.h>
  17 +#include <linux/irq.h>
  18 +#include <linux/mfd/core.h>
  19 +#include <linux/interrupt.h>
  20 +#include <linux/regmap.h>
  21 +#include <linux/mfd/da9063/core.h>
  22 +#include <linux/mfd/da9063/pdata.h>
  23 +
  24 +#define DA9063_REG_EVENT_A_OFFSET 0
  25 +#define DA9063_REG_EVENT_B_OFFSET 1
  26 +#define DA9063_REG_EVENT_C_OFFSET 2
  27 +#define DA9063_REG_EVENT_D_OFFSET 3
  28 +#define EVENTS_BUF_LEN 4
  29 +
  30 +static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 };
  31 +
  32 +struct da9063_irq_data {
  33 + u16 reg;
  34 + u8 mask;
  35 +};
  36 +
  37 +static struct regmap_irq da9063_irqs[] = {
  38 + /* DA9063 event A register */
  39 + [DA9063_IRQ_ONKEY] = {
  40 + .reg_offset = DA9063_REG_EVENT_A_OFFSET,
  41 + .mask = DA9063_M_ONKEY,
  42 + },
  43 + [DA9063_IRQ_ALARM] = {
  44 + .reg_offset = DA9063_REG_EVENT_A_OFFSET,
  45 + .mask = DA9063_M_ALARM,
  46 + },
  47 + [DA9063_IRQ_TICK] = {
  48 + .reg_offset = DA9063_REG_EVENT_A_OFFSET,
  49 + .mask = DA9063_M_TICK,
  50 + },
  51 + [DA9063_IRQ_ADC_RDY] = {
  52 + .reg_offset = DA9063_REG_EVENT_A_OFFSET,
  53 + .mask = DA9063_M_ADC_RDY,
  54 + },
  55 + [DA9063_IRQ_SEQ_RDY] = {
  56 + .reg_offset = DA9063_REG_EVENT_A_OFFSET,
  57 + .mask = DA9063_M_SEQ_RDY,
  58 + },
  59 + /* DA9063 event B register */
  60 + [DA9063_IRQ_WAKE] = {
  61 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  62 + .mask = DA9063_M_WAKE,
  63 + },
  64 + [DA9063_IRQ_TEMP] = {
  65 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  66 + .mask = DA9063_M_TEMP,
  67 + },
  68 + [DA9063_IRQ_COMP_1V2] = {
  69 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  70 + .mask = DA9063_M_COMP_1V2,
  71 + },
  72 + [DA9063_IRQ_LDO_LIM] = {
  73 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  74 + .mask = DA9063_M_LDO_LIM,
  75 + },
  76 + [DA9063_IRQ_REG_UVOV] = {
  77 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  78 + .mask = DA9063_M_UVOV,
  79 + },
  80 + [DA9063_IRQ_VDD_MON] = {
  81 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  82 + .mask = DA9063_M_VDD_MON,
  83 + },
  84 + [DA9063_IRQ_WARN] = {
  85 + .reg_offset = DA9063_REG_EVENT_B_OFFSET,
  86 + .mask = DA9063_M_VDD_WARN,
  87 + },
  88 + /* DA9063 event C register */
  89 + [DA9063_IRQ_GPI0] = {
  90 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  91 + .mask = DA9063_M_GPI0,
  92 + },
  93 + [DA9063_IRQ_GPI1] = {
  94 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  95 + .mask = DA9063_M_GPI1,
  96 + },
  97 + [DA9063_IRQ_GPI2] = {
  98 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  99 + .mask = DA9063_M_GPI2,
  100 + },
  101 + [DA9063_IRQ_GPI3] = {
  102 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  103 + .mask = DA9063_M_GPI3,
  104 + },
  105 + [DA9063_IRQ_GPI4] = {
  106 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  107 + .mask = DA9063_M_GPI4,
  108 + },
  109 + [DA9063_IRQ_GPI5] = {
  110 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  111 + .mask = DA9063_M_GPI5,
  112 + },
  113 + [DA9063_IRQ_GPI6] = {
  114 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  115 + .mask = DA9063_M_GPI6,
  116 + },
  117 + [DA9063_IRQ_GPI7] = {
  118 + .reg_offset = DA9063_REG_EVENT_C_OFFSET,
  119 + .mask = DA9063_M_GPI7,
  120 + },
  121 + /* DA9063 event D register */
  122 + [DA9063_IRQ_GPI8] = {
  123 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  124 + .mask = DA9063_M_GPI8,
  125 + },
  126 + [DA9063_IRQ_GPI9] = {
  127 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  128 + .mask = DA9063_M_GPI9,
  129 + },
  130 + [DA9063_IRQ_GPI10] = {
  131 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  132 + .mask = DA9063_M_GPI10,
  133 + },
  134 + [DA9063_IRQ_GPI11] = {
  135 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  136 + .mask = DA9063_M_GPI11,
  137 + },
  138 + [DA9063_IRQ_GPI12] = {
  139 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  140 + .mask = DA9063_M_GPI12,
  141 + },
  142 + [DA9063_IRQ_GPI13] = {
  143 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  144 + .mask = DA9063_M_GPI13,
  145 + },
  146 + [DA9063_IRQ_GPI14] = {
  147 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  148 + .mask = DA9063_M_GPI14,
  149 + },
  150 + [DA9063_IRQ_GPI15] = {
  151 + .reg_offset = DA9063_REG_EVENT_D_OFFSET,
  152 + .mask = DA9063_M_GPI15,
  153 + },
  154 +};
  155 +
  156 +static struct regmap_irq_chip da9063_irq_chip = {
  157 + .name = "da9063-irq",
  158 + .irqs = da9063_irqs,
  159 + .num_irqs = DA9063_NUM_IRQ,
  160 +
  161 + .num_regs = 4,
  162 + .status_base = DA9063_REG_EVENT_A,
  163 + .mask_base = DA9063_REG_IRQ_MASK_A,
  164 + .ack_base = DA9063_REG_EVENT_A,
  165 + .init_ack_masked = true,
  166 +};
  167 +
  168 +int da9063_irq_init(struct da9063 *da9063)
  169 +{
  170 + int ret;
  171 +
  172 + if (!da9063->chip_irq) {
  173 + dev_err(da9063->dev, "No IRQ configured\n");
  174 + return -EINVAL;
  175 + }
  176 +
  177 + ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq,
  178 + IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
  179 + da9063->irq_base, &da9063_irq_chip,
  180 + &da9063->regmap_irq);
  181 + if (ret) {
  182 + dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
  183 + da9063->chip_irq, ret);
  184 + return ret;
  185 + }
  186 +
  187 + return 0;
  188 +}
  189 +
  190 +void da9063_irq_exit(struct da9063 *da9063)
  191 +{
  192 + regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
  193 +}
include/linux/mfd/da9063/core.h
... ... @@ -33,6 +33,41 @@
33 33 PMIC_DA9063 = 0x61,
34 34 };
35 35  
  36 +/* Interrupts */
  37 +enum da9063_irqs {
  38 + DA9063_IRQ_ONKEY = 0,
  39 + DA9063_IRQ_ALARM,
  40 + DA9063_IRQ_TICK,
  41 + DA9063_IRQ_ADC_RDY,
  42 + DA9063_IRQ_SEQ_RDY,
  43 + DA9063_IRQ_WAKE,
  44 + DA9063_IRQ_TEMP,
  45 + DA9063_IRQ_COMP_1V2,
  46 + DA9063_IRQ_LDO_LIM,
  47 + DA9063_IRQ_REG_UVOV,
  48 + DA9063_IRQ_VDD_MON,
  49 + DA9063_IRQ_WARN,
  50 + DA9063_IRQ_GPI0,
  51 + DA9063_IRQ_GPI1,
  52 + DA9063_IRQ_GPI2,
  53 + DA9063_IRQ_GPI3,
  54 + DA9063_IRQ_GPI4,
  55 + DA9063_IRQ_GPI5,
  56 + DA9063_IRQ_GPI6,
  57 + DA9063_IRQ_GPI7,
  58 + DA9063_IRQ_GPI8,
  59 + DA9063_IRQ_GPI9,
  60 + DA9063_IRQ_GPI10,
  61 + DA9063_IRQ_GPI11,
  62 + DA9063_IRQ_GPI12,
  63 + DA9063_IRQ_GPI13,
  64 + DA9063_IRQ_GPI14,
  65 + DA9063_IRQ_GPI15,
  66 +};
  67 +
  68 +#define DA9063_IRQ_BASE_OFFSET 0
  69 +#define DA9063_NUM_IRQ (DA9063_IRQ_GPI15 + 1 - DA9063_IRQ_BASE_OFFSET)
  70 +
36 71 struct da9063 {
37 72 /* Device */
38 73 struct device *dev;
39 74  
40 75  
... ... @@ -46,11 +81,14 @@
46 81 /* Interrupts */
47 82 int chip_irq;
48 83 unsigned int irq_base;
  84 + struct regmap_irq_chip_data *regmap_irq;
49 85 };
50 86  
51 87 int da9063_device_init(struct da9063 *da9063, unsigned int irq);
  88 +int da9063_irq_init(struct da9063 *da9063);
52 89  
53 90 void da9063_device_exit(struct da9063 *da9063);
  91 +void da9063_irq_exit(struct da9063 *da9063);
54 92  
55 93 #endif /* __MFD_DA9063_CORE_H__ */