xref: /openbmc/u-boot/drivers/gpio/sunxi_gpio.c (revision e77e65df)
1 /*
2  * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
3  *
4  * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
5  *
6  * (C) Copyright 2007-2011
7  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
8  * Tom Cubie <tangliang@allwinnertech.com>
9  *
10  * SPDX-License-Identifier:	GPL-2.0+
11  */
12 
13 #include <common.h>
14 #include <dm.h>
15 #include <errno.h>
16 #include <fdtdec.h>
17 #include <malloc.h>
18 #include <asm/io.h>
19 #include <asm/gpio.h>
20 #include <dm/device-internal.h>
21 #ifdef CONFIG_AXP209_POWER
22 #include <axp209.h>
23 #endif
24 
25 DECLARE_GLOBAL_DATA_PTR;
26 
27 #define SUNXI_GPIOS_PER_BANK	SUNXI_GPIO_A_NR
28 
29 struct sunxi_gpio_platdata {
30 	struct sunxi_gpio *regs;
31 	const char *bank_name;	/* Name of bank, e.g. "B" */
32 	int gpio_count;
33 };
34 
35 #ifndef CONFIG_DM_GPIO
36 static int sunxi_gpio_output(u32 pin, u32 val)
37 {
38 	u32 dat;
39 	u32 bank = GPIO_BANK(pin);
40 	u32 num = GPIO_NUM(pin);
41 	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
42 
43 	dat = readl(&pio->dat);
44 	if (val)
45 		dat |= 0x1 << num;
46 	else
47 		dat &= ~(0x1 << num);
48 
49 	writel(dat, &pio->dat);
50 
51 	return 0;
52 }
53 
54 static int sunxi_gpio_input(u32 pin)
55 {
56 	u32 dat;
57 	u32 bank = GPIO_BANK(pin);
58 	u32 num = GPIO_NUM(pin);
59 	struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
60 
61 	dat = readl(&pio->dat);
62 	dat >>= num;
63 
64 	return dat & 0x1;
65 }
66 
67 int gpio_request(unsigned gpio, const char *label)
68 {
69 	return 0;
70 }
71 
72 int gpio_free(unsigned gpio)
73 {
74 	return 0;
75 }
76 
77 int gpio_direction_input(unsigned gpio)
78 {
79 #ifdef AXP_GPIO
80 	if (gpio >= SUNXI_GPIO_AXP0_START)
81 		return axp_gpio_direction_input(gpio - SUNXI_GPIO_AXP0_START);
82 #endif
83 	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
84 
85 	return 0;
86 }
87 
88 int gpio_direction_output(unsigned gpio, int value)
89 {
90 #ifdef AXP_GPIO
91 	if (gpio >= SUNXI_GPIO_AXP0_START)
92 		return axp_gpio_direction_output(gpio - SUNXI_GPIO_AXP0_START,
93 						 value);
94 #endif
95 	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
96 
97 	return sunxi_gpio_output(gpio, value);
98 }
99 
100 int gpio_get_value(unsigned gpio)
101 {
102 #ifdef AXP_GPIO
103 	if (gpio >= SUNXI_GPIO_AXP0_START)
104 		return axp_gpio_get_value(gpio - SUNXI_GPIO_AXP0_START);
105 #endif
106 	return sunxi_gpio_input(gpio);
107 }
108 
109 int gpio_set_value(unsigned gpio, int value)
110 {
111 #ifdef AXP_GPIO
112 	if (gpio >= SUNXI_GPIO_AXP0_START)
113 		return axp_gpio_set_value(gpio - SUNXI_GPIO_AXP0_START, value);
114 #endif
115 	return sunxi_gpio_output(gpio, value);
116 }
117 
118 int sunxi_name_to_gpio(const char *name)
119 {
120 	int group = 0;
121 	int groupsize = 9 * 32;
122 	long pin;
123 	char *eptr;
124 
125 #ifdef AXP_GPIO
126 	if (strncasecmp(name, "AXP0-", 5) == 0) {
127 		name += 5;
128 		pin = simple_strtol(name, &eptr, 10);
129 		if (!*name || *eptr)
130 			return -1;
131 		return SUNXI_GPIO_AXP0_START + pin;
132 	}
133 #endif
134 	if (*name == 'P' || *name == 'p')
135 		name++;
136 	if (*name >= 'A') {
137 		group = *name - (*name > 'a' ? 'a' : 'A');
138 		groupsize = 32;
139 		name++;
140 	}
141 
142 	pin = simple_strtol(name, &eptr, 10);
143 	if (!*name || *eptr)
144 		return -1;
145 	if (pin < 0 || pin > groupsize || group >= 9)
146 		return -1;
147 	return group * 32 + pin;
148 }
149 #endif
150 
151 #ifdef CONFIG_DM_GPIO
152 static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
153 {
154 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
155 
156 	sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
157 
158 	return 0;
159 }
160 
161 static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
162 				       int value)
163 {
164 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
165 	u32 num = GPIO_NUM(offset);
166 
167 	sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
168 	clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
169 
170 	return 0;
171 }
172 
173 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
174 {
175 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
176 	u32 num = GPIO_NUM(offset);
177 	unsigned dat;
178 
179 	dat = readl(&plat->regs->dat);
180 	dat >>= num;
181 
182 	return dat & 0x1;
183 }
184 
185 static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
186 				int value)
187 {
188 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
189 	u32 num = GPIO_NUM(offset);
190 
191 	clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
192 	return 0;
193 }
194 
195 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
196 {
197 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
198 	int func;
199 
200 	func = sunxi_gpio_get_cfgbank(plat->regs, offset);
201 	if (func == SUNXI_GPIO_OUTPUT)
202 		return GPIOF_OUTPUT;
203 	else if (func == SUNXI_GPIO_INPUT)
204 		return GPIOF_INPUT;
205 	else
206 		return GPIOF_FUNC;
207 }
208 
209 static const struct dm_gpio_ops gpio_sunxi_ops = {
210 	.direction_input	= sunxi_gpio_direction_input,
211 	.direction_output	= sunxi_gpio_direction_output,
212 	.get_value		= sunxi_gpio_get_value,
213 	.set_value		= sunxi_gpio_set_value,
214 	.get_function		= sunxi_gpio_get_function,
215 };
216 
217 /**
218  * Returns the name of a GPIO bank
219  *
220  * GPIO banks are named A, B, C, ...
221  *
222  * @bank:	Bank number (0, 1..n-1)
223  * @return allocated string containing the name
224  */
225 static char *gpio_bank_name(int bank)
226 {
227 	char *name;
228 
229 	name = malloc(2);
230 	if (name) {
231 		name[0] = 'A' + bank;
232 		name[1] = '\0';
233 	}
234 
235 	return name;
236 }
237 
238 static int gpio_sunxi_probe(struct udevice *dev)
239 {
240 	struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
241 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
242 
243 	/* Tell the uclass how many GPIOs we have */
244 	if (plat) {
245 		uc_priv->gpio_count = plat->gpio_count;
246 		uc_priv->bank_name = plat->bank_name;
247 	}
248 
249 	return 0;
250 }
251 /**
252  * We have a top-level GPIO device with no actual GPIOs. It has a child
253  * device for each Sunxi bank.
254  */
255 static int gpio_sunxi_bind(struct udevice *parent)
256 {
257 	struct sunxi_gpio_platdata *plat = parent->platdata;
258 	struct sunxi_gpio_reg *ctlr;
259 	int bank;
260 	int ret;
261 
262 	/* If this is a child device, there is nothing to do here */
263 	if (plat)
264 		return 0;
265 
266 	ctlr = (struct sunxi_gpio_reg *)fdtdec_get_addr(gd->fdt_blob,
267 						   parent->of_offset, "reg");
268 	for (bank = 0; bank < SUNXI_GPIO_BANKS; bank++) {
269 		struct sunxi_gpio_platdata *plat;
270 		struct udevice *dev;
271 
272 		plat = calloc(1, sizeof(*plat));
273 		if (!plat)
274 			return -ENOMEM;
275 		plat->regs = &ctlr->gpio_bank[bank];
276 		plat->bank_name = gpio_bank_name(bank);
277 		plat->gpio_count = SUNXI_GPIOS_PER_BANK;
278 
279 		ret = device_bind(parent, parent->driver,
280 					plat->bank_name, plat, -1, &dev);
281 		if (ret)
282 			return ret;
283 		dev->of_offset = parent->of_offset;
284 	}
285 
286 	return 0;
287 }
288 
289 static const struct udevice_id sunxi_gpio_ids[] = {
290 	{ .compatible = "allwinner,sun7i-a20-pinctrl" },
291 	{ }
292 };
293 
294 U_BOOT_DRIVER(gpio_sunxi) = {
295 	.name	= "gpio_sunxi",
296 	.id	= UCLASS_GPIO,
297 	.ops	= &gpio_sunxi_ops,
298 	.of_match = sunxi_gpio_ids,
299 	.bind	= gpio_sunxi_bind,
300 	.probe	= gpio_sunxi_probe,
301 };
302 #endif
303