blob: 9549c74c2bee62db86d23b3964f4f6ebaf51c692 [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>
9#include <malloc.h>
Simon Glassb43d0442012-02-15 15:51:13 -080010#include <asm/gpio.h>
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +010011#include <dm/device_compat.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010012#include <dm/lists.h>
Simon Glass12faa022017-05-18 20:09:18 -060013#include <dm/of.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010014#include <dm/pinctrl.h>
Simon Glass16e10402015-01-05 20:05:29 -070015#include <dt-bindings/gpio/gpio.h>
Patrick Delaunay23aee612020-01-13 11:35:13 +010016#include <dt-bindings/gpio/sandbox-gpio.h>
Simon Glassb43d0442012-02-15 15:51:13 -080017
Simon Glassb43d0442012-02-15 15:51:13 -080018
19struct gpio_state {
20 const char *label; /* label given by requester */
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010021 ulong dir_flags; /* dir_flags (GPIOD_...) */
Simon Glassb43d0442012-02-15 15:51:13 -080022};
23
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010024/* Access routines for GPIO dir flags */
25static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
Simon Glassb43d0442012-02-15 15:51:13 -080026{
Simon Glassde0977b2015-03-05 12:25:20 -070027 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -070028 struct gpio_state *state = dev_get_priv(dev);
29
30 if (offset >= uc_priv->gpio_count) {
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010031 static ulong invalid_dir_flags;
Simon Glassb4d70702014-02-26 15:59:25 -070032 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010033 return &invalid_dir_flags;
Simon Glassb43d0442012-02-15 15:51:13 -080034 }
35
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010036 return &state[offset].dir_flags;
37
Simon Glassb43d0442012-02-15 15:51:13 -080038}
39
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010040static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
Simon Glassb43d0442012-02-15 15:51:13 -080041{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010042 return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
Simon Glassb43d0442012-02-15 15:51:13 -080043}
44
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010045static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
Simon Glassb4d70702014-02-26 15:59:25 -070046 int value)
Simon Glassb43d0442012-02-15 15:51:13 -080047{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010048 ulong *gpio = get_gpio_dir_flags(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -080049
50 if (value)
51 *gpio |= flag;
52 else
53 *gpio &= ~flag;
54
55 return 0;
56}
57
Simon Glassb43d0442012-02-15 15:51:13 -080058/*
59 * Back-channel sandbox-internal-only access to GPIO state
60 */
61
Heiko Schocherb74fcb42014-05-22 12:43:05 +020062int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080063{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010064 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glassb4d70702014-02-26 15:59:25 -070065 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010066 return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
Simon Glassb43d0442012-02-15 15:51:13 -080067}
68
Heiko Schocherb74fcb42014-05-22 12:43:05 +020069int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -080070{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010071 return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
Simon Glassb43d0442012-02-15 15:51:13 -080072}
73
Heiko Schocherb74fcb42014-05-22 12:43:05 +020074int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080075{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010076 return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
Simon Glassb43d0442012-02-15 15:51:13 -080077}
78
Heiko Schocherb74fcb42014-05-22 12:43:05 +020079int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
Simon Glassb43d0442012-02-15 15:51:13 -080080{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010081 set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
82 set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
83
84 return 0;
85}
86
87ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
88{
89 return *get_gpio_dir_flags(dev, offset);
90}
91
92int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
93 ulong flags)
94{
95 *get_gpio_dir_flags(dev, offset) = flags;
96
97 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -080098}
99
100/*
101 * These functions implement the public interface within U-Boot
102 */
103
Simon Glassb4d70702014-02-26 15:59:25 -0700104/* set GPIO port 'offset' as an input */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200105static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800106{
Simon Glassb4d70702014-02-26 15:59:25 -0700107 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800108
Simon Glassb4d70702014-02-26 15:59:25 -0700109 return sandbox_gpio_set_direction(dev, offset, 0);
Simon Glassb43d0442012-02-15 15:51:13 -0800110}
111
Simon Glassb4d70702014-02-26 15:59:25 -0700112/* set GPIO port 'offset' as an output, with polarity 'value' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200113static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
Simon Glassb4d70702014-02-26 15:59:25 -0700114 int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800115{
Simon Glassb4d70702014-02-26 15:59:25 -0700116 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800117
Simon Glassb4d70702014-02-26 15:59:25 -0700118 return sandbox_gpio_set_direction(dev, offset, 1) |
119 sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800120}
121
Simon Glassb4d70702014-02-26 15:59:25 -0700122/* read GPIO IN value of port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200123static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800124{
Simon Glassb4d70702014-02-26 15:59:25 -0700125 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800126
Simon Glassb4d70702014-02-26 15:59:25 -0700127 return sandbox_gpio_get_value(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800128}
129
Simon Glassb4d70702014-02-26 15:59:25 -0700130/* write GPIO OUT value to port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200131static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800132{
Simon Glassb4d70702014-02-26 15:59:25 -0700133 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800134
Simon Glassb4d70702014-02-26 15:59:25 -0700135 if (!sandbox_gpio_get_direction(dev, offset)) {
136 printf("sandbox_gpio: error: set_value on input gpio %u\n",
137 offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800138 return -1;
139 }
140
Simon Glassb4d70702014-02-26 15:59:25 -0700141 return sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800142}
143
Simon Glass32048632014-10-04 11:29:45 -0600144static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
145{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100146 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glass32048632014-10-04 11:29:45 -0600147 return GPIOF_OUTPUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100148 if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
149 return GPIOF_INPUT;
150
151 return GPIOF_INPUT; /*GPIO is not configurated */
Simon Glass32048632014-10-04 11:29:45 -0600152}
153
Simon Glass16e10402015-01-05 20:05:29 -0700154static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
Simon Glass12faa022017-05-18 20:09:18 -0600155 struct ofnode_phandle_args *args)
Simon Glass16e10402015-01-05 20:05:29 -0700156{
157 desc->offset = args->args[0];
158 if (args->args_count < 2)
159 return 0;
Patrick Delaunay23aee612020-01-13 11:35:13 +0100160 /* treat generic binding with gpio uclass */
161 gpio_xlate_offs_flags(dev, desc, args);
162
163 /* sandbox test specific, not defined in gpio.h */
164 if (args->args[1] & GPIO_IN)
Simon Glass16e10402015-01-05 20:05:29 -0700165 desc->flags |= GPIOD_IS_IN;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100166
Patrick Delaunay23aee612020-01-13 11:35:13 +0100167 if (args->args[1] & GPIO_OUT)
Simon Glass16e10402015-01-05 20:05:29 -0700168 desc->flags |= GPIOD_IS_OUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100169
Patrick Delaunay23aee612020-01-13 11:35:13 +0100170 if (args->args[1] & GPIO_OUT_ACTIVE)
Simon Glass16e10402015-01-05 20:05:29 -0700171 desc->flags |= GPIOD_IS_OUT_ACTIVE;
172
173 return 0;
174}
175
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100176static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
177 ulong flags)
178{
179 ulong *dir_flags;
180
181 debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
182
183 dir_flags = get_gpio_dir_flags(dev, offset);
184
185 *dir_flags = flags;
186
187 return 0;
188}
189
190static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
191 ulong *flags)
192{
193 debug("%s: offset:%u\n", __func__, offset);
194 *flags = *get_gpio_dir_flags(dev, offset);
195
196 return 0;
197}
198
Simon Glassb4d70702014-02-26 15:59:25 -0700199static const struct dm_gpio_ops gpio_sandbox_ops = {
Simon Glassb4d70702014-02-26 15:59:25 -0700200 .direction_input = sb_gpio_direction_input,
201 .direction_output = sb_gpio_direction_output,
202 .get_value = sb_gpio_get_value,
203 .set_value = sb_gpio_set_value,
Simon Glass32048632014-10-04 11:29:45 -0600204 .get_function = sb_gpio_get_function,
Simon Glass16e10402015-01-05 20:05:29 -0700205 .xlate = sb_gpio_xlate,
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100206 .set_dir_flags = sb_gpio_set_dir_flags,
207 .get_dir_flags = sb_gpio_get_dir_flags,
Simon Glassb4d70702014-02-26 15:59:25 -0700208};
209
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200210static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
Simon Glassb43d0442012-02-15 15:51:13 -0800211{
Simon Glassde0977b2015-03-05 12:25:20 -0700212 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb43d0442012-02-15 15:51:13 -0800213
Simon Glass9e7ab232018-02-03 10:36:59 -0700214 uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
215 0);
Simon Glass1185fcb2017-05-18 20:09:20 -0600216 uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
Simon Glassb43d0442012-02-15 15:51:13 -0800217
Simon Glassb4d70702014-02-26 15:59:25 -0700218 return 0;
219}
Simon Glassb43d0442012-02-15 15:51:13 -0800220
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200221static int gpio_sandbox_probe(struct udevice *dev)
Simon Glassb4d70702014-02-26 15:59:25 -0700222{
Simon Glassde0977b2015-03-05 12:25:20 -0700223 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -0700224
Simon Glass1185fcb2017-05-18 20:09:20 -0600225 if (!dev_of_valid(dev))
Simon Glassb4d70702014-02-26 15:59:25 -0700226 /* Tell the uclass how many GPIOs we have */
227 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
Simon Glassb4d70702014-02-26 15:59:25 -0700228
229 dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
230
231 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -0800232}
Simon Glassb4d70702014-02-26 15:59:25 -0700233
Simon Glassa367f1d2014-10-04 11:29:46 -0600234static int gpio_sandbox_remove(struct udevice *dev)
235{
236 free(dev->priv);
237
238 return 0;
239}
240
Simon Glass767827a2014-06-11 23:29:45 -0600241static const struct udevice_id sandbox_gpio_ids[] = {
Simon Glassb4d70702014-02-26 15:59:25 -0700242 { .compatible = "sandbox,gpio" },
243 { }
244};
245
246U_BOOT_DRIVER(gpio_sandbox) = {
247 .name = "gpio_sandbox",
248 .id = UCLASS_GPIO,
249 .of_match = sandbox_gpio_ids,
250 .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
251 .probe = gpio_sandbox_probe,
Simon Glassa367f1d2014-10-04 11:29:46 -0600252 .remove = gpio_sandbox_remove,
Simon Glassb4d70702014-02-26 15:59:25 -0700253 .ops = &gpio_sandbox_ops,
254};
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100255
256/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
257
258struct sb_pinctrl_priv {
259 int pinctrl_ngpios;
260 struct list_head gpio_dev;
261};
262
263struct sb_gpio_bank {
264 struct udevice *gpio_dev;
265 struct list_head list;
266};
267
268static int sb_populate_gpio_dev_list(struct udevice *dev)
269{
270 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
271 struct udevice *gpio_dev;
272 struct udevice *child;
273 struct sb_gpio_bank *gpio_bank;
274 int ret;
275
276 /*
277 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
278 * a list with all gpio device reference which belongs to the
279 * current pin-controller. This list is used to find pin_name and
280 * pin muxing
281 */
282 list_for_each_entry(child, &dev->child_head, sibling_node) {
283 ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
284 &gpio_dev);
285 if (ret < 0)
286 continue;
287
288 gpio_bank = malloc(sizeof(*gpio_bank));
289 if (!gpio_bank) {
290 dev_err(dev, "Not enough memory\n");
291 return -ENOMEM;
292 }
293
294 gpio_bank->gpio_dev = gpio_dev;
295 list_add_tail(&gpio_bank->list, &priv->gpio_dev);
296 }
297
298 return 0;
299}
300
301static int sb_pinctrl_get_pins_count(struct udevice *dev)
302{
303 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
304 struct gpio_dev_priv *uc_priv;
305 struct sb_gpio_bank *gpio_bank;
306
307 /*
308 * if get_pins_count has already been executed once on this
309 * pin-controller, no need to run it again
310 */
311 if (priv->pinctrl_ngpios)
312 return priv->pinctrl_ngpios;
313
314 if (list_empty(&priv->gpio_dev))
315 sb_populate_gpio_dev_list(dev);
316 /*
317 * walk through all banks to retrieve the pin-controller
318 * pins number
319 */
320 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
321 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
322
323 priv->pinctrl_ngpios += uc_priv->gpio_count;
324 }
325
326 return priv->pinctrl_ngpios;
327}
328
329static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
330 unsigned int selector,
331 unsigned int *idx)
332{
333 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
334 struct sb_gpio_bank *gpio_bank;
335 struct gpio_dev_priv *uc_priv;
336 int pin_count = 0;
337
338 if (list_empty(&priv->gpio_dev))
339 sb_populate_gpio_dev_list(dev);
340
341 /* look up for the bank which owns the requested pin */
342 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
343 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
344
345 if (selector < (pin_count + uc_priv->gpio_count)) {
346 /*
347 * we found the bank, convert pin selector to
348 * gpio bank index
349 */
350 *idx = selector - pin_count;
351
352 return gpio_bank->gpio_dev;
353 }
354 pin_count += uc_priv->gpio_count;
355 }
356
357 return NULL;
358}
359
360static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
361 unsigned int selector)
362{
363 struct gpio_dev_priv *uc_priv;
364 struct udevice *gpio_dev;
365 unsigned int gpio_idx;
366 static char pin_name[PINNAME_SIZE];
367
368 /* look up for the bank which owns the requested pin */
369 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
370 if (!gpio_dev) {
371 snprintf(pin_name, PINNAME_SIZE, "Error");
372 } else {
373 uc_priv = dev_get_uclass_priv(gpio_dev);
374
375 snprintf(pin_name, PINNAME_SIZE, "%s%d",
376 uc_priv->bank_name,
377 gpio_idx);
378 }
379
380 return pin_name;
381}
382
383static char *get_dir_flags_string(ulong flags)
384{
385 if (flags & GPIOD_OPEN_DRAIN)
386 return "drive-open-drain";
387 if (flags & GPIOD_OPEN_SOURCE)
388 return "drive-open-source";
389 if (flags & GPIOD_PULL_UP)
390 return "bias-pull-up";
391 if (flags & GPIOD_PULL_DOWN)
392 return "bias-pull-down";
393 return ".";
394}
395
396static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
397 unsigned int selector,
398 char *buf, int size)
399{
400 struct udevice *gpio_dev;
401 unsigned int gpio_idx;
402 ulong dir_flags;
403 int function;
404
405 /* look up for the bank which owns the requested pin */
406 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
407 if (!gpio_dev) {
408 snprintf(buf, size, "Error");
409 } else {
410 function = sb_gpio_get_function(gpio_dev, gpio_idx);
411 dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
412
413 snprintf(buf, size, "gpio %s %s",
414 function == GPIOF_OUTPUT ? "output" : "input",
415 get_dir_flags_string(dir_flags));
416 }
417
418 return 0;
419}
420
421static int sandbox_pinctrl_probe(struct udevice *dev)
422{
423 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
424
425 INIT_LIST_HEAD(&priv->gpio_dev);
426
427 return 0;
428}
429
430static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
431 .get_pin_name = sb_pinctrl_get_pin_name,
432 .get_pins_count = sb_pinctrl_get_pins_count,
433 .get_pin_muxing = sb_pinctrl_get_pin_muxing,
434};
435
436static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
437 { .compatible = "sandbox,pinctrl-gpio" },
438 { /* sentinel */ }
439};
440
441U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
442 .name = "sandbox_pinctrl_gpio",
443 .id = UCLASS_PINCTRL,
444 .of_match = sandbox_pinctrl_gpio_match,
445 .ops = &sandbox_pinctrl_gpio_ops,
446 .bind = dm_scan_fdt_dev,
447 .probe = sandbox_pinctrl_probe,
448 .priv_auto_alloc_size = sizeof(struct sb_pinctrl_priv),
449};