From: Beniamino Galvani <b.galv...@gmail.com> Update the Meson pinctrl/gpio driver to support a live device tree.
Signed-off-by: Beniamino Galvani <b.galv...@gmail.com> Link: https://lore.kernel.org/r/20170709223006.3998-5-b.galv...@gmail.com Signed-off-by: Neil Armstrong <neil.armstr...@linaro.org> --- drivers/pinctrl/meson/pinctrl-meson.c | 73 +++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index babf1bccc9697596522dc93d8906ff0454cfebf5..21409063ee89cd2f8aa3d511f3fed6b64f800e51 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -10,6 +10,8 @@ #include <dm/device-internal.h> #include <dm/device_compat.h> #include <dm/lists.h> +#include <dm/of_addr.h> +#include <linux/ioport.h> #include <dm/pinctrl.h> #include <fdt_support.h> #include <linux/bitops.h> @@ -319,88 +321,91 @@ int meson_gpio_probe(struct udevice *dev) return 0; } -static fdt_addr_t parse_address(int offset, const char *name, int na, int ns) +static phys_addr_t parse_address(struct udevice *dev, ofnode node, + const char *name) { - int index, len = 0; - const fdt32_t *reg; + struct resource r; + fdt_size_t sz; + int na, ns, index; - index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name); + index = ofnode_stringlist_search(node, "reg-names", name); if (index < 0) return FDT_ADDR_T_NONE; - reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len); - if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) + if (of_live_active()) { + if (of_address_to_resource(ofnode_to_np(node), index, &r)) + return FDT_ADDR_T_NONE; + else + return r.start; + } + + na = dev_read_addr_cells(dev->parent); + if (na < 1) { + debug("bad #address-cells\n"); return FDT_ADDR_T_NONE; + } - reg += index * (na + ns); + ns = dev_read_size_cells(dev->parent); + if (ns < 1) { + debug("bad #size-cells\n"); + return FDT_ADDR_T_NONE; + } - return fdt_translate_address((void *)gd->fdt_blob, offset, reg); + return fdtdec_get_addr_size_fixed(gd->fdt_blob, ofnode_to_offset(node), + "reg", index, na, ns, &sz, true); } int meson_pinctrl_probe(struct udevice *dev) { struct meson_pinctrl *priv = dev_get_priv(dev); + ofnode node, gpio = ofnode_null(); struct uclass_driver *drv; struct udevice *gpio_dev; - fdt_addr_t addr; - int node, gpio = -1, len; - int na, ns; + phys_addr_t addr; char *name; + int len; - /* FIXME: Should use livetree */ - na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent)); - if (na < 1) { - debug("bad #address-cells\n"); - return -EINVAL; - } - - ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); - if (ns < 1) { - debug("bad #size-cells\n"); - return -EINVAL; - } - - fdt_for_each_subnode(node, gd->fdt_blob, dev_of_offset(dev)) { - if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) { + dev_for_each_subnode(node, dev) { + if (ofnode_read_prop(node, "gpio-controller", &len)) { gpio = node; break; } } - if (!gpio) { + if (!ofnode_valid(gpio)) { debug("gpio node not found\n"); return -EINVAL; } - addr = parse_address(gpio, "mux", na, ns); + addr = parse_address(dev, gpio, "mux"); if (addr == FDT_ADDR_T_NONE) { debug("mux address not found\n"); return -EINVAL; } priv->reg_mux = (void __iomem *)addr; - addr = parse_address(gpio, "gpio", na, ns); + addr = parse_address(dev, gpio, "gpio"); if (addr == FDT_ADDR_T_NONE) { debug("gpio address not found\n"); return -EINVAL; } priv->reg_gpio = (void __iomem *)addr; - addr = parse_address(gpio, "pull", na, ns); + addr = parse_address(dev, gpio, "pull"); /* Use gpio region if pull one is not present */ if (addr == FDT_ADDR_T_NONE) priv->reg_pull = priv->reg_gpio; else priv->reg_pull = (void __iomem *)addr; - addr = parse_address(gpio, "pull-enable", na, ns); + addr = parse_address(dev, gpio, "pull-enable"); /* Use pull region if pull-enable one is not present */ if (addr == FDT_ADDR_T_NONE) priv->reg_pullen = priv->reg_pull; else priv->reg_pullen = (void __iomem *)addr; - addr = parse_address(gpio, "ds", na, ns); + addr = parse_address(dev, gpio, "ds"); /* Drive strength region is optional */ if (addr == FDT_ADDR_T_NONE) priv->reg_ds = NULL; @@ -420,8 +425,8 @@ int meson_pinctrl_probe(struct udevice *dev) sprintf(name, "meson-gpio"); /* Create child device UCLASS_GPIO and bind it */ - device_bind(dev, priv->data->gpio_driver, name, NULL, - offset_to_ofnode(gpio), &gpio_dev); + device_bind_with_driver_data(dev, priv->data->gpio_driver, name, 0, + gpio, &gpio_dev); return 0; } -- 2.34.1