xref: /OK3568_Linux_fs/kernel/drivers/ssb/driver_gpio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Sonics Silicon Backplane
3*4882a593Smuzhiyun  * GPIO driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2011, Broadcom Corporation
6*4882a593Smuzhiyun  * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Licensed under the GNU/GPL. See COPYING for details.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "ssb_private.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/gpio/driver.h>
14*4882a593Smuzhiyun #include <linux/irq.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/irqdomain.h>
17*4882a593Smuzhiyun #include <linux/export.h>
18*4882a593Smuzhiyun #include <linux/ssb/ssb.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /**************************************************
22*4882a593Smuzhiyun  * Shared
23*4882a593Smuzhiyun  **************************************************/
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SSB_EMBEDDED)
ssb_gpio_to_irq(struct gpio_chip * chip,unsigned int gpio)26*4882a593Smuzhiyun static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (bus->bustype == SSB_BUSTYPE_SSB)
31*4882a593Smuzhiyun 		return irq_find_mapping(bus->irq_domain, gpio);
32*4882a593Smuzhiyun 	else
33*4882a593Smuzhiyun 		return -EINVAL;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun #endif
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /**************************************************
38*4882a593Smuzhiyun  * ChipCommon
39*4882a593Smuzhiyun  **************************************************/
40*4882a593Smuzhiyun 
ssb_gpio_chipco_get_value(struct gpio_chip * chip,unsigned int gpio)41*4882a593Smuzhiyun static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned int gpio)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
ssb_gpio_chipco_set_value(struct gpio_chip * chip,unsigned int gpio,int value)48*4882a593Smuzhiyun static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned int gpio,
49*4882a593Smuzhiyun 				      int value)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
ssb_gpio_chipco_direction_input(struct gpio_chip * chip,unsigned int gpio)56*4882a593Smuzhiyun static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
57*4882a593Smuzhiyun 					   unsigned int gpio)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
62*4882a593Smuzhiyun 	return 0;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
ssb_gpio_chipco_direction_output(struct gpio_chip * chip,unsigned int gpio,int value)65*4882a593Smuzhiyun static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
66*4882a593Smuzhiyun 					    unsigned int gpio, int value)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
71*4882a593Smuzhiyun 	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
72*4882a593Smuzhiyun 	return 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
ssb_gpio_chipco_request(struct gpio_chip * chip,unsigned int gpio)75*4882a593Smuzhiyun static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned int gpio)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
80*4882a593Smuzhiyun 	/* clear pulldown */
81*4882a593Smuzhiyun 	ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
82*4882a593Smuzhiyun 	/* Set pullup */
83*4882a593Smuzhiyun 	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
ssb_gpio_chipco_free(struct gpio_chip * chip,unsigned int gpio)88*4882a593Smuzhiyun static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned int gpio)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	/* clear pullup */
93*4882a593Smuzhiyun 	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SSB_EMBEDDED)
ssb_gpio_irq_chipco_mask(struct irq_data * d)97*4882a593Smuzhiyun static void ssb_gpio_irq_chipco_mask(struct irq_data *d)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
100*4882a593Smuzhiyun 	int gpio = irqd_to_hwirq(d);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
ssb_gpio_irq_chipco_unmask(struct irq_data * d)105*4882a593Smuzhiyun static void ssb_gpio_irq_chipco_unmask(struct irq_data *d)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
108*4882a593Smuzhiyun 	int gpio = irqd_to_hwirq(d);
109*4882a593Smuzhiyun 	u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio));
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val);
112*4882a593Smuzhiyun 	ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio));
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static struct irq_chip ssb_gpio_irq_chipco_chip = {
116*4882a593Smuzhiyun 	.name		= "SSB-GPIO-CC",
117*4882a593Smuzhiyun 	.irq_mask	= ssb_gpio_irq_chipco_mask,
118*4882a593Smuzhiyun 	.irq_unmask	= ssb_gpio_irq_chipco_unmask,
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun 
ssb_gpio_irq_chipco_handler(int irq,void * dev_id)121*4882a593Smuzhiyun static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	struct ssb_bus *bus = dev_id;
124*4882a593Smuzhiyun 	struct ssb_chipcommon *chipco = &bus->chipco;
125*4882a593Smuzhiyun 	u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN);
126*4882a593Smuzhiyun 	u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ);
127*4882a593Smuzhiyun 	u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL);
128*4882a593Smuzhiyun 	unsigned long irqs = (val ^ pol) & mask;
129*4882a593Smuzhiyun 	int gpio;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	if (!irqs)
132*4882a593Smuzhiyun 		return IRQ_NONE;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
135*4882a593Smuzhiyun 		generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
136*4882a593Smuzhiyun 	ssb_chipco_gpio_polarity(chipco, irqs, val & irqs);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return IRQ_HANDLED;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
ssb_gpio_irq_chipco_domain_init(struct ssb_bus * bus)141*4882a593Smuzhiyun static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct ssb_chipcommon *chipco = &bus->chipco;
144*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
145*4882a593Smuzhiyun 	int gpio, hwirq, err;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (bus->bustype != SSB_BUSTYPE_SSB)
148*4882a593Smuzhiyun 		return 0;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
151*4882a593Smuzhiyun 						&irq_domain_simple_ops, chipco);
152*4882a593Smuzhiyun 	if (!bus->irq_domain) {
153*4882a593Smuzhiyun 		err = -ENODEV;
154*4882a593Smuzhiyun 		goto err_irq_domain;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
157*4882a593Smuzhiyun 		int irq = irq_create_mapping(bus->irq_domain, gpio);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 		irq_set_chip_data(irq, bus);
160*4882a593Smuzhiyun 		irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip,
161*4882a593Smuzhiyun 					 handle_simple_irq);
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	hwirq = ssb_mips_irq(bus->chipco.dev) + 2;
165*4882a593Smuzhiyun 	err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED,
166*4882a593Smuzhiyun 			  "gpio", bus);
167*4882a593Smuzhiyun 	if (err)
168*4882a593Smuzhiyun 		goto err_req_irq;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0);
171*4882a593Smuzhiyun 	chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun err_req_irq:
176*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
177*4882a593Smuzhiyun 		int irq = irq_find_mapping(bus->irq_domain, gpio);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		irq_dispose_mapping(irq);
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 	irq_domain_remove(bus->irq_domain);
182*4882a593Smuzhiyun err_irq_domain:
183*4882a593Smuzhiyun 	return err;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
ssb_gpio_irq_chipco_domain_exit(struct ssb_bus * bus)186*4882a593Smuzhiyun static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	struct ssb_chipcommon *chipco = &bus->chipco;
189*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
190*4882a593Smuzhiyun 	int gpio;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	if (bus->bustype != SSB_BUSTYPE_SSB)
193*4882a593Smuzhiyun 		return;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO);
196*4882a593Smuzhiyun 	free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco);
197*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
198*4882a593Smuzhiyun 		int irq = irq_find_mapping(bus->irq_domain, gpio);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		irq_dispose_mapping(irq);
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 	irq_domain_remove(bus->irq_domain);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun #else
ssb_gpio_irq_chipco_domain_init(struct ssb_bus * bus)205*4882a593Smuzhiyun static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	return 0;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
ssb_gpio_irq_chipco_domain_exit(struct ssb_bus * bus)210*4882a593Smuzhiyun static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun #endif
214*4882a593Smuzhiyun 
ssb_gpio_chipco_init(struct ssb_bus * bus)215*4882a593Smuzhiyun static int ssb_gpio_chipco_init(struct ssb_bus *bus)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
218*4882a593Smuzhiyun 	int err;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	chip->label		= "ssb_chipco_gpio";
221*4882a593Smuzhiyun 	chip->owner		= THIS_MODULE;
222*4882a593Smuzhiyun 	chip->request		= ssb_gpio_chipco_request;
223*4882a593Smuzhiyun 	chip->free		= ssb_gpio_chipco_free;
224*4882a593Smuzhiyun 	chip->get		= ssb_gpio_chipco_get_value;
225*4882a593Smuzhiyun 	chip->set		= ssb_gpio_chipco_set_value;
226*4882a593Smuzhiyun 	chip->direction_input	= ssb_gpio_chipco_direction_input;
227*4882a593Smuzhiyun 	chip->direction_output	= ssb_gpio_chipco_direction_output;
228*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SSB_EMBEDDED)
229*4882a593Smuzhiyun 	chip->to_irq		= ssb_gpio_to_irq;
230*4882a593Smuzhiyun #endif
231*4882a593Smuzhiyun 	chip->ngpio		= 16;
232*4882a593Smuzhiyun 	/* There is just one SoC in one device and its GPIO addresses should be
233*4882a593Smuzhiyun 	 * deterministic to address them more easily. The other buses could get
234*4882a593Smuzhiyun 	 * a random base number. */
235*4882a593Smuzhiyun 	if (bus->bustype == SSB_BUSTYPE_SSB)
236*4882a593Smuzhiyun 		chip->base		= 0;
237*4882a593Smuzhiyun 	else
238*4882a593Smuzhiyun 		chip->base		= -1;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	err = ssb_gpio_irq_chipco_domain_init(bus);
241*4882a593Smuzhiyun 	if (err)
242*4882a593Smuzhiyun 		return err;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	err = gpiochip_add_data(chip, bus);
245*4882a593Smuzhiyun 	if (err) {
246*4882a593Smuzhiyun 		ssb_gpio_irq_chipco_domain_exit(bus);
247*4882a593Smuzhiyun 		return err;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /**************************************************
254*4882a593Smuzhiyun  * EXTIF
255*4882a593Smuzhiyun  **************************************************/
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun #ifdef CONFIG_SSB_DRIVER_EXTIF
258*4882a593Smuzhiyun 
ssb_gpio_extif_get_value(struct gpio_chip * chip,unsigned int gpio)259*4882a593Smuzhiyun static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned int gpio)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
ssb_gpio_extif_set_value(struct gpio_chip * chip,unsigned int gpio,int value)266*4882a593Smuzhiyun static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned int gpio,
267*4882a593Smuzhiyun 				     int value)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
ssb_gpio_extif_direction_input(struct gpio_chip * chip,unsigned int gpio)274*4882a593Smuzhiyun static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
275*4882a593Smuzhiyun 					  unsigned int gpio)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
280*4882a593Smuzhiyun 	return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
ssb_gpio_extif_direction_output(struct gpio_chip * chip,unsigned int gpio,int value)283*4882a593Smuzhiyun static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
284*4882a593Smuzhiyun 					   unsigned int gpio, int value)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	struct ssb_bus *bus = gpiochip_get_data(chip);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
289*4882a593Smuzhiyun 	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
290*4882a593Smuzhiyun 	return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SSB_EMBEDDED)
ssb_gpio_irq_extif_mask(struct irq_data * d)294*4882a593Smuzhiyun static void ssb_gpio_irq_extif_mask(struct irq_data *d)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
297*4882a593Smuzhiyun 	int gpio = irqd_to_hwirq(d);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0);
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
ssb_gpio_irq_extif_unmask(struct irq_data * d)302*4882a593Smuzhiyun static void ssb_gpio_irq_extif_unmask(struct irq_data *d)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
305*4882a593Smuzhiyun 	int gpio = irqd_to_hwirq(d);
306*4882a593Smuzhiyun 	u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio));
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val);
309*4882a593Smuzhiyun 	ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio));
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun static struct irq_chip ssb_gpio_irq_extif_chip = {
313*4882a593Smuzhiyun 	.name		= "SSB-GPIO-EXTIF",
314*4882a593Smuzhiyun 	.irq_mask	= ssb_gpio_irq_extif_mask,
315*4882a593Smuzhiyun 	.irq_unmask	= ssb_gpio_irq_extif_unmask,
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun 
ssb_gpio_irq_extif_handler(int irq,void * dev_id)318*4882a593Smuzhiyun static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct ssb_bus *bus = dev_id;
321*4882a593Smuzhiyun 	struct ssb_extif *extif = &bus->extif;
322*4882a593Smuzhiyun 	u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN);
323*4882a593Smuzhiyun 	u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK);
324*4882a593Smuzhiyun 	u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL);
325*4882a593Smuzhiyun 	unsigned long irqs = (val ^ pol) & mask;
326*4882a593Smuzhiyun 	int gpio;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	if (!irqs)
329*4882a593Smuzhiyun 		return IRQ_NONE;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
332*4882a593Smuzhiyun 		generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
333*4882a593Smuzhiyun 	ssb_extif_gpio_polarity(extif, irqs, val & irqs);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	return IRQ_HANDLED;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
ssb_gpio_irq_extif_domain_init(struct ssb_bus * bus)338*4882a593Smuzhiyun static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	struct ssb_extif *extif = &bus->extif;
341*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
342*4882a593Smuzhiyun 	int gpio, hwirq, err;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	if (bus->bustype != SSB_BUSTYPE_SSB)
345*4882a593Smuzhiyun 		return 0;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
348*4882a593Smuzhiyun 						&irq_domain_simple_ops, extif);
349*4882a593Smuzhiyun 	if (!bus->irq_domain) {
350*4882a593Smuzhiyun 		err = -ENODEV;
351*4882a593Smuzhiyun 		goto err_irq_domain;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
354*4882a593Smuzhiyun 		int irq = irq_create_mapping(bus->irq_domain, gpio);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		irq_set_chip_data(irq, bus);
357*4882a593Smuzhiyun 		irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip,
358*4882a593Smuzhiyun 					 handle_simple_irq);
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	hwirq = ssb_mips_irq(bus->extif.dev) + 2;
362*4882a593Smuzhiyun 	err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED,
363*4882a593Smuzhiyun 			  "gpio", bus);
364*4882a593Smuzhiyun 	if (err)
365*4882a593Smuzhiyun 		goto err_req_irq;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	ssb_extif_gpio_intmask(&bus->extif, ~0, 0);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	return 0;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun err_req_irq:
372*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
373*4882a593Smuzhiyun 		int irq = irq_find_mapping(bus->irq_domain, gpio);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 		irq_dispose_mapping(irq);
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 	irq_domain_remove(bus->irq_domain);
378*4882a593Smuzhiyun err_irq_domain:
379*4882a593Smuzhiyun 	return err;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
ssb_gpio_irq_extif_domain_exit(struct ssb_bus * bus)382*4882a593Smuzhiyun static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	struct ssb_extif *extif = &bus->extif;
385*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
386*4882a593Smuzhiyun 	int gpio;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	if (bus->bustype != SSB_BUSTYPE_SSB)
389*4882a593Smuzhiyun 		return;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif);
392*4882a593Smuzhiyun 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
393*4882a593Smuzhiyun 		int irq = irq_find_mapping(bus->irq_domain, gpio);
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 		irq_dispose_mapping(irq);
396*4882a593Smuzhiyun 	}
397*4882a593Smuzhiyun 	irq_domain_remove(bus->irq_domain);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun #else
ssb_gpio_irq_extif_domain_init(struct ssb_bus * bus)400*4882a593Smuzhiyun static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun 	return 0;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
ssb_gpio_irq_extif_domain_exit(struct ssb_bus * bus)405*4882a593Smuzhiyun static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun #endif
409*4882a593Smuzhiyun 
ssb_gpio_extif_init(struct ssb_bus * bus)410*4882a593Smuzhiyun static int ssb_gpio_extif_init(struct ssb_bus *bus)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	struct gpio_chip *chip = &bus->gpio;
413*4882a593Smuzhiyun 	int err;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	chip->label		= "ssb_extif_gpio";
416*4882a593Smuzhiyun 	chip->owner		= THIS_MODULE;
417*4882a593Smuzhiyun 	chip->get		= ssb_gpio_extif_get_value;
418*4882a593Smuzhiyun 	chip->set		= ssb_gpio_extif_set_value;
419*4882a593Smuzhiyun 	chip->direction_input	= ssb_gpio_extif_direction_input;
420*4882a593Smuzhiyun 	chip->direction_output	= ssb_gpio_extif_direction_output;
421*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SSB_EMBEDDED)
422*4882a593Smuzhiyun 	chip->to_irq		= ssb_gpio_to_irq;
423*4882a593Smuzhiyun #endif
424*4882a593Smuzhiyun 	chip->ngpio		= 5;
425*4882a593Smuzhiyun 	/* There is just one SoC in one device and its GPIO addresses should be
426*4882a593Smuzhiyun 	 * deterministic to address them more easily. The other buses could get
427*4882a593Smuzhiyun 	 * a random base number. */
428*4882a593Smuzhiyun 	if (bus->bustype == SSB_BUSTYPE_SSB)
429*4882a593Smuzhiyun 		chip->base		= 0;
430*4882a593Smuzhiyun 	else
431*4882a593Smuzhiyun 		chip->base		= -1;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	err = ssb_gpio_irq_extif_domain_init(bus);
434*4882a593Smuzhiyun 	if (err)
435*4882a593Smuzhiyun 		return err;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	err = gpiochip_add_data(chip, bus);
438*4882a593Smuzhiyun 	if (err) {
439*4882a593Smuzhiyun 		ssb_gpio_irq_extif_domain_exit(bus);
440*4882a593Smuzhiyun 		return err;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return 0;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun #else
ssb_gpio_extif_init(struct ssb_bus * bus)447*4882a593Smuzhiyun static int ssb_gpio_extif_init(struct ssb_bus *bus)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	return -ENOTSUPP;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun #endif
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun /**************************************************
454*4882a593Smuzhiyun  * Init
455*4882a593Smuzhiyun  **************************************************/
456*4882a593Smuzhiyun 
ssb_gpio_init(struct ssb_bus * bus)457*4882a593Smuzhiyun int ssb_gpio_init(struct ssb_bus *bus)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun 	if (ssb_chipco_available(&bus->chipco))
460*4882a593Smuzhiyun 		return ssb_gpio_chipco_init(bus);
461*4882a593Smuzhiyun 	else if (ssb_extif_available(&bus->extif))
462*4882a593Smuzhiyun 		return ssb_gpio_extif_init(bus);
463*4882a593Smuzhiyun 	return -1;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
ssb_gpio_unregister(struct ssb_bus * bus)466*4882a593Smuzhiyun int ssb_gpio_unregister(struct ssb_bus *bus)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun 	if (ssb_chipco_available(&bus->chipco) ||
469*4882a593Smuzhiyun 	    ssb_extif_available(&bus->extif)) {
470*4882a593Smuzhiyun 		gpiochip_remove(&bus->gpio);
471*4882a593Smuzhiyun 		return 0;
472*4882a593Smuzhiyun 	}
473*4882a593Smuzhiyun 	return -1;
474*4882a593Smuzhiyun }
475