]> git.sur5r.net Git - u-boot/commitdiff
dm: gpio: add BCM6345 gpio driver
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Sun, 7 May 2017 18:09:30 +0000 (20:09 +0200)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Wed, 10 May 2017 14:16:09 +0000 (16:16 +0200)
This driver is based on linux/arch/mips/bcm63xx/gpio.c, simplified to allow
defining one or two independent banks for each Broadcom SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/bcm6345_gpio.c [new file with mode: 0644]

index 99516119ff1d2486c1ef902d7a060aa35a004bfc..325d053931f73decd19aa8a2e1cae81793617a7f 100644 (file)
@@ -21,6 +21,12 @@ config ALTERA_PIO
          Select this to enable PIO for Altera devices. Please find
          details on the "Embedded Peripherals IP User Guide" of Altera.
 
          Select this to enable PIO for Altera devices. Please find
          details on the "Embedded Peripherals IP User Guide" of Altera.
 
+config BCM6345_GPIO
+       bool "BCM6345 GPIO driver"
+       depends on DM_GPIO && ARCH_BMIPS
+       help
+         This driver supports the GPIO banks on BCM6345 SoCs.
+
 config DWAPB_GPIO
        bool "DWAPB GPIO driver"
        depends on DM && DM_GPIO
 config DWAPB_GPIO
        bool "DWAPB GPIO driver"
        depends on DM && DM_GPIO
index 0ca845f54caa6bcc1111e44ad591eb7016de9429..03df558879b00963d9a6614fd0a96a06094e012f 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_DM_74X164)               += 74x164_gpio.o
 
 obj-$(CONFIG_AT91_GPIO)        += at91_gpio.o
 obj-$(CONFIG_ATMEL_PIO4)       += atmel_pio4.o
 
 obj-$(CONFIG_AT91_GPIO)        += at91_gpio.o
 obj-$(CONFIG_ATMEL_PIO4)       += atmel_pio4.o
+obj-$(CONFIG_BCM6345_GPIO)     += bcm6345_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)  += intel_ich6_gpio.o
 obj-$(CONFIG_INTEL_BROADWELL_GPIO)     += intel_broadwell_gpio.o
 obj-$(CONFIG_KIRKWOOD_GPIO)    += kw_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)  += intel_ich6_gpio.o
 obj-$(CONFIG_INTEL_BROADWELL_GPIO)     += intel_broadwell_gpio.o
 obj-$(CONFIG_KIRKWOOD_GPIO)    += kw_gpio.o
diff --git a/drivers/gpio/bcm6345_gpio.c b/drivers/gpio/bcm6345_gpio.c
new file mode 100644 (file)
index 0000000..1c46020
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/bcm63xx/gpio.c:
+ *     Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *     Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <dm/device.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct bcm6345_gpio_priv {
+       void __iomem *reg_dirout;
+       void __iomem *reg_data;
+};
+
+static int bcm6345_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+
+       return !!(readl_be(priv->reg_data) & BIT(offset));
+}
+
+static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset,
+                                 int value)
+{
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+
+       if (value)
+               setbits_be32(priv->reg_data, BIT(offset));
+       else
+               clrbits_be32(priv->reg_data, BIT(offset));
+
+       return 0;
+}
+
+static int bcm6345_gpio_set_direction(void __iomem *dirout, unsigned offset,
+                                     bool input)
+{
+       if (input)
+               clrbits_be32(dirout, BIT(offset));
+       else
+               setbits_be32(dirout, BIT(offset));
+
+       return 0;
+}
+
+static int bcm6345_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+
+       return bcm6345_gpio_set_direction(priv->reg_dirout, offset, 1);
+}
+
+static int bcm6345_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                        int value)
+{
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+
+       return bcm6345_gpio_set_direction(priv->reg_dirout, offset, 0);
+}
+
+static int bcm6345_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+
+       if (readl_be(priv->reg_dirout) & BIT(offset))
+               return GPIOF_OUTPUT;
+       else
+               return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops bcm6345_gpio_ops = {
+       .direction_input = bcm6345_gpio_direction_input,
+       .direction_output = bcm6345_gpio_direction_output,
+       .get_value = bcm6345_gpio_get_value,
+       .set_value = bcm6345_gpio_set_value,
+       .get_function = bcm6345_gpio_get_function,
+};
+
+static int bcm6345_gpio_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
+       fdt_addr_t data_addr, dirout_addr;
+       fdt_size_t data_size, dirout_size;
+
+       dirout_addr = dev_get_addr_size_index(dev, 0, &dirout_size);
+       if (dirout_addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       data_addr = dev_get_addr_size_index(dev, 1, &data_size);
+       if (data_addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       priv->reg_data = ioremap(data_addr, data_size);
+       priv->reg_dirout = ioremap(dirout_addr, dirout_size);
+
+       uc_priv->gpio_count = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+                                             "ngpios", 32);
+       uc_priv->bank_name = dev->name;
+
+       return 0;
+}
+
+static const struct udevice_id bcm6345_gpio_ids[] = {
+       { .compatible = "brcm,bcm6345-gpio" },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6345_gpio) = {
+       .name = "bcm6345-gpio",
+       .id = UCLASS_GPIO,
+       .of_match = bcm6345_gpio_ids,
+       .ops = &bcm6345_gpio_ops,
+       .priv_auto_alloc_size = sizeof(struct bcm6345_gpio_priv),
+       .probe = bcm6345_gpio_probe,
+};