]> Git Repo - u-boot.git/blame - drivers/gpio/rk_gpio.c
Merge tag 'v2024.10-rc4' into next
[u-boot.git] / drivers / gpio / rk_gpio.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
1f8f7730
SG
2/*
3 * (C) Copyright 2015 Google, Inc
4 *
5 * (C) Copyright 2008-2014 Rockchip Electronics
6 * Peter, Software Engineering, <[email protected]>.
1f8f7730
SG
7 */
8
1f8f7730 9#include <dm.h>
48647828 10#include <syscon.h>
1221ce45 11#include <linux/errno.h>
1f8f7730 12#include <asm/gpio.h>
15f09a1a 13#include <asm/arch-rockchip/clock.h>
88b962f3 14#include <asm/arch-rockchip/hardware.h>
15f09a1a 15#include <asm/arch-rockchip/gpio.h>
48647828 16#include <dm/pinctrl.h>
88b962f3
JK
17#include <dm/read.h>
18#include <dt-bindings/pinctrl/rockchip.h>
19
20#define SWPORT_DR 0x0000
21#define SWPORT_DDR 0x0004
22#define EXT_PORT 0x0050
23#define SWPORT_DR_L 0x0000
24#define SWPORT_DR_H 0x0004
25#define SWPORT_DDR_L 0x0008
26#define SWPORT_DDR_H 0x000C
27#define EXT_PORT_V2 0x0070
28#define VER_ID_V2 0x0078
1f8f7730
SG
29
30enum {
31 ROCKCHIP_GPIOS_PER_BANK = 32,
32};
33
1f8f7730 34struct rockchip_gpio_priv {
88b962f3 35 void __iomem *regs;
48647828
SG
36 struct udevice *pinctrl;
37 int bank;
1f8f7730 38 char name[2];
88b962f3 39 u32 version;
1f8f7730
SG
40};
41
88b962f3 42static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
1f8f7730
SG
43{
44 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
88b962f3 45 u32 mask = BIT(offset), data;
1f8f7730 46
88b962f3
JK
47 if (priv->version)
48 data = readl(priv->regs + EXT_PORT_V2);
49 else
50 data = readl(priv->regs + EXT_PORT);
1f8f7730 51
88b962f3 52 return (data & mask) ? 1 : 0;
1f8f7730
SG
53}
54
88b962f3
JK
55static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
56 int value)
1f8f7730
SG
57{
58 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
88b962f3 59 u32 mask = BIT(offset), data = value ? mask : 0;
1f8f7730 60
88b962f3
JK
61 if (priv->version && offset >= 16)
62 rk_clrsetreg(priv->regs + SWPORT_DR_H, mask >> 16, data >> 16);
63 else if (priv->version)
64 rk_clrsetreg(priv->regs + SWPORT_DR_L, mask, data);
65 else
66 clrsetbits_le32(priv->regs + SWPORT_DR, mask, data);
1f8f7730
SG
67
68 return 0;
69}
70
88b962f3 71static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
1f8f7730
SG
72{
73 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
88b962f3
JK
74 u32 mask = BIT(offset);
75
76 if (priv->version && offset >= 16)
77 rk_clrreg(priv->regs + SWPORT_DDR_H, mask >> 16);
78 else if (priv->version)
79 rk_clrreg(priv->regs + SWPORT_DDR_L, mask);
80 else
81 clrbits_le32(priv->regs + SWPORT_DDR, mask);
1f8f7730 82
88b962f3 83 return 0;
1f8f7730
SG
84}
85
88b962f3
JK
86static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
87 int value)
1f8f7730
SG
88{
89 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
88b962f3
JK
90 u32 mask = BIT(offset);
91
92 rockchip_gpio_set_value(dev, offset, value);
1f8f7730 93
88b962f3
JK
94 if (priv->version && offset >= 16)
95 rk_setreg(priv->regs + SWPORT_DDR_H, mask >> 16);
96 else if (priv->version)
97 rk_setreg(priv->regs + SWPORT_DDR_L, mask);
98 else
99 setbits_le32(priv->regs + SWPORT_DDR, mask);
1f8f7730
SG
100
101 return 0;
102}
103
104static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
105{
48647828 106 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
88b962f3 107 u32 mask = BIT(offset), data;
48647828
SG
108 int ret;
109
88b962f3
JK
110 if (CONFIG_IS_ENABLED(PINCTRL)) {
111 ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
112 if (ret < 0)
113 return ret;
114 else if (ret != RK_FUNC_GPIO)
115 return GPIOF_FUNC;
116 }
117
118 if (priv->version && offset >= 16)
119 data = readl(priv->regs + SWPORT_DDR_H) << 16;
120 else if (priv->version)
121 data = readl(priv->regs + SWPORT_DDR_L);
122 else
123 data = readl(priv->regs + SWPORT_DDR);
48647828 124
88b962f3 125 return (data & mask) ? GPIOF_OUTPUT : GPIOF_INPUT;
1f8f7730
SG
126}
127
aa48c94c
SG
128/* Simple SPL interface to GPIOs */
129#ifdef CONFIG_SPL_BUILD
130
131enum {
132 PULL_NONE_1V8 = 0,
133 PULL_DOWN_1V8 = 1,
134 PULL_UP_1V8 = 3,
135};
136
137int spl_gpio_set_pull(void *vregs, uint gpio, int pull)
138{
139 u32 *regs = vregs;
140 uint val;
141
142 regs += gpio >> GPIO_BANK_SHIFT;
143 gpio &= GPIO_OFFSET_MASK;
144 switch (pull) {
145 case GPIO_PULL_UP:
146 val = PULL_UP_1V8;
147 break;
148 case GPIO_PULL_DOWN:
149 val = PULL_DOWN_1V8;
150 break;
151 case GPIO_PULL_NORMAL:
152 default:
153 val = PULL_NONE_1V8;
154 break;
155 }
156 clrsetbits_le32(regs, 3 << (gpio * 2), val << (gpio * 2));
157
158 return 0;
159}
160
161int spl_gpio_output(void *vregs, uint gpio, int value)
162{
163 struct rockchip_gpio_regs * const regs = vregs;
164
165 clrsetbits_le32(&regs->swport_dr, 1 << gpio, value << gpio);
166
167 /* Set direction */
168 clrsetbits_le32(&regs->swport_ddr, 1 << gpio, 1 << gpio);
169
170 return 0;
171}
172#endif /* CONFIG_SPL_BUILD */
173
1f8f7730
SG
174static int rockchip_gpio_probe(struct udevice *dev)
175{
176 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
177 struct rockchip_gpio_priv *priv = dev_get_priv(dev);
904b8700 178 struct ofnode_phandle_args args;
1f8f7730 179 char *end;
48647828 180 int ret;
1f8f7730 181
a1d3480b 182 priv->regs = dev_read_addr_ptr(dev);
88b962f3
JK
183
184 if (CONFIG_IS_ENABLED(PINCTRL)) {
185 ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
186 if (ret)
187 return ret;
188 }
48647828 189
904b8700
CM
190 /*
191 * If "gpio-ranges" is present in the devicetree use it to parse
192 * the GPIO bank ID, otherwise use the legacy method.
193 */
194 ret = ofnode_parse_phandle_with_args(dev_ofnode(dev),
195 "gpio-ranges", NULL, 3,
196 0, &args);
197 if (!ret || ret != -ENOENT) {
198 uc_priv->gpio_count = args.args[2];
3c454977 199 priv->bank = args.args[1] / ROCKCHIP_GPIOS_PER_BANK;
904b8700
CM
200 } else {
201 uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
f41738d0
JK
202 ret = dev_read_alias_seq(dev, &priv->bank);
203 if (ret) {
204 end = strrchr(dev->name, '@');
205 priv->bank = trailing_strtoln(dev->name, end);
206 }
904b8700
CM
207 }
208
48647828 209 priv->name[0] = 'A' + priv->bank;
1f8f7730
SG
210 uc_priv->bank_name = priv->name;
211
88b962f3
JK
212 priv->version = readl(priv->regs + VER_ID_V2);
213
1f8f7730
SG
214 return 0;
215}
216
217static const struct dm_gpio_ops gpio_rockchip_ops = {
218 .direction_input = rockchip_gpio_direction_input,
219 .direction_output = rockchip_gpio_direction_output,
220 .get_value = rockchip_gpio_get_value,
221 .set_value = rockchip_gpio_set_value,
222 .get_function = rockchip_gpio_get_function,
1f8f7730
SG
223};
224
225static const struct udevice_id rockchip_gpio_ids[] = {
226 { .compatible = "rockchip,gpio-bank" },
227 { }
228};
229
e3e2470f
WL
230U_BOOT_DRIVER(rockchip_gpio_bank) = {
231 .name = "rockchip_gpio_bank",
1f8f7730
SG
232 .id = UCLASS_GPIO,
233 .of_match = rockchip_gpio_ids,
234 .ops = &gpio_rockchip_ops,
41575d8e 235 .priv_auto = sizeof(struct rockchip_gpio_priv),
1f8f7730
SG
236 .probe = rockchip_gpio_probe,
237};
This page took 0.336615 seconds and 4 git commands to generate.