blob: da5ec5b2ecce61b35e7a5912ef7416c29851e382 [file] [log] [blame]
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +09001/*
Sangbeom Kim63063bf2012-07-11 21:06:55 +09002 * sec-irq.c
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +09003 *
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd
5 * http://www.samsung.com
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/device.h>
15#include <linux/interrupt.h>
16#include <linux/irq.h>
Sangbeom Kim54227bc2012-07-11 21:07:16 +090017#include <linux/mfd/samsung/core.h>
18#include <linux/mfd/samsung/irq.h>
19#include <linux/mfd/samsung/s5m8763.h>
20#include <linux/mfd/samsung/s5m8767.h>
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +090021
Sangbeom Kim63063bf2012-07-11 21:06:55 +090022struct sec_irq_data {
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +090023 int reg;
24 int mask;
25};
26
Sangbeom Kim63063bf2012-07-11 21:06:55 +090027static struct sec_irq_data s5m8767_irqs[] = {
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +090028 [S5M8767_IRQ_PWRR] = {
29 .reg = 1,
30 .mask = S5M8767_IRQ_PWRR_MASK,
31 },
32 [S5M8767_IRQ_PWRF] = {
33 .reg = 1,
34 .mask = S5M8767_IRQ_PWRF_MASK,
35 },
36 [S5M8767_IRQ_PWR1S] = {
37 .reg = 1,
38 .mask = S5M8767_IRQ_PWR1S_MASK,
39 },
40 [S5M8767_IRQ_JIGR] = {
41 .reg = 1,
42 .mask = S5M8767_IRQ_JIGR_MASK,
43 },
44 [S5M8767_IRQ_JIGF] = {
45 .reg = 1,
46 .mask = S5M8767_IRQ_JIGF_MASK,
47 },
48 [S5M8767_IRQ_LOWBAT2] = {
49 .reg = 1,
50 .mask = S5M8767_IRQ_LOWBAT2_MASK,
51 },
52 [S5M8767_IRQ_LOWBAT1] = {
53 .reg = 1,
54 .mask = S5M8767_IRQ_LOWBAT1_MASK,
55 },
56 [S5M8767_IRQ_MRB] = {
57 .reg = 2,
58 .mask = S5M8767_IRQ_MRB_MASK,
59 },
60 [S5M8767_IRQ_DVSOK2] = {
61 .reg = 2,
62 .mask = S5M8767_IRQ_DVSOK2_MASK,
63 },
64 [S5M8767_IRQ_DVSOK3] = {
65 .reg = 2,
66 .mask = S5M8767_IRQ_DVSOK3_MASK,
67 },
68 [S5M8767_IRQ_DVSOK4] = {
69 .reg = 2,
70 .mask = S5M8767_IRQ_DVSOK4_MASK,
71 },
72 [S5M8767_IRQ_RTC60S] = {
73 .reg = 3,
74 .mask = S5M8767_IRQ_RTC60S_MASK,
75 },
76 [S5M8767_IRQ_RTCA1] = {
77 .reg = 3,
78 .mask = S5M8767_IRQ_RTCA1_MASK,
79 },
80 [S5M8767_IRQ_RTCA2] = {
81 .reg = 3,
82 .mask = S5M8767_IRQ_RTCA2_MASK,
83 },
84 [S5M8767_IRQ_SMPL] = {
85 .reg = 3,
86 .mask = S5M8767_IRQ_SMPL_MASK,
87 },
88 [S5M8767_IRQ_RTC1S] = {
89 .reg = 3,
90 .mask = S5M8767_IRQ_RTC1S_MASK,
91 },
92 [S5M8767_IRQ_WTSR] = {
93 .reg = 3,
94 .mask = S5M8767_IRQ_WTSR_MASK,
95 },
96};
97
Sangbeom Kim63063bf2012-07-11 21:06:55 +090098static struct sec_irq_data s5m8763_irqs[] = {
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +090099 [S5M8763_IRQ_DCINF] = {
100 .reg = 1,
101 .mask = S5M8763_IRQ_DCINF_MASK,
102 },
103 [S5M8763_IRQ_DCINR] = {
104 .reg = 1,
105 .mask = S5M8763_IRQ_DCINR_MASK,
106 },
107 [S5M8763_IRQ_JIGF] = {
108 .reg = 1,
109 .mask = S5M8763_IRQ_JIGF_MASK,
110 },
111 [S5M8763_IRQ_JIGR] = {
112 .reg = 1,
113 .mask = S5M8763_IRQ_JIGR_MASK,
114 },
115 [S5M8763_IRQ_PWRONF] = {
116 .reg = 1,
117 .mask = S5M8763_IRQ_PWRONF_MASK,
118 },
119 [S5M8763_IRQ_PWRONR] = {
120 .reg = 1,
121 .mask = S5M8763_IRQ_PWRONR_MASK,
122 },
123 [S5M8763_IRQ_WTSREVNT] = {
124 .reg = 2,
125 .mask = S5M8763_IRQ_WTSREVNT_MASK,
126 },
127 [S5M8763_IRQ_SMPLEVNT] = {
128 .reg = 2,
129 .mask = S5M8763_IRQ_SMPLEVNT_MASK,
130 },
131 [S5M8763_IRQ_ALARM1] = {
132 .reg = 2,
133 .mask = S5M8763_IRQ_ALARM1_MASK,
134 },
135 [S5M8763_IRQ_ALARM0] = {
136 .reg = 2,
137 .mask = S5M8763_IRQ_ALARM0_MASK,
138 },
139 [S5M8763_IRQ_ONKEY1S] = {
140 .reg = 3,
141 .mask = S5M8763_IRQ_ONKEY1S_MASK,
142 },
143 [S5M8763_IRQ_TOPOFFR] = {
144 .reg = 3,
145 .mask = S5M8763_IRQ_TOPOFFR_MASK,
146 },
147 [S5M8763_IRQ_DCINOVPR] = {
148 .reg = 3,
149 .mask = S5M8763_IRQ_DCINOVPR_MASK,
150 },
151 [S5M8763_IRQ_CHGRSTF] = {
152 .reg = 3,
153 .mask = S5M8763_IRQ_CHGRSTF_MASK,
154 },
155 [S5M8763_IRQ_DONER] = {
156 .reg = 3,
157 .mask = S5M8763_IRQ_DONER_MASK,
158 },
159 [S5M8763_IRQ_CHGFAULT] = {
160 .reg = 3,
161 .mask = S5M8763_IRQ_CHGFAULT_MASK,
162 },
163 [S5M8763_IRQ_LOBAT1] = {
164 .reg = 4,
165 .mask = S5M8763_IRQ_LOBAT1_MASK,
166 },
167 [S5M8763_IRQ_LOBAT2] = {
168 .reg = 4,
169 .mask = S5M8763_IRQ_LOBAT2_MASK,
170 },
171};
172
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900173static inline struct sec_irq_data *
174irq_to_s5m8767_irq(struct sec_pmic_dev *sec_pmic, int irq)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900175{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900176 return &s5m8767_irqs[irq - sec_pmic->irq_base];
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900177}
178
179static void s5m8767_irq_lock(struct irq_data *data)
180{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900181 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900182
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900183 mutex_lock(&sec_pmic->irqlock);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900184}
185
186static void s5m8767_irq_sync_unlock(struct irq_data *data)
187{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900188 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900189 int i;
190
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900191 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]);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900196 }
197 }
198
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900199 mutex_unlock(&sec_pmic->irqlock);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900200}
201
202static void s5m8767_irq_unmask(struct irq_data *data)
203{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900204 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,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900206 data->irq);
207
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900208 sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900209}
210
211static void s5m8767_irq_mask(struct irq_data *data)
212{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900213 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,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900215 data->irq);
216
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900217 sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900218}
219
220static struct irq_chip s5m8767_irq_chip = {
221 .name = "s5m8767",
222 .irq_bus_lock = s5m8767_irq_lock,
223 .irq_bus_sync_unlock = s5m8767_irq_sync_unlock,
224 .irq_mask = s5m8767_irq_mask,
225 .irq_unmask = s5m8767_irq_unmask,
226};
227
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900228static inline struct sec_irq_data *
229irq_to_s5m8763_irq(struct sec_pmic_dev *sec_pmic, int irq)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900230{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900231 return &s5m8763_irqs[irq - sec_pmic->irq_base];
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900232}
233
234static void s5m8763_irq_lock(struct irq_data *data)
235{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900236 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900237
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900238 mutex_lock(&sec_pmic->irqlock);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900239}
240
241static void s5m8763_irq_sync_unlock(struct irq_data *data)
242{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900243 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900244 int i;
245
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900246 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]);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900251 }
252 }
253
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900254 mutex_unlock(&sec_pmic->irqlock);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900255}
256
257static void s5m8763_irq_unmask(struct irq_data *data)
258{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900259 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,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900261 data->irq);
262
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900263 sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900264}
265
266static void s5m8763_irq_mask(struct irq_data *data)
267{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900268 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,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900270 data->irq);
271
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900272 sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900273}
274
275static struct irq_chip s5m8763_irq_chip = {
276 .name = "s5m8763",
277 .irq_bus_lock = s5m8763_irq_lock,
278 .irq_bus_sync_unlock = s5m8763_irq_sync_unlock,
279 .irq_mask = s5m8763_irq_mask,
280 .irq_unmask = s5m8763_irq_unmask,
281};
282
283
284static irqreturn_t s5m8767_irq_thread(int irq, void *data)
285{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900286 struct sec_pmic_dev *sec_pmic = data;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900287 u8 irq_reg[NUM_IRQ_REGS-1];
288 int ret;
289 int i;
290
291
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900292 ret = sec_bulk_read(sec_pmic, S5M8767_REG_INT1,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900293 NUM_IRQ_REGS - 1, irq_reg);
294 if (ret < 0) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900295 dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n",
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900296 ret);
297 return IRQ_NONE;
298 }
299
300 for (i = 0; i < NUM_IRQ_REGS - 1; i++)
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900301 irq_reg[i] &= ~sec_pmic->irq_masks_cur[i];
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900302
303 for (i = 0; i < S5M8767_IRQ_NR; i++) {
304 if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900305 handle_nested_irq(sec_pmic->irq_base + i);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900306 }
307
308 return IRQ_HANDLED;
309}
310
311static irqreturn_t s5m8763_irq_thread(int irq, void *data)
312{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900313 struct sec_pmic_dev *sec_pmic = data;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900314 u8 irq_reg[NUM_IRQ_REGS];
315 int ret;
316 int i;
317
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900318 ret = sec_bulk_read(sec_pmic, S5M8763_REG_IRQ1,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900319 NUM_IRQ_REGS, irq_reg);
320 if (ret < 0) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900321 dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n",
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900322 ret);
323 return IRQ_NONE;
324 }
325
326 for (i = 0; i < NUM_IRQ_REGS; i++)
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900327 irq_reg[i] &= ~sec_pmic->irq_masks_cur[i];
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900328
329 for (i = 0; i < S5M8763_IRQ_NR; i++) {
330 if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900331 handle_nested_irq(sec_pmic->irq_base + i);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900332 }
333
334 return IRQ_HANDLED;
335}
336
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900337int sec_irq_resume(struct sec_pmic_dev *sec_pmic)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900338{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900339 if (sec_pmic->irq && sec_pmic->irq_base) {
340 switch (sec_pmic->device_type) {
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900341 case S5M8763X:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900342 s5m8763_irq_thread(sec_pmic->irq_base, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900343 break;
344 case S5M8767X:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900345 s5m8767_irq_thread(sec_pmic->irq_base, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900346 break;
347 default:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900348 dev_err(sec_pmic->dev,
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100349 "Unknown device type %d\n",
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900350 sec_pmic->device_type);
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100351 return -EINVAL;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900352
353 }
354 }
355 return 0;
356}
357
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900358int sec_irq_init(struct sec_pmic_dev *sec_pmic)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900359{
360 int i;
361 int cur_irq;
362 int ret = 0;
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900363 int type = sec_pmic->device_type;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900364
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900365 if (!sec_pmic->irq) {
366 dev_warn(sec_pmic->dev,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900367 "No interrupt specified, no interrupts\n");
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900368 sec_pmic->irq_base = 0;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900369 return 0;
370 }
371
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900372 if (!sec_pmic->irq_base) {
373 dev_err(sec_pmic->dev,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900374 "No interrupt base specified, no interrupts\n");
375 return 0;
376 }
377
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900378 mutex_init(&sec_pmic->irqlock);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900379
380 switch (type) {
381 case S5M8763X:
382 for (i = 0; i < NUM_IRQ_REGS; i++) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900383 sec_pmic->irq_masks_cur[i] = 0xff;
384 sec_pmic->irq_masks_cache[i] = 0xff;
385 sec_reg_write(sec_pmic, S5M8763_REG_IRQM1 + i,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900386 0xff);
387 }
388
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900389 sec_reg_write(sec_pmic, S5M8763_REG_STATUSM1, 0xff);
390 sec_reg_write(sec_pmic, S5M8763_REG_STATUSM2, 0xff);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900391
392 for (i = 0; i < S5M8763_IRQ_NR; i++) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900393 cur_irq = i + sec_pmic->irq_base;
394 irq_set_chip_data(cur_irq, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900395 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
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900405 ret = request_threaded_irq(sec_pmic->irq, NULL,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900406 s5m8763_irq_thread,
407 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900408 "sec-pmic-irq", sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900409 if (ret) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900410 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n",
411 sec_pmic->irq, ret);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900412 return ret;
413 }
414 break;
415 case S5M8767X:
416 for (i = 0; i < NUM_IRQ_REGS - 1; i++) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900417 sec_pmic->irq_masks_cur[i] = 0xff;
418 sec_pmic->irq_masks_cache[i] = 0xff;
419 sec_reg_write(sec_pmic, S5M8767_REG_INT1M + i,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900420 0xff);
421 }
422 for (i = 0; i < S5M8767_IRQ_NR; i++) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900423 cur_irq = i + sec_pmic->irq_base;
424 irq_set_chip_data(cur_irq, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900425 if (ret) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900426 dev_err(sec_pmic->dev,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900427 "Failed to irq_set_chip_data %d: %d\n",
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900428 sec_pmic->irq, ret);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900429 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
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900442 ret = request_threaded_irq(sec_pmic->irq, NULL,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900443 s5m8767_irq_thread,
444 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900445 "sec-pmic-irq", sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900446 if (ret) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900447 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n",
448 sec_pmic->irq, ret);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900449 return ret;
450 }
451 break;
452 default:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900453 dev_err(sec_pmic->dev,
454 "Unknown device type %d\n", sec_pmic->device_type);
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100455 return -EINVAL;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900456 }
457
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900458 if (!sec_pmic->ono)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900459 return 0;
460
461 switch (type) {
462 case S5M8763X:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900463 ret = request_threaded_irq(sec_pmic->ono, NULL,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900464 s5m8763_irq_thread,
465 IRQF_TRIGGER_FALLING |
466 IRQF_TRIGGER_RISING |
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900467 IRQF_ONESHOT, "sec_pmic-ono",
468 sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900469 break;
470 case S5M8767X:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900471 ret = request_threaded_irq(sec_pmic->ono, NULL,
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900472 s5m8767_irq_thread,
473 IRQF_TRIGGER_FALLING |
474 IRQF_TRIGGER_RISING |
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900475 IRQF_ONESHOT, "sec_pmic-ono", sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900476 break;
477 default:
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100478 ret = -EINVAL;
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900479 break;
480 }
481
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100482 if (ret) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900483 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n",
484 sec_pmic->ono, ret);
Jonghwan Choic7a1fcf2012-02-20 16:22:56 +0100485 return ret;
486 }
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900487
488 return 0;
489}
490
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900491void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900492{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900493 if (sec_pmic->ono)
494 free_irq(sec_pmic->ono, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900495
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900496 if (sec_pmic->irq)
497 free_irq(sec_pmic->irq, sec_pmic);
Sangbeom Kim5ac2ffa72011-12-23 17:28:09 +0900498}