1/*
2 * tps65912-irq.c  --  TI TPS6591x
3 *
4 * Copyright 2011 Texas Instruments Inc.
5 *
6 * Author: Margarita Olaya <magi@slimlogic.co.uk>
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 * This driver is based on wm8350 implementation.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/bug.h>
19#include <linux/device.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22#include <linux/gpio.h>
23#include <linux/mfd/tps65912.h>
24
25static inline int irq_to_tps65912_irq(struct tps65912 *tps65912,
26							int irq)
27{
28	return irq - tps65912->irq_base;
29}
30
31/*
32 * This is a threaded IRQ handler so can access I2C/SPI.  Since the
33 * IRQ handler explicitly clears the IRQ it handles the IRQ line
34 * will be reasserted and the physical IRQ will be handled again if
35 * another interrupt is asserted while we run - in the normal course
36 * of events this is a rare occurrence so we save I2C/SPI reads. We're
37 * also assuming that it's rare to get lots of interrupts firing
38 * simultaneously so try to minimise I/O.
39 */
40static irqreturn_t tps65912_irq(int irq, void *irq_data)
41{
42	struct tps65912 *tps65912 = irq_data;
43	u32 irq_sts;
44	u32 irq_mask;
45	u8 reg;
46	int i;
47
48
49	tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
50	irq_sts = reg;
51	tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
52	irq_sts |= reg << 8;
53	tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
54	irq_sts |= reg << 16;
55	tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
56	irq_sts |= reg << 24;
57
58	tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
59	irq_mask = reg;
60	tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
61	irq_mask |= reg << 8;
62	tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
63	irq_mask |= reg << 16;
64	tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
65	irq_mask |= reg << 24;
66
67	irq_sts &= ~irq_mask;
68	if (!irq_sts)
69		return IRQ_NONE;
70
71	for (i = 0; i < tps65912->irq_num; i++) {
72		if (!(irq_sts & (1 << i)))
73			continue;
74
75		handle_nested_irq(tps65912->irq_base + i);
76	}
77
78	/* Write the STS register back to clear IRQs we handled */
79	reg = irq_sts & 0xFF;
80	irq_sts >>= 8;
81	if (reg)
82		tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
83	reg = irq_sts & 0xFF;
84	irq_sts >>= 8;
85	if (reg)
86		tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
87	reg = irq_sts & 0xFF;
88	irq_sts >>= 8;
89	if (reg)
90		tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
91	reg = irq_sts & 0xFF;
92	if (reg)
93		tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
94
95	return IRQ_HANDLED;
96}
97
98static void tps65912_irq_lock(struct irq_data *data)
99{
100	struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
101
102	mutex_lock(&tps65912->irq_lock);
103}
104
105static void tps65912_irq_sync_unlock(struct irq_data *data)
106{
107	struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
108	u32 reg_mask;
109	u8 reg;
110
111	tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
112	reg_mask = reg;
113	tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
114	reg_mask |= reg << 8;
115	tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
116	reg_mask |= reg << 16;
117	tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
118	reg_mask |= reg << 24;
119
120	if (tps65912->irq_mask != reg_mask) {
121		reg = tps65912->irq_mask & 0xFF;
122		tps65912->write(tps65912, TPS65912_INT_MSK, 1, &reg);
123		reg = tps65912->irq_mask >> 8 & 0xFF;
124		tps65912->write(tps65912, TPS65912_INT_MSK2, 1, &reg);
125		reg = tps65912->irq_mask >> 16 & 0xFF;
126		tps65912->write(tps65912, TPS65912_INT_MSK3, 1, &reg);
127		reg = tps65912->irq_mask >> 24 & 0xFF;
128		tps65912->write(tps65912, TPS65912_INT_MSK4, 1, &reg);
129	}
130
131	mutex_unlock(&tps65912->irq_lock);
132}
133
134static void tps65912_irq_enable(struct irq_data *data)
135{
136	struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
137
138	tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq));
139}
140
141static void tps65912_irq_disable(struct irq_data *data)
142{
143	struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
144
145	tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq));
146}
147
148static struct irq_chip tps65912_irq_chip = {
149	.name = "tps65912",
150	.irq_bus_lock = tps65912_irq_lock,
151	.irq_bus_sync_unlock = tps65912_irq_sync_unlock,
152	.irq_disable = tps65912_irq_disable,
153	.irq_enable = tps65912_irq_enable,
154};
155
156int tps65912_irq_init(struct tps65912 *tps65912, int irq,
157			    struct tps65912_platform_data *pdata)
158{
159	int ret, cur_irq;
160	int flags = IRQF_ONESHOT;
161	u8 reg;
162
163	if (!irq) {
164		dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n");
165		return 0;
166	}
167
168	if (!pdata || !pdata->irq_base) {
169		dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n");
170		return 0;
171	}
172
173	/* Clear unattended interrupts */
174	tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
175	tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
176	tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
177	tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
178	tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
179	tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
180	tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
181	tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
182
183	/* Mask top level interrupts */
184	tps65912->irq_mask = 0xFFFFFFFF;
185
186	mutex_init(&tps65912->irq_lock);
187	tps65912->chip_irq = irq;
188	tps65912->irq_base = pdata->irq_base;
189
190	tps65912->irq_num = TPS65912_NUM_IRQ;
191
192	/* Register with genirq */
193	for (cur_irq = tps65912->irq_base;
194	     cur_irq < tps65912->irq_num + tps65912->irq_base;
195	     cur_irq++) {
196		irq_set_chip_data(cur_irq, tps65912);
197		irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip,
198					 handle_edge_irq);
199		irq_set_nested_thread(cur_irq, 1);
200		/* ARM needs us to explicitly flag the IRQ as valid
201		 * and will set them noprobe when we do so. */
202#ifdef CONFIG_ARM
203		set_irq_flags(cur_irq, IRQF_VALID);
204#else
205		irq_set_noprobe(cur_irq);
206#endif
207	}
208
209	ret = request_threaded_irq(irq, NULL, tps65912_irq, flags,
210				   "tps65912", tps65912);
211
212	irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
213	if (ret != 0)
214		dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret);
215
216	return ret;
217}
218
219int tps65912_irq_exit(struct tps65912 *tps65912)
220{
221	free_irq(tps65912->chip_irq, tps65912);
222	return 0;
223}
224