Skip to content

Commit 7c1bc0d

Browse files
rmileckiralfbaechle
authored andcommitted
ssb: gpio: add own IRQ domain
Signed-off-by: Rafał Miłecki <[email protected]> Acked-by: Hauke Mehrtens <[email protected]> Acked-by: Michael Buesch <[email protected]> Signed-off-by: John Crispin <[email protected]> Patchwork: http://patchwork.linux-mips.org/patch/6342/
1 parent 89fb3ac commit 7c1bc0d

File tree

4 files changed

+299
-21
lines changed

4 files changed

+299
-21
lines changed

drivers/ssb/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ config SSB_DRIVER_GIGE
168168
config SSB_DRIVER_GPIO
169169
bool "SSB GPIO driver"
170170
depends on SSB && GPIOLIB
171+
select IRQ_DOMAIN if SSB_EMBEDDED
171172
help
172173
Driver to provide access to the GPIO pins on the bus.
173174

drivers/ssb/driver_gpio.c

Lines changed: 290 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,40 @@
99
*/
1010

1111
#include <linux/gpio.h>
12+
#include <linux/irq.h>
13+
#include <linux/interrupt.h>
14+
#include <linux/irqdomain.h>
1215
#include <linux/export.h>
1316
#include <linux/ssb/ssb.h>
1417

1518
#include "ssb_private.h"
1619

20+
21+
/**************************************************
22+
* Shared
23+
**************************************************/
24+
1725
static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
1826
{
1927
return container_of(chip, struct ssb_bus, gpio);
2028
}
2129

30+
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
31+
static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
32+
{
33+
struct ssb_bus *bus = ssb_gpio_get_bus(chip);
34+
35+
if (bus->bustype == SSB_BUSTYPE_SSB)
36+
return irq_find_mapping(bus->irq_domain, gpio);
37+
else
38+
return -EINVAL;
39+
}
40+
#endif
41+
42+
/**************************************************
43+
* ChipCommon
44+
**************************************************/
45+
2246
static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
2347
{
2448
struct ssb_bus *bus = ssb_gpio_get_bus(chip);
@@ -74,19 +98,129 @@ static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
7498
ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
7599
}
76100

77-
static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio)
101+
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
102+
static void ssb_gpio_irq_chipco_mask(struct irq_data *d)
78103
{
79-
struct ssb_bus *bus = ssb_gpio_get_bus(chip);
104+
struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
105+
int gpio = irqd_to_hwirq(d);
80106

81-
if (bus->bustype == SSB_BUSTYPE_SSB)
82-
return ssb_mips_irq(bus->chipco.dev) + 2;
83-
else
84-
return -EINVAL;
107+
ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0);
108+
}
109+
110+
static void ssb_gpio_irq_chipco_unmask(struct irq_data *d)
111+
{
112+
struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
113+
int gpio = irqd_to_hwirq(d);
114+
u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio));
115+
116+
ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val);
117+
ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio));
118+
}
119+
120+
static struct irq_chip ssb_gpio_irq_chipco_chip = {
121+
.name = "SSB-GPIO-CC",
122+
.irq_mask = ssb_gpio_irq_chipco_mask,
123+
.irq_unmask = ssb_gpio_irq_chipco_unmask,
124+
};
125+
126+
static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id)
127+
{
128+
struct ssb_bus *bus = dev_id;
129+
struct ssb_chipcommon *chipco = &bus->chipco;
130+
u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN);
131+
u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ);
132+
u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL);
133+
unsigned long irqs = (val ^ pol) & mask;
134+
int gpio;
135+
136+
if (!irqs)
137+
return IRQ_NONE;
138+
139+
for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
140+
generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
141+
ssb_chipco_gpio_polarity(chipco, irqs, val & irqs);
142+
143+
return IRQ_HANDLED;
144+
}
145+
146+
static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
147+
{
148+
struct ssb_chipcommon *chipco = &bus->chipco;
149+
struct gpio_chip *chip = &bus->gpio;
150+
int gpio, hwirq, err;
151+
152+
if (bus->bustype != SSB_BUSTYPE_SSB)
153+
return 0;
154+
155+
bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
156+
&irq_domain_simple_ops, chipco);
157+
if (!bus->irq_domain) {
158+
err = -ENODEV;
159+
goto err_irq_domain;
160+
}
161+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
162+
int irq = irq_create_mapping(bus->irq_domain, gpio);
163+
164+
irq_set_chip_data(irq, bus);
165+
irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip,
166+
handle_simple_irq);
167+
}
168+
169+
hwirq = ssb_mips_irq(bus->chipco.dev) + 2;
170+
err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED,
171+
"gpio", bus);
172+
if (err)
173+
goto err_req_irq;
174+
175+
ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0);
176+
chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO);
177+
178+
return 0;
179+
180+
err_req_irq:
181+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
182+
int irq = irq_find_mapping(bus->irq_domain, gpio);
183+
184+
irq_dispose_mapping(irq);
185+
}
186+
irq_domain_remove(bus->irq_domain);
187+
err_irq_domain:
188+
return err;
189+
}
190+
191+
static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
192+
{
193+
struct ssb_chipcommon *chipco = &bus->chipco;
194+
struct gpio_chip *chip = &bus->gpio;
195+
int gpio;
196+
197+
if (bus->bustype != SSB_BUSTYPE_SSB)
198+
return;
199+
200+
chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO);
201+
free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco);
202+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
203+
int irq = irq_find_mapping(bus->irq_domain, gpio);
204+
205+
irq_dispose_mapping(irq);
206+
}
207+
irq_domain_remove(bus->irq_domain);
208+
}
209+
#else
210+
static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
211+
{
212+
return 0;
85213
}
86214

215+
static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
216+
{
217+
}
218+
#endif
219+
87220
static int ssb_gpio_chipco_init(struct ssb_bus *bus)
88221
{
89222
struct gpio_chip *chip = &bus->gpio;
223+
int err;
90224

91225
chip->label = "ssb_chipco_gpio";
92226
chip->owner = THIS_MODULE;
@@ -96,7 +230,9 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus)
96230
chip->set = ssb_gpio_chipco_set_value;
97231
chip->direction_input = ssb_gpio_chipco_direction_input;
98232
chip->direction_output = ssb_gpio_chipco_direction_output;
99-
chip->to_irq = ssb_gpio_chipco_to_irq;
233+
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
234+
chip->to_irq = ssb_gpio_to_irq;
235+
#endif
100236
chip->ngpio = 16;
101237
/* There is just one SoC in one device and its GPIO addresses should be
102238
* deterministic to address them more easily. The other buses could get
@@ -106,9 +242,23 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus)
106242
else
107243
chip->base = -1;
108244

109-
return gpiochip_add(chip);
245+
err = ssb_gpio_irq_chipco_domain_init(bus);
246+
if (err)
247+
return err;
248+
249+
err = gpiochip_add(chip);
250+
if (err) {
251+
ssb_gpio_irq_chipco_domain_exit(bus);
252+
return err;
253+
}
254+
255+
return 0;
110256
}
111257

258+
/**************************************************
259+
* EXTIF
260+
**************************************************/
261+
112262
#ifdef CONFIG_SSB_DRIVER_EXTIF
113263

114264
static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
@@ -145,27 +295,137 @@ static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
145295
return 0;
146296
}
147297

148-
static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio)
298+
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
299+
static void ssb_gpio_irq_extif_mask(struct irq_data *d)
149300
{
150-
struct ssb_bus *bus = ssb_gpio_get_bus(chip);
301+
struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
302+
int gpio = irqd_to_hwirq(d);
151303

152-
if (bus->bustype == SSB_BUSTYPE_SSB)
153-
return ssb_mips_irq(bus->extif.dev) + 2;
154-
else
155-
return -EINVAL;
304+
ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0);
305+
}
306+
307+
static void ssb_gpio_irq_extif_unmask(struct irq_data *d)
308+
{
309+
struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
310+
int gpio = irqd_to_hwirq(d);
311+
u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio));
312+
313+
ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val);
314+
ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio));
315+
}
316+
317+
static struct irq_chip ssb_gpio_irq_extif_chip = {
318+
.name = "SSB-GPIO-EXTIF",
319+
.irq_mask = ssb_gpio_irq_extif_mask,
320+
.irq_unmask = ssb_gpio_irq_extif_unmask,
321+
};
322+
323+
static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id)
324+
{
325+
struct ssb_bus *bus = dev_id;
326+
struct ssb_extif *extif = &bus->extif;
327+
u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN);
328+
u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK);
329+
u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL);
330+
unsigned long irqs = (val ^ pol) & mask;
331+
int gpio;
332+
333+
if (!irqs)
334+
return IRQ_NONE;
335+
336+
for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
337+
generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
338+
ssb_extif_gpio_polarity(extif, irqs, val & irqs);
339+
340+
return IRQ_HANDLED;
341+
}
342+
343+
static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
344+
{
345+
struct ssb_extif *extif = &bus->extif;
346+
struct gpio_chip *chip = &bus->gpio;
347+
int gpio, hwirq, err;
348+
349+
if (bus->bustype != SSB_BUSTYPE_SSB)
350+
return 0;
351+
352+
bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
353+
&irq_domain_simple_ops, extif);
354+
if (!bus->irq_domain) {
355+
err = -ENODEV;
356+
goto err_irq_domain;
357+
}
358+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
359+
int irq = irq_create_mapping(bus->irq_domain, gpio);
360+
361+
irq_set_chip_data(irq, bus);
362+
irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip,
363+
handle_simple_irq);
364+
}
365+
366+
hwirq = ssb_mips_irq(bus->extif.dev) + 2;
367+
err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED,
368+
"gpio", bus);
369+
if (err)
370+
goto err_req_irq;
371+
372+
ssb_extif_gpio_intmask(&bus->extif, ~0, 0);
373+
374+
return 0;
375+
376+
err_req_irq:
377+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
378+
int irq = irq_find_mapping(bus->irq_domain, gpio);
379+
380+
irq_dispose_mapping(irq);
381+
}
382+
irq_domain_remove(bus->irq_domain);
383+
err_irq_domain:
384+
return err;
385+
}
386+
387+
static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
388+
{
389+
struct ssb_extif *extif = &bus->extif;
390+
struct gpio_chip *chip = &bus->gpio;
391+
int gpio;
392+
393+
if (bus->bustype != SSB_BUSTYPE_SSB)
394+
return;
395+
396+
free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif);
397+
for (gpio = 0; gpio < chip->ngpio; gpio++) {
398+
int irq = irq_find_mapping(bus->irq_domain, gpio);
399+
400+
irq_dispose_mapping(irq);
401+
}
402+
irq_domain_remove(bus->irq_domain);
156403
}
404+
#else
405+
static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
406+
{
407+
return 0;
408+
}
409+
410+
static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
411+
{
412+
}
413+
#endif
157414

158415
static int ssb_gpio_extif_init(struct ssb_bus *bus)
159416
{
160417
struct gpio_chip *chip = &bus->gpio;
418+
int err;
161419

162420
chip->label = "ssb_extif_gpio";
163421
chip->owner = THIS_MODULE;
164422
chip->get = ssb_gpio_extif_get_value;
165423
chip->set = ssb_gpio_extif_set_value;
166424
chip->direction_input = ssb_gpio_extif_direction_input;
167425
chip->direction_output = ssb_gpio_extif_direction_output;
168-
chip->to_irq = ssb_gpio_extif_to_irq;
426+
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
427+
chip->to_irq = ssb_gpio_to_irq;
428+
#endif
169429
chip->ngpio = 5;
170430
/* There is just one SoC in one device and its GPIO addresses should be
171431
* deterministic to address them more easily. The other buses could get
@@ -175,7 +435,17 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
175435
else
176436
chip->base = -1;
177437

178-
return gpiochip_add(chip);
438+
err = ssb_gpio_irq_extif_domain_init(bus);
439+
if (err)
440+
return err;
441+
442+
err = gpiochip_add(chip);
443+
if (err) {
444+
ssb_gpio_irq_extif_domain_exit(bus);
445+
return err;
446+
}
447+
448+
return 0;
179449
}
180450

181451
#else
@@ -185,6 +455,10 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
185455
}
186456
#endif
187457

458+
/**************************************************
459+
* Init
460+
**************************************************/
461+
188462
int ssb_gpio_init(struct ssb_bus *bus)
189463
{
190464
if (ssb_chipco_available(&bus->chipco))

0 commit comments

Comments
 (0)