diff options
author | Krystian Garbaciak <krystian.garbaciak@diasemi.com> | 2013-07-29 13:00:44 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-08-19 21:16:00 -0400 |
commit | a0e08b8606f3c0722b235a09b537264e5b14f748 (patch) | |
tree | 693a33759ad3d21937f5db74de2d3e99e99bf171 | |
parent | 8e685483b0ba17fe08cfc36fb86b3688a24b2090 (diff) |
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>
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/da9063-core.c | 56 | ||||
-rw-r--r-- | drivers/mfd/da9063-irq.c | 193 | ||||
-rw-r--r-- | include/linux/mfd/da9063/core.h | 38 |
4 files changed, 288 insertions, 1 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0bb84d59f3fa..15b905c6553c 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -107,7 +107,7 @@ obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o | |||
107 | da9055-objs := da9055-core.o da9055-i2c.o | 107 | da9055-objs := da9055-core.o da9055-i2c.o |
108 | obj-$(CONFIG_MFD_DA9055) += da9055.o | 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 | obj-$(CONFIG_MFD_DA9063) += da9063.o | 111 | obj-$(CONFIG_MFD_DA9063) += da9063.o |
112 | 112 | ||
113 | obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o | 113 | obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o |
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index 29f3ed1f076c..c9cf8d988406 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c | |||
@@ -34,9 +34,52 @@ | |||
34 | #include <linux/uaccess.h> | 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 | static struct mfd_cell da9063_devs[] = { | 78 | static struct mfd_cell da9063_devs[] = { |
38 | { | 79 | { |
39 | .name = DA9063_DRVNAME_REGULATORS, | 80 | .name = DA9063_DRVNAME_REGULATORS, |
81 | .num_resources = ARRAY_SIZE(da9063_regulators_resources), | ||
82 | .resources = da9063_regulators_resources, | ||
40 | }, | 83 | }, |
41 | { | 84 | { |
42 | .name = DA9063_DRVNAME_LEDS, | 85 | .name = DA9063_DRVNAME_LEDS, |
@@ -46,12 +89,18 @@ static struct mfd_cell da9063_devs[] = { | |||
46 | }, | 89 | }, |
47 | { | 90 | { |
48 | .name = DA9063_DRVNAME_HWMON, | 91 | .name = DA9063_DRVNAME_HWMON, |
92 | .num_resources = ARRAY_SIZE(da9063_hwmon_resources), | ||
93 | .resources = da9063_hwmon_resources, | ||
49 | }, | 94 | }, |
50 | { | 95 | { |
51 | .name = DA9063_DRVNAME_ONKEY, | 96 | .name = DA9063_DRVNAME_ONKEY, |
97 | .num_resources = ARRAY_SIZE(da9063_onkey_resources), | ||
98 | .resources = da9063_onkey_resources, | ||
52 | }, | 99 | }, |
53 | { | 100 | { |
54 | .name = DA9063_DRVNAME_RTC, | 101 | .name = DA9063_DRVNAME_RTC, |
102 | .num_resources = ARRAY_SIZE(da9063_rtc_resources), | ||
103 | .resources = da9063_rtc_resources, | ||
55 | }, | 104 | }, |
56 | { | 105 | { |
57 | .name = DA9063_DRVNAME_VIBRATION, | 106 | .name = DA9063_DRVNAME_VIBRATION, |
@@ -110,6 +159,12 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) | |||
110 | "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n", | 159 | "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n", |
111 | model, revision); | 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 | ret = mfd_add_devices(da9063->dev, -1, da9063_devs, | 168 | ret = mfd_add_devices(da9063->dev, -1, da9063_devs, |
114 | ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base, | 169 | ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base, |
115 | NULL); | 170 | NULL); |
@@ -122,6 +177,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) | |||
122 | void da9063_device_exit(struct da9063 *da9063) | 177 | void da9063_device_exit(struct da9063 *da9063) |
123 | { | 178 | { |
124 | mfd_remove_devices(da9063->dev); | 179 | mfd_remove_devices(da9063->dev); |
180 | da9063_irq_exit(da9063); | ||
125 | } | 181 | } |
126 | 182 | ||
127 | MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); | 183 | MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); |
diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c new file mode 100644 index 000000000000..822922602ce9 --- /dev/null +++ b/drivers/mfd/da9063-irq.c | |||
@@ -0,0 +1,193 @@ | |||
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 | } | ||
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index ec2fd2aa24ae..2d2a0af675fd 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h | |||
@@ -33,6 +33,41 @@ enum da9063_models { | |||
33 | PMIC_DA9063 = 0x61, | 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 | struct da9063 { | 71 | struct da9063 { |
37 | /* Device */ | 72 | /* Device */ |
38 | struct device *dev; | 73 | struct device *dev; |
@@ -46,10 +81,13 @@ struct da9063 { | |||
46 | /* Interrupts */ | 81 | /* Interrupts */ |
47 | int chip_irq; | 82 | int chip_irq; |
48 | unsigned int irq_base; | 83 | unsigned int irq_base; |
84 | struct regmap_irq_chip_data *regmap_irq; | ||
49 | }; | 85 | }; |
50 | 86 | ||
51 | int da9063_device_init(struct da9063 *da9063, unsigned int irq); | 87 | int da9063_device_init(struct da9063 *da9063, unsigned int irq); |
88 | int da9063_irq_init(struct da9063 *da9063); | ||
52 | 89 | ||
53 | void da9063_device_exit(struct da9063 *da9063); | 90 | void da9063_device_exit(struct da9063 *da9063); |
91 | void da9063_irq_exit(struct da9063 *da9063); | ||
54 | 92 | ||
55 | #endif /* __MFD_DA9063_CORE_H__ */ | 93 | #endif /* __MFD_DA9063_CORE_H__ */ |