]>
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> | |
11 | #include <dm.h> | |
48647828 | 12 | #include <syscon.h> |
1221ce45 | 13 | #include <linux/errno.h> |
1f8f7730 SG |
14 | #include <asm/gpio.h> |
15 | #include <asm/io.h> | |
48647828 SG |
16 | #include <asm/arch/clock.h> |
17 | #include <dm/pinctrl.h> | |
48647828 | 18 | #include <dt-bindings/clock/rk3288-cru.h> |
1f8f7730 SG |
19 | |
20 | enum { | |
21 | ROCKCHIP_GPIOS_PER_BANK = 32, | |
22 | }; | |
23 | ||
24 | #define OFFSET_TO_BIT(bit) (1UL << (bit)) | |
25 | ||
26 | struct rockchip_gpio_priv { | |
27 | struct rockchip_gpio_regs *regs; | |
48647828 SG |
28 | struct udevice *pinctrl; |
29 | int bank; | |
1f8f7730 SG |
30 | char name[2]; |
31 | }; | |
32 | ||
33 | static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset) | |
34 | { | |
35 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
36 | struct rockchip_gpio_regs *regs = priv->regs; | |
37 | ||
38 | clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); | |
39 | ||
40 | return 0; | |
41 | } | |
42 | ||
43 | static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset, | |
44 | int value) | |
45 | { | |
46 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
47 | struct rockchip_gpio_regs *regs = priv->regs; | |
48 | int mask = OFFSET_TO_BIT(offset); | |
49 | ||
50 | clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); | |
51 | setbits_le32(®s->swport_ddr, mask); | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset) | |
57 | { | |
58 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
59 | struct rockchip_gpio_regs *regs = priv->regs; | |
60 | ||
7d0c2c3f | 61 | return readl(®s->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0; |
1f8f7730 SG |
62 | } |
63 | ||
64 | static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset, | |
65 | int value) | |
66 | { | |
67 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
68 | struct rockchip_gpio_regs *regs = priv->regs; | |
69 | int mask = OFFSET_TO_BIT(offset); | |
70 | ||
71 | clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) | |
77 | { | |
48647828 SG |
78 | #ifdef CONFIG_SPL_BUILD |
79 | return -ENODATA; | |
80 | #else | |
81 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
82 | struct rockchip_gpio_regs *regs = priv->regs; | |
83 | bool is_output; | |
84 | int ret; | |
85 | ||
86 | ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset); | |
87 | if (ret) | |
88 | return ret; | |
89 | ||
90 | /* If it's not 0, then it is not a GPIO */ | |
91 | if (ret) | |
92 | return GPIOF_FUNC; | |
93 | is_output = readl(®s->swport_ddr) & OFFSET_TO_BIT(offset); | |
94 | ||
95 | return is_output ? GPIOF_OUTPUT : GPIOF_INPUT; | |
96 | #endif | |
1f8f7730 SG |
97 | } |
98 | ||
1f8f7730 SG |
99 | static int rockchip_gpio_probe(struct udevice *dev) |
100 | { | |
101 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
102 | struct rockchip_gpio_priv *priv = dev_get_priv(dev); | |
103 | char *end; | |
48647828 | 104 | int ret; |
1f8f7730 | 105 | |
a1d3480b | 106 | priv->regs = dev_read_addr_ptr(dev); |
3f603cbb | 107 | ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); |
48647828 SG |
108 | if (ret) |
109 | return ret; | |
48647828 | 110 | |
1f8f7730 SG |
111 | uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; |
112 | end = strrchr(dev->name, '@'); | |
48647828 SG |
113 | priv->bank = trailing_strtoln(dev->name, end); |
114 | priv->name[0] = 'A' + priv->bank; | |
1f8f7730 SG |
115 | uc_priv->bank_name = priv->name; |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
120 | static const struct dm_gpio_ops gpio_rockchip_ops = { | |
121 | .direction_input = rockchip_gpio_direction_input, | |
122 | .direction_output = rockchip_gpio_direction_output, | |
123 | .get_value = rockchip_gpio_get_value, | |
124 | .set_value = rockchip_gpio_set_value, | |
125 | .get_function = rockchip_gpio_get_function, | |
1f8f7730 SG |
126 | }; |
127 | ||
128 | static const struct udevice_id rockchip_gpio_ids[] = { | |
129 | { .compatible = "rockchip,gpio-bank" }, | |
130 | { } | |
131 | }; | |
132 | ||
133 | U_BOOT_DRIVER(gpio_rockchip) = { | |
134 | .name = "gpio_rockchip", | |
135 | .id = UCLASS_GPIO, | |
136 | .of_match = rockchip_gpio_ids, | |
137 | .ops = &gpio_rockchip_ops, | |
138 | .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv), | |
139 | .probe = rockchip_gpio_probe, | |
140 | }; |