]>
Commit | Line | Data |
---|---|---|
b8f748d6 SB |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * (C) Copyright 2016 Nexell | |
4 | * DeokJin, Lee <[email protected]> | |
5 | */ | |
6 | ||
b8f748d6 SB |
7 | #include <dm.h> |
8 | #include <errno.h> | |
9 | #include <malloc.h> | |
401d1c4f | 10 | #include <asm/global_data.h> |
b8f748d6 SB |
11 | #include <asm/io.h> |
12 | #include <asm/gpio.h> | |
13 | ||
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
16 | struct nx_gpio_regs { | |
17 | u32 data; /* Data register */ | |
18 | u32 outputenb; /* Output Enable register */ | |
19 | u32 detmode[2]; /* Detect Mode Register */ | |
20 | u32 intenb; /* Interrupt Enable Register */ | |
21 | u32 det; /* Event Detect Register */ | |
22 | u32 pad; /* Pad Status Register */ | |
23 | }; | |
24 | ||
25 | struct nx_alive_gpio_regs { | |
26 | u32 pwrgate; /* Power Gating Register */ | |
27 | u32 reserved0[28]; /* Reserved0 */ | |
28 | u32 outputenb_reset;/* Alive GPIO Output Enable Reset Register */ | |
29 | u32 outputenb; /* Alive GPIO Output Enable Register */ | |
30 | u32 outputenb_read; /* Alive GPIO Output Read Register */ | |
31 | u32 reserved1[3]; /* Reserved1 */ | |
32 | u32 pad_reset; /* Alive GPIO Output Reset Register */ | |
33 | u32 data; /* Alive GPIO Output Register */ | |
34 | u32 pad_read; /* Alive GPIO Pad Read Register */ | |
35 | u32 reserved2[33]; /* Reserved2 */ | |
36 | u32 pad; /* Alive GPIO Input Value Register */ | |
37 | }; | |
38 | ||
8a8d24bd | 39 | struct nx_gpio_plat { |
b8f748d6 SB |
40 | void *regs; |
41 | int gpio_count; | |
42 | const char *bank_name; | |
43 | }; | |
44 | ||
45 | static int nx_alive_gpio_is_check(struct udevice *dev) | |
46 | { | |
8a8d24bd | 47 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
48 | const char *bank_name = plat->bank_name; |
49 | ||
50 | if (!strcmp(bank_name, "gpio_alv")) | |
51 | return 1; | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin) | |
57 | { | |
8a8d24bd | 58 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
59 | struct nx_alive_gpio_regs *const regs = plat->regs; |
60 | ||
61 | setbits_le32(®s->outputenb_reset, 1 << pin); | |
62 | ||
63 | return 0; | |
64 | } | |
65 | ||
66 | static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin, | |
67 | int val) | |
68 | { | |
8a8d24bd | 69 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
70 | struct nx_alive_gpio_regs *const regs = plat->regs; |
71 | ||
72 | if (val) | |
73 | setbits_le32(®s->data, 1 << pin); | |
74 | else | |
75 | setbits_le32(®s->pad_reset, 1 << pin); | |
76 | ||
77 | setbits_le32(®s->outputenb, 1 << pin); | |
78 | ||
79 | return 0; | |
80 | } | |
81 | ||
82 | static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin) | |
83 | { | |
8a8d24bd | 84 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
85 | struct nx_alive_gpio_regs *const regs = plat->regs; |
86 | unsigned int mask = 1UL << pin; | |
87 | unsigned int value; | |
88 | ||
89 | value = (readl(®s->pad_read) & mask) >> pin; | |
90 | ||
91 | return value; | |
92 | } | |
93 | ||
94 | static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin, | |
95 | int val) | |
96 | { | |
8a8d24bd | 97 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
98 | struct nx_alive_gpio_regs *const regs = plat->regs; |
99 | ||
100 | if (val) | |
101 | setbits_le32(®s->data, 1 << pin); | |
102 | else | |
103 | clrbits_le32(®s->pad_reset, 1 << pin); | |
104 | ||
105 | return 0; | |
106 | } | |
107 | ||
108 | static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin) | |
109 | { | |
8a8d24bd | 110 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
111 | struct nx_alive_gpio_regs *const regs = plat->regs; |
112 | unsigned int mask = (1UL << pin); | |
113 | unsigned int output; | |
114 | ||
115 | output = readl(®s->outputenb_read) & mask; | |
116 | ||
117 | if (output) | |
118 | return GPIOF_OUTPUT; | |
119 | else | |
120 | return GPIOF_INPUT; | |
121 | } | |
122 | ||
123 | static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin) | |
124 | { | |
8a8d24bd | 125 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
126 | struct nx_gpio_regs *const regs = plat->regs; |
127 | ||
128 | if (nx_alive_gpio_is_check(dev)) | |
129 | return nx_alive_gpio_direction_input(dev, pin); | |
130 | ||
131 | clrbits_le32(®s->outputenb, 1 << pin); | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin, | |
137 | int val) | |
138 | { | |
8a8d24bd | 139 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
140 | struct nx_gpio_regs *const regs = plat->regs; |
141 | ||
142 | if (nx_alive_gpio_is_check(dev)) | |
143 | return nx_alive_gpio_direction_output(dev, pin, val); | |
144 | ||
145 | if (val) | |
146 | setbits_le32(®s->data, 1 << pin); | |
147 | else | |
148 | clrbits_le32(®s->data, 1 << pin); | |
149 | ||
150 | setbits_le32(®s->outputenb, 1 << pin); | |
151 | ||
152 | return 0; | |
153 | } | |
154 | ||
155 | static int nx_gpio_get_value(struct udevice *dev, unsigned int pin) | |
156 | { | |
8a8d24bd | 157 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
158 | struct nx_gpio_regs *const regs = plat->regs; |
159 | unsigned int mask = 1UL << pin; | |
160 | unsigned int value; | |
161 | ||
162 | if (nx_alive_gpio_is_check(dev)) | |
163 | return nx_alive_gpio_get_value(dev, pin); | |
164 | ||
165 | value = (readl(®s->pad) & mask) >> pin; | |
166 | ||
167 | return value; | |
168 | } | |
169 | ||
170 | static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val) | |
171 | { | |
8a8d24bd | 172 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
173 | struct nx_gpio_regs *const regs = plat->regs; |
174 | ||
175 | if (nx_alive_gpio_is_check(dev)) | |
176 | return nx_alive_gpio_set_value(dev, pin, val); | |
177 | ||
178 | if (val) | |
179 | setbits_le32(®s->data, 1 << pin); | |
180 | else | |
181 | clrbits_le32(®s->data, 1 << pin); | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | static int nx_gpio_get_function(struct udevice *dev, unsigned int pin) | |
187 | { | |
8a8d24bd | 188 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
189 | struct nx_gpio_regs *const regs = plat->regs; |
190 | unsigned int mask = (1UL << pin); | |
191 | unsigned int output; | |
192 | ||
193 | if (nx_alive_gpio_is_check(dev)) | |
194 | return nx_alive_gpio_get_function(dev, pin); | |
195 | ||
196 | output = readl(®s->outputenb) & mask; | |
197 | ||
198 | if (output) | |
199 | return GPIOF_OUTPUT; | |
200 | else | |
201 | return GPIOF_INPUT; | |
202 | } | |
203 | ||
204 | static int nx_gpio_probe(struct udevice *dev) | |
205 | { | |
206 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
8a8d24bd | 207 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
208 | |
209 | uc_priv->gpio_count = plat->gpio_count; | |
210 | uc_priv->bank_name = plat->bank_name; | |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
d1998a9f | 215 | static int nx_gpio_of_to_plat(struct udevice *dev) |
b8f748d6 | 216 | { |
8a8d24bd | 217 | struct nx_gpio_plat *plat = dev_get_plat(dev); |
b8f748d6 SB |
218 | |
219 | plat->regs = map_physmem(devfdt_get_addr(dev), | |
220 | sizeof(struct nx_gpio_regs), | |
221 | MAP_NOCACHE); | |
222 | plat->gpio_count = dev_read_s32_default(dev, "nexell,gpio-bank-width", | |
223 | 32); | |
224 | plat->bank_name = dev_read_string(dev, "gpio-bank-name"); | |
225 | ||
226 | return 0; | |
227 | } | |
228 | ||
229 | static const struct dm_gpio_ops nx_gpio_ops = { | |
230 | .direction_input = nx_gpio_direction_input, | |
231 | .direction_output = nx_gpio_direction_output, | |
232 | .get_value = nx_gpio_get_value, | |
233 | .set_value = nx_gpio_set_value, | |
234 | .get_function = nx_gpio_get_function, | |
235 | }; | |
236 | ||
237 | static const struct udevice_id nx_gpio_ids[] = { | |
238 | { .compatible = "nexell,nexell-gpio" }, | |
239 | { } | |
240 | }; | |
241 | ||
242 | U_BOOT_DRIVER(nx_gpio) = { | |
243 | .name = "nx_gpio", | |
244 | .id = UCLASS_GPIO, | |
245 | .of_match = nx_gpio_ids, | |
246 | .ops = &nx_gpio_ops, | |
d1998a9f | 247 | .of_to_plat = nx_gpio_of_to_plat, |
8a8d24bd | 248 | .plat_auto = sizeof(struct nx_gpio_plat), |
b8f748d6 SB |
249 | .probe = nx_gpio_probe, |
250 | }; |