X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fgpio%2Fbcm2835_gpio.c;h=f4b67f1cf0aff523a19bcaf6bcf64833f0c1abca;hb=b0b13f4114d30b6756e0f6f3b5819d78de22541e;hp=0244c01882863903596f76f153a11cbbaf98dc3e;hpb=674ca84d11391cd2e7faf8f638fc25ed4b782a91;p=oweals%2Fu-boot.git diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c index 0244c01882..f4b67f1cf0 100644 --- a/drivers/gpio/bcm2835_gpio.c +++ b/drivers/gpio/bcm2835_gpio.c @@ -1,18 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2012 Vikram Narayananan * - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include #include #include #include +#include struct bcm2835_gpios { struct bcm2835_gpio_regs *reg; + struct udevice *pinctrl; }; static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio) @@ -28,7 +30,7 @@ static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio) return 0; } -static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio, +static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio, int value) { struct bcm2835_gpios *gpios = dev_get_priv(dev); @@ -44,15 +46,6 @@ static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio, return 0; } -static bool bcm2835_gpio_is_output(const struct bcm2835_gpios *gpios, int gpio) -{ - u32 val; - - val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); - val &= BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio); - return val ? true : false; -} - static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio) { unsigned val; @@ -83,16 +76,21 @@ static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio, static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset) { - struct bcm2835_gpios *gpios = dev_get_priv(dev); + struct bcm2835_gpios *priv = dev_get_priv(dev); + int funcid; - /* GPIOF_FUNC is not implemented yet */ - if (bcm2835_gpio_is_output(gpios, offset)) + funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset); + + switch (funcid) { + case BCM2835_GPIO_OUTPUT: return GPIOF_OUTPUT; - else + case BCM2835_GPIO_INPUT: return GPIOF_INPUT; + default: + return GPIOF_FUNC; + } } - static const struct dm_gpio_ops gpio_bcm2835_ops = { .direction_input = bcm2835_gpio_direction_input, .direction_output = bcm2835_gpio_direction_output, @@ -105,19 +103,40 @@ static int bcm2835_gpio_probe(struct udevice *dev) { struct bcm2835_gpios *gpios = dev_get_priv(dev); struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev); - struct gpio_dev_priv *uc_priv = dev->uclass_priv; + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); uc_priv->bank_name = "GPIO"; uc_priv->gpio_count = BCM2835_GPIO_COUNT; gpios->reg = (struct bcm2835_gpio_regs *)plat->base; + /* We know we're spawned by the pinctrl driver */ + gpios->pinctrl = dev->parent; + + return 0; +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev); + fdt_addr_t addr; + + addr = devfdt_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = addr; return 0; } +#endif U_BOOT_DRIVER(gpio_bcm2835) = { .name = "gpio_bcm2835", .id = UCLASS_GPIO, + .ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata), + .platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata), .ops = &gpio_bcm2835_ops, .probe = bcm2835_gpio_probe, + .flags = DM_FLAG_PRE_RELOC, .priv_auto_alloc_size = sizeof(struct bcm2835_gpios), };