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