ARM: dts: npcm8xx: add npcm845 function node
[platform/kernel/u-boot.git] / drivers / gpio / sunxi_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
4  *
5  * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
6  *
7  * (C) Copyright 2007-2011
8  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
9  * Tom Cubie <tangliang@allwinnertech.com>
10  */
11
12 #include <common.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <fdtdec.h>
16 #include <malloc.h>
17 #include <asm/io.h>
18 #include <asm/gpio.h>
19 #include <dt-bindings/gpio/gpio.h>
20
21 #if !CONFIG_IS_ENABLED(DM_GPIO)
22 static int sunxi_gpio_output(u32 pin, u32 val)
23 {
24         u32 dat;
25         u32 bank = GPIO_BANK(pin);
26         u32 num = GPIO_NUM(pin);
27         struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
28
29         dat = readl(&pio->dat);
30         if (val)
31                 dat |= 0x1 << num;
32         else
33                 dat &= ~(0x1 << num);
34
35         writel(dat, &pio->dat);
36
37         return 0;
38 }
39
40 static int sunxi_gpio_input(u32 pin)
41 {
42         u32 dat;
43         u32 bank = GPIO_BANK(pin);
44         u32 num = GPIO_NUM(pin);
45         struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
46
47         dat = readl(&pio->dat);
48         dat >>= num;
49
50         return dat & 0x1;
51 }
52
53 int gpio_request(unsigned gpio, const char *label)
54 {
55         return 0;
56 }
57
58 int gpio_free(unsigned gpio)
59 {
60         return 0;
61 }
62
63 int gpio_direction_input(unsigned gpio)
64 {
65         sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
66
67         return 0;
68 }
69
70 int gpio_direction_output(unsigned gpio, int value)
71 {
72         sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
73
74         return sunxi_gpio_output(gpio, value);
75 }
76
77 int gpio_get_value(unsigned gpio)
78 {
79         return sunxi_gpio_input(gpio);
80 }
81
82 int gpio_set_value(unsigned gpio, int value)
83 {
84         return sunxi_gpio_output(gpio, value);
85 }
86
87 int sunxi_name_to_gpio(const char *name)
88 {
89         int group = 0;
90         int groupsize = 9 * 32;
91         long pin;
92         char *eptr;
93
94         if (*name == 'P' || *name == 'p')
95                 name++;
96         if (*name >= 'A') {
97                 group = *name - (*name > 'a' ? 'a' : 'A');
98                 groupsize = 32;
99                 name++;
100         }
101
102         pin = simple_strtol(name, &eptr, 10);
103         if (!*name || *eptr)
104                 return -1;
105         if (pin < 0 || pin > groupsize || group >= 9)
106                 return -1;
107         return group * 32 + pin;
108 }
109 #endif /* DM_GPIO */
110
111 #if CONFIG_IS_ENABLED(DM_GPIO)
112 /* TODO(sjg@chromium.org): Remove this function and use device tree */
113 int sunxi_name_to_gpio(const char *name)
114 {
115         unsigned int gpio;
116         int ret;
117 #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
118         char lookup[8];
119
120         if (strcasecmp(name, "AXP0-VBUS-DETECT") == 0) {
121                 sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
122                         SUNXI_GPIO_AXP0_VBUS_DETECT);
123                 name = lookup;
124         } else if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) {
125                 sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
126                         SUNXI_GPIO_AXP0_VBUS_ENABLE);
127                 name = lookup;
128         }
129 #endif
130         ret = gpio_lookup_name(name, NULL, NULL, &gpio);
131
132         return ret ? ret : gpio;
133 }
134
135 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
136 {
137         struct sunxi_gpio_plat *plat = dev_get_plat(dev);
138         u32 num = GPIO_NUM(offset);
139         unsigned dat;
140
141         dat = readl(&plat->regs->dat);
142         dat >>= num;
143
144         return dat & 0x1;
145 }
146
147 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
148 {
149         struct sunxi_gpio_plat *plat = dev_get_plat(dev);
150         int func;
151
152         func = sunxi_gpio_get_cfgbank(plat->regs, offset);
153         if (func == SUNXI_GPIO_OUTPUT)
154                 return GPIOF_OUTPUT;
155         else if (func == SUNXI_GPIO_INPUT)
156                 return GPIOF_INPUT;
157         else
158                 return GPIOF_FUNC;
159 }
160
161 static int sunxi_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
162                             struct ofnode_phandle_args *args)
163 {
164         int ret;
165
166         ret = device_get_child(dev, args->args[0], &desc->dev);
167         if (ret)
168                 return ret;
169         desc->offset = args->args[1];
170         desc->flags = gpio_flags_xlate(args->args[2]);
171
172         return 0;
173 }
174
175 static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
176                                 ulong flags)
177 {
178         struct sunxi_gpio_plat *plat = dev_get_plat(dev);
179
180         if (flags & GPIOD_IS_OUT) {
181                 u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
182                 u32 num = GPIO_NUM(offset);
183
184                 clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
185                 sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
186         } else if (flags & GPIOD_IS_IN) {
187                 u32 pull = 0;
188
189                 if (flags & GPIOD_PULL_UP)
190                         pull = 1;
191                 else if (flags & GPIOD_PULL_DOWN)
192                         pull = 2;
193                 sunxi_gpio_set_pull_bank(plat->regs, offset, pull);
194                 sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
195         }
196
197         return 0;
198 }
199
200 static const struct dm_gpio_ops gpio_sunxi_ops = {
201         .get_value              = sunxi_gpio_get_value,
202         .get_function           = sunxi_gpio_get_function,
203         .xlate                  = sunxi_gpio_xlate,
204         .set_flags              = sunxi_gpio_set_flags,
205 };
206
207 static int gpio_sunxi_probe(struct udevice *dev)
208 {
209         struct sunxi_gpio_plat *plat = dev_get_plat(dev);
210         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
211
212         /* Tell the uclass how many GPIOs we have */
213         if (plat) {
214                 uc_priv->gpio_count = SUNXI_GPIOS_PER_BANK;
215                 uc_priv->bank_name = plat->bank_name;
216         }
217
218         return 0;
219 }
220
221 U_BOOT_DRIVER(gpio_sunxi) = {
222         .name   = "gpio_sunxi",
223         .id     = UCLASS_GPIO,
224         .probe  = gpio_sunxi_probe,
225         .ops    = &gpio_sunxi_ops,
226 };
227 #endif /* DM_GPIO */