gpio: ftgpio010: Add support for Faraday Technology FTGPIO010

Add Faraday Technology's FTGPIO010 controller driver.

Signed-off-by: Sergei Antonov <saproj@gmail.com>
This commit is contained in:
Sergei Antonov 2022-09-12 13:09:15 +03:00 committed by Tom Rini
parent 2afa989fbe
commit d100d3e18e
3 changed files with 118 additions and 0 deletions

View file

@ -605,4 +605,10 @@ config TURRIS_OMNIA_MCU
help help
Support for GPIOs on MCU connected to Turris Omnia via i2c. 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 endif

View file

@ -75,3 +75,4 @@ obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
obj-$(CONFIG_FTGPIO010) += ftgpio010.o

111
drivers/gpio/ftgpio010.c Normal file
View file

@ -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,
};