3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
6 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
8 * SPDX-License-Identifier: GPL-2.0+
14 #include <asm/arch/imx-regs.h>
18 enum mxc_gpio_direction {
19 MXC_GPIO_DIRECTION_IN,
20 MXC_GPIO_DIRECTION_OUT,
23 #define GPIO_NAME_SIZE 20
24 #define GPIO_PER_BANK 32
26 struct mxc_gpio_plat {
27 struct gpio_regs *regs;
30 struct mxc_bank_info {
31 char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
32 struct gpio_regs *regs;
35 #ifndef CONFIG_DM_GPIO
36 #define GPIO_TO_PORT(n) (n / 32)
38 /* GPIO port description */
39 static unsigned long gpio_ports[] = {
40 [0] = GPIO1_BASE_ADDR,
41 [1] = GPIO2_BASE_ADDR,
42 [2] = GPIO3_BASE_ADDR,
43 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
44 defined(CONFIG_MX53) || defined(CONFIG_MX6)
45 [3] = GPIO4_BASE_ADDR,
47 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
48 [4] = GPIO5_BASE_ADDR,
49 [5] = GPIO6_BASE_ADDR,
51 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
52 [6] = GPIO7_BASE_ADDR,
56 static int mxc_gpio_direction(unsigned int gpio,
57 enum mxc_gpio_direction direction)
59 unsigned int port = GPIO_TO_PORT(gpio);
60 struct gpio_regs *regs;
63 if (port >= ARRAY_SIZE(gpio_ports))
68 regs = (struct gpio_regs *)gpio_ports[port];
70 l = readl(®s->gpio_dir);
73 case MXC_GPIO_DIRECTION_OUT:
76 case MXC_GPIO_DIRECTION_IN:
79 writel(l, ®s->gpio_dir);
84 int gpio_set_value(unsigned gpio, int value)
86 unsigned int port = GPIO_TO_PORT(gpio);
87 struct gpio_regs *regs;
90 if (port >= ARRAY_SIZE(gpio_ports))
95 regs = (struct gpio_regs *)gpio_ports[port];
97 l = readl(®s->gpio_dr);
102 writel(l, ®s->gpio_dr);
107 int gpio_get_value(unsigned gpio)
109 unsigned int port = GPIO_TO_PORT(gpio);
110 struct gpio_regs *regs;
113 if (port >= ARRAY_SIZE(gpio_ports))
118 regs = (struct gpio_regs *)gpio_ports[port];
120 val = (readl(®s->gpio_psr) >> gpio) & 0x01;
125 int gpio_request(unsigned gpio, const char *label)
127 unsigned int port = GPIO_TO_PORT(gpio);
128 if (port >= ARRAY_SIZE(gpio_ports))
133 int gpio_free(unsigned gpio)
138 int gpio_direction_input(unsigned gpio)
140 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
143 int gpio_direction_output(unsigned gpio, int value)
145 int ret = gpio_set_value(gpio, value);
150 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
154 #ifdef CONFIG_DM_GPIO
156 * gpio_is_requested() - check if a GPIO has been requested
158 * @bank: Bank to check
159 * @offset: GPIO offset within bank to check
160 * @return true if marked as requested, false if not
162 static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
164 return *bank->label[offset] != '\0';
167 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
171 val = readl(®s->gpio_dir);
173 return val & (1 << offset) ? 1 : 0;
176 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
177 enum mxc_gpio_direction direction)
181 l = readl(®s->gpio_dir);
184 case MXC_GPIO_DIRECTION_OUT:
187 case MXC_GPIO_DIRECTION_IN:
190 writel(l, ®s->gpio_dir);
193 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
198 l = readl(®s->gpio_dr);
203 writel(l, ®s->gpio_dr);
206 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
208 return (readl(®s->gpio_psr) >> offset) & 0x01;
211 static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
213 return (readl(®s->gpio_dr) >> offset) & 0x01;
216 static int check_requested(struct udevice *dev, unsigned offset,
219 struct mxc_bank_info *bank = dev_get_priv(dev);
220 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
222 if (!gpio_is_requested(bank, offset)) {
223 printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
224 func, uc_priv->bank_name, offset);
231 /* set GPIO pin 'gpio' as an input */
232 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
234 struct mxc_bank_info *bank = dev_get_priv(dev);
237 ret = check_requested(dev, offset, __func__);
241 /* Configure GPIO direction as input. */
242 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
247 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
248 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
251 struct mxc_bank_info *bank = dev_get_priv(dev);
254 ret = check_requested(dev, offset, __func__);
258 /* Configure GPIO output value. */
259 mxc_gpio_bank_set_value(bank->regs, offset, value);
261 /* Configure GPIO direction as output. */
262 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
267 /* read GPIO IN value of pin 'gpio' */
268 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
270 struct mxc_bank_info *bank = dev_get_priv(dev);
273 ret = check_requested(dev, offset, __func__);
277 return mxc_gpio_bank_get_value(bank->regs, offset);
280 /* write GPIO OUT value to pin 'gpio' */
281 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
284 struct mxc_bank_info *bank = dev_get_priv(dev);
287 ret = check_requested(dev, offset, __func__);
291 mxc_gpio_bank_set_value(bank->regs, offset, value);
296 static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
297 char *buf, int bufsize)
299 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
300 struct mxc_bank_info *bank = dev_get_priv(dev);
306 label = bank->label[offset];
307 is_output = mxc_gpio_is_output(bank->regs, offset);
308 size = snprintf(buf, bufsize, "%s%d: ",
309 uc_priv->bank_name ? uc_priv->bank_name : "", offset);
312 requested = gpio_is_requested(bank, offset);
313 snprintf(buf, bufsize, "%s: %d [%c]%s%s",
314 is_output ? "out" : " in",
316 mxc_gpio_bank_get_output_value(bank->regs, offset) :
317 mxc_gpio_bank_get_value(bank->regs, offset),
318 requested ? 'x' : ' ',
319 requested ? " " : "",
325 static int mxc_gpio_request(struct udevice *dev, unsigned offset,
328 struct mxc_bank_info *bank = dev_get_priv(dev);
330 if (gpio_is_requested(bank, offset))
333 strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
334 bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
339 static int mxc_gpio_free(struct udevice *dev, unsigned offset)
341 struct mxc_bank_info *bank = dev_get_priv(dev);
344 ret = check_requested(dev, offset, __func__);
347 bank->label[offset][0] = '\0';
352 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
354 struct mxc_bank_info *bank = dev_get_priv(dev);
356 if (!gpio_is_requested(bank, offset))
359 /* GPIOF_FUNC is not implemented yet */
360 if (mxc_gpio_is_output(bank->regs, offset))
366 static const struct dm_gpio_ops gpio_mxc_ops = {
367 .request = mxc_gpio_request,
368 .free = mxc_gpio_free,
369 .direction_input = mxc_gpio_direction_input,
370 .direction_output = mxc_gpio_direction_output,
371 .get_value = mxc_gpio_get_value,
372 .set_value = mxc_gpio_set_value,
373 .get_function = mxc_gpio_get_function,
374 .get_state = mxc_gpio_get_state,
377 static const struct mxc_gpio_plat mxc_plat[] = {
378 { (struct gpio_regs *)GPIO1_BASE_ADDR },
379 { (struct gpio_regs *)GPIO2_BASE_ADDR },
380 { (struct gpio_regs *)GPIO3_BASE_ADDR },
381 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
382 defined(CONFIG_MX53) || defined(CONFIG_MX6)
383 { (struct gpio_regs *)GPIO4_BASE_ADDR },
385 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
386 { (struct gpio_regs *)GPIO5_BASE_ADDR },
387 { (struct gpio_regs *)GPIO6_BASE_ADDR },
389 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
390 { (struct gpio_regs *)GPIO7_BASE_ADDR },
394 static int mxc_gpio_probe(struct udevice *dev)
396 struct mxc_bank_info *bank = dev_get_priv(dev);
397 struct mxc_gpio_plat *plat = dev_get_platdata(dev);
398 struct gpio_dev_priv *uc_priv = dev->uclass_priv;
402 banknum = plat - mxc_plat;
403 sprintf(name, "GPIO%d_", banknum + 1);
407 uc_priv->bank_name = str;
408 uc_priv->gpio_count = GPIO_PER_BANK;
409 bank->regs = plat->regs;
414 U_BOOT_DRIVER(gpio_mxc) = {
417 .ops = &gpio_mxc_ops,
418 .probe = mxc_gpio_probe,
419 .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
422 U_BOOT_DEVICES(mxc_gpios) = {
423 { "gpio_mxc", &mxc_plat[0] },
424 { "gpio_mxc", &mxc_plat[1] },
425 { "gpio_mxc", &mxc_plat[2] },
426 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
427 defined(CONFIG_MX53) || defined(CONFIG_MX6)
428 { "gpio_mxc", &mxc_plat[3] },
430 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
431 { "gpio_mxc", &mxc_plat[4] },
432 { "gpio_mxc", &mxc_plat[5] },
434 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
435 { "gpio_mxc", &mxc_plat[6] },