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+
18 #include <asm/arch/gpio.h>
21 #include <dm/device-internal.h>
22 #include <dt-bindings/gpio/gpio.h>
24 DECLARE_GLOBAL_DATA_PTR
;
26 #define SUNXI_GPIOS_PER_BANK SUNXI_GPIO_A_NR
28 struct sunxi_gpio_platdata
{
29 struct sunxi_gpio
*regs
;
30 const char *bank_name
; /* Name of bank, e.g. "B" */
34 #ifndef CONFIG_DM_GPIO
35 static int sunxi_gpio_output(u32 pin
, u32 val
)
38 u32 bank
= GPIO_BANK(pin
);
39 u32 num
= GPIO_NUM(pin
);
40 struct sunxi_gpio
*pio
= BANK_TO_GPIO(bank
);
42 dat
= readl(&pio
->dat
);
48 writel(dat
, &pio
->dat
);
53 static int sunxi_gpio_input(u32 pin
)
56 u32 bank
= GPIO_BANK(pin
);
57 u32 num
= GPIO_NUM(pin
);
58 struct sunxi_gpio
*pio
= BANK_TO_GPIO(bank
);
60 dat
= readl(&pio
->dat
);
66 int gpio_request(unsigned gpio
, const char *label
)
71 int gpio_free(unsigned gpio
)
76 int gpio_direction_input(unsigned gpio
)
78 sunxi_gpio_set_cfgpin(gpio
, SUNXI_GPIO_INPUT
);
83 int gpio_direction_output(unsigned gpio
, int value
)
85 sunxi_gpio_set_cfgpin(gpio
, SUNXI_GPIO_OUTPUT
);
87 return sunxi_gpio_output(gpio
, value
);
90 int gpio_get_value(unsigned gpio
)
92 return sunxi_gpio_input(gpio
);
95 int gpio_set_value(unsigned gpio
, int value
)
97 return sunxi_gpio_output(gpio
, value
);
100 int sunxi_name_to_gpio(const char *name
)
103 int groupsize
= 9 * 32;
107 if (*name
== 'P' || *name
== 'p')
110 group
= *name
- (*name
> 'a' ? 'a' : 'A');
115 pin
= simple_strtol(name
, &eptr
, 10);
118 if (pin
< 0 || pin
> groupsize
|| group
>= 9)
120 return group
* 32 + pin
;
124 int sunxi_name_to_gpio_bank(const char *name
)
128 if (*name
== 'P' || *name
== 'p')
131 group
= *name
- (*name
> 'a' ? 'a' : 'A');
138 #ifdef CONFIG_DM_GPIO
139 /* TODO(sjg@chromium.org): Remove this function and use device tree */
140 int sunxi_name_to_gpio(const char *name
)
144 #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
147 if (strcasecmp(name
, "AXP0-VBUS-DETECT") == 0) {
148 sprintf(lookup
, SUNXI_GPIO_AXP0_PREFIX
"%d",
149 SUNXI_GPIO_AXP0_VBUS_DETECT
);
151 } else if (strcasecmp(name
, "AXP0-VBUS-ENABLE") == 0) {
152 sprintf(lookup
, SUNXI_GPIO_AXP0_PREFIX
"%d",
153 SUNXI_GPIO_AXP0_VBUS_ENABLE
);
157 ret
= gpio_lookup_name(name
, NULL
, NULL
, &gpio
);
159 return ret
? ret
: gpio
;
162 static int sunxi_gpio_direction_input(struct udevice
*dev
, unsigned offset
)
164 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
166 sunxi_gpio_set_cfgbank(plat
->regs
, offset
, SUNXI_GPIO_INPUT
);
171 static int sunxi_gpio_direction_output(struct udevice
*dev
, unsigned offset
,
174 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
175 u32 num
= GPIO_NUM(offset
);
177 sunxi_gpio_set_cfgbank(plat
->regs
, offset
, SUNXI_GPIO_OUTPUT
);
178 clrsetbits_le32(&plat
->regs
->dat
, 1 << num
, value
? (1 << num
) : 0);
183 static int sunxi_gpio_get_value(struct udevice
*dev
, unsigned offset
)
185 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
186 u32 num
= GPIO_NUM(offset
);
189 dat
= readl(&plat
->regs
->dat
);
195 static int sunxi_gpio_set_value(struct udevice
*dev
, unsigned offset
,
198 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
199 u32 num
= GPIO_NUM(offset
);
201 clrsetbits_le32(&plat
->regs
->dat
, 1 << num
, value
? (1 << num
) : 0);
205 static int sunxi_gpio_get_function(struct udevice
*dev
, unsigned offset
)
207 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
210 func
= sunxi_gpio_get_cfgbank(plat
->regs
, offset
);
211 if (func
== SUNXI_GPIO_OUTPUT
)
213 else if (func
== SUNXI_GPIO_INPUT
)
219 static int sunxi_gpio_xlate(struct udevice
*dev
, struct gpio_desc
*desc
,
220 struct ofnode_phandle_args
*args
)
224 ret
= device_get_child(dev
, args
->args
[0], &desc
->dev
);
227 desc
->offset
= args
->args
[1];
228 desc
->flags
= args
->args
[2] & GPIO_ACTIVE_LOW
? GPIOD_ACTIVE_LOW
: 0;
233 static const struct dm_gpio_ops gpio_sunxi_ops
= {
234 .direction_input
= sunxi_gpio_direction_input
,
235 .direction_output
= sunxi_gpio_direction_output
,
236 .get_value
= sunxi_gpio_get_value
,
237 .set_value
= sunxi_gpio_set_value
,
238 .get_function
= sunxi_gpio_get_function
,
239 .xlate
= sunxi_gpio_xlate
,
243 * Returns the name of a GPIO bank
245 * GPIO banks are named A, B, C, ...
247 * @bank: Bank number (0, 1..n-1)
248 * @return allocated string containing the name
250 static char *gpio_bank_name(int bank
)
257 name
[1] = 'A' + bank
;
264 static int gpio_sunxi_probe(struct udevice
*dev
)
266 struct sunxi_gpio_platdata
*plat
= dev_get_platdata(dev
);
267 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
269 /* Tell the uclass how many GPIOs we have */
271 uc_priv
->gpio_count
= plat
->gpio_count
;
272 uc_priv
->bank_name
= plat
->bank_name
;
278 struct sunxi_gpio_soc_data
{
284 * We have a top-level GPIO device with no actual GPIOs. It has a child
285 * device for each Sunxi bank.
287 static int gpio_sunxi_bind(struct udevice
*parent
)
289 struct sunxi_gpio_soc_data
*soc_data
=
290 (struct sunxi_gpio_soc_data
*)dev_get_driver_data(parent
);
291 struct sunxi_gpio_platdata
*plat
= parent
->platdata
;
292 struct sunxi_gpio_reg
*ctlr
;
295 /* If this is a child device, there is nothing to do here */
299 ctlr
= (struct sunxi_gpio_reg
*)devfdt_get_addr(parent
);
300 for (bank
= 0; bank
< soc_data
->no_banks
; bank
++) {
301 struct sunxi_gpio_platdata
*plat
;
304 plat
= calloc(1, sizeof(*plat
));
307 plat
->regs
= &ctlr
->gpio_bank
[bank
];
308 plat
->bank_name
= gpio_bank_name(soc_data
->start
+ bank
);
309 plat
->gpio_count
= SUNXI_GPIOS_PER_BANK
;
311 ret
= device_bind(parent
, parent
->driver
,
312 plat
->bank_name
, plat
, -1, &dev
);
315 dev_set_of_offset(dev
, dev_of_offset(parent
));
321 static const struct sunxi_gpio_soc_data soc_data_a_all
= {
323 .no_banks
= SUNXI_GPIO_BANKS
,
326 static const struct sunxi_gpio_soc_data soc_data_l_1
= {
331 static const struct sunxi_gpio_soc_data soc_data_l_2
= {
336 static const struct sunxi_gpio_soc_data soc_data_l_3
= {
341 #define ID(_compat_, _soc_data_) \
342 { .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
344 static const struct udevice_id sunxi_gpio_ids
[] = {
345 ID("allwinner,sun4i-a10-pinctrl", a_all
),
346 ID("allwinner,sun5i-a10s-pinctrl", a_all
),
347 ID("allwinner,sun5i-a13-pinctrl", a_all
),
348 ID("allwinner,sun6i-a31-pinctrl", a_all
),
349 ID("allwinner,sun6i-a31s-pinctrl", a_all
),
350 ID("allwinner,sun7i-a20-pinctrl", a_all
),
351 ID("allwinner,sun8i-a23-pinctrl", a_all
),
352 ID("allwinner,sun8i-a33-pinctrl", a_all
),
353 ID("allwinner,sun8i-a83t-pinctrl", a_all
),
354 ID("allwinner,sun8i-h3-pinctrl", a_all
),
355 ID("allwinner,sun8i-r40-pinctrl", a_all
),
356 ID("allwinner,sun9i-a80-pinctrl", a_all
),
357 ID("allwinner,sun6i-a31-r-pinctrl", l_2
),
358 ID("allwinner,sun8i-a23-r-pinctrl", l_1
),
359 ID("allwinner,sun8i-a83t-r-pinctrl", l_1
),
360 ID("allwinner,sun8i-h3-r-pinctrl", l_1
),
361 ID("allwinner,sun9i-a80-r-pinctrl", l_3
),
365 U_BOOT_DRIVER(gpio_sunxi
) = {
366 .name
= "gpio_sunxi",
368 .ops
= &gpio_sunxi_ops
,
369 .of_match
= sunxi_gpio_ids
,
370 .bind
= gpio_sunxi_bind
,
371 .probe
= gpio_sunxi_probe
,