2 * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
4 * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
6 * (C) Copyright 2007-2011
7 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
8 * Tom Cubie <tangliang@allwinnertech.com>
10 * SPDX-License-Identifier: GPL-2.0+
20 #include <dm/device-internal.h>
21 #ifdef CONFIG_AXP209_POWER
25 DECLARE_GLOBAL_DATA_PTR;
27 #define SUNXI_GPIOS_PER_BANK SUNXI_GPIO_A_NR
29 struct sunxi_gpio_platdata {
30 struct sunxi_gpio *regs;
31 const char *bank_name; /* Name of bank, e.g. "B" */
35 #ifndef CONFIG_DM_GPIO
36 static int sunxi_gpio_output(u32 pin, u32 val)
39 u32 bank = GPIO_BANK(pin);
40 u32 num = GPIO_NUM(pin);
41 struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
43 dat = readl(&pio->dat);
49 writel(dat, &pio->dat);
54 static int sunxi_gpio_input(u32 pin)
57 u32 bank = GPIO_BANK(pin);
58 u32 num = GPIO_NUM(pin);
59 struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
61 dat = readl(&pio->dat);
67 int gpio_request(unsigned gpio, const char *label)
72 int gpio_free(unsigned gpio)
77 int gpio_direction_input(unsigned gpio)
80 if (gpio >= SUNXI_GPIO_AXP0_START)
81 return axp_gpio_direction_input(gpio - SUNXI_GPIO_AXP0_START);
83 sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
88 int gpio_direction_output(unsigned gpio, int value)
91 if (gpio >= SUNXI_GPIO_AXP0_START)
92 return axp_gpio_direction_output(gpio - SUNXI_GPIO_AXP0_START,
95 sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
97 return sunxi_gpio_output(gpio, value);
100 int gpio_get_value(unsigned gpio)
103 if (gpio >= SUNXI_GPIO_AXP0_START)
104 return axp_gpio_get_value(gpio - SUNXI_GPIO_AXP0_START);
106 return sunxi_gpio_input(gpio);
109 int gpio_set_value(unsigned gpio, int value)
112 if (gpio >= SUNXI_GPIO_AXP0_START)
113 return axp_gpio_set_value(gpio - SUNXI_GPIO_AXP0_START, value);
115 return sunxi_gpio_output(gpio, value);
118 int sunxi_name_to_gpio(const char *name)
121 int groupsize = 9 * 32;
126 if (strncasecmp(name, "AXP0-", 5) == 0) {
128 pin = simple_strtol(name, &eptr, 10);
131 return SUNXI_GPIO_AXP0_START + pin;
134 if (*name == 'P' || *name == 'p')
137 group = *name - (*name > 'a' ? 'a' : 'A');
142 pin = simple_strtol(name, &eptr, 10);
145 if (pin < 0 || pin > groupsize || group >= 9)
147 return group * 32 + pin;
151 #ifdef CONFIG_DM_GPIO
152 static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
154 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
156 sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
161 static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
164 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
165 u32 num = GPIO_NUM(offset);
167 sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
168 clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
173 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
175 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
176 u32 num = GPIO_NUM(offset);
179 dat = readl(&plat->regs->dat);
185 static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
188 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
189 u32 num = GPIO_NUM(offset);
191 clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
195 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
197 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
200 func = sunxi_gpio_get_cfgbank(plat->regs, offset);
201 if (func == SUNXI_GPIO_OUTPUT)
203 else if (func == SUNXI_GPIO_INPUT)
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,
218 * Returns the name of a GPIO bank
220 * GPIO banks are named A, B, C, ...
222 * @bank: Bank number (0, 1..n-1)
223 * @return allocated string containing the name
225 static char *gpio_bank_name(int bank)
231 name[0] = 'A' + bank;
238 static int gpio_sunxi_probe(struct udevice *dev)
240 struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
241 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
243 /* Tell the uclass how many GPIOs we have */
245 uc_priv->gpio_count = plat->gpio_count;
246 uc_priv->bank_name = plat->bank_name;
252 * We have a top-level GPIO device with no actual GPIOs. It has a child
253 * device for each Sunxi bank.
255 static int gpio_sunxi_bind(struct udevice *parent)
257 struct sunxi_gpio_platdata *plat = parent->platdata;
258 struct sunxi_gpio_reg *ctlr;
262 /* If this is a child device, there is nothing to do here */
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;
272 plat = calloc(1, sizeof(*plat));
275 plat->regs = &ctlr->gpio_bank[bank];
276 plat->bank_name = gpio_bank_name(bank);
277 plat->gpio_count = SUNXI_GPIOS_PER_BANK;
279 ret = device_bind(parent, parent->driver,
280 plat->bank_name, plat, -1, &dev);
283 dev->of_offset = parent->of_offset;
289 static const struct udevice_id sunxi_gpio_ids[] = {
290 { .compatible = "allwinner,sun7i-a20-pinctrl" },
294 U_BOOT_DRIVER(gpio_sunxi) = {
295 .name = "gpio_sunxi",
297 .ops = &gpio_sunxi_ops,
298 .of_match = sunxi_gpio_ids,
299 .bind = gpio_sunxi_bind,
300 .probe = gpio_sunxi_probe,