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