blob: 52851e58b69f4669c4b9d6a7eccaf6b4710ecc07 [file] [log] [blame]
Stefan Bosch9c21d402020-07-10 19:07:27 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2016 Nexell
4 * DeokJin, Lee <truevirtue@nexell.co.kr>
5 */
6
7#include <common.h>
8#include <dm.h>
9#include <errno.h>
10#include <malloc.h>
11#include <asm/io.h>
12#include <asm/gpio.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16struct 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
25struct 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
Simon Glassb75b15b2020-12-03 16:55:23 -070039struct nx_gpio_plat {
Stefan Bosch9c21d402020-07-10 19:07:27 +020040 void *regs;
41 int gpio_count;
42 const char *bank_name;
43};
44
45static int nx_alive_gpio_is_check(struct udevice *dev)
46{
Simon Glassb75b15b2020-12-03 16:55:23 -070047 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +020048 const char *bank_name = plat->bank_name;
49
50 if (!strcmp(bank_name, "gpio_alv"))
51 return 1;
52
53 return 0;
54}
55
56static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin)
57{
Simon Glassb75b15b2020-12-03 16:55:23 -070058 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +020059 struct nx_alive_gpio_regs *const regs = plat->regs;
60
61 setbits_le32(&regs->outputenb_reset, 1 << pin);
62
63 return 0;
64}
65
66static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin,
67 int val)
68{
Simon Glassb75b15b2020-12-03 16:55:23 -070069 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +020070 struct nx_alive_gpio_regs *const regs = plat->regs;
71
72 if (val)
73 setbits_le32(&regs->data, 1 << pin);
74 else
75 setbits_le32(&regs->pad_reset, 1 << pin);
76
77 setbits_le32(&regs->outputenb, 1 << pin);
78
79 return 0;
80}
81
82static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin)
83{
Simon Glassb75b15b2020-12-03 16:55:23 -070084 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +020085 struct nx_alive_gpio_regs *const regs = plat->regs;
86 unsigned int mask = 1UL << pin;
87 unsigned int value;
88
89 value = (readl(&regs->pad_read) & mask) >> pin;
90
91 return value;
92}
93
94static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin,
95 int val)
96{
Simon Glassb75b15b2020-12-03 16:55:23 -070097 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +020098 struct nx_alive_gpio_regs *const regs = plat->regs;
99
100 if (val)
101 setbits_le32(&regs->data, 1 << pin);
102 else
103 clrbits_le32(&regs->pad_reset, 1 << pin);
104
105 return 0;
106}
107
108static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin)
109{
Simon Glassb75b15b2020-12-03 16:55:23 -0700110 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200111 struct nx_alive_gpio_regs *const regs = plat->regs;
112 unsigned int mask = (1UL << pin);
113 unsigned int output;
114
115 output = readl(&regs->outputenb_read) & mask;
116
117 if (output)
118 return GPIOF_OUTPUT;
119 else
120 return GPIOF_INPUT;
121}
122
123static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin)
124{
Simon Glassb75b15b2020-12-03 16:55:23 -0700125 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200126 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(&regs->outputenb, 1 << pin);
132
133 return 0;
134}
135
136static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin,
137 int val)
138{
Simon Glassb75b15b2020-12-03 16:55:23 -0700139 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200140 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(&regs->data, 1 << pin);
147 else
148 clrbits_le32(&regs->data, 1 << pin);
149
150 setbits_le32(&regs->outputenb, 1 << pin);
151
152 return 0;
153}
154
155static int nx_gpio_get_value(struct udevice *dev, unsigned int pin)
156{
Simon Glassb75b15b2020-12-03 16:55:23 -0700157 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200158 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(&regs->pad) & mask) >> pin;
166
167 return value;
168}
169
170static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val)
171{
Simon Glassb75b15b2020-12-03 16:55:23 -0700172 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200173 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(&regs->data, 1 << pin);
180 else
181 clrbits_le32(&regs->data, 1 << pin);
182
183 return 0;
184}
185
186static int nx_gpio_get_function(struct udevice *dev, unsigned int pin)
187{
Simon Glassb75b15b2020-12-03 16:55:23 -0700188 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200189 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(&regs->outputenb) & mask;
197
198 if (output)
199 return GPIOF_OUTPUT;
200 else
201 return GPIOF_INPUT;
202}
203
204static int nx_gpio_probe(struct udevice *dev)
205{
206 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb75b15b2020-12-03 16:55:23 -0700207 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200208
209 uc_priv->gpio_count = plat->gpio_count;
210 uc_priv->bank_name = plat->bank_name;
211
212 return 0;
213}
214
Simon Glassaad29ae2020-12-03 16:55:21 -0700215static int nx_gpio_of_to_plat(struct udevice *dev)
Stefan Bosch9c21d402020-07-10 19:07:27 +0200216{
Simon Glassb75b15b2020-12-03 16:55:23 -0700217 struct nx_gpio_plat *plat = dev_get_plat(dev);
Stefan Bosch9c21d402020-07-10 19:07:27 +0200218
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
229static 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
237static const struct udevice_id nx_gpio_ids[] = {
238 { .compatible = "nexell,nexell-gpio" },
239 { }
240};
241
242U_BOOT_DRIVER(nx_gpio) = {
243 .name = "nx_gpio",
244 .id = UCLASS_GPIO,
245 .of_match = nx_gpio_ids,
246 .ops = &nx_gpio_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700247 .of_to_plat = nx_gpio_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700248 .plat_auto = sizeof(struct nx_gpio_plat),
Stefan Bosch9c21d402020-07-10 19:07:27 +0200249 .probe = nx_gpio_probe,
250};