blob: 7a6eae9ba18654aac42df247969408449dd407af [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasut12a8d792015-06-23 15:54:19 +02002/*
3 * (C) Copyright 2015 Marek Vasut <marex@denx.de>
4 *
5 * DesignWare APB GPIO driver
Marek Vasut12a8d792015-06-23 15:54:19 +02006 */
7
Marek Vasut12a8d792015-06-23 15:54:19 +02008#include <asm/gpio.h>
9#include <asm/io.h>
Maksim Kiselev11129b02023-11-30 00:47:31 +030010#include <dm/device.h>
Marek Vasut12a8d792015-06-23 15:54:19 +020011#include <dm/device-internal.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070013#include <dm/devres.h>
Maksim Kiselev11129b02023-11-30 00:47:31 +030014#include <dm/read.h>
Marek Vasut12a8d792015-06-23 15:54:19 +020015#include <errno.h>
Ley Foon Tana804dd02018-09-04 14:04:58 +080016#include <reset.h>
Marek Vasut12a8d792015-06-23 15:54:19 +020017
Phil Edworthy26c43ca2016-11-03 11:05:12 +000018#define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc)
19#define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc)
Marek Vasut12a8d792015-06-23 15:54:19 +020020#define GPIO_INTEN 0x30
21#define GPIO_INTMASK 0x34
22#define GPIO_INTTYPE_LEVEL 0x38
23#define GPIO_INT_POLARITY 0x3c
24#define GPIO_INTSTATUS 0x40
25#define GPIO_PORTA_DEBOUNCE 0x48
26#define GPIO_PORTA_EOI 0x4c
Phil Edworthy26c43ca2016-11-03 11:05:12 +000027#define GPIO_EXT_PORT(p) (0x50 + (p) * 4)
Marek Vasut12a8d792015-06-23 15:54:19 +020028
Ley Foon Tana804dd02018-09-04 14:04:58 +080029struct gpio_dwapb_priv {
30 struct reset_ctl_bulk resets;
31};
32
Simon Glassb75b15b2020-12-03 16:55:23 -070033struct gpio_dwapb_plat {
Marek Vasut12a8d792015-06-23 15:54:19 +020034 const char *name;
35 int bank;
36 int pins;
Sean Anderson2f3c3352020-09-14 11:01:59 -040037 void __iomem *base;
Marek Vasut12a8d792015-06-23 15:54:19 +020038};
39
40static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin)
41{
Simon Glassb75b15b2020-12-03 16:55:23 -070042 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +020043
Phil Edworthy26c43ca2016-11-03 11:05:12 +000044 clrbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020045 return 0;
46}
47
48static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin,
49 int val)
50{
Simon Glassb75b15b2020-12-03 16:55:23 -070051 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +020052
Phil Edworthy26c43ca2016-11-03 11:05:12 +000053 setbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020054
55 if (val)
Phil Edworthy26c43ca2016-11-03 11:05:12 +000056 setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020057 else
Phil Edworthy26c43ca2016-11-03 11:05:12 +000058 clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020059
60 return 0;
61}
62
Marek Vasut12a8d792015-06-23 15:54:19 +020063static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val)
64{
Simon Glassb75b15b2020-12-03 16:55:23 -070065 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +020066
67 if (val)
Phil Edworthy26c43ca2016-11-03 11:05:12 +000068 setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020069 else
Phil Edworthy26c43ca2016-11-03 11:05:12 +000070 clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
Marek Vasut12a8d792015-06-23 15:54:19 +020071
72 return 0;
73}
74
Ley Foon Tana4f80b72018-08-16 13:46:30 +080075static int dwapb_gpio_get_function(struct udevice *dev, unsigned offset)
76{
Simon Glassb75b15b2020-12-03 16:55:23 -070077 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Ley Foon Tana4f80b72018-08-16 13:46:30 +080078 u32 gpio;
79
80 gpio = readl(plat->base + GPIO_SWPORT_DDR(plat->bank));
81
82 if (gpio & BIT(offset))
83 return GPIOF_OUTPUT;
84 else
85 return GPIOF_INPUT;
86}
87
Sean Andersonccca40b2020-09-14 11:02:01 -040088static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin)
89{
Simon Glassb75b15b2020-12-03 16:55:23 -070090 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Sean Andersonccca40b2020-09-14 11:02:01 -040091 u32 value;
92
93 if (dwapb_gpio_get_function(dev, pin) == GPIOF_OUTPUT)
94 value = readl(plat->base + GPIO_SWPORT_DR(plat->bank));
95 else
96 value = readl(plat->base + GPIO_EXT_PORT(plat->bank));
97 return !!(value & BIT(pin));
98}
99
Marek Vasut12a8d792015-06-23 15:54:19 +0200100static const struct dm_gpio_ops gpio_dwapb_ops = {
101 .direction_input = dwapb_gpio_direction_input,
102 .direction_output = dwapb_gpio_direction_output,
103 .get_value = dwapb_gpio_get_value,
104 .set_value = dwapb_gpio_set_value,
Ley Foon Tana4f80b72018-08-16 13:46:30 +0800105 .get_function = dwapb_gpio_get_function,
Marek Vasut12a8d792015-06-23 15:54:19 +0200106};
107
Ley Foon Tana804dd02018-09-04 14:04:58 +0800108static int gpio_dwapb_reset(struct udevice *dev)
109{
110 int ret;
111 struct gpio_dwapb_priv *priv = dev_get_priv(dev);
112
113 ret = reset_get_bulk(dev, &priv->resets);
114 if (ret) {
115 /* Return 0 if error due to !CONFIG_DM_RESET and reset
116 * DT property is not present.
117 */
118 if (ret == -ENOENT || ret == -ENOTSUPP)
119 return 0;
120
121 dev_warn(dev, "Can't get reset: %d\n", ret);
122 return ret;
123 }
124
125 ret = reset_deassert_bulk(&priv->resets);
126 if (ret) {
127 reset_release_bulk(&priv->resets);
128 dev_err(dev, "Failed to reset: %d\n", ret);
129 return ret;
130 }
131
132 return 0;
133}
134
Marek Vasut12a8d792015-06-23 15:54:19 +0200135static int gpio_dwapb_probe(struct udevice *dev)
136{
137 struct gpio_dev_priv *priv = dev_get_uclass_priv(dev);
Simon Glass95588622020-12-22 19:30:28 -0700138 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +0200139
Ley Foon Tana804dd02018-09-04 14:04:58 +0800140 if (!plat) {
141 /* Reset on parent device only */
142 return gpio_dwapb_reset(dev);
143 }
Marek Vasut12a8d792015-06-23 15:54:19 +0200144
145 priv->gpio_count = plat->pins;
146 priv->bank_name = plat->name;
147
148 return 0;
149}
150
151static int gpio_dwapb_bind(struct udevice *dev)
152{
Simon Glassb75b15b2020-12-03 16:55:23 -0700153 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +0200154 struct udevice *subdev;
155 fdt_addr_t base;
Simon Goldschmidt3aa78972019-05-09 22:12:00 +0200156 int ret, bank = 0;
157 ofnode node;
Marek Vasut12a8d792015-06-23 15:54:19 +0200158
159 /* If this is a child device, there is nothing to do here */
160 if (plat)
161 return 0;
162
Ley Foon Tan53bdf4e2018-08-16 02:05:54 +0800163 base = dev_read_addr(dev);
Marek Vasut12a8d792015-06-23 15:54:19 +0200164 if (base == FDT_ADDR_T_NONE) {
165 debug("Can't get the GPIO register base address\n");
166 return -ENXIO;
167 }
168
Simon Goldschmidt3aa78972019-05-09 22:12:00 +0200169 for (node = dev_read_first_subnode(dev); ofnode_valid(node);
170 node = dev_read_next_subnode(node)) {
171 if (!ofnode_read_bool(node, "gpio-controller"))
Marek Vasut12a8d792015-06-23 15:54:19 +0200172 continue;
173
Ley Foon Tan16a48f52018-09-19 16:26:33 +0800174 plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL);
Marek Vasut12a8d792015-06-23 15:54:19 +0200175 if (!plat)
176 return -ENOMEM;
177
Sean Anderson2f3c3352020-09-14 11:01:59 -0400178 plat->base = (void *)base;
Marek Vasut12a8d792015-06-23 15:54:19 +0200179 plat->bank = bank;
Simon Goldschmidt3aa78972019-05-09 22:12:00 +0200180 plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0);
181
182 if (ofnode_read_string_index(node, "bank-name", 0,
183 &plat->name)) {
Simon Goldschmidt6a54b8a2018-11-02 11:54:50 +0100184 /*
185 * Fall back to node name. This means accessing pins
186 * via bank name won't work.
187 */
Sean Anderson2fb5b782020-09-14 11:02:00 -0400188 char name[32];
189
190 snprintf(name, sizeof(name), "%s_",
191 ofnode_get_name(node));
192 plat->name = strdup(name);
193 if (!plat->name) {
194 kfree(plat);
195 return -ENOMEM;
196 }
Simon Goldschmidt6a54b8a2018-11-02 11:54:50 +0100197 }
Marek Vasut12a8d792015-06-23 15:54:19 +0200198
Simon Glass884870f2020-11-28 17:50:01 -0700199 ret = device_bind(dev, dev->driver, plat->name, plat, node,
200 &subdev);
Marek Vasut12a8d792015-06-23 15:54:19 +0200201 if (ret)
Ley Foon Tan16a48f52018-09-19 16:26:33 +0800202 return ret;
Marek Vasut12a8d792015-06-23 15:54:19 +0200203
Marek Vasut12a8d792015-06-23 15:54:19 +0200204 bank++;
205 }
206
207 return 0;
Marek Vasut12a8d792015-06-23 15:54:19 +0200208}
209
Ley Foon Tana804dd02018-09-04 14:04:58 +0800210static int gpio_dwapb_remove(struct udevice *dev)
211{
Simon Glassb75b15b2020-12-03 16:55:23 -0700212 struct gpio_dwapb_plat *plat = dev_get_plat(dev);
Ley Foon Tana804dd02018-09-04 14:04:58 +0800213 struct gpio_dwapb_priv *priv = dev_get_priv(dev);
214
215 if (!plat && priv)
216 return reset_release_bulk(&priv->resets);
217
218 return 0;
219}
220
Marek Vasut12a8d792015-06-23 15:54:19 +0200221static const struct udevice_id gpio_dwapb_ids[] = {
222 { .compatible = "snps,dw-apb-gpio" },
223 { }
224};
225
226U_BOOT_DRIVER(gpio_dwapb) = {
227 .name = "gpio-dwapb",
228 .id = UCLASS_GPIO,
229 .of_match = gpio_dwapb_ids,
230 .ops = &gpio_dwapb_ops,
231 .bind = gpio_dwapb_bind,
232 .probe = gpio_dwapb_probe,
Ley Foon Tana804dd02018-09-04 14:04:58 +0800233 .remove = gpio_dwapb_remove,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700234 .priv_auto = sizeof(struct gpio_dwapb_priv),
Marek Vasut12a8d792015-06-23 15:54:19 +0200235};