[U-Boot] [PATCH] gpio: atmel_pio4: rework to support driver model & DT

Andreas Bießmann andreas at biessmann.org
Tue May 3 13:20:11 CEST 2016


Dear Wenyou,

On 2016-04-15 02:49, Wenyou Yang wrote:
> Rework the driver to support the driver model and the device tree.

Could you please put this one into a series with the pinctrl driver?

> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---
> 
>  drivers/gpio/Kconfig      |   2 +-
>  drivers/gpio/atmel_pio4.c | 106 
> +++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 86 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 2311309..62e730d 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -30,7 +30,7 @@ config DWAPB_GPIO
> 
>  config ATMEL_PIO4
>  	bool "ATMEL PIO4 driver"
> -	depends on DM
> +	depends on DM_GPIO
>  	default n
>  	help
>  	  Say yes here to support the Atmel PIO4 driver.
> diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c
> index d71f525..543b037 100644
> --- a/drivers/gpio/atmel_pio4.c
> +++ b/drivers/gpio/atmel_pio4.c
> @@ -9,9 +9,12 @@
>  #include <common.h>
>  #include <dm.h>
>  #include <asm/arch/hardware.h>
> +#include <asm/gpio.h>
>  #include <mach/gpio.h>
>  #include <mach/atmel_pio4.h>
> 
> +DECLARE_GLOBAL_DATA_PTR;
> +
>  #define ATMEL_PIO4_PINS_PER_BANK	32
> 
>  /*
> @@ -200,14 +203,38 @@ int atmel_pio4_get_pio_input(u32 port, u32 pin)
>  }
> 
>  #ifdef CONFIG_DM_GPIO
> +
> +struct atmel_pioctrl_data {
> +	u32 nbanks;
> +};
> +
> +struct atmel_pio4_platdata {
> +	struct atmel_pio4_port *reg_base;
> +};
> +
> +static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice 
> *dev,
> +						    u32 bank)
> +{
> +	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
> +	struct atmel_pio4_port *port_base =
> +			(struct atmel_pio4_port *)((u32)plat->reg_base +
> +			ATMEL_PIO_BANK_OFFSET * bank);
> +
> +	return port_base;
> +}
> +
>  static int atmel_pio4_direction_input(struct udevice *dev, unsigned 
> offset)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> -	struct atmel_pio4_port *port_base = (atmel_pio4_port 
> *)plat->base_addr;
> -	u32 mask = 0x01 << offset;
> -	u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO;
> +	u32 bank = ATMEL_PIO_BANK(offset);
> +	u32 line = ATMEL_PIO_LINE(offset);
> +	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
> +	u32 mask = BIT(line);
> +	u32 reg;
> 
>  	writel(mask, &port_base->mskr);
> +	reg = readl(&port_base->cfgr);
> +	reg &= ~ATMEL_PIO_CFGR_FUNC_MASK;
> +	reg &= ~ATMEL_PIO_DIR_MASK;
>  	writel(reg, &port_base->cfgr);
> 
>  	return 0;
> @@ -216,12 +243,16 @@ static int atmel_pio4_direction_input(struct
> udevice *dev, unsigned offset)
>  static int atmel_pio4_direction_output(struct udevice *dev,
>  				       unsigned offset, int value)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> -	struct atmel_pio4_port *port_base = (atmel_pio4_port 
> *)plat->base_addr;
> -	u32 mask = 0x01 << offset;
> -	u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR;
> +	u32 bank = ATMEL_PIO_BANK(offset);
> +	u32 line = ATMEL_PIO_LINE(offset);
> +	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
> +	u32 mask = BIT(line);
> +	u32 reg;
> 
>  	writel(mask, &port_base->mskr);
> +	reg = readl(&port_base->cfgr);
> +	reg &= ~ATMEL_PIO_CFGR_FUNC_MASK;
> +	reg |= ATMEL_PIO_DIR_MASK;
>  	writel(reg, &port_base->cfgr);
> 
>  	if (value)
> @@ -234,9 +265,10 @@ static int atmel_pio4_direction_output(struct 
> udevice *dev,
> 
>  static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> -	struct atmel_pio4_port *port_base = (atmel_pio4_port 
> *)plat->base_addr;
> -	u32 mask = 0x01 << offset;
> +	u32 bank = ATMEL_PIO_BANK(offset);
> +	u32 line = ATMEL_PIO_LINE(offset);
> +	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
> +	u32 mask = BIT(line);
> 
>  	return (readl(&port_base->pdsr) & mask) ? 1 : 0;
>  }
> @@ -244,9 +276,10 @@ static int atmel_pio4_get_value(struct udevice
> *dev, unsigned offset)
>  static int atmel_pio4_set_value(struct udevice *dev,
>  				unsigned offset, int value)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> -	struct atmel_pio4_port *port_base = (atmel_pio4_port 
> *)plat->base_addr;
> -	u32 mask = 0x01 << offset;
> +	u32 bank = ATMEL_PIO_BANK(offset);
> +	u32 line = ATMEL_PIO_LINE(offset);
> +	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
> +	u32 mask = BIT(line);
> 
>  	if (value)
>  		writel(mask, &port_base->sodr);
> @@ -258,14 +291,15 @@ static int atmel_pio4_set_value(struct udevice 
> *dev,
> 
>  static int atmel_pio4_get_function(struct udevice *dev, unsigned 
> offset)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> -	struct atmel_pio4_port *port_base = (atmel_pio4_port 
> *)plat->base_addr;
> -	u32 mask = 0x01 << offset;
> +	u32 bank = ATMEL_PIO_BANK(offset);
> +	u32 line = ATMEL_PIO_LINE(offset);
> +	struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
> +	u32 mask = BIT(line);
> 
>  	writel(mask, &port_base->mskr);
> 
>  	return (readl(&port_base->cfgr) &
> -		ATMEL_PIO4_CFGR_DIR) ? GPIOF_OUTPUT : GPIOF_INPUT;
> +		ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT;

Could you please also check, that the ATMEL_PIO4_CFGR_DIR is deleted 
with this patch (or better with 'pinctrl: at91-pio4: add pinctrl 
driver')

>  }
> 
>  static const struct dm_gpio_ops atmel_pio4_ops = {
> @@ -278,19 +312,49 @@ static const struct dm_gpio_ops atmel_pio4_ops = 
> {
> 
>  static int atmel_pio4_probe(struct udevice *dev)
>  {
> -	struct at91_port_platdata *plat = dev_get_platdata(dev);
> +	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
>  	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +	struct atmel_pioctrl_data *pioctrl_data;
> +	fdt_addr_t addr_base;
> +	u32 nbanks;
> 
> -	uc_priv->bank_name = plat->bank_name;
> -	uc_priv->gpio_count = ATMEL_PIO4_PINS_PER_BANK;
> +	addr_base = dev_get_addr(dev);
> +	if (addr_base == FDT_ADDR_T_NONE)
> +		return -ENODEV;
> +
> +	plat->reg_base = (struct atmel_pio4_port *)addr_base;
> +
> +	pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev);
> +	nbanks = pioctrl_data->nbanks;
> +
> +	uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev->of_offset, 
> NULL);
> +	uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK;
> 
>  	return 0;
>  }
> 
> +/*
> + * The number of banks can be different from a SoC to another one.
> + * We can have up to 16 banks.
> + */
> +static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
> +	.nbanks	= 4,
> +};
> +
> +static const struct udevice_id atmel_pio4_ids[] = {
> +	{
> +		.compatible = "atmel,sama5d2-gpio",
> +		.data = (ulong)&atmel_sama5d2_pioctrl_data,
> +	},
> +	{}
> +};
> +
>  U_BOOT_DRIVER(gpio_atmel_pio4) = {
>  	.name	= "gpio_atmel_pio4",
>  	.id	= UCLASS_GPIO,
>  	.ops	= &atmel_pio4_ops,
>  	.probe	= atmel_pio4_probe,
> +	.of_match = atmel_pio4_ids,
> +	.platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
>  };
>  #endif

Looks good in general, please resend with pinctrl patches in the same 
series.

Best regards

Andreas


More information about the U-Boot mailing list