gpio: ftgpio010: Add support for Faraday Technology FTGPIO010
authorSergei Antonov <saproj@gmail.com>
Mon, 12 Sep 2022 10:09:15 +0000 (13:09 +0300)
committerTom Rini <trini@konsulko.com>
Fri, 7 Oct 2022 01:05:17 +0000 (21:05 -0400)
Add Faraday Technology's FTGPIO010 controller driver.

Signed-off-by: Sergei Antonov <saproj@gmail.com>
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/ftgpio010.c [new file with mode: 0644]

index c949f9d..2a60478 100644 (file)
@@ -605,4 +605,10 @@ config TURRIS_OMNIA_MCU
        help
           Support for GPIOs on MCU connected to Turris Omnia via i2c.
 
+config FTGPIO010
+       bool "Faraday Technology FTGPIO010 driver"
+       depends on DM_GPIO
+       help
+          Support for GPIOs on Faraday Technology's FTGPIO010 controller.
+
 endif
index 9d718a5..eee7908 100644 (file)
@@ -75,3 +75,4 @@ obj-$(CONFIG_SL28CPLD_GPIO)   += sl28cpld-gpio.o
 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN)      += zynqmp_gpio_modepin.o
 obj-$(CONFIG_SLG7XL45106_I2C_GPO)      += gpio_slg7xl45106.o
 obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU)      += turris_omnia_mcu.o
+obj-$(CONFIG_FTGPIO010)                += ftgpio010.o
diff --git a/drivers/gpio/ftgpio010.c b/drivers/gpio/ftgpio010.c
new file mode 100644 (file)
index 0000000..6c091d4
--- /dev/null
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Faraday Technology's FTGPIO010 controller.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+struct ftgpio010_regs {
+       u32 out;
+       u32 in;
+       u32 direction;  // 1 - output
+       u32 reserved;
+       u32 set;
+       u32 clear;
+};
+
+struct ftgpio010_plat {
+       struct ftgpio010_regs __iomem *regs;
+};
+
+static int ftgpio010_direction_input(struct udevice *dev, unsigned int pin)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+       struct ftgpio010_regs *const regs = plat->regs;
+
+       clrbits_le32(&regs->direction, 1 << pin);
+       return 0;
+}
+
+static int ftgpio010_direction_output(struct udevice *dev, unsigned int pin,
+                                     int val)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+       struct ftgpio010_regs *const regs = plat->regs;
+
+       /* change the data first, then the direction. to avoid glitch */
+       out_le32(val ? &regs->set : &regs->clear, 1 << pin);
+       setbits_le32(&regs->direction, 1 << pin);
+
+       return 0;
+}
+
+static int ftgpio010_get_value(struct udevice *dev, unsigned int pin)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+       struct ftgpio010_regs *const regs = plat->regs;
+
+       return in_le32(&regs->in) >> pin & 1;
+}
+
+static int ftgpio010_set_value(struct udevice *dev, unsigned int pin, int val)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+       struct ftgpio010_regs *const regs = plat->regs;
+
+       out_le32(val ? &regs->set : &regs->clear, 1 << pin);
+       return 0;
+}
+
+static int ftgpio010_get_function(struct udevice *dev, unsigned int pin)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+       struct ftgpio010_regs *const regs = plat->regs;
+
+       if (in_le32(&regs->direction) >> pin & 1)
+               return GPIOF_OUTPUT;
+       return GPIOF_INPUT;
+}
+
+static int ftgpio010_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+       uc_priv->gpio_count = ofnode_read_u32_default(dev_ofnode(dev),
+                                                     "nr-gpios", 32);
+       return 0;
+}
+
+static int ftgpio010_of_to_plat(struct udevice *dev)
+{
+       struct ftgpio010_plat *plat = dev_get_plat(dev);
+
+       plat->regs = dev_read_addr_ptr(dev);
+       return 0;
+}
+
+static const struct dm_gpio_ops ftgpio010_ops = {
+       .direction_input        = ftgpio010_direction_input,
+       .direction_output       = ftgpio010_direction_output,
+       .get_value              = ftgpio010_get_value,
+       .set_value              = ftgpio010_set_value,
+       .get_function           = ftgpio010_get_function,
+};
+
+static const struct udevice_id ftgpio010_ids[] = {
+       { .compatible = "faraday,ftgpio010" },
+       { }
+};
+
+U_BOOT_DRIVER(ftgpio010) = {
+       .name           = "ftgpio010",
+       .id             = UCLASS_GPIO,
+       .of_match       = ftgpio010_ids,
+       .ops            = &ftgpio010_ops,
+       .of_to_plat     = ftgpio010_of_to_plat,
+       .plat_auto      = sizeof(struct ftgpio010_plat),
+       .probe          = ftgpio010_probe,
+};