]>
Commit | Line | Data |
---|---|---|
1f8f7730 SG |
1 | /* |
2 | * (C) Copyright 2015 Google, Inc | |
3 | * | |
4 | * (C) Copyright 2008-2014 Rockchip Electronics | |
5 | * Peter, Software Engineering, <superpeter.cai@gmail.com>. | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
48647828 | 11 | #include <clk.h> |
1f8f7730 | 12 | #include <dm.h> |
48647828 | 13 | #include <syscon.h> |
1f8f7730 SG |
14 | #include <asm/errno.h> |
15 | #include <asm/gpio.h> | |
16 | #include <asm/io.h> | |
48647828 SG |
17 | #include <asm/arch/clock.h> |
18 | #include <dm/pinctrl.h> | |
1f8f7730 | 19 | #include <dt-bindings/gpio/gpio.h> |
48647828 | 20 | #include <dt-bindings/clock/rk3288-cru.h> |
1f8f7730 SG |
21 | |
22 | enum { | |
23 | ROCKCHIP_GPIOS_PER_BANK = 32, | |
24 | }; | |
25 | ||
26 | #define OFFSET_TO_BIT(bit) (1UL << (bit)) | |
27 | ||
28 | struct rockchip_gpio_priv { | |
29 | struct rockchip_gpio_regs *regs; | |
48647828 SG |
30 | struct udevice *pinctrl; |
31 | int bank; | |
1f8f7730 SG |
32 | char name[2]; |
33 | }; | |
34 | ||
35 | static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset) | |
36 | { | |
37 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
38 | struct rockchip_gpio_regs *regs = priv->regs; | |
39 | ||
40 | clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
45 | static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset, | |
46 | int value) | |
47 | { | |
48 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
49 | struct rockchip_gpio_regs *regs = priv->regs; | |
50 | int mask = OFFSET_TO_BIT(offset); | |
51 | ||
52 | clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); | |
53 | setbits_le32(®s->swport_ddr, mask); | |
54 | ||
55 | return 0; | |
56 | } | |
57 | ||
58 | static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset) | |
59 | { | |
60 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
61 | struct rockchip_gpio_regs *regs = priv->regs; | |
62 | ||
7d0c2c3f | 63 | return readl(®s->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0; |
1f8f7730 SG |
64 | } |
65 | ||
66 | static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset, | |
67 | int value) | |
68 | { | |
69 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
70 | struct rockchip_gpio_regs *regs = priv->regs; | |
71 | int mask = OFFSET_TO_BIT(offset); | |
72 | ||
73 | clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) | |
79 | { | |
48647828 SG |
80 | #ifdef CONFIG_SPL_BUILD |
81 | return -ENODATA; | |
82 | #else | |
83 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
84 | struct rockchip_gpio_regs *regs = priv->regs; | |
85 | bool is_output; | |
86 | int ret; | |
87 | ||
88 | ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset); | |
89 | if (ret) | |
90 | return ret; | |
91 | ||
92 | /* If it's not 0, then it is not a GPIO */ | |
93 | if (ret) | |
94 | return GPIOF_FUNC; | |
95 | is_output = readl(®s->swport_ddr) & OFFSET_TO_BIT(offset); | |
96 | ||
97 | return is_output ? GPIOF_OUTPUT : GPIOF_INPUT; | |
98 | #endif | |
1f8f7730 SG |
99 | } |
100 | ||
101 | static int rockchip_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, | |
102 | struct fdtdec_phandle_args *args) | |
103 | { | |
104 | desc->offset = args->args[0]; | |
105 | desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; | |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
110 | static int rockchip_gpio_probe(struct udevice *dev) | |
111 | { | |
112 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
113 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
114 | char *end; | |
48647828 | 115 | int ret; |
1f8f7730 | 116 | |
48647828 | 117 | /* This only supports RK3288 at present */ |
1f8f7730 | 118 | priv->regs = (struct rockchip_gpio_regs *)dev_get_addr(dev); |
3f603cbb | 119 | ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); |
48647828 SG |
120 | if (ret) |
121 | return ret; | |
48647828 | 122 | |
1f8f7730 SG |
123 | uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; |
124 | end = strrchr(dev->name, '@'); | |
48647828 SG |
125 | priv->bank = trailing_strtoln(dev->name, end); |
126 | priv->name[0] = 'A' + priv->bank; | |
1f8f7730 SG |
127 | uc_priv->bank_name = priv->name; |
128 | ||
129 | return 0; | |
130 | } | |
131 | ||
132 | static const struct dm_gpio_ops gpio_rockchip_ops = { | |
133 | .direction_input = rockchip_gpio_direction_input, | |
134 | .direction_output = rockchip_gpio_direction_output, | |
135 | .get_value = rockchip_gpio_get_value, | |
136 | .set_value = rockchip_gpio_set_value, | |
137 | .get_function = rockchip_gpio_get_function, | |
138 | .xlate = rockchip_gpio_xlate, | |
139 | }; | |
140 | ||
141 | static const struct udevice_id rockchip_gpio_ids[] = { | |
142 | { .compatible = "rockchip,gpio-bank" }, | |
143 | { } | |
144 | }; | |
145 | ||
146 | U_BOOT_DRIVER(gpio_rockchip) = { | |
147 | .name = "gpio_rockchip", | |
148 | .id = UCLASS_GPIO, | |
149 | .of_match = rockchip_gpio_ids, | |
150 | .ops = &gpio_rockchip_ops, | |
151 | .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv), | |
152 | .probe = rockchip_gpio_probe, | |
153 | }; |