blob: 8688f12e43c72bdffc477b5681ca0f4c38de62d9 [file] [log] [blame]
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Broadcom
4 */
5
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +05306#include <errno.h>
7#include <asm/gpio.h>
8#include <asm/io.h>
9#include <dm.h>
10#include <dm/device_compat.h>
11#include <dm/devres.h>
12#include <dm/pinctrl.h>
13
14/*
15 * There are five GPIO bank register. Each bank can configure max of 32 gpios.
16 * BANK0 - gpios 0 to 31
17 * BANK1 - gpios 32 to 63
18 * BANK2 - gpios 64 to 95
19 * BANK3 - gpios 96 to 127
20 * BANK4 - gpios 128 to 150
21 *
22 * Offset difference between consecutive bank register is 0x200
23 */
24#define NGPIO_PER_BANK 32
25#define GPIO_BANK_SIZE 0x200
26#define GPIO_BANK(pin) ((pin) / NGPIO_PER_BANK)
27#define GPIO_SHIFT(pin) ((pin) % NGPIO_PER_BANK)
28#define GPIO_REG(pin, reg) (GPIO_BANK_SIZE * GPIO_BANK(pin) + (reg))
29
30/* device register offset */
31#define DATA_IN_OFFSET 0x00
32#define DATA_OUT_OFFSET 0x04
33#define OUT_EN_OFFSET 0x08
34
35/**
36 * struct iproc_gpio_pctrl_map - gpio and pinctrl mapping
37 * @gpio_pin: start of gpio number in gpio-ranges
38 * @pctrl_pin: start of pinctrl number in gpio-ranges
39 * @npins: total number of pins in gpio-ranges
40 * @node: list node
41 */
42struct iproc_gpio_pctrl_map {
43 u32 gpio_pin;
44 u32 pctrl_pin;
45 u32 npins;
46 struct list_head node;
47};
48
49/**
50 * struct iproc_gpio_pctrl_map - gpio device instance
51 * @pinctrl_dev:pointer to pinctrl device
52 * @gpiomap: list node having mapping between gpio and pinctrl
53 * @base: I/O register base address of gpio device
54 * @name: gpio device name, ex GPIO0, GPIO1
55 * @ngpios: total number of gpios
56 */
Simon Glassb75b15b2020-12-03 16:55:23 -070057struct iproc_gpio_plat {
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +053058 struct udevice *pinctrl_dev;
59 struct list_head gpiomap;
60 void __iomem *base;
61 char *name;
62 u32 ngpios;
63};
64
65/**
66 * iproc_gpio_set_bit - set or clear one bit in an iproc GPIO register.
67 *
68 * The bit relates to a GPIO pin.
69 *
70 * @plat: iproc GPIO device
71 * @reg: register offset
72 * @gpio: GPIO pin
73 * @set: set or clear
74 */
Simon Glassb75b15b2020-12-03 16:55:23 -070075static inline void iproc_gpio_set_bit(struct iproc_gpio_plat *plat,
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +053076 u32 reg, u32 gpio, bool set)
77{
78 u32 offset = GPIO_REG(gpio, reg);
79 u32 shift = GPIO_SHIFT(gpio);
80
81 clrsetbits_le32(plat->base + offset, BIT(shift),
82 (set ? BIT(shift) : 0));
83}
84
Simon Glassb75b15b2020-12-03 16:55:23 -070085static inline bool iproc_gpio_get_bit(struct iproc_gpio_plat *plat,
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +053086 u32 reg, u32 gpio)
87{
88 u32 offset = GPIO_REG(gpio, reg);
89 u32 shift = GPIO_SHIFT(gpio);
90
91 return readl(plat->base + offset) & BIT(shift);
92}
93
94/**
95 * iproc_get_gpio_pctrl_mapping() - get associated pinctrl pin from gpio pin
96 *
97 * @plat: iproc GPIO device
98 * @gpio: GPIO pin
99 */
Simon Glassb75b15b2020-12-03 16:55:23 -0700100static u32 iproc_get_pctrl_from_gpio(struct iproc_gpio_plat *plat, u32 gpio)
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530101{
102 struct iproc_gpio_pctrl_map *range = NULL;
103 struct list_head *pos, *tmp;
104 u32 ret = 0;
105
106 list_for_each_safe(pos, tmp, &plat->gpiomap) {
107 range = list_entry(pos, struct iproc_gpio_pctrl_map, node);
108 if (gpio == range->gpio_pin ||
109 gpio < (range->gpio_pin + range->npins)) {
110 ret = range->pctrl_pin + (gpio - range->gpio_pin);
111 break;
112 }
113 }
114
115 return ret;
116}
117
118/**
119 * iproc_get_gpio_pctrl_mapping() - get mapping between gpio and pinctrl
120 *
121 * Read dt node "gpio-ranges" to get gpio and pinctrl mapping and store
122 * in private data structure to use it later while enabling gpio.
123 *
124 * @dev: pointer to GPIO device
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100125 * Return: 0 on success and -ENOMEM on failure
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530126 */
127static int iproc_get_gpio_pctrl_mapping(struct udevice *dev)
128{
Simon Glassb75b15b2020-12-03 16:55:23 -0700129 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530130 struct iproc_gpio_pctrl_map *range = NULL;
131 struct ofnode_phandle_args args;
132 int index = 0, ret;
133
134 for (;; index++) {
135 ret = dev_read_phandle_with_args(dev, "gpio-ranges",
136 NULL, 3, index, &args);
137 if (ret)
138 break;
139
140 range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
141 if (!range)
142 return -ENOMEM;
143
144 range->gpio_pin = args.args[0];
145 range->pctrl_pin = args.args[1];
146 range->npins = args.args[2];
147 list_add_tail(&range->node, &plat->gpiomap);
148 }
149
150 return 0;
151}
152
153static int iproc_gpio_request(struct udevice *dev, u32 gpio, const char *label)
154{
Simon Glassb75b15b2020-12-03 16:55:23 -0700155 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530156 u32 pctrl;
157
158 /* nothing to do if there is no corresponding pinctrl device */
159 if (!plat->pinctrl_dev)
160 return 0;
161
162 pctrl = iproc_get_pctrl_from_gpio(plat, gpio);
163
164 return pinctrl_request(plat->pinctrl_dev, pctrl, 0);
165}
166
167static int iproc_gpio_direction_input(struct udevice *dev, u32 gpio)
168{
Simon Glassb75b15b2020-12-03 16:55:23 -0700169 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530170
171 iproc_gpio_set_bit(plat, OUT_EN_OFFSET, gpio, false);
172 dev_dbg(dev, "gpio:%u set input\n", gpio);
173
174 return 0;
175}
176
177static int iproc_gpio_direction_output(struct udevice *dev, u32 gpio, int value)
178{
Simon Glassb75b15b2020-12-03 16:55:23 -0700179 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530180
181 iproc_gpio_set_bit(plat, OUT_EN_OFFSET, gpio, true);
182 iproc_gpio_set_bit(plat, DATA_OUT_OFFSET, gpio, value);
183 dev_dbg(dev, "gpio:%u set output, value:%d\n", gpio, value);
184
185 return 0;
186}
187
188static int iproc_gpio_get_value(struct udevice *dev, u32 gpio)
189{
Simon Glassb75b15b2020-12-03 16:55:23 -0700190 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530191 int value;
192
193 value = iproc_gpio_get_bit(plat, DATA_IN_OFFSET, gpio);
194 dev_dbg(dev, "gpio:%u get, value:%d\n", gpio, value);
195
196 return value;
197}
198
199static int iproc_gpio_set_value(struct udevice *dev, u32 gpio, int value)
200{
Simon Glassb75b15b2020-12-03 16:55:23 -0700201 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530202
203 if (iproc_gpio_get_bit(plat, OUT_EN_OFFSET, gpio))
204 iproc_gpio_set_bit(plat, DATA_OUT_OFFSET, gpio, value);
205
206 dev_dbg(dev, "gpio:%u set, value:%d\n", gpio, value);
207 return 0;
208}
209
210static int iproc_gpio_get_function(struct udevice *dev, u32 gpio)
211{
Simon Glassb75b15b2020-12-03 16:55:23 -0700212 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530213
214 if (iproc_gpio_get_bit(plat, OUT_EN_OFFSET, gpio))
215 return GPIOF_OUTPUT;
216 else
217 return GPIOF_INPUT;
218}
219
Simon Glassaad29ae2020-12-03 16:55:21 -0700220static int iproc_gpio_of_to_plat(struct udevice *dev)
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530221{
Simon Glassb75b15b2020-12-03 16:55:23 -0700222 struct iproc_gpio_plat *plat = dev_get_plat(dev);
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530223 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
224 int ret;
225 char name[10];
226
227 plat->base = dev_read_addr_ptr(dev);
228 if (!plat->base) {
229 debug("%s: Failed to get base address\n", __func__);
230 return -EINVAL;
231 }
232
233 ret = dev_read_u32(dev, "ngpios", &plat->ngpios);
234 if (ret < 0) {
235 dev_err(dev, "%s: Failed to get ngpios\n", __func__);
236 return ret;
237 }
238
239 uclass_get_device_by_phandle(UCLASS_PINCTRL, dev, "gpio-ranges",
240 &plat->pinctrl_dev);
241 if (ret < 0) {
242 dev_err(dev, "%s: Failed to get pinctrl phandle\n", __func__);
243 return ret;
244 }
245
246 INIT_LIST_HEAD(&plat->gpiomap);
247 ret = iproc_get_gpio_pctrl_mapping(dev);
248 if (ret < 0) {
249 dev_err(dev, "%s: Failed to get gpio to pctrl map ret(%d)\n",
250 __func__, ret);
251 return ret;
252 }
253
Simon Glassb4db3722020-12-16 21:20:24 -0700254 snprintf(name, sizeof(name), "GPIO%d", dev_seq(dev));
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530255 plat->name = strdup(name);
256 if (!plat->name)
257 return -ENOMEM;
258
259 uc_priv->gpio_count = plat->ngpios;
260 uc_priv->bank_name = plat->name;
261
262 dev_info(dev, ":bank name(%s) base %p, #gpios %d\n",
263 plat->name, plat->base, plat->ngpios);
264
265 return 0;
266}
267
268static const struct dm_gpio_ops iproc_gpio_ops = {
269 .request = iproc_gpio_request,
270 .direction_input = iproc_gpio_direction_input,
271 .direction_output = iproc_gpio_direction_output,
272 .get_value = iproc_gpio_get_value,
273 .set_value = iproc_gpio_set_value,
274 .get_function = iproc_gpio_get_function,
275};
276
277static const struct udevice_id iproc_gpio_ids[] = {
278 { .compatible = "brcm,iproc-gpio" },
279 { }
280};
281
282U_BOOT_DRIVER(iproc_gpio) = {
283 .name = "iproc_gpio",
284 .id = UCLASS_GPIO,
285 .of_match = iproc_gpio_ids,
286 .ops = &iproc_gpio_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700287 .of_to_plat = iproc_gpio_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700288 .plat_auto = sizeof(struct iproc_gpio_plat),
Rayagonda Kokatanurf600db42020-05-05 23:26:46 +0530289};