/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Western Digital Corporation or its affiliates. * * Authors: * Anup Patel */ #include #include #include #include /* List of FDT gpio drivers generated at compile time */ extern const struct fdt_driver *const fdt_gpio_drivers[]; static int fdt_gpio_init(const void *fdt, int nodeoff) { /* Check "gpio-controller" property */ if (!fdt_getprop(fdt, nodeoff, "gpio-controller", NULL)) return SBI_EINVAL; return fdt_driver_init_by_offset(fdt, nodeoff, fdt_gpio_drivers); } static int fdt_gpio_chip_find(const void *fdt, int nodeoff, struct gpio_chip **out_chip) { int rc; struct gpio_chip *chip = gpio_chip_find(nodeoff); if (!chip) { /* GPIO chip not found so initialize matching driver */ rc = fdt_gpio_init(fdt, nodeoff); if (rc) return rc; /* Try to find GPIO chip again */ chip = gpio_chip_find(nodeoff); if (!chip) return SBI_ENOSYS; } if (out_chip) *out_chip = chip; return 0; } int fdt_gpio_pin_get(const void *fdt, int nodeoff, int index, struct gpio_pin *out_pin) { int rc; const struct fdt_gpio *drv; struct gpio_chip *chip = NULL; struct fdt_phandle_args pargs; if (!fdt || (nodeoff < 0) || (index < 0) || !out_pin) return SBI_EINVAL; pargs.node_offset = pargs.args_count = 0; rc = fdt_parse_phandle_with_args(fdt, nodeoff, "gpios", "#gpio-cells", index, &pargs); if (rc) return rc; rc = fdt_gpio_chip_find(fdt, pargs.node_offset, &chip); if (rc) return rc; drv = chip->driver; if (!drv || !drv->xlate) return SBI_ENOSYS; return drv->xlate(chip, &pargs, out_pin); } int fdt_gpio_simple_xlate(struct gpio_chip *chip, const struct fdt_phandle_args *pargs, struct gpio_pin *out_pin) { if ((pargs->args_count < 2) || (chip->ngpio <= pargs->args[0])) return SBI_EINVAL; out_pin->chip = chip; out_pin->offset = pargs->args[0]; out_pin->flags = pargs->args[1]; return 0; }