2 * s2mpu09-irq.c - Interrupt controller support for S2MPU09
4 * Copyright (C) 2016 Samsung Electronics Co.Ltd
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/err.h>
23 #include <linux/irq.h>
24 #include <linux/interrupt.h>
25 #include <linux/gpio.h>
26 #include <linux/mfd/samsung/s2mpu09.h>
27 #include <linux/mfd/samsung/s2mpu09-regulator.h>
29 static const u8 s2mpu09_mask_reg
[] = {
30 /* TODO: Need to check other INTMASK */
31 [PMIC_INT1
] = S2MPU09_PMIC_REG_INT1M
,
32 [PMIC_INT2
] = S2MPU09_PMIC_REG_INT2M
,
33 [PMIC_INT3
] = S2MPU09_PMIC_REG_INT3M
,
34 [PMIC_INT4
] = S2MPU09_PMIC_REG_INT4M
,
35 [PMIC_INT5
] = S2MPU09_PMIC_REG_INT5M
,
38 static struct i2c_client
*get_i2c(struct s2mpu09_dev
*s2mpu09
,
39 enum s2mpu09_irq_source src
)
42 case PMIC_INT1
... PMIC_INT5
:
45 return ERR_PTR(-EINVAL
);
49 struct s2mpu09_irq_data
{
51 enum s2mpu09_irq_source group
;
54 #define DECLARE_IRQ(idx, _group, _mask) \
55 [(idx)] = { .group = (_group), .mask = (_mask) }
56 static const struct s2mpu09_irq_data s2mpu09_irqs
[] = {
57 DECLARE_IRQ(S2MPU09_PMIC_IRQ_PWRONR_INT1
, PMIC_INT1
, 1 << 1),
58 DECLARE_IRQ(S2MPU09_PMIC_IRQ_PWRONF_INT1
, PMIC_INT1
, 1 << 0),
59 DECLARE_IRQ(S2MPU09_PMIC_IRQ_JIGONBF_INT1
, PMIC_INT1
, 1 << 2),
60 DECLARE_IRQ(S2MPU09_PMIC_IRQ_JIGONBR_INT1
, PMIC_INT1
, 1 << 3),
61 DECLARE_IRQ(S2MPU09_PMIC_IRQ_ACOKF_INT1
, PMIC_INT1
, 1 << 4),
62 DECLARE_IRQ(S2MPU09_PMIC_IRQ_ACOKR_INT1
, PMIC_INT1
, 1 << 5),
63 DECLARE_IRQ(S2MPU09_PMIC_IRQ_PWRON1S_INT1
, PMIC_INT1
, 1 << 6),
64 DECLARE_IRQ(S2MPU09_PMIC_IRQ_MRB_INT1
, PMIC_INT1
, 1 << 7),
66 DECLARE_IRQ(S2MPU09_PMIC_IRQ_RTC60S_INT2
, PMIC_INT2
, 1 << 0),
67 DECLARE_IRQ(S2MPU09_PMIC_IRQ_RTCA1_INT2
, PMIC_INT2
, 1 << 1),
68 DECLARE_IRQ(S2MPU09_PMIC_IRQ_RTCA0_INT2
, PMIC_INT2
, 1 << 2),
69 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SMPL_INT2
, PMIC_INT2
, 1 << 3),
70 DECLARE_IRQ(S2MPU09_PMIC_IRQ_RTC1S_INT2
, PMIC_INT2
, 1 << 4),
71 DECLARE_IRQ(S2MPU09_PMIC_IRQ_WTSR_INT2
, PMIC_INT2
, 1 << 5),
72 DECLARE_IRQ(S2MPU09_PMIC_IRQ_WTSRB_INT2
, PMIC_INT2
, 1 << 7),
74 DECLARE_IRQ(S2MPU09_PMIC_IRQ_120C_INT3
, PMIC_INT3
, 1 << 0),
75 DECLARE_IRQ(S2MPU09_PMIC_IRQ_140C_INT3
, PMIC_INT3
, 1 << 1),
76 DECLARE_IRQ(S2MPU09_PMIC_IRQ_TSD_INT3
, PMIC_INT3
, 1 << 2),
77 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB1_INT3
, PMIC_INT3
, 1 << 6),
78 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB2_INT3
, PMIC_INT3
, 1 << 7),
80 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB3_INT4
, PMIC_INT4
, 1 << 0),
81 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB4_INT4
, PMIC_INT4
, 1 << 1),
82 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB5_INT4
, PMIC_INT4
, 1 << 2),
83 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB6_INT4
, PMIC_INT4
, 1 << 3),
84 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB7_INT4
, PMIC_INT4
, 1 << 4),
85 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB8_INT4
, PMIC_INT4
, 1 << 5),
86 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB9_INT4
, PMIC_INT4
, 1 << 6),
87 DECLARE_IRQ(S2MPU09_PMIC_IRQ_OCPB10_INT4
, PMIC_INT4
, 1 << 7),
89 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO2_INT5
, PMIC_INT5
, 1 << 0),
90 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO18_INT5
, PMIC_INT5
, 1 << 1),
91 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO19_INT5
, PMIC_INT5
, 1 << 2),
92 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO33_INT5
, PMIC_INT5
, 1 << 3),
93 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO34_INT5
, PMIC_INT5
, 1 << 4),
94 DECLARE_IRQ(S2MPU09_PMIC_IRQ_SCLDO35_INT5
, PMIC_INT5
, 1 << 5),
97 static void s2mpu09_irq_lock(struct irq_data
*data
)
99 struct s2mpu09_dev
*s2mpu09
= irq_get_chip_data(data
->irq
);
101 mutex_lock(&s2mpu09
->irqlock
);
104 static void s2mpu09_irq_sync_unlock(struct irq_data
*data
)
106 struct s2mpu09_dev
*s2mpu09
= irq_get_chip_data(data
->irq
);
109 for (i
= 0; i
< S2MPU09_IRQ_GROUP_NR
; i
++) {
110 u8 mask_reg
= s2mpu09_mask_reg
[i
];
111 struct i2c_client
*i2c
= get_i2c(s2mpu09
, i
);
113 if (mask_reg
== S2MPU09_REG_INVALID
||
116 s2mpu09
->irq_masks_cache
[i
] = s2mpu09
->irq_masks_cur
[i
];
118 s2mpu09_write_reg(i2c
, s2mpu09_mask_reg
[i
],
119 s2mpu09
->irq_masks_cur
[i
]);
122 mutex_unlock(&s2mpu09
->irqlock
);
125 static const inline struct s2mpu09_irq_data
*
126 irq_to_s2mpu09_irq(struct s2mpu09_dev
*s2mpu09
, int irq
)
128 return &s2mpu09_irqs
[irq
- s2mpu09
->irq_base
];
131 static void s2mpu09_irq_mask(struct irq_data
*data
)
133 struct s2mpu09_dev
*s2mpu09
= irq_get_chip_data(data
->irq
);
134 const struct s2mpu09_irq_data
*irq_data
=
135 irq_to_s2mpu09_irq(s2mpu09
, data
->irq
);
137 if (irq_data
->group
>= S2MPU09_IRQ_GROUP_NR
)
140 s2mpu09
->irq_masks_cur
[irq_data
->group
] |= irq_data
->mask
;
143 static void s2mpu09_irq_unmask(struct irq_data
*data
)
145 struct s2mpu09_dev
*s2mpu09
= irq_get_chip_data(data
->irq
);
146 const struct s2mpu09_irq_data
*irq_data
=
147 irq_to_s2mpu09_irq(s2mpu09
, data
->irq
);
149 if (irq_data
->group
>= S2MPU09_IRQ_GROUP_NR
)
152 s2mpu09
->irq_masks_cur
[irq_data
->group
] &= ~irq_data
->mask
;
155 static struct irq_chip s2mpu09_irq_chip
= {
156 .name
= MFD_DEV_NAME
,
157 .irq_bus_lock
= s2mpu09_irq_lock
,
158 .irq_bus_sync_unlock
= s2mpu09_irq_sync_unlock
,
159 .irq_mask
= s2mpu09_irq_mask
,
160 .irq_unmask
= s2mpu09_irq_unmask
,
163 static irqreturn_t
s2mpu09_irq_thread(int irq
, void *data
)
165 struct s2mpu09_dev
*s2mpu09
= data
;
166 u8 irq_reg
[S2MPU09_IRQ_GROUP_NR
] = {0};
170 //pr_debug("%s: irq gpio pre-state(0x%02x)\n", __func__,
171 pr_err("%s: irq gpio pre-state(0x%02x)\n", __func__
,
172 gpio_get_value(s2mpu09
->irq_gpio
));
174 ret
= s2mpu09_read_reg(s2mpu09
->i2c
,
175 S2MPU09_PMIC_REG_INTSRC
, &irq_src
);
176 pr_err("%s: interrupt source(0x%02x)\n", __func__
, irq_src
);
178 pr_err("%s:%s Failed to read interrupt source: %d\n",
179 MFD_DEV_NAME
, __func__
, ret
);
183 pr_info("%s: interrupt source(0x%02x)\n", __func__
, irq_src
);
185 if (irq_src
& S2MPU09_IRQSRC_PMIC
) {
187 ret
= s2mpu09_bulk_read(s2mpu09
->pmic
, S2MPU09_PMIC_REG_INT1
,
188 S2MPU09_NUM_IRQ_PMIC_REGS
, &irq_reg
[PMIC_INT1
]);
190 pr_err("%s:%s Failed to read pmic interrupt: %d\n",
191 MFD_DEV_NAME
, __func__
, ret
);
195 pr_info("%s: pmic interrupt(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
196 __func__
, irq_reg
[PMIC_INT1
], irq_reg
[PMIC_INT2
], irq_reg
[PMIC_INT3
],
197 irq_reg
[PMIC_INT4
], irq_reg
[PMIC_INT5
]);
201 for (i
= 0; i
< S2MPU09_IRQ_GROUP_NR
; i
++)
202 irq_reg
[i
] &= ~s2mpu09
->irq_masks_cur
[i
];
205 for (i
= 0; i
< S2MPU09_IRQ_NR
; i
++) {
206 if (irq_reg
[s2mpu09_irqs
[i
].group
] & s2mpu09_irqs
[i
].mask
)
207 handle_nested_irq(s2mpu09
->irq_base
+ i
);
213 int s2mpu09_irq_init(struct s2mpu09_dev
*s2mpu09
)
220 if (!s2mpu09
->irq_gpio
) {
221 dev_warn(s2mpu09
->dev
, "No interrupt specified.\n");
222 s2mpu09
->irq_base
= 0;
226 if (!s2mpu09
->irq_base
) {
227 dev_err(s2mpu09
->dev
, "No interrupt base specified.\n");
231 mutex_init(&s2mpu09
->irqlock
);
233 s2mpu09
->irq
= gpio_to_irq(s2mpu09
->irq_gpio
);
234 pr_info("%s:%s irq=%d, irq->gpio=%d\n", MFD_DEV_NAME
, __func__
,
235 s2mpu09
->irq
, s2mpu09
->irq_gpio
);
237 ret
= gpio_request(s2mpu09
->irq_gpio
, "pmic_irq");
239 dev_err(s2mpu09
->dev
, "%s: failed requesting gpio %d\n",
240 __func__
, s2mpu09
->irq_gpio
);
243 gpio_direction_input(s2mpu09
->irq_gpio
);
244 gpio_free(s2mpu09
->irq_gpio
);
246 /* Mask individual interrupt sources */
247 for (i
= 0; i
< S2MPU09_IRQ_GROUP_NR
; i
++) {
248 struct i2c_client
*i2c
;
250 s2mpu09
->irq_masks_cur
[i
] = 0xff;
251 s2mpu09
->irq_masks_cache
[i
] = 0xff;
253 i2c
= get_i2c(s2mpu09
, i
);
255 if (IS_ERR_OR_NULL(i2c
))
257 if (s2mpu09_mask_reg
[i
] == S2MPU09_REG_INVALID
)
260 s2mpu09_write_reg(i2c
, s2mpu09_mask_reg
[i
], 0xff);
263 /* Register with genirq */
264 for (i
= 0; i
< S2MPU09_IRQ_NR
; i
++) {
265 cur_irq
= i
+ s2mpu09
->irq_base
;
266 irq_set_chip_data(cur_irq
, s2mpu09
);
267 irq_set_chip_and_handler(cur_irq
, &s2mpu09_irq_chip
,
269 irq_set_nested_thread(cur_irq
, 1);
271 set_irq_flags(cur_irq
, IRQF_VALID
);
273 irq_set_noprobe(cur_irq
);
277 s2mpu09_write_reg(s2mpu09
->i2c
, S2MPU09_PMIC_REG_INTSRC_MASK
, 0xff);
278 /* Unmask s2mpu09 interrupt */
279 ret
= s2mpu09_read_reg(s2mpu09
->i2c
, S2MPU09_PMIC_REG_INTSRC_MASK
,
282 pr_err("%s:%s fail to read intsrc mask reg\n",
283 MFD_DEV_NAME
, __func__
);
287 i2c_data
&= ~(S2MPU09_IRQSRC_PMIC
); /* Unmask pmic interrupt */
288 s2mpu09_write_reg(s2mpu09
->i2c
, S2MPU09_PMIC_REG_INTSRC_MASK
,
291 pr_info("%s:%s s2mpu09_PMIC_REG_INTSRC_MASK=0x%02x\n",
292 MFD_DEV_NAME
, __func__
, i2c_data
);
294 ret
= request_threaded_irq(s2mpu09
->irq
, NULL
, s2mpu09_irq_thread
,
295 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
,
296 "s2mpu09-irq", s2mpu09
);
299 dev_err(s2mpu09
->dev
, "Failed to request IRQ %d: %d\n",
307 void s2mpu09_irq_exit(struct s2mpu09_dev
*s2mpu09
)
310 free_irq(s2mpu09
->irq
, s2mpu09
);