blob: b9a1d65acc409e3fb5c24124ec766373512ec5f1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassb43d0442012-02-15 15:51:13 -08002/*
3 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glassb43d0442012-02-15 15:51:13 -08004 */
5
6#include <common.h>
Simon Glassb4d70702014-02-26 15:59:25 -07007#include <dm.h>
8#include <fdtdec.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glassb4d70702014-02-26 15:59:25 -070010#include <malloc.h>
Simon Glassb43d0442012-02-15 15:51:13 -080011#include <asm/gpio.h>
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +010012#include <dm/device_compat.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010013#include <dm/lists.h>
Simon Glass12faa022017-05-18 20:09:18 -060014#include <dm/of.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010015#include <dm/pinctrl.h>
Simon Glass16e10402015-01-05 20:05:29 -070016#include <dt-bindings/gpio/gpio.h>
Patrick Delaunay23aee612020-01-13 11:35:13 +010017#include <dt-bindings/gpio/sandbox-gpio.h>
Simon Glassb43d0442012-02-15 15:51:13 -080018
Simon Glassb43d0442012-02-15 15:51:13 -080019
20struct gpio_state {
21 const char *label; /* label given by requester */
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010022 ulong dir_flags; /* dir_flags (GPIOD_...) */
Simon Glassb43d0442012-02-15 15:51:13 -080023};
24
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010025/* Access routines for GPIO dir flags */
26static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
Simon Glassb43d0442012-02-15 15:51:13 -080027{
Simon Glassde0977b2015-03-05 12:25:20 -070028 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -070029 struct gpio_state *state = dev_get_priv(dev);
30
31 if (offset >= uc_priv->gpio_count) {
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010032 static ulong invalid_dir_flags;
Simon Glassb4d70702014-02-26 15:59:25 -070033 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010034 return &invalid_dir_flags;
Simon Glassb43d0442012-02-15 15:51:13 -080035 }
36
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010037 return &state[offset].dir_flags;
38
Simon Glassb43d0442012-02-15 15:51:13 -080039}
40
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010041static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
Simon Glassb43d0442012-02-15 15:51:13 -080042{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010043 return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
Simon Glassb43d0442012-02-15 15:51:13 -080044}
45
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010046static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
Simon Glassb4d70702014-02-26 15:59:25 -070047 int value)
Simon Glassb43d0442012-02-15 15:51:13 -080048{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010049 ulong *gpio = get_gpio_dir_flags(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -080050
51 if (value)
52 *gpio |= flag;
53 else
54 *gpio &= ~flag;
55
56 return 0;
57}
58
Simon Glassb43d0442012-02-15 15:51:13 -080059/*
60 * Back-channel sandbox-internal-only access to GPIO state
61 */
62
Heiko Schocherb74fcb42014-05-22 12:43:05 +020063int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080064{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010065 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glassb4d70702014-02-26 15:59:25 -070066 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010067 return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
Simon Glassb43d0442012-02-15 15:51:13 -080068}
69
Heiko Schocherb74fcb42014-05-22 12:43:05 +020070int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -080071{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010072 return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
Simon Glassb43d0442012-02-15 15:51:13 -080073}
74
Heiko Schocherb74fcb42014-05-22 12:43:05 +020075int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080076{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010077 return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
Simon Glassb43d0442012-02-15 15:51:13 -080078}
79
Heiko Schocherb74fcb42014-05-22 12:43:05 +020080int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
Simon Glassb43d0442012-02-15 15:51:13 -080081{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010082 set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
83 set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
84
85 return 0;
86}
87
88ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
89{
90 return *get_gpio_dir_flags(dev, offset);
91}
92
93int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
94 ulong flags)
95{
96 *get_gpio_dir_flags(dev, offset) = flags;
97
98 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -080099}
100
101/*
102 * These functions implement the public interface within U-Boot
103 */
104
Simon Glassb4d70702014-02-26 15:59:25 -0700105/* set GPIO port 'offset' as an input */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200106static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800107{
Simon Glassb4d70702014-02-26 15:59:25 -0700108 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800109
Simon Glassb4d70702014-02-26 15:59:25 -0700110 return sandbox_gpio_set_direction(dev, offset, 0);
Simon Glassb43d0442012-02-15 15:51:13 -0800111}
112
Simon Glassb4d70702014-02-26 15:59:25 -0700113/* set GPIO port 'offset' as an output, with polarity 'value' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200114static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
Simon Glassb4d70702014-02-26 15:59:25 -0700115 int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800116{
Simon Glassb4d70702014-02-26 15:59:25 -0700117 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800118
Simon Glassb4d70702014-02-26 15:59:25 -0700119 return sandbox_gpio_set_direction(dev, offset, 1) |
120 sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800121}
122
Simon Glassb4d70702014-02-26 15:59:25 -0700123/* read GPIO IN value of port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200124static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800125{
Simon Glassb4d70702014-02-26 15:59:25 -0700126 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800127
Simon Glassb4d70702014-02-26 15:59:25 -0700128 return sandbox_gpio_get_value(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800129}
130
Simon Glassb4d70702014-02-26 15:59:25 -0700131/* write GPIO OUT value to port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200132static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800133{
Simon Glassb4d70702014-02-26 15:59:25 -0700134 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800135
Simon Glassb4d70702014-02-26 15:59:25 -0700136 if (!sandbox_gpio_get_direction(dev, offset)) {
137 printf("sandbox_gpio: error: set_value on input gpio %u\n",
138 offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800139 return -1;
140 }
141
Simon Glassb4d70702014-02-26 15:59:25 -0700142 return sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800143}
144
Simon Glass32048632014-10-04 11:29:45 -0600145static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
146{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100147 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glass32048632014-10-04 11:29:45 -0600148 return GPIOF_OUTPUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100149 if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
150 return GPIOF_INPUT;
151
152 return GPIOF_INPUT; /*GPIO is not configurated */
Simon Glass32048632014-10-04 11:29:45 -0600153}
154
Simon Glass16e10402015-01-05 20:05:29 -0700155static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
Simon Glass12faa022017-05-18 20:09:18 -0600156 struct ofnode_phandle_args *args)
Simon Glass16e10402015-01-05 20:05:29 -0700157{
158 desc->offset = args->args[0];
159 if (args->args_count < 2)
160 return 0;
Patrick Delaunay23aee612020-01-13 11:35:13 +0100161 /* treat generic binding with gpio uclass */
162 gpio_xlate_offs_flags(dev, desc, args);
163
164 /* sandbox test specific, not defined in gpio.h */
165 if (args->args[1] & GPIO_IN)
Simon Glass16e10402015-01-05 20:05:29 -0700166 desc->flags |= GPIOD_IS_IN;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100167
Patrick Delaunay23aee612020-01-13 11:35:13 +0100168 if (args->args[1] & GPIO_OUT)
Simon Glass16e10402015-01-05 20:05:29 -0700169 desc->flags |= GPIOD_IS_OUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100170
Patrick Delaunay23aee612020-01-13 11:35:13 +0100171 if (args->args[1] & GPIO_OUT_ACTIVE)
Simon Glass16e10402015-01-05 20:05:29 -0700172 desc->flags |= GPIOD_IS_OUT_ACTIVE;
173
174 return 0;
175}
176
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100177static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
178 ulong flags)
179{
180 ulong *dir_flags;
181
182 debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
183
184 dir_flags = get_gpio_dir_flags(dev, offset);
185
186 *dir_flags = flags;
187
188 return 0;
189}
190
191static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
192 ulong *flags)
193{
194 debug("%s: offset:%u\n", __func__, offset);
195 *flags = *get_gpio_dir_flags(dev, offset);
196
197 return 0;
198}
199
Simon Glassb4d70702014-02-26 15:59:25 -0700200static const struct dm_gpio_ops gpio_sandbox_ops = {
Simon Glassb4d70702014-02-26 15:59:25 -0700201 .direction_input = sb_gpio_direction_input,
202 .direction_output = sb_gpio_direction_output,
203 .get_value = sb_gpio_get_value,
204 .set_value = sb_gpio_set_value,
Simon Glass32048632014-10-04 11:29:45 -0600205 .get_function = sb_gpio_get_function,
Simon Glass16e10402015-01-05 20:05:29 -0700206 .xlate = sb_gpio_xlate,
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100207 .set_dir_flags = sb_gpio_set_dir_flags,
208 .get_dir_flags = sb_gpio_get_dir_flags,
Simon Glassb4d70702014-02-26 15:59:25 -0700209};
210
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200211static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
Simon Glassb43d0442012-02-15 15:51:13 -0800212{
Simon Glassde0977b2015-03-05 12:25:20 -0700213 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb43d0442012-02-15 15:51:13 -0800214
Simon Glass9e7ab232018-02-03 10:36:59 -0700215 uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
216 0);
Simon Glass1185fcb2017-05-18 20:09:20 -0600217 uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
Simon Glassb43d0442012-02-15 15:51:13 -0800218
Simon Glassb4d70702014-02-26 15:59:25 -0700219 return 0;
220}
Simon Glassb43d0442012-02-15 15:51:13 -0800221
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200222static int gpio_sandbox_probe(struct udevice *dev)
Simon Glassb4d70702014-02-26 15:59:25 -0700223{
Simon Glassde0977b2015-03-05 12:25:20 -0700224 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -0700225
Simon Glass1185fcb2017-05-18 20:09:20 -0600226 if (!dev_of_valid(dev))
Simon Glassb4d70702014-02-26 15:59:25 -0700227 /* Tell the uclass how many GPIOs we have */
228 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
Simon Glassb4d70702014-02-26 15:59:25 -0700229
230 dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
231
232 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -0800233}
Simon Glassb4d70702014-02-26 15:59:25 -0700234
Simon Glassa367f1d2014-10-04 11:29:46 -0600235static int gpio_sandbox_remove(struct udevice *dev)
236{
237 free(dev->priv);
238
239 return 0;
240}
241
Simon Glass767827a2014-06-11 23:29:45 -0600242static const struct udevice_id sandbox_gpio_ids[] = {
Simon Glassb4d70702014-02-26 15:59:25 -0700243 { .compatible = "sandbox,gpio" },
244 { }
245};
246
Walter Lozano2901ac62020-06-25 01:10:04 -0300247U_BOOT_DRIVER(sandbox_gpio) = {
248 .name = "sandbox_gpio",
Simon Glassb4d70702014-02-26 15:59:25 -0700249 .id = UCLASS_GPIO,
250 .of_match = sandbox_gpio_ids,
251 .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
252 .probe = gpio_sandbox_probe,
Simon Glassa367f1d2014-10-04 11:29:46 -0600253 .remove = gpio_sandbox_remove,
Simon Glassb4d70702014-02-26 15:59:25 -0700254 .ops = &gpio_sandbox_ops,
255};
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100256
Walter Lozano48e5b042020-06-25 01:10:06 -0300257U_BOOT_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
258
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100259/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
260
261struct sb_pinctrl_priv {
262 int pinctrl_ngpios;
263 struct list_head gpio_dev;
264};
265
266struct sb_gpio_bank {
267 struct udevice *gpio_dev;
268 struct list_head list;
269};
270
271static int sb_populate_gpio_dev_list(struct udevice *dev)
272{
273 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
274 struct udevice *gpio_dev;
275 struct udevice *child;
276 struct sb_gpio_bank *gpio_bank;
277 int ret;
278
279 /*
280 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
281 * a list with all gpio device reference which belongs to the
282 * current pin-controller. This list is used to find pin_name and
283 * pin muxing
284 */
285 list_for_each_entry(child, &dev->child_head, sibling_node) {
286 ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
287 &gpio_dev);
288 if (ret < 0)
289 continue;
290
291 gpio_bank = malloc(sizeof(*gpio_bank));
292 if (!gpio_bank) {
293 dev_err(dev, "Not enough memory\n");
294 return -ENOMEM;
295 }
296
297 gpio_bank->gpio_dev = gpio_dev;
298 list_add_tail(&gpio_bank->list, &priv->gpio_dev);
299 }
300
301 return 0;
302}
303
304static int sb_pinctrl_get_pins_count(struct udevice *dev)
305{
306 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
307 struct gpio_dev_priv *uc_priv;
308 struct sb_gpio_bank *gpio_bank;
309
310 /*
311 * if get_pins_count has already been executed once on this
312 * pin-controller, no need to run it again
313 */
314 if (priv->pinctrl_ngpios)
315 return priv->pinctrl_ngpios;
316
317 if (list_empty(&priv->gpio_dev))
318 sb_populate_gpio_dev_list(dev);
319 /*
320 * walk through all banks to retrieve the pin-controller
321 * pins number
322 */
323 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
324 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
325
326 priv->pinctrl_ngpios += uc_priv->gpio_count;
327 }
328
329 return priv->pinctrl_ngpios;
330}
331
332static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
333 unsigned int selector,
334 unsigned int *idx)
335{
336 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
337 struct sb_gpio_bank *gpio_bank;
338 struct gpio_dev_priv *uc_priv;
339 int pin_count = 0;
340
341 if (list_empty(&priv->gpio_dev))
342 sb_populate_gpio_dev_list(dev);
343
344 /* look up for the bank which owns the requested pin */
345 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
346 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
347
348 if (selector < (pin_count + uc_priv->gpio_count)) {
349 /*
350 * we found the bank, convert pin selector to
351 * gpio bank index
352 */
353 *idx = selector - pin_count;
354
355 return gpio_bank->gpio_dev;
356 }
357 pin_count += uc_priv->gpio_count;
358 }
359
360 return NULL;
361}
362
363static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
364 unsigned int selector)
365{
366 struct gpio_dev_priv *uc_priv;
367 struct udevice *gpio_dev;
368 unsigned int gpio_idx;
369 static char pin_name[PINNAME_SIZE];
370
371 /* look up for the bank which owns the requested pin */
372 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
373 if (!gpio_dev) {
374 snprintf(pin_name, PINNAME_SIZE, "Error");
375 } else {
376 uc_priv = dev_get_uclass_priv(gpio_dev);
377
378 snprintf(pin_name, PINNAME_SIZE, "%s%d",
379 uc_priv->bank_name,
380 gpio_idx);
381 }
382
383 return pin_name;
384}
385
386static char *get_dir_flags_string(ulong flags)
387{
388 if (flags & GPIOD_OPEN_DRAIN)
389 return "drive-open-drain";
390 if (flags & GPIOD_OPEN_SOURCE)
391 return "drive-open-source";
392 if (flags & GPIOD_PULL_UP)
393 return "bias-pull-up";
394 if (flags & GPIOD_PULL_DOWN)
395 return "bias-pull-down";
396 return ".";
397}
398
399static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
400 unsigned int selector,
401 char *buf, int size)
402{
403 struct udevice *gpio_dev;
404 unsigned int gpio_idx;
405 ulong dir_flags;
406 int function;
407
408 /* look up for the bank which owns the requested pin */
409 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
410 if (!gpio_dev) {
411 snprintf(buf, size, "Error");
412 } else {
413 function = sb_gpio_get_function(gpio_dev, gpio_idx);
414 dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
415
416 snprintf(buf, size, "gpio %s %s",
417 function == GPIOF_OUTPUT ? "output" : "input",
418 get_dir_flags_string(dir_flags));
419 }
420
421 return 0;
422}
423
424static int sandbox_pinctrl_probe(struct udevice *dev)
425{
426 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
427
428 INIT_LIST_HEAD(&priv->gpio_dev);
429
430 return 0;
431}
432
433static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
434 .get_pin_name = sb_pinctrl_get_pin_name,
435 .get_pins_count = sb_pinctrl_get_pins_count,
436 .get_pin_muxing = sb_pinctrl_get_pin_muxing,
437};
438
439static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
440 { .compatible = "sandbox,pinctrl-gpio" },
441 { /* sentinel */ }
442};
443
444U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
445 .name = "sandbox_pinctrl_gpio",
446 .id = UCLASS_PINCTRL,
447 .of_match = sandbox_pinctrl_gpio_match,
448 .ops = &sandbox_pinctrl_gpio_ops,
449 .bind = dm_scan_fdt_dev,
450 .probe = sandbox_pinctrl_probe,
451 .priv_auto_alloc_size = sizeof(struct sb_pinctrl_priv),
452};