xref: /linux/drivers/ssb/driver_gpio.c (revision ec43b08b5733494ad88aa618ecdf534320dd8207)
1*ec43b08bSHauke Mehrtens /*
2*ec43b08bSHauke Mehrtens  * Sonics Silicon Backplane
3*ec43b08bSHauke Mehrtens  * GPIO driver
4*ec43b08bSHauke Mehrtens  *
5*ec43b08bSHauke Mehrtens  * Copyright 2011, Broadcom Corporation
6*ec43b08bSHauke Mehrtens  * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7*ec43b08bSHauke Mehrtens  *
8*ec43b08bSHauke Mehrtens  * Licensed under the GNU/GPL. See COPYING for details.
9*ec43b08bSHauke Mehrtens  */
10*ec43b08bSHauke Mehrtens 
11*ec43b08bSHauke Mehrtens #include <linux/gpio.h>
12*ec43b08bSHauke Mehrtens #include <linux/export.h>
13*ec43b08bSHauke Mehrtens #include <linux/ssb/ssb.h>
14*ec43b08bSHauke Mehrtens 
15*ec43b08bSHauke Mehrtens #include "ssb_private.h"
16*ec43b08bSHauke Mehrtens 
17*ec43b08bSHauke Mehrtens static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
18*ec43b08bSHauke Mehrtens {
19*ec43b08bSHauke Mehrtens 	return container_of(chip, struct ssb_bus, gpio);
20*ec43b08bSHauke Mehrtens }
21*ec43b08bSHauke Mehrtens 
22*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
23*ec43b08bSHauke Mehrtens {
24*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
25*ec43b08bSHauke Mehrtens 
26*ec43b08bSHauke Mehrtens 	return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
27*ec43b08bSHauke Mehrtens }
28*ec43b08bSHauke Mehrtens 
29*ec43b08bSHauke Mehrtens static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
30*ec43b08bSHauke Mehrtens 				      int value)
31*ec43b08bSHauke Mehrtens {
32*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
33*ec43b08bSHauke Mehrtens 
34*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
35*ec43b08bSHauke Mehrtens }
36*ec43b08bSHauke Mehrtens 
37*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
38*ec43b08bSHauke Mehrtens 					   unsigned gpio)
39*ec43b08bSHauke Mehrtens {
40*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
41*ec43b08bSHauke Mehrtens 
42*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
43*ec43b08bSHauke Mehrtens 	return 0;
44*ec43b08bSHauke Mehrtens }
45*ec43b08bSHauke Mehrtens 
46*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
47*ec43b08bSHauke Mehrtens 					    unsigned gpio, int value)
48*ec43b08bSHauke Mehrtens {
49*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
50*ec43b08bSHauke Mehrtens 
51*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
52*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
53*ec43b08bSHauke Mehrtens 	return 0;
54*ec43b08bSHauke Mehrtens }
55*ec43b08bSHauke Mehrtens 
56*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
57*ec43b08bSHauke Mehrtens {
58*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
59*ec43b08bSHauke Mehrtens 
60*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
61*ec43b08bSHauke Mehrtens 	/* clear pulldown */
62*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
63*ec43b08bSHauke Mehrtens 	/* Set pullup */
64*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
65*ec43b08bSHauke Mehrtens 
66*ec43b08bSHauke Mehrtens 	return 0;
67*ec43b08bSHauke Mehrtens }
68*ec43b08bSHauke Mehrtens 
69*ec43b08bSHauke Mehrtens static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
70*ec43b08bSHauke Mehrtens {
71*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
72*ec43b08bSHauke Mehrtens 
73*ec43b08bSHauke Mehrtens 	/* clear pullup */
74*ec43b08bSHauke Mehrtens 	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
75*ec43b08bSHauke Mehrtens }
76*ec43b08bSHauke Mehrtens 
77*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_init(struct ssb_bus *bus)
78*ec43b08bSHauke Mehrtens {
79*ec43b08bSHauke Mehrtens 	struct gpio_chip *chip = &bus->gpio;
80*ec43b08bSHauke Mehrtens 
81*ec43b08bSHauke Mehrtens 	chip->label		= "ssb_chipco_gpio";
82*ec43b08bSHauke Mehrtens 	chip->owner		= THIS_MODULE;
83*ec43b08bSHauke Mehrtens 	chip->request		= ssb_gpio_chipco_request;
84*ec43b08bSHauke Mehrtens 	chip->free		= ssb_gpio_chipco_free;
85*ec43b08bSHauke Mehrtens 	chip->get		= ssb_gpio_chipco_get_value;
86*ec43b08bSHauke Mehrtens 	chip->set		= ssb_gpio_chipco_set_value;
87*ec43b08bSHauke Mehrtens 	chip->direction_input	= ssb_gpio_chipco_direction_input;
88*ec43b08bSHauke Mehrtens 	chip->direction_output	= ssb_gpio_chipco_direction_output;
89*ec43b08bSHauke Mehrtens 	chip->ngpio		= 16;
90*ec43b08bSHauke Mehrtens 	/* There is just one SoC in one device and its GPIO addresses should be
91*ec43b08bSHauke Mehrtens 	 * deterministic to address them more easily. The other buses could get
92*ec43b08bSHauke Mehrtens 	 * a random base number. */
93*ec43b08bSHauke Mehrtens 	if (bus->bustype == SSB_BUSTYPE_SSB)
94*ec43b08bSHauke Mehrtens 		chip->base		= 0;
95*ec43b08bSHauke Mehrtens 	else
96*ec43b08bSHauke Mehrtens 		chip->base		= -1;
97*ec43b08bSHauke Mehrtens 
98*ec43b08bSHauke Mehrtens 	return gpiochip_add(chip);
99*ec43b08bSHauke Mehrtens }
100*ec43b08bSHauke Mehrtens 
101*ec43b08bSHauke Mehrtens #ifdef CONFIG_SSB_DRIVER_EXTIF
102*ec43b08bSHauke Mehrtens 
103*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
104*ec43b08bSHauke Mehrtens {
105*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
106*ec43b08bSHauke Mehrtens 
107*ec43b08bSHauke Mehrtens 	return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
108*ec43b08bSHauke Mehrtens }
109*ec43b08bSHauke Mehrtens 
110*ec43b08bSHauke Mehrtens static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
111*ec43b08bSHauke Mehrtens 				     int value)
112*ec43b08bSHauke Mehrtens {
113*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
114*ec43b08bSHauke Mehrtens 
115*ec43b08bSHauke Mehrtens 	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
116*ec43b08bSHauke Mehrtens }
117*ec43b08bSHauke Mehrtens 
118*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
119*ec43b08bSHauke Mehrtens 					  unsigned gpio)
120*ec43b08bSHauke Mehrtens {
121*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
122*ec43b08bSHauke Mehrtens 
123*ec43b08bSHauke Mehrtens 	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
124*ec43b08bSHauke Mehrtens 	return 0;
125*ec43b08bSHauke Mehrtens }
126*ec43b08bSHauke Mehrtens 
127*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
128*ec43b08bSHauke Mehrtens 					   unsigned gpio, int value)
129*ec43b08bSHauke Mehrtens {
130*ec43b08bSHauke Mehrtens 	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
131*ec43b08bSHauke Mehrtens 
132*ec43b08bSHauke Mehrtens 	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
133*ec43b08bSHauke Mehrtens 	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
134*ec43b08bSHauke Mehrtens 	return 0;
135*ec43b08bSHauke Mehrtens }
136*ec43b08bSHauke Mehrtens 
137*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus)
138*ec43b08bSHauke Mehrtens {
139*ec43b08bSHauke Mehrtens 	struct gpio_chip *chip = &bus->gpio;
140*ec43b08bSHauke Mehrtens 
141*ec43b08bSHauke Mehrtens 	chip->label		= "ssb_extif_gpio";
142*ec43b08bSHauke Mehrtens 	chip->owner		= THIS_MODULE;
143*ec43b08bSHauke Mehrtens 	chip->get		= ssb_gpio_extif_get_value;
144*ec43b08bSHauke Mehrtens 	chip->set		= ssb_gpio_extif_set_value;
145*ec43b08bSHauke Mehrtens 	chip->direction_input	= ssb_gpio_extif_direction_input;
146*ec43b08bSHauke Mehrtens 	chip->direction_output	= ssb_gpio_extif_direction_output;
147*ec43b08bSHauke Mehrtens 	chip->ngpio		= 5;
148*ec43b08bSHauke Mehrtens 	/* There is just one SoC in one device and its GPIO addresses should be
149*ec43b08bSHauke Mehrtens 	 * deterministic to address them more easily. The other buses could get
150*ec43b08bSHauke Mehrtens 	 * a random base number. */
151*ec43b08bSHauke Mehrtens 	if (bus->bustype == SSB_BUSTYPE_SSB)
152*ec43b08bSHauke Mehrtens 		chip->base		= 0;
153*ec43b08bSHauke Mehrtens 	else
154*ec43b08bSHauke Mehrtens 		chip->base		= -1;
155*ec43b08bSHauke Mehrtens 
156*ec43b08bSHauke Mehrtens 	return gpiochip_add(chip);
157*ec43b08bSHauke Mehrtens }
158*ec43b08bSHauke Mehrtens 
159*ec43b08bSHauke Mehrtens #else
160*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus)
161*ec43b08bSHauke Mehrtens {
162*ec43b08bSHauke Mehrtens 	return -ENOTSUPP;
163*ec43b08bSHauke Mehrtens }
164*ec43b08bSHauke Mehrtens #endif
165*ec43b08bSHauke Mehrtens 
166*ec43b08bSHauke Mehrtens int ssb_gpio_init(struct ssb_bus *bus)
167*ec43b08bSHauke Mehrtens {
168*ec43b08bSHauke Mehrtens 	if (ssb_chipco_available(&bus->chipco))
169*ec43b08bSHauke Mehrtens 		return ssb_gpio_chipco_init(bus);
170*ec43b08bSHauke Mehrtens 	else if (ssb_extif_available(&bus->extif))
171*ec43b08bSHauke Mehrtens 		return ssb_gpio_extif_init(bus);
172*ec43b08bSHauke Mehrtens 	else
173*ec43b08bSHauke Mehrtens 		SSB_WARN_ON(1);
174*ec43b08bSHauke Mehrtens 
175*ec43b08bSHauke Mehrtens 	return -1;
176*ec43b08bSHauke Mehrtens }
177