diff options
author | Sangbeom Kim <sbkim73@samsung.com> | 2012-07-11 08:08:11 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-07-16 08:31:59 -0400 |
commit | 6445b84abf91549d8568fb5d9155447e6dba86cc (patch) | |
tree | 07b8341d4360f80630146cb21c171d6e518202d9 | |
parent | 9b6d1343068d87f06c8dabf6628a30ea38082eb0 (diff) |
mfd: Add s2mps11 irq driver
This patch support irq handling driver for s2mps11.
As this patch use regmap_irq, s5m8767 and s5m8763 are modified with
regmap_irq.
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/mfd/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mfd/sec-irq.c | 477 | ||||
-rw-r--r-- | include/linux/mfd/samsung/core.h | 2 | ||||
-rw-r--r-- | include/linux/mfd/samsung/irq.h | 42 |
4 files changed, 193 insertions, 329 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index bad68f82772a..3c263a57b760 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -513,6 +513,7 @@ config MFD_SEC_CORE | |||
513 | depends on I2C=y && GENERIC_HARDIRQS | 513 | depends on I2C=y && GENERIC_HARDIRQS |
514 | select MFD_CORE | 514 | select MFD_CORE |
515 | select REGMAP_I2C | 515 | select REGMAP_I2C |
516 | select REGMAP_IRQ | ||
516 | help | 517 | help |
517 | Support for the Samsung Electronics MFD series. | 518 | Support for the Samsung Electronics MFD series. |
518 | This driver provides common support for accessing the device, | 519 | This driver provides common support for accessing the device, |
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index da5ec5b2ecce..c901fa50fea1 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c | |||
@@ -14,351 +14,260 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/regmap.h> | ||
18 | |||
17 | #include <linux/mfd/samsung/core.h> | 19 | #include <linux/mfd/samsung/core.h> |
18 | #include <linux/mfd/samsung/irq.h> | 20 | #include <linux/mfd/samsung/irq.h> |
21 | #include <linux/mfd/samsung/s2mps11.h> | ||
19 | #include <linux/mfd/samsung/s5m8763.h> | 22 | #include <linux/mfd/samsung/s5m8763.h> |
20 | #include <linux/mfd/samsung/s5m8767.h> | 23 | #include <linux/mfd/samsung/s5m8767.h> |
21 | 24 | ||
22 | struct sec_irq_data { | 25 | static struct regmap_irq s2mps11_irqs[] = { |
23 | int reg; | 26 | [S2MPS11_IRQ_PWRONF] = { |
24 | int mask; | 27 | .reg_offset = 1, |
28 | .mask = S2MPS11_IRQ_PWRONF_MASK, | ||
29 | }, | ||
30 | [S2MPS11_IRQ_PWRONR] = { | ||
31 | .reg_offset = 1, | ||
32 | .mask = S2MPS11_IRQ_PWRONR_MASK, | ||
33 | }, | ||
34 | [S2MPS11_IRQ_JIGONBF] = { | ||
35 | .reg_offset = 1, | ||
36 | .mask = S2MPS11_IRQ_JIGONBF_MASK, | ||
37 | }, | ||
38 | [S2MPS11_IRQ_JIGONBR] = { | ||
39 | .reg_offset = 1, | ||
40 | .mask = S2MPS11_IRQ_JIGONBR_MASK, | ||
41 | }, | ||
42 | [S2MPS11_IRQ_ACOKBF] = { | ||
43 | .reg_offset = 1, | ||
44 | .mask = S2MPS11_IRQ_ACOKBF_MASK, | ||
45 | }, | ||
46 | [S2MPS11_IRQ_ACOKBR] = { | ||
47 | .reg_offset = 1, | ||
48 | .mask = S2MPS11_IRQ_ACOKBR_MASK, | ||
49 | }, | ||
50 | [S2MPS11_IRQ_PWRON1S] = { | ||
51 | .reg_offset = 1, | ||
52 | .mask = S2MPS11_IRQ_PWRON1S_MASK, | ||
53 | }, | ||
54 | [S2MPS11_IRQ_MRB] = { | ||
55 | .reg_offset = 1, | ||
56 | .mask = S2MPS11_IRQ_MRB_MASK, | ||
57 | }, | ||
58 | [S2MPS11_IRQ_RTC60S] = { | ||
59 | .reg_offset = 2, | ||
60 | .mask = S2MPS11_IRQ_RTC60S_MASK, | ||
61 | }, | ||
62 | [S2MPS11_IRQ_RTCA1] = { | ||
63 | .reg_offset = 2, | ||
64 | .mask = S2MPS11_IRQ_RTCA1_MASK, | ||
65 | }, | ||
66 | [S2MPS11_IRQ_RTCA2] = { | ||
67 | .reg_offset = 2, | ||
68 | .mask = S2MPS11_IRQ_RTCA2_MASK, | ||
69 | }, | ||
70 | [S2MPS11_IRQ_SMPL] = { | ||
71 | .reg_offset = 2, | ||
72 | .mask = S2MPS11_IRQ_SMPL_MASK, | ||
73 | }, | ||
74 | [S2MPS11_IRQ_RTC1S] = { | ||
75 | .reg_offset = 2, | ||
76 | .mask = S2MPS11_IRQ_RTC1S_MASK, | ||
77 | }, | ||
78 | [S2MPS11_IRQ_WTSR] = { | ||
79 | .reg_offset = 2, | ||
80 | .mask = S2MPS11_IRQ_WTSR_MASK, | ||
81 | }, | ||
82 | [S2MPS11_IRQ_INT120C] = { | ||
83 | .reg_offset = 3, | ||
84 | .mask = S2MPS11_IRQ_INT120C_MASK, | ||
85 | }, | ||
86 | [S2MPS11_IRQ_INT140C] = { | ||
87 | .reg_offset = 3, | ||
88 | .mask = S2MPS11_IRQ_INT140C_MASK, | ||
89 | }, | ||
25 | }; | 90 | }; |
26 | 91 | ||
27 | static struct sec_irq_data s5m8767_irqs[] = { | 92 | |
93 | static struct regmap_irq s5m8767_irqs[] = { | ||
28 | [S5M8767_IRQ_PWRR] = { | 94 | [S5M8767_IRQ_PWRR] = { |
29 | .reg = 1, | 95 | .reg_offset = 1, |
30 | .mask = S5M8767_IRQ_PWRR_MASK, | 96 | .mask = S5M8767_IRQ_PWRR_MASK, |
31 | }, | 97 | }, |
32 | [S5M8767_IRQ_PWRF] = { | 98 | [S5M8767_IRQ_PWRF] = { |
33 | .reg = 1, | 99 | .reg_offset = 1, |
34 | .mask = S5M8767_IRQ_PWRF_MASK, | 100 | .mask = S5M8767_IRQ_PWRF_MASK, |
35 | }, | 101 | }, |
36 | [S5M8767_IRQ_PWR1S] = { | 102 | [S5M8767_IRQ_PWR1S] = { |
37 | .reg = 1, | 103 | .reg_offset = 1, |
38 | .mask = S5M8767_IRQ_PWR1S_MASK, | 104 | .mask = S5M8767_IRQ_PWR1S_MASK, |
39 | }, | 105 | }, |
40 | [S5M8767_IRQ_JIGR] = { | 106 | [S5M8767_IRQ_JIGR] = { |
41 | .reg = 1, | 107 | .reg_offset = 1, |
42 | .mask = S5M8767_IRQ_JIGR_MASK, | 108 | .mask = S5M8767_IRQ_JIGR_MASK, |
43 | }, | 109 | }, |
44 | [S5M8767_IRQ_JIGF] = { | 110 | [S5M8767_IRQ_JIGF] = { |
45 | .reg = 1, | 111 | .reg_offset = 1, |
46 | .mask = S5M8767_IRQ_JIGF_MASK, | 112 | .mask = S5M8767_IRQ_JIGF_MASK, |
47 | }, | 113 | }, |
48 | [S5M8767_IRQ_LOWBAT2] = { | 114 | [S5M8767_IRQ_LOWBAT2] = { |
49 | .reg = 1, | 115 | .reg_offset = 1, |
50 | .mask = S5M8767_IRQ_LOWBAT2_MASK, | 116 | .mask = S5M8767_IRQ_LOWBAT2_MASK, |
51 | }, | 117 | }, |
52 | [S5M8767_IRQ_LOWBAT1] = { | 118 | [S5M8767_IRQ_LOWBAT1] = { |
53 | .reg = 1, | 119 | .reg_offset = 1, |
54 | .mask = S5M8767_IRQ_LOWBAT1_MASK, | 120 | .mask = S5M8767_IRQ_LOWBAT1_MASK, |
55 | }, | 121 | }, |
56 | [S5M8767_IRQ_MRB] = { | 122 | [S5M8767_IRQ_MRB] = { |
57 | .reg = 2, | 123 | .reg_offset = 2, |
58 | .mask = S5M8767_IRQ_MRB_MASK, | 124 | .mask = S5M8767_IRQ_MRB_MASK, |
59 | }, | 125 | }, |
60 | [S5M8767_IRQ_DVSOK2] = { | 126 | [S5M8767_IRQ_DVSOK2] = { |
61 | .reg = 2, | 127 | .reg_offset = 2, |
62 | .mask = S5M8767_IRQ_DVSOK2_MASK, | 128 | .mask = S5M8767_IRQ_DVSOK2_MASK, |
63 | }, | 129 | }, |
64 | [S5M8767_IRQ_DVSOK3] = { | 130 | [S5M8767_IRQ_DVSOK3] = { |
65 | .reg = 2, | 131 | .reg_offset = 2, |
66 | .mask = S5M8767_IRQ_DVSOK3_MASK, | 132 | .mask = S5M8767_IRQ_DVSOK3_MASK, |
67 | }, | 133 | }, |
68 | [S5M8767_IRQ_DVSOK4] = { | 134 | [S5M8767_IRQ_DVSOK4] = { |
69 | .reg = 2, | 135 | .reg_offset = 2, |
70 | .mask = S5M8767_IRQ_DVSOK4_MASK, | 136 | .mask = S5M8767_IRQ_DVSOK4_MASK, |
71 | }, | 137 | }, |
72 | [S5M8767_IRQ_RTC60S] = { | 138 | [S5M8767_IRQ_RTC60S] = { |
73 | .reg = 3, | 139 | .reg_offset = 3, |
74 | .mask = S5M8767_IRQ_RTC60S_MASK, | 140 | .mask = S5M8767_IRQ_RTC60S_MASK, |
75 | }, | 141 | }, |
76 | [S5M8767_IRQ_RTCA1] = { | 142 | [S5M8767_IRQ_RTCA1] = { |
77 | .reg = 3, | 143 | .reg_offset = 3, |
78 | .mask = S5M8767_IRQ_RTCA1_MASK, | 144 | .mask = S5M8767_IRQ_RTCA1_MASK, |
79 | }, | 145 | }, |
80 | [S5M8767_IRQ_RTCA2] = { | 146 | [S5M8767_IRQ_RTCA2] = { |
81 | .reg = 3, | 147 | .reg_offset = 3, |
82 | .mask = S5M8767_IRQ_RTCA2_MASK, | 148 | .mask = S5M8767_IRQ_RTCA2_MASK, |
83 | }, | 149 | }, |
84 | [S5M8767_IRQ_SMPL] = { | 150 | [S5M8767_IRQ_SMPL] = { |
85 | .reg = 3, | 151 | .reg_offset = 3, |
86 | .mask = S5M8767_IRQ_SMPL_MASK, | 152 | .mask = S5M8767_IRQ_SMPL_MASK, |
87 | }, | 153 | }, |
88 | [S5M8767_IRQ_RTC1S] = { | 154 | [S5M8767_IRQ_RTC1S] = { |
89 | .reg = 3, | 155 | .reg_offset = 3, |
90 | .mask = S5M8767_IRQ_RTC1S_MASK, | 156 | .mask = S5M8767_IRQ_RTC1S_MASK, |
91 | }, | 157 | }, |
92 | [S5M8767_IRQ_WTSR] = { | 158 | [S5M8767_IRQ_WTSR] = { |
93 | .reg = 3, | 159 | .reg_offset = 3, |
94 | .mask = S5M8767_IRQ_WTSR_MASK, | 160 | .mask = S5M8767_IRQ_WTSR_MASK, |
95 | }, | 161 | }, |
96 | }; | 162 | }; |
97 | 163 | ||
98 | static struct sec_irq_data s5m8763_irqs[] = { | 164 | static struct regmap_irq s5m8763_irqs[] = { |
99 | [S5M8763_IRQ_DCINF] = { | 165 | [S5M8763_IRQ_DCINF] = { |
100 | .reg = 1, | 166 | .reg_offset = 1, |
101 | .mask = S5M8763_IRQ_DCINF_MASK, | 167 | .mask = S5M8763_IRQ_DCINF_MASK, |
102 | }, | 168 | }, |
103 | [S5M8763_IRQ_DCINR] = { | 169 | [S5M8763_IRQ_DCINR] = { |
104 | .reg = 1, | 170 | .reg_offset = 1, |
105 | .mask = S5M8763_IRQ_DCINR_MASK, | 171 | .mask = S5M8763_IRQ_DCINR_MASK, |
106 | }, | 172 | }, |
107 | [S5M8763_IRQ_JIGF] = { | 173 | [S5M8763_IRQ_JIGF] = { |
108 | .reg = 1, | 174 | .reg_offset = 1, |
109 | .mask = S5M8763_IRQ_JIGF_MASK, | 175 | .mask = S5M8763_IRQ_JIGF_MASK, |
110 | }, | 176 | }, |
111 | [S5M8763_IRQ_JIGR] = { | 177 | [S5M8763_IRQ_JIGR] = { |
112 | .reg = 1, | 178 | .reg_offset = 1, |
113 | .mask = S5M8763_IRQ_JIGR_MASK, | 179 | .mask = S5M8763_IRQ_JIGR_MASK, |
114 | }, | 180 | }, |
115 | [S5M8763_IRQ_PWRONF] = { | 181 | [S5M8763_IRQ_PWRONF] = { |
116 | .reg = 1, | 182 | .reg_offset = 1, |
117 | .mask = S5M8763_IRQ_PWRONF_MASK, | 183 | .mask = S5M8763_IRQ_PWRONF_MASK, |
118 | }, | 184 | }, |
119 | [S5M8763_IRQ_PWRONR] = { | 185 | [S5M8763_IRQ_PWRONR] = { |
120 | .reg = 1, | 186 | .reg_offset = 1, |
121 | .mask = S5M8763_IRQ_PWRONR_MASK, | 187 | .mask = S5M8763_IRQ_PWRONR_MASK, |
122 | }, | 188 | }, |
123 | [S5M8763_IRQ_WTSREVNT] = { | 189 | [S5M8763_IRQ_WTSREVNT] = { |
124 | .reg = 2, | 190 | .reg_offset = 2, |
125 | .mask = S5M8763_IRQ_WTSREVNT_MASK, | 191 | .mask = S5M8763_IRQ_WTSREVNT_MASK, |
126 | }, | 192 | }, |
127 | [S5M8763_IRQ_SMPLEVNT] = { | 193 | [S5M8763_IRQ_SMPLEVNT] = { |
128 | .reg = 2, | 194 | .reg_offset = 2, |
129 | .mask = S5M8763_IRQ_SMPLEVNT_MASK, | 195 | .mask = S5M8763_IRQ_SMPLEVNT_MASK, |
130 | }, | 196 | }, |
131 | [S5M8763_IRQ_ALARM1] = { | 197 | [S5M8763_IRQ_ALARM1] = { |
132 | .reg = 2, | 198 | .reg_offset = 2, |
133 | .mask = S5M8763_IRQ_ALARM1_MASK, | 199 | .mask = S5M8763_IRQ_ALARM1_MASK, |
134 | }, | 200 | }, |
135 | [S5M8763_IRQ_ALARM0] = { | 201 | [S5M8763_IRQ_ALARM0] = { |
136 | .reg = 2, | 202 | .reg_offset = 2, |
137 | .mask = S5M8763_IRQ_ALARM0_MASK, | 203 | .mask = S5M8763_IRQ_ALARM0_MASK, |
138 | }, | 204 | }, |
139 | [S5M8763_IRQ_ONKEY1S] = { | 205 | [S5M8763_IRQ_ONKEY1S] = { |
140 | .reg = 3, | 206 | .reg_offset = 3, |
141 | .mask = S5M8763_IRQ_ONKEY1S_MASK, | 207 | .mask = S5M8763_IRQ_ONKEY1S_MASK, |
142 | }, | 208 | }, |
143 | [S5M8763_IRQ_TOPOFFR] = { | 209 | [S5M8763_IRQ_TOPOFFR] = { |
144 | .reg = 3, | 210 | .reg_offset = 3, |
145 | .mask = S5M8763_IRQ_TOPOFFR_MASK, | 211 | .mask = S5M8763_IRQ_TOPOFFR_MASK, |
146 | }, | 212 | }, |
147 | [S5M8763_IRQ_DCINOVPR] = { | 213 | [S5M8763_IRQ_DCINOVPR] = { |
148 | .reg = 3, | 214 | .reg_offset = 3, |
149 | .mask = S5M8763_IRQ_DCINOVPR_MASK, | 215 | .mask = S5M8763_IRQ_DCINOVPR_MASK, |
150 | }, | 216 | }, |
151 | [S5M8763_IRQ_CHGRSTF] = { | 217 | [S5M8763_IRQ_CHGRSTF] = { |
152 | .reg = 3, | 218 | .reg_offset = 3, |
153 | .mask = S5M8763_IRQ_CHGRSTF_MASK, | 219 | .mask = S5M8763_IRQ_CHGRSTF_MASK, |
154 | }, | 220 | }, |
155 | [S5M8763_IRQ_DONER] = { | 221 | [S5M8763_IRQ_DONER] = { |
156 | .reg = 3, | 222 | .reg_offset = 3, |
157 | .mask = S5M8763_IRQ_DONER_MASK, | 223 | .mask = S5M8763_IRQ_DONER_MASK, |
158 | }, | 224 | }, |
159 | [S5M8763_IRQ_CHGFAULT] = { | 225 | [S5M8763_IRQ_CHGFAULT] = { |
160 | .reg = 3, | 226 | .reg_offset = 3, |
161 | .mask = S5M8763_IRQ_CHGFAULT_MASK, | 227 | .mask = S5M8763_IRQ_CHGFAULT_MASK, |
162 | }, | 228 | }, |
163 | [S5M8763_IRQ_LOBAT1] = { | 229 | [S5M8763_IRQ_LOBAT1] = { |
164 | .reg = 4, | 230 | .reg_offset = 4, |
165 | .mask = S5M8763_IRQ_LOBAT1_MASK, | 231 | .mask = S5M8763_IRQ_LOBAT1_MASK, |
166 | }, | 232 | }, |
167 | [S5M8763_IRQ_LOBAT2] = { | 233 | [S5M8763_IRQ_LOBAT2] = { |
168 | .reg = 4, | 234 | .reg_offset = 4, |
169 | .mask = S5M8763_IRQ_LOBAT2_MASK, | 235 | .mask = S5M8763_IRQ_LOBAT2_MASK, |
170 | }, | 236 | }, |
171 | }; | 237 | }; |
172 | 238 | ||
173 | static inline struct sec_irq_data * | 239 | static struct regmap_irq_chip s2mps11_irq_chip = { |
174 | irq_to_s5m8767_irq(struct sec_pmic_dev *sec_pmic, int irq) | 240 | .name = "s2mps11", |
175 | { | 241 | .irqs = s2mps11_irqs, |
176 | return &s5m8767_irqs[irq - sec_pmic->irq_base]; | 242 | .num_irqs = ARRAY_SIZE(s2mps11_irqs), |
177 | } | 243 | .num_regs = 3, |
178 | 244 | .status_base = S2MPS11_REG_INT1, | |
179 | static void s5m8767_irq_lock(struct irq_data *data) | 245 | .mask_base = S2MPS11_REG_INT1M, |
180 | { | 246 | .ack_base = S2MPS11_REG_INT1, |
181 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | 247 | }; |
182 | |||
183 | mutex_lock(&sec_pmic->irqlock); | ||
184 | } | ||
185 | |||
186 | static void s5m8767_irq_sync_unlock(struct irq_data *data) | ||
187 | { | ||
188 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
189 | int i; | ||
190 | |||
191 | for (i = 0; i < ARRAY_SIZE(sec_pmic->irq_masks_cur); i++) { | ||
192 | if (sec_pmic->irq_masks_cur[i] != sec_pmic->irq_masks_cache[i]) { | ||
193 | sec_pmic->irq_masks_cache[i] = sec_pmic->irq_masks_cur[i]; | ||
194 | sec_reg_write(sec_pmic, S5M8767_REG_INT1M + i, | ||
195 | sec_pmic->irq_masks_cur[i]); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | mutex_unlock(&sec_pmic->irqlock); | ||
200 | } | ||
201 | |||
202 | static void s5m8767_irq_unmask(struct irq_data *data) | ||
203 | { | ||
204 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
205 | struct sec_irq_data *irq_data = irq_to_s5m8767_irq(sec_pmic, | ||
206 | data->irq); | ||
207 | |||
208 | sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | ||
209 | } | ||
210 | |||
211 | static void s5m8767_irq_mask(struct irq_data *data) | ||
212 | { | ||
213 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
214 | struct sec_irq_data *irq_data = irq_to_s5m8767_irq(sec_pmic, | ||
215 | data->irq); | ||
216 | |||
217 | sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; | ||
218 | } | ||
219 | 248 | ||
220 | static struct irq_chip s5m8767_irq_chip = { | 249 | static struct regmap_irq_chip s5m8767_irq_chip = { |
221 | .name = "s5m8767", | 250 | .name = "s5m8767", |
222 | .irq_bus_lock = s5m8767_irq_lock, | 251 | .irqs = s5m8767_irqs, |
223 | .irq_bus_sync_unlock = s5m8767_irq_sync_unlock, | 252 | .num_irqs = ARRAY_SIZE(s5m8767_irqs), |
224 | .irq_mask = s5m8767_irq_mask, | 253 | .num_regs = 3, |
225 | .irq_unmask = s5m8767_irq_unmask, | 254 | .status_base = S5M8767_REG_INT1, |
255 | .mask_base = S5M8767_REG_INT1M, | ||
256 | .ack_base = S5M8767_REG_INT1, | ||
226 | }; | 257 | }; |
227 | 258 | ||
228 | static inline struct sec_irq_data * | 259 | static struct regmap_irq_chip s5m8763_irq_chip = { |
229 | irq_to_s5m8763_irq(struct sec_pmic_dev *sec_pmic, int irq) | ||
230 | { | ||
231 | return &s5m8763_irqs[irq - sec_pmic->irq_base]; | ||
232 | } | ||
233 | |||
234 | static void s5m8763_irq_lock(struct irq_data *data) | ||
235 | { | ||
236 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
237 | |||
238 | mutex_lock(&sec_pmic->irqlock); | ||
239 | } | ||
240 | |||
241 | static void s5m8763_irq_sync_unlock(struct irq_data *data) | ||
242 | { | ||
243 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
244 | int i; | ||
245 | |||
246 | for (i = 0; i < ARRAY_SIZE(sec_pmic->irq_masks_cur); i++) { | ||
247 | if (sec_pmic->irq_masks_cur[i] != sec_pmic->irq_masks_cache[i]) { | ||
248 | sec_pmic->irq_masks_cache[i] = sec_pmic->irq_masks_cur[i]; | ||
249 | sec_reg_write(sec_pmic, S5M8763_REG_IRQM1 + i, | ||
250 | sec_pmic->irq_masks_cur[i]); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | mutex_unlock(&sec_pmic->irqlock); | ||
255 | } | ||
256 | |||
257 | static void s5m8763_irq_unmask(struct irq_data *data) | ||
258 | { | ||
259 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
260 | struct sec_irq_data *irq_data = irq_to_s5m8763_irq(sec_pmic, | ||
261 | data->irq); | ||
262 | |||
263 | sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | ||
264 | } | ||
265 | |||
266 | static void s5m8763_irq_mask(struct irq_data *data) | ||
267 | { | ||
268 | struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); | ||
269 | struct sec_irq_data *irq_data = irq_to_s5m8763_irq(sec_pmic, | ||
270 | data->irq); | ||
271 | |||
272 | sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; | ||
273 | } | ||
274 | |||
275 | static struct irq_chip s5m8763_irq_chip = { | ||
276 | .name = "s5m8763", | 260 | .name = "s5m8763", |
277 | .irq_bus_lock = s5m8763_irq_lock, | 261 | .irqs = s5m8763_irqs, |
278 | .irq_bus_sync_unlock = s5m8763_irq_sync_unlock, | 262 | .num_irqs = ARRAY_SIZE(s5m8763_irqs), |
279 | .irq_mask = s5m8763_irq_mask, | 263 | .num_regs = 4, |
280 | .irq_unmask = s5m8763_irq_unmask, | 264 | .status_base = S5M8763_REG_IRQ1, |
265 | .mask_base = S5M8763_REG_IRQM1, | ||
266 | .ack_base = S5M8763_REG_IRQ1, | ||
281 | }; | 267 | }; |
282 | 268 | ||
283 | |||
284 | static irqreturn_t s5m8767_irq_thread(int irq, void *data) | ||
285 | { | ||
286 | struct sec_pmic_dev *sec_pmic = data; | ||
287 | u8 irq_reg[NUM_IRQ_REGS-1]; | ||
288 | int ret; | ||
289 | int i; | ||
290 | |||
291 | |||
292 | ret = sec_bulk_read(sec_pmic, S5M8767_REG_INT1, | ||
293 | NUM_IRQ_REGS - 1, irq_reg); | ||
294 | if (ret < 0) { | ||
295 | dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n", | ||
296 | ret); | ||
297 | return IRQ_NONE; | ||
298 | } | ||
299 | |||
300 | for (i = 0; i < NUM_IRQ_REGS - 1; i++) | ||
301 | irq_reg[i] &= ~sec_pmic->irq_masks_cur[i]; | ||
302 | |||
303 | for (i = 0; i < S5M8767_IRQ_NR; i++) { | ||
304 | if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask) | ||
305 | handle_nested_irq(sec_pmic->irq_base + i); | ||
306 | } | ||
307 | |||
308 | return IRQ_HANDLED; | ||
309 | } | ||
310 | |||
311 | static irqreturn_t s5m8763_irq_thread(int irq, void *data) | ||
312 | { | ||
313 | struct sec_pmic_dev *sec_pmic = data; | ||
314 | u8 irq_reg[NUM_IRQ_REGS]; | ||
315 | int ret; | ||
316 | int i; | ||
317 | |||
318 | ret = sec_bulk_read(sec_pmic, S5M8763_REG_IRQ1, | ||
319 | NUM_IRQ_REGS, irq_reg); | ||
320 | if (ret < 0) { | ||
321 | dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n", | ||
322 | ret); | ||
323 | return IRQ_NONE; | ||
324 | } | ||
325 | |||
326 | for (i = 0; i < NUM_IRQ_REGS; i++) | ||
327 | irq_reg[i] &= ~sec_pmic->irq_masks_cur[i]; | ||
328 | |||
329 | for (i = 0; i < S5M8763_IRQ_NR; i++) { | ||
330 | if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask) | ||
331 | handle_nested_irq(sec_pmic->irq_base + i); | ||
332 | } | ||
333 | |||
334 | return IRQ_HANDLED; | ||
335 | } | ||
336 | |||
337 | int sec_irq_resume(struct sec_pmic_dev *sec_pmic) | ||
338 | { | ||
339 | if (sec_pmic->irq && sec_pmic->irq_base) { | ||
340 | switch (sec_pmic->device_type) { | ||
341 | case S5M8763X: | ||
342 | s5m8763_irq_thread(sec_pmic->irq_base, sec_pmic); | ||
343 | break; | ||
344 | case S5M8767X: | ||
345 | s5m8767_irq_thread(sec_pmic->irq_base, sec_pmic); | ||
346 | break; | ||
347 | default: | ||
348 | dev_err(sec_pmic->dev, | ||
349 | "Unknown device type %d\n", | ||
350 | sec_pmic->device_type); | ||
351 | return -EINVAL; | ||
352 | |||
353 | } | ||
354 | } | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | int sec_irq_init(struct sec_pmic_dev *sec_pmic) | 269 | int sec_irq_init(struct sec_pmic_dev *sec_pmic) |
359 | { | 270 | { |
360 | int i; | ||
361 | int cur_irq; | ||
362 | int ret = 0; | 271 | int ret = 0; |
363 | int type = sec_pmic->device_type; | 272 | int type = sec_pmic->device_type; |
364 | 273 | ||
@@ -369,119 +278,33 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) | |||
369 | return 0; | 278 | return 0; |
370 | } | 279 | } |
371 | 280 | ||
372 | if (!sec_pmic->irq_base) { | ||
373 | dev_err(sec_pmic->dev, | ||
374 | "No interrupt base specified, no interrupts\n"); | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | mutex_init(&sec_pmic->irqlock); | ||
379 | |||
380 | switch (type) { | 281 | switch (type) { |
381 | case S5M8763X: | 282 | case S5M8763X: |
382 | for (i = 0; i < NUM_IRQ_REGS; i++) { | 283 | ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, |
383 | sec_pmic->irq_masks_cur[i] = 0xff; | 284 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
384 | sec_pmic->irq_masks_cache[i] = 0xff; | 285 | sec_pmic->irq_base, &s5m8763_irq_chip, |
385 | sec_reg_write(sec_pmic, S5M8763_REG_IRQM1 + i, | 286 | &sec_pmic->irq_data); |
386 | 0xff); | ||
387 | } | ||
388 | |||
389 | sec_reg_write(sec_pmic, S5M8763_REG_STATUSM1, 0xff); | ||
390 | sec_reg_write(sec_pmic, S5M8763_REG_STATUSM2, 0xff); | ||
391 | |||
392 | for (i = 0; i < S5M8763_IRQ_NR; i++) { | ||
393 | cur_irq = i + sec_pmic->irq_base; | ||
394 | irq_set_chip_data(cur_irq, sec_pmic); | ||
395 | irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip, | ||
396 | handle_edge_irq); | ||
397 | irq_set_nested_thread(cur_irq, 1); | ||
398 | #ifdef CONFIG_ARM | ||
399 | set_irq_flags(cur_irq, IRQF_VALID); | ||
400 | #else | ||
401 | irq_set_noprobe(cur_irq); | ||
402 | #endif | ||
403 | } | ||
404 | |||
405 | ret = request_threaded_irq(sec_pmic->irq, NULL, | ||
406 | s5m8763_irq_thread, | ||
407 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
408 | "sec-pmic-irq", sec_pmic); | ||
409 | if (ret) { | ||
410 | dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", | ||
411 | sec_pmic->irq, ret); | ||
412 | return ret; | ||
413 | } | ||
414 | break; | 287 | break; |
415 | case S5M8767X: | 288 | case S5M8767X: |
416 | for (i = 0; i < NUM_IRQ_REGS - 1; i++) { | 289 | ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, |
417 | sec_pmic->irq_masks_cur[i] = 0xff; | 290 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
418 | sec_pmic->irq_masks_cache[i] = 0xff; | 291 | sec_pmic->irq_base, &s5m8767_irq_chip, |
419 | sec_reg_write(sec_pmic, S5M8767_REG_INT1M + i, | 292 | &sec_pmic->irq_data); |
420 | 0xff); | ||
421 | } | ||
422 | for (i = 0; i < S5M8767_IRQ_NR; i++) { | ||
423 | cur_irq = i + sec_pmic->irq_base; | ||
424 | irq_set_chip_data(cur_irq, sec_pmic); | ||
425 | if (ret) { | ||
426 | dev_err(sec_pmic->dev, | ||
427 | "Failed to irq_set_chip_data %d: %d\n", | ||
428 | sec_pmic->irq, ret); | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip, | ||
433 | handle_edge_irq); | ||
434 | irq_set_nested_thread(cur_irq, 1); | ||
435 | #ifdef CONFIG_ARM | ||
436 | set_irq_flags(cur_irq, IRQF_VALID); | ||
437 | #else | ||
438 | irq_set_noprobe(cur_irq); | ||
439 | #endif | ||
440 | } | ||
441 | |||
442 | ret = request_threaded_irq(sec_pmic->irq, NULL, | ||
443 | s5m8767_irq_thread, | ||
444 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
445 | "sec-pmic-irq", sec_pmic); | ||
446 | if (ret) { | ||
447 | dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", | ||
448 | sec_pmic->irq, ret); | ||
449 | return ret; | ||
450 | } | ||
451 | break; | 293 | break; |
452 | default: | 294 | case S2MPS11X: |
453 | dev_err(sec_pmic->dev, | 295 | ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, |
454 | "Unknown device type %d\n", sec_pmic->device_type); | 296 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
455 | return -EINVAL; | 297 | sec_pmic->irq_base, &s2mps11_irq_chip, |
456 | } | 298 | &sec_pmic->irq_data); |
457 | |||
458 | if (!sec_pmic->ono) | ||
459 | return 0; | ||
460 | |||
461 | switch (type) { | ||
462 | case S5M8763X: | ||
463 | ret = request_threaded_irq(sec_pmic->ono, NULL, | ||
464 | s5m8763_irq_thread, | ||
465 | IRQF_TRIGGER_FALLING | | ||
466 | IRQF_TRIGGER_RISING | | ||
467 | IRQF_ONESHOT, "sec_pmic-ono", | ||
468 | sec_pmic); | ||
469 | break; | ||
470 | case S5M8767X: | ||
471 | ret = request_threaded_irq(sec_pmic->ono, NULL, | ||
472 | s5m8767_irq_thread, | ||
473 | IRQF_TRIGGER_FALLING | | ||
474 | IRQF_TRIGGER_RISING | | ||
475 | IRQF_ONESHOT, "sec_pmic-ono", sec_pmic); | ||
476 | break; | 299 | break; |
477 | default: | 300 | default: |
478 | ret = -EINVAL; | 301 | dev_err(sec_pmic->dev, "Unknown device type %d\n", |
479 | break; | 302 | sec_pmic->device_type); |
303 | return -EINVAL; | ||
480 | } | 304 | } |
481 | 305 | ||
482 | if (ret) { | 306 | if (ret != 0) { |
483 | dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", | 307 | dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); |
484 | sec_pmic->ono, ret); | ||
485 | return ret; | 308 | return ret; |
486 | } | 309 | } |
487 | 310 | ||
@@ -490,9 +313,5 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) | |||
490 | 313 | ||
491 | void sec_irq_exit(struct sec_pmic_dev *sec_pmic) | 314 | void sec_irq_exit(struct sec_pmic_dev *sec_pmic) |
492 | { | 315 | { |
493 | if (sec_pmic->ono) | 316 | regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data); |
494 | free_irq(sec_pmic->ono, sec_pmic); | ||
495 | |||
496 | if (sec_pmic->irq) | ||
497 | free_irq(sec_pmic->irq, sec_pmic); | ||
498 | } | 317 | } |
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 323e200bc82c..b50c38f8bc48 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h | |||
@@ -48,6 +48,8 @@ struct sec_pmic_dev { | |||
48 | int device_type; | 48 | int device_type; |
49 | int irq_base; | 49 | int irq_base; |
50 | int irq; | 50 | int irq; |
51 | struct regmap_irq_chip_data *irq_data; | ||
52 | |||
51 | int ono; | 53 | int ono; |
52 | u8 irq_masks_cur[NUM_IRQ_REGS]; | 54 | u8 irq_masks_cur[NUM_IRQ_REGS]; |
53 | u8 irq_masks_cache[NUM_IRQ_REGS]; | 55 | u8 irq_masks_cache[NUM_IRQ_REGS]; |
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h index 7f7a6248f707..d43b4f9e7fb2 100644 --- a/include/linux/mfd/samsung/irq.h +++ b/include/linux/mfd/samsung/irq.h | |||
@@ -13,6 +13,48 @@ | |||
13 | #ifndef __LINUX_MFD_SEC_IRQ_H | 13 | #ifndef __LINUX_MFD_SEC_IRQ_H |
14 | #define __LINUX_MFD_SEC_IRQ_H | 14 | #define __LINUX_MFD_SEC_IRQ_H |
15 | 15 | ||
16 | enum s2mps11_irq { | ||
17 | S2MPS11_IRQ_PWRONF, | ||
18 | S2MPS11_IRQ_PWRONR, | ||
19 | S2MPS11_IRQ_JIGONBF, | ||
20 | S2MPS11_IRQ_JIGONBR, | ||
21 | S2MPS11_IRQ_ACOKBF, | ||
22 | S2MPS11_IRQ_ACOKBR, | ||
23 | S2MPS11_IRQ_PWRON1S, | ||
24 | S2MPS11_IRQ_MRB, | ||
25 | |||
26 | S2MPS11_IRQ_RTC60S, | ||
27 | S2MPS11_IRQ_RTCA1, | ||
28 | S2MPS11_IRQ_RTCA2, | ||
29 | S2MPS11_IRQ_SMPL, | ||
30 | S2MPS11_IRQ_RTC1S, | ||
31 | S2MPS11_IRQ_WTSR, | ||
32 | |||
33 | S2MPS11_IRQ_INT120C, | ||
34 | S2MPS11_IRQ_INT140C, | ||
35 | |||
36 | S2MPS11_IRQ_NR, | ||
37 | }; | ||
38 | |||
39 | #define S2MPS11_IRQ_PWRONF_MASK (1 << 0) | ||
40 | #define S2MPS11_IRQ_PWRONR_MASK (1 << 1) | ||
41 | #define S2MPS11_IRQ_JIGONBF_MASK (1 << 2) | ||
42 | #define S2MPS11_IRQ_JIGONBR_MASK (1 << 3) | ||
43 | #define S2MPS11_IRQ_ACOKBF_MASK (1 << 4) | ||
44 | #define S2MPS11_IRQ_ACOKBR_MASK (1 << 5) | ||
45 | #define S2MPS11_IRQ_PWRON1S_MASK (1 << 6) | ||
46 | #define S2MPS11_IRQ_MRB_MASK (1 << 7) | ||
47 | |||
48 | #define S2MPS11_IRQ_RTC60S_MASK (1 << 0) | ||
49 | #define S2MPS11_IRQ_RTCA1_MASK (1 << 1) | ||
50 | #define S2MPS11_IRQ_RTCA2_MASK (1 << 2) | ||
51 | #define S2MPS11_IRQ_SMPL_MASK (1 << 3) | ||
52 | #define S2MPS11_IRQ_RTC1S_MASK (1 << 4) | ||
53 | #define S2MPS11_IRQ_WTSR_MASK (1 << 5) | ||
54 | |||
55 | #define S2MPS11_IRQ_INT120C_MASK (1 << 0) | ||
56 | #define S2MPS11_IRQ_INT140C_MASK (1 << 1) | ||
57 | |||
16 | enum s5m8767_irq { | 58 | enum s5m8767_irq { |
17 | S5M8767_IRQ_PWRR, | 59 | S5M8767_IRQ_PWRR, |
18 | S5M8767_IRQ_PWRF, | 60 | S5M8767_IRQ_PWRF, |