]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/sunxi_gpio.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / gpio / sunxi_gpio.c
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
22 DECLARE_GLOBAL_DATA_PTR;
23
24 #define SUNXI_GPIOS_PER_BANK    SUNXI_GPIO_A_NR
25
26 struct sunxi_gpio_platdata {
27         struct sunxi_gpio *regs;
28         const char *bank_name;  /* Name of bank, e.g. "B" */
29         int gpio_count;
30 };
31
32 #ifndef CONFIG_DM_GPIO
33 static int sunxi_gpio_output(u32 pin, u32 val)
34 {
35         u32 dat;
36         u32 bank = GPIO_BANK(pin);
37         u32 num = GPIO_NUM(pin);
38         struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
39
40         dat = readl(&pio->dat);
41         if (val)
42                 dat |= 0x1 << num;
43         else
44                 dat &= ~(0x1 << num);
45
46         writel(dat, &pio->dat);
47
48         return 0;
49 }
50
51 static int sunxi_gpio_input(u32 pin)
52 {
53         u32 dat;
54         u32 bank = GPIO_BANK(pin);
55         u32 num = GPIO_NUM(pin);
56         struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
57
58         dat = readl(&pio->dat);
59         dat >>= num;
60
61         return dat & 0x1;
62 }
63
64 int gpio_request(unsigned gpio, const char *label)
65 {
66         return 0;
67 }
68
69 int gpio_free(unsigned gpio)
70 {
71         return 0;
72 }
73
74 int gpio_direction_input(unsigned gpio)
75 {
76         sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
77
78         return sunxi_gpio_input(gpio);
79 }
80
81 int gpio_direction_output(unsigned gpio, int value)
82 {
83         sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
84
85         return sunxi_gpio_output(gpio, value);
86 }
87
88 int gpio_get_value(unsigned gpio)
89 {
90         return sunxi_gpio_input(gpio);
91 }
92
93 int gpio_set_value(unsigned gpio, int value)
94 {
95         return sunxi_gpio_output(gpio, value);
96 }
97
98 int sunxi_name_to_gpio(const char *name)
99 {
100         int group = 0;
101         int groupsize = 9 * 32;
102         long pin;
103         char *eptr;
104         if (*name == 'P' || *name == 'p')
105                 name++;
106         if (*name >= 'A') {
107                 group = *name - (*name > 'a' ? 'a' : 'A');
108                 groupsize = 32;
109                 name++;
110         }
111
112         pin = simple_strtol(name, &eptr, 10);
113         if (!*name || *eptr)
114                 return -1;
115         if (pin < 0 || pin > groupsize || group >= 9)
116                 return -1;
117         return group * 32 + pin;
118 }
119 #endif
120
121 #ifdef CONFIG_DM_GPIO
122 static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
123 {
124         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
125
126         sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
127
128         return 0;
129 }
130
131 static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
132                                        int value)
133 {
134         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
135         u32 num = GPIO_NUM(offset);
136
137         sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
138         clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
139
140         return 0;
141 }
142
143 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
144 {
145         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
146         u32 num = GPIO_NUM(offset);
147         unsigned dat;
148
149         dat = readl(&plat->regs->dat);
150         dat >>= num;
151
152         return dat & 0x1;
153 }
154
155 static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
156                                 int value)
157 {
158         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
159         u32 num = GPIO_NUM(offset);
160
161         clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
162         return 0;
163 }
164
165 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
166 {
167         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
168         int func;
169
170         func = sunxi_gpio_get_cfgbank(plat->regs, offset);
171         if (func == SUNXI_GPIO_OUTPUT)
172                 return GPIOF_OUTPUT;
173         else if (func == SUNXI_GPIO_INPUT)
174                 return GPIOF_INPUT;
175         else
176                 return GPIOF_FUNC;
177 }
178
179 static const struct dm_gpio_ops gpio_sunxi_ops = {
180         .direction_input        = sunxi_gpio_direction_input,
181         .direction_output       = sunxi_gpio_direction_output,
182         .get_value              = sunxi_gpio_get_value,
183         .set_value              = sunxi_gpio_set_value,
184         .get_function           = sunxi_gpio_get_function,
185 };
186
187 /**
188  * Returns the name of a GPIO bank
189  *
190  * GPIO banks are named A, B, C, ...
191  *
192  * @bank:       Bank number (0, 1..n-1)
193  * @return allocated string containing the name
194  */
195 static char *gpio_bank_name(int bank)
196 {
197         char *name;
198
199         name = malloc(2);
200         if (name) {
201                 name[0] = 'A' + bank;
202                 name[1] = '\0';
203         }
204
205         return name;
206 }
207
208 static int gpio_sunxi_probe(struct udevice *dev)
209 {
210         struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
211         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
212
213         /* Tell the uclass how many GPIOs we have */
214         if (plat) {
215                 uc_priv->gpio_count = plat->gpio_count;
216                 uc_priv->bank_name = plat->bank_name;
217         }
218
219         return 0;
220 }
221 /**
222  * We have a top-level GPIO device with no actual GPIOs. It has a child
223  * device for each Sunxi bank.
224  */
225 static int gpio_sunxi_bind(struct udevice *parent)
226 {
227         struct sunxi_gpio_platdata *plat = parent->platdata;
228         struct sunxi_gpio_reg *ctlr;
229         int bank;
230         int ret;
231
232         /* If this is a child device, there is nothing to do here */
233         if (plat)
234                 return 0;
235
236         ctlr = (struct sunxi_gpio_reg *)fdtdec_get_addr(gd->fdt_blob,
237                                                    parent->of_offset, "reg");
238         for (bank = 0; bank < SUNXI_GPIO_BANKS; bank++) {
239                 struct sunxi_gpio_platdata *plat;
240                 struct udevice *dev;
241
242                 plat = calloc(1, sizeof(*plat));
243                 if (!plat)
244                         return -ENOMEM;
245                 plat->regs = &ctlr->gpio_bank[bank];
246                 plat->bank_name = gpio_bank_name(bank);
247                 plat->gpio_count = SUNXI_GPIOS_PER_BANK;
248
249                 ret = device_bind(parent, parent->driver,
250                                         plat->bank_name, plat, -1, &dev);
251                 if (ret)
252                         return ret;
253                 dev->of_offset = parent->of_offset;
254         }
255
256         return 0;
257 }
258
259 static const struct udevice_id sunxi_gpio_ids[] = {
260         { .compatible = "allwinner,sun7i-a20-pinctrl" },
261         { }
262 };
263
264 U_BOOT_DRIVER(gpio_sunxi) = {
265         .name   = "gpio_sunxi",
266         .id     = UCLASS_GPIO,
267         .ops    = &gpio_sunxi_ops,
268         .of_match = sunxi_gpio_ids,
269         .bind   = gpio_sunxi_bind,
270         .probe  = gpio_sunxi_probe,
271 };
272 #endif