aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/driver_gpio.c
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2014-01-13 13:56:08 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-01-24 16:39:54 -0500
commit7c1bc0da3206de789a71c4aae8ac44d580bc5578 (patch)
tree4b73ed9000e7b1f1dbff5f6530b163ac7de1158b /drivers/ssb/driver_gpio.c
parent89fb3ac8621ba78cf11cc7bb1eb0991d204d5b18 (diff)
ssb: gpio: add own IRQ domain
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Acked-by: Hauke Mehrtens <hauke@hauke-m.de> Acked-by: Michael Buesch <m@bues.ch> Signed-off-by: John Crispin <blogic@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/6342/
Diffstat (limited to 'drivers/ssb/driver_gpio.c')
-rw-r--r--drivers/ssb/driver_gpio.c306
1 files changed, 290 insertions, 16 deletions
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
index dc109de228c6..ba350d2035c0 100644
--- a/drivers/ssb/driver_gpio.c
+++ b/drivers/ssb/driver_gpio.c
@@ -9,16 +9,40 @@
9 */ 9 */
10 10
11#include <linux/gpio.h> 11#include <linux/gpio.h>
12#include <linux/irq.h>
13#include <linux/interrupt.h>
14#include <linux/irqdomain.h>
12#include <linux/export.h> 15#include <linux/export.h>
13#include <linux/ssb/ssb.h> 16#include <linux/ssb/ssb.h>
14 17
15#include "ssb_private.h" 18#include "ssb_private.h"
16 19
20
21/**************************************************
22 * Shared
23 **************************************************/
24
17static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) 25static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
18{ 26{
19 return container_of(chip, struct ssb_bus, gpio); 27 return container_of(chip, struct ssb_bus, gpio);
20} 28}
21 29
30#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
31static 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
22static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) 46static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
23{ 47{
24 struct ssb_bus *bus = ssb_gpio_get_bus(chip); 48 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)
74 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); 98 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
75} 99}
76 100
77static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio) 101#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
102static void ssb_gpio_irq_chipco_mask(struct irq_data *d)
78{ 103{
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);
80 106
81 if (bus->bustype == SSB_BUSTYPE_SSB) 107 ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0);
82 return ssb_mips_irq(bus->chipco.dev) + 2; 108}
83 else 109
84 return -EINVAL; 110static 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
120static 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
126static 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
146static 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
180err_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);
187err_irq_domain:
188 return err;
189}
190
191static 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
210static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
211{
212 return 0;
85} 213}
86 214
215static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
216{
217}
218#endif
219
87static int ssb_gpio_chipco_init(struct ssb_bus *bus) 220static int ssb_gpio_chipco_init(struct ssb_bus *bus)
88{ 221{
89 struct gpio_chip *chip = &bus->gpio; 222 struct gpio_chip *chip = &bus->gpio;
223 int err;
90 224
91 chip->label = "ssb_chipco_gpio"; 225 chip->label = "ssb_chipco_gpio";
92 chip->owner = THIS_MODULE; 226 chip->owner = THIS_MODULE;
@@ -96,7 +230,9 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus)
96 chip->set = ssb_gpio_chipco_set_value; 230 chip->set = ssb_gpio_chipco_set_value;
97 chip->direction_input = ssb_gpio_chipco_direction_input; 231 chip->direction_input = ssb_gpio_chipco_direction_input;
98 chip->direction_output = ssb_gpio_chipco_direction_output; 232 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
100 chip->ngpio = 16; 236 chip->ngpio = 16;
101 /* There is just one SoC in one device and its GPIO addresses should be 237 /* There is just one SoC in one device and its GPIO addresses should be
102 * deterministic to address them more easily. The other buses could get 238 * 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)
106 else 242 else
107 chip->base = -1; 243 chip->base = -1;
108 244
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;
110} 256}
111 257
258/**************************************************
259 * EXTIF
260 **************************************************/
261
112#ifdef CONFIG_SSB_DRIVER_EXTIF 262#ifdef CONFIG_SSB_DRIVER_EXTIF
113 263
114static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) 264static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
@@ -145,19 +295,127 @@ static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
145 return 0; 295 return 0;
146} 296}
147 297
148static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio) 298#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
299static void ssb_gpio_irq_extif_mask(struct irq_data *d)
149{ 300{
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);
151 303
152 if (bus->bustype == SSB_BUSTYPE_SSB) 304 ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0);
153 return ssb_mips_irq(bus->extif.dev) + 2; 305}
154 else 306
155 return -EINVAL; 307static 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
317static 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
323static 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
343static 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
376err_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);
383err_irq_domain:
384 return err;
385}
386
387static 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);
156} 403}
404#else
405static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
406{
407 return 0;
408}
409
410static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
411{
412}
413#endif
157 414
158static int ssb_gpio_extif_init(struct ssb_bus *bus) 415static int ssb_gpio_extif_init(struct ssb_bus *bus)
159{ 416{
160 struct gpio_chip *chip = &bus->gpio; 417 struct gpio_chip *chip = &bus->gpio;
418 int err;
161 419
162 chip->label = "ssb_extif_gpio"; 420 chip->label = "ssb_extif_gpio";
163 chip->owner = THIS_MODULE; 421 chip->owner = THIS_MODULE;
@@ -165,7 +423,9 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
165 chip->set = ssb_gpio_extif_set_value; 423 chip->set = ssb_gpio_extif_set_value;
166 chip->direction_input = ssb_gpio_extif_direction_input; 424 chip->direction_input = ssb_gpio_extif_direction_input;
167 chip->direction_output = ssb_gpio_extif_direction_output; 425 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
169 chip->ngpio = 5; 429 chip->ngpio = 5;
170 /* There is just one SoC in one device and its GPIO addresses should be 430 /* There is just one SoC in one device and its GPIO addresses should be
171 * deterministic to address them more easily. The other buses could get 431 * 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)
175 else 435 else
176 chip->base = -1; 436 chip->base = -1;
177 437
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;
179} 449}
180 450
181#else 451#else
@@ -185,6 +455,10 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
185} 455}
186#endif 456#endif
187 457
458/**************************************************
459 * Init
460 **************************************************/
461
188int ssb_gpio_init(struct ssb_bus *bus) 462int ssb_gpio_init(struct ssb_bus *bus)
189{ 463{
190 if (ssb_chipco_available(&bus->chipco)) 464 if (ssb_chipco_available(&bus->chipco))