2 * s2mu004-irq.c - Interrupt controller support for s2mu004
4 * Copyright (C) 2015 Samsung Electronics Co.Ltd
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * This driver is based on s2mu004-irq.c
24 #include <linux/err.h>
25 #include <linux/irq.h>
26 #include <linux/interrupt.h>
27 #include <linux/gpio.h>
28 #include <linux/mfd/samsung/s2mu004.h>
29 #include <linux/mfd/samsung/s2mu004-private.h>
31 static const u8 s2mu004_mask_reg
[] = {
32 [CHG_INT1
] = S2MU004_REG_SC_INT1_MASK
,
33 [CHG_INT2
] = S2MU004_REG_SC_INT2_MASK
,
34 #if defined(CONFIG_MUIC_S2MU004_HV)
35 [AFC_INT
] = S2MU004_REG_AFC_INT_MASK
,
37 [MUIC_INT1
] = S2MU004_REG_MUIC_INT1_MASK
,
38 [MUIC_INT2
] = S2MU004_REG_MUIC_INT2_MASK
,
41 struct s2mu004_irq_data
{
43 enum s2mu004_irq_source group
;
46 #define DECLARE_IRQ(idx, _group, _mask) \
47 [(idx)] = { .group = (_group), .mask = (_mask) }
49 static const struct s2mu004_irq_data s2mu004_irqs
[] = {
50 DECLARE_IRQ(S2MU004_CHG1_IRQ_SYS
, CHG_INT1
, 1 << 0),
51 DECLARE_IRQ(S2MU004_CHG1_IRQ_Poor_CHG
, CHG_INT1
, 1 << 1),
52 DECLARE_IRQ(S2MU004_CHG1_IRQ_CHG_Fault
, CHG_INT1
, 1 << 2),
53 DECLARE_IRQ(S2MU004_CHG1_IRQ_CHG_RSTART
, CHG_INT1
, 1 << 3),
54 DECLARE_IRQ(S2MU004_CHG1_IRQ_DONE
, CHG_INT1
, 1 << 4),
55 DECLARE_IRQ(S2MU004_CHG1_IRQ_TOP_OFF
, CHG_INT1
, 1 << 5),
56 DECLARE_IRQ(S2MU004_CHG1_IRQ_WCIN
, CHG_INT1
, 1 << 6),
57 DECLARE_IRQ(S2MU004_CHG1_IRQ_CHGIN
, CHG_INT1
, 1 << 7),
59 DECLARE_IRQ(S2MU004_CHG2_IRQ_ICR
, CHG_INT2
, 1 << 0),
60 DECLARE_IRQ(S2MU004_CHG2_IRQ_IVR
, CHG_INT2
, 1 << 1),
61 DECLARE_IRQ(S2MU004_CHG2_IRQ_AICL
, CHG_INT2
, 1 << 2),
62 DECLARE_IRQ(S2MU004_CHG2_IRQ_TX_Fault
, CHG_INT2
, 1 << 3),
63 DECLARE_IRQ(S2MU004_CHG2_IRQ_OTG_Fault
, CHG_INT2
, 1 << 4),
64 DECLARE_IRQ(S2MU004_CHG2_IRQ_DET_BAT
, CHG_INT2
, 1 << 5),
65 DECLARE_IRQ(S2MU004_CHG2_IRQ_BAT
, CHG_INT2
, 1 << 6),
67 #if defined(CONFIG_HV_MUIC_S2MU004_AFC)
68 DECLARE_IRQ(S2MU004_AFC_IRQ_VbADC
, AFC_INT
, 1 << 0),
69 DECLARE_IRQ(S2MU004_AFC_IRQ_VDNMon
, AFC_INT
, 1 << 1),
70 DECLARE_IRQ(S2MU004_AFC_IRQ_DNRes
, AFC_INT
, 1 << 2),
71 DECLARE_IRQ(S2MU004_AFC_IRQ_MPNack
, AFC_INT
, 1 << 3),
72 DECLARE_IRQ(S2MU004_AFC_IRQ_MRxTrf
, AFC_INT
, 1 << 5),
73 DECLARE_IRQ(S2MU004_AFC_IRQ_MRxPerr
, AFC_INT
, 1 << 6),
74 DECLARE_IRQ(S2MU004_AFC_IRQ_MRxRdy
, AFC_INT
, 1 << 7),
76 DECLARE_IRQ(S2MU004_MUIC_IRQ1_ATTATCH
, MUIC_INT1
, 1 << 0),
77 DECLARE_IRQ(S2MU004_MUIC_IRQ1_DETACH
, MUIC_INT1
, 1 << 1),
78 DECLARE_IRQ(S2MU004_MUIC_IRQ1_KP
, MUIC_INT1
, 1 << 2),
79 DECLARE_IRQ(S2MU004_MUIC_IRQ1_LKP
, MUIC_INT1
, 1 << 3),
80 DECLARE_IRQ(S2MU004_MUIC_IRQ1_LKR
, MUIC_INT1
, 1 << 4),
81 DECLARE_IRQ(S2MU004_MUIC_IRQ1_RID_CHG
, MUIC_INT1
, 1 << 5),
83 DECLARE_IRQ(S2MU004_MUIC_IRQ2_VBUS_ON
, MUIC_INT2
, 1 << 0),
84 DECLARE_IRQ(S2MU004_MUIC_IRQ2_RSVD_ATTACH
, MUIC_INT2
, 1 << 1),
85 DECLARE_IRQ(S2MU004_MUIC_IRQ2_ADC_CHANGE
, MUIC_INT2
, 1 << 2),
86 DECLARE_IRQ(S2MU004_MUIC_IRQ2_STUCK
, MUIC_INT2
, 1 << 3),
87 DECLARE_IRQ(S2MU004_MUIC_IRQ2_STUCKRCV
, MUIC_INT2
, 1 << 4),
88 DECLARE_IRQ(S2MU004_MUIC_IRQ2_MHDL
, MUIC_INT2
, 1 << 5),
89 DECLARE_IRQ(S2MU004_MUIC_IRQ2_AV_CHARGE
, MUIC_INT2
, 1 << 6),
90 DECLARE_IRQ(S2MU004_MUIC_IRQ2_VBUS_OFF
, MUIC_INT2
, 1 << 7),
93 static void s2mu004_irq_lock(struct irq_data
*data
)
95 struct s2mu004_dev
*s2mu004
= irq_get_chip_data(data
->irq
);
97 mutex_lock(&s2mu004
->irqlock
);
100 static void s2mu004_irq_sync_unlock(struct irq_data
*data
)
102 struct s2mu004_dev
*s2mu004
= irq_get_chip_data(data
->irq
);
105 for (i
= 0; i
< S2MU004_IRQ_GROUP_NR
; i
++) {
106 u8 mask_reg
= s2mu004_mask_reg
[i
];
107 struct i2c_client
*i2c
= s2mu004
->i2c
;
109 if (mask_reg
== S2MU004_REG_INVALID
||
112 s2mu004
->irq_masks_cache
[i
] = s2mu004
->irq_masks_cur
[i
];
114 s2mu004_write_reg(i2c
, s2mu004_mask_reg
[i
],
115 s2mu004
->irq_masks_cur
[i
]);
118 mutex_unlock(&s2mu004
->irqlock
);
121 static const inline struct s2mu004_irq_data
*
122 irq_to_s2mu004_irq(struct s2mu004_dev
*s2mu004
, int irq
)
124 return &s2mu004_irqs
[irq
- s2mu004
->irq_base
];
127 static void s2mu004_irq_mask(struct irq_data
*data
)
129 struct s2mu004_dev
*s2mu004
= irq_get_chip_data(data
->irq
);
130 const struct s2mu004_irq_data
*irq_data
=
131 irq_to_s2mu004_irq(s2mu004
, data
->irq
);
133 if (irq_data
->group
>= S2MU004_IRQ_GROUP_NR
)
136 s2mu004
->irq_masks_cur
[irq_data
->group
] |= irq_data
->mask
;
139 static void s2mu004_irq_unmask(struct irq_data
*data
)
141 struct s2mu004_dev
*s2mu004
= irq_get_chip_data(data
->irq
);
142 const struct s2mu004_irq_data
*irq_data
=
143 irq_to_s2mu004_irq(s2mu004
, data
->irq
);
145 if (irq_data
->group
>= S2MU004_IRQ_GROUP_NR
)
148 s2mu004
->irq_masks_cur
[irq_data
->group
] &= ~irq_data
->mask
;
151 static struct irq_chip s2mu004_irq_chip
= {
152 .name
= MFD_DEV_NAME
,
153 .irq_bus_lock
= s2mu004_irq_lock
,
154 .irq_bus_sync_unlock
= s2mu004_irq_sync_unlock
,
155 .irq_mask
= s2mu004_irq_mask
,
156 .irq_unmask
= s2mu004_irq_unmask
,
159 static irqreturn_t
s2mu004_irq_thread(int irq
, void *data
)
161 struct s2mu004_dev
*s2mu004
= data
;
162 u8 irq_reg
[S2MU004_IRQ_GROUP_NR
] = {0};
165 #if defined(CONFIG_MUIC_S2MU004_HV)
169 pr_debug("%s: irq gpio pre-state(0x%02x)\n", __func__
,
170 gpio_get_value(s2mu004
->irq_gpio
));
172 /* CHG_INT1 ~ INT2 */
173 ret
= s2mu004_read_reg(s2mu004
->i2c
, S2MU004_REG_SC_INT1
,
175 if (irq_reg
[CHG_INT1
])
176 pr_info("%s: charger interrupt(0x%02x)\n",
177 __func__
, irq_reg
[CHG_INT1
]);
179 ret
= s2mu004_read_reg(s2mu004
->i2c
, S2MU004_REG_SC_INT2
,
181 if (irq_reg
[CHG_INT2
])
182 pr_info("%s: charger interrupt(0x%02x)\n",
183 __func__
, irq_reg
[CHG_INT2
]);
185 #if defined(CONFIG_MUIC_S2MU004_HV)
187 ret
= s2mu004_read_reg(s2mu004
->i2c
, S2MU004_REG_AFC_INT
,
189 if (irq_reg
[AFC_INT
]) {
190 pr_info("%s: AFC interrupt(0x%02x)\n",
191 __func__
, irq_reg
[AFC_INT
]);
193 ret
= s2mu004_read_reg(s2mu004
->i2c
, 0x48,
195 pr_info("%s: 0x48 (0x%02x)\n",
196 __func__
, temp_vdadc
);
200 /* MUIC INT1 ~ INT2 */
201 ret
= s2mu004_bulk_read(s2mu004
->i2c
, S2MU004_REG_MUIC_INT1
,
202 S2MU004_NUM_IRQ_MUIC_REGS
, &irq_reg
[MUIC_INT1
]);
203 if (irq_reg
[MUIC_INT1
] || irq_reg
[MUIC_INT2
])
204 pr_info("%s: muic interrupt(0x%02x, 0x%02x)\n", __func__
,
205 irq_reg
[MUIC_INT1
], irq_reg
[MUIC_INT2
]);
207 if (s2mu004
->pmic_rev
== 0) {
208 s2mu004_read_reg(s2mu004
->i2c
, S2MU004_REG_MUIC_ADC
, &temp
);
210 /* checking VBUS_WAKEUP bit of R(0x61) */
211 s2mu004_read_reg(s2mu004
->i2c
, 0x69, &temp_2
);
212 if ((temp_2
& 0x02) && (temp
!= 0x18)
213 && (temp
!= 0x19) && (temp
!= 0x1C) && (temp
!= 0x1D))
214 s2mu004_update_reg(s2mu004
->i2c
, 0x89, 0x01, 0x03);
215 if (irq_reg
[MUIC_INT2
] & 0x80)
216 s2mu004_update_reg(s2mu004
->i2c
, 0x89, 0x03, 0x03);
220 for (i
= 0; i
< S2MU004_IRQ_GROUP_NR
; i
++)
221 irq_reg
[i
] &= ~s2mu004
->irq_masks_cur
[i
];
224 for (i
= 0; i
< S2MU004_IRQ_NR
; i
++) {
225 if (irq_reg
[s2mu004_irqs
[i
].group
] & s2mu004_irqs
[i
].mask
)
226 handle_nested_irq(s2mu004
->irq_base
+ i
);
231 static int irq_is_enable
= true;
232 int s2mu004_irq_init(struct s2mu004_dev
*s2mu004
)
236 struct i2c_client
*i2c
= s2mu004
->i2c
;
239 if (!s2mu004
->irq_gpio
) {
240 dev_warn(s2mu004
->dev
, "No interrupt specified.\n");
241 s2mu004
->irq_base
= 0;
245 if (!s2mu004
->irq_base
) {
246 dev_err(s2mu004
->dev
, "No interrupt base specified.\n");
250 mutex_init(&s2mu004
->irqlock
);
252 s2mu004
->irq
= gpio_to_irq(s2mu004
->irq_gpio
);
253 pr_err("%s:%s irq=%d, irq->gpio=%d\n", MFD_DEV_NAME
, __func__
,
254 s2mu004
->irq
, s2mu004
->irq_gpio
);
256 ret
= gpio_request(s2mu004
->irq_gpio
, "if_pmic_irq");
258 dev_err(s2mu004
->dev
, "%s: failed requesting gpio %d\n",
259 __func__
, s2mu004
->irq_gpio
);
262 gpio_direction_input(s2mu004
->irq_gpio
);
263 gpio_free(s2mu004
->irq_gpio
);
265 /* Mask individual interrupt sources */
266 for (i
= 0; i
< S2MU004_IRQ_GROUP_NR
; i
++) {
268 s2mu004
->irq_masks_cur
[i
] = 0xff;
269 s2mu004
->irq_masks_cache
[i
] = 0xff;
271 if (IS_ERR_OR_NULL(i2c
))
273 if (s2mu004_mask_reg
[i
] == S2MU004_REG_INVALID
)
275 s2mu004_write_reg(i2c
, s2mu004_mask_reg
[i
], 0xff);
278 /* Register with genirq */
279 for (i
= 0; i
< S2MU004_IRQ_NR
; i
++) {
281 cur_irq
= i
+ s2mu004
->irq_base
;
282 irq_set_chip_data(cur_irq
, s2mu004
);
283 irq_set_chip_and_handler(cur_irq
, &s2mu004_irq_chip
,
285 irq_set_nested_thread(cur_irq
, 1);
287 set_irq_flags(cur_irq
, IRQF_VALID
);
289 irq_set_noprobe(cur_irq
);
294 ret
= request_threaded_irq(s2mu004
->irq
, NULL
,
296 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
,
297 "s2mu004-irq", s2mu004
);
301 dev_err(s2mu004
->dev
, "Failed to request IRQ %d: %d\n",
309 void s2mu004_irq_exit(struct s2mu004_dev
*s2mu004
)
312 free_irq(s2mu004
->irq
, s2mu004
);