Am Mittwoch, den 13.01.2016, 14:46 +0100 schrieb Daniel Schwierzeck: > Am Dienstag, den 12.01.2016, 15:48 +0530 schrieb Purna Chandra > Mandal: > > In PIC32 GPIO controller is part of PIC32 pin controller. > > PIC32 has ten independently programmable ports and each with > > multiple > > pins. > > Each of these pins can be configured and used as GPIO, provided > > they > > are not in use for other peripherals. > > > > Signed-off-by: Purna Chandra Mandal <purna.man...@microchip.com> > > Reviewed-by: Daniel Schwierzeck <daniel.schwierz...@gmail.com> > > nits below > > > > > --- > > > > Changes in v3: > > - add check on dev_get_addr() > > > > Changes in v2: None > > > > drivers/gpio/Kconfig | 7 ++ > > drivers/gpio/Makefile | 2 +- > > drivers/gpio/pic32_gpio.c | 175 > > ++++++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 183 insertions(+), 1 deletion(-) > > create mode 100644 drivers/gpio/pic32_gpio.c > > > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > > index e60e9fd..13e9a6a 100644 > > --- a/drivers/gpio/Kconfig > > +++ b/drivers/gpio/Kconfig > > @@ -83,4 +83,11 @@ config VYBRID_GPIO > > help > > Say yes here to support Vybrid vf610 GPIOs. > > > > +config PIC32_GPIO > > + bool "Microchip PIC32 GPIO driver" > > + depends on DM_GPIO > > + default y if MACH_PIC32
this should be depends on DM_GPIO && MACH_PIC32 > > + help > > + Say yes here to support Microchip PIC32 GPIOs. > > + > > endmenu > > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > > index fb4fd25..845a6d4 100644 > > --- a/drivers/gpio/Makefile > > +++ b/drivers/gpio/Makefile > > @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o > > obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o > > obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o > > obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o > > - > > +obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o > > diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c > > new file mode 100644 > > index 0000000..5b23af4 > > --- /dev/null > > +++ b/drivers/gpio/pic32_gpio.c > > @@ -0,0 +1,175 @@ > > +/* > > + * Copyright (c) 2015 Microchip Technology Inc > > + * Purna Chandra Mandal <purna.man...@microchip.com> > > + * > > + * SPDX-License-Identifier: GPL-2.0+ > > + */ > > + > > +#include <common.h> > > +#include <dm.h> > > +#include <errno.h> > > +#include <malloc.h> > > +#include <asm/io.h> > > +#include <asm/gpio.h> > > +#include <linux/compat.h> > > +#include <dt-bindings/gpio/gpio.h> > > +#include <mach/pic32.h> > > + > > +DECLARE_GLOBAL_DATA_PTR; > > + > > +/* Peripheral Pin Control */ > > +struct pic32_reg_port { > > + struct pic32_reg_atomic ansel; > > + struct pic32_reg_atomic tris; > > + struct pic32_reg_atomic port; > > + struct pic32_reg_atomic lat; > > + struct pic32_reg_atomic open_drain; > > + struct pic32_reg_atomic cnpu; > > + struct pic32_reg_atomic cnpd; > > + struct pic32_reg_atomic cncon; > > +}; > > + > > +enum { > > + MICROCHIP_GPIO_DIR_OUT, > > + MICROCHIP_GPIO_DIR_IN, > > + MICROCHIP_GPIOS_PER_BANK = 16, > > +}; > > + > > +struct pic32_gpio_priv { > > + struct pic32_reg_port *regs; > > + char name[2]; > > +}; > > + > > +static int pic32_gpio_get_value(struct udevice *dev, unsigned > > offset) > > +{ > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + > > + return !!(readl(&priv->regs->port.raw) & BIT(offset)); > > +} > > + > > +static int pic32_gpio_set_value(struct udevice *dev, unsigned > > offset, > > + int value) > > +{ > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + int mask = BIT(offset); > > + > > + if (value) > > + writel(mask, &priv->regs->port.set); > > + else > > + writel(mask, &priv->regs->port.clr); > > + > > + return 0; > > +} > > + > > +static int pic32_gpio_direction(struct udevice *dev, unsigned > > offset) > > +{ > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + > > + if (readl(&priv->regs->ansel.raw) & BIT(offset)) > > + return -1; > > + > > + if (readl(&priv->regs->tris.raw) & BIT(offset)) > > + return MICROCHIP_GPIO_DIR_IN; > > + else > > + return MICROCHIP_GPIO_DIR_OUT; > > +} > > + > > +static int pic32_gpio_direction_input(struct udevice *dev, > > unsigned > > offset) > > +{ > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + int mask = BIT(offset); > > + > > + writel(mask, &priv->regs->ansel.clr); > > + writel(mask, &priv->regs->tris.set); > > + > > + return 0; > > +} > > + > > +static int pic32_gpio_direction_output(struct udevice *dev, > > + unsigned offset, int value) > > +{ > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + int mask = BIT(offset); > > + > > + writel(mask, &priv->regs->ansel.clr); > > + writel(mask, &priv->regs->tris.clr); > > + > > + pic32_gpio_set_value(dev, offset, value); > > + return 0; > > +} > > + > > +static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc > > *desc, > > + struct fdtdec_phandle_args *args) > > +{ > > + desc->offset = args->args[0]; > > + desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? > > GPIOD_ACTIVE_LOW : 0; > > + > > + return 0; > > +} > > + > > +static int pic32_gpio_get_function(struct udevice *dev, unsigned > > offset) > > +{ > > + int ret = GPIOF_UNUSED; > > + > > + switch (pic32_gpio_direction(dev, offset)) { > > + case MICROCHIP_GPIO_DIR_OUT: > > + ret = GPIOF_OUTPUT; > > + break; > > + case MICROCHIP_GPIO_DIR_IN: > > + ret = GPIOF_INPUT; > > + break; > > + default: > > + ret = GPIOF_UNUSED; > > + break; > > + } > > + return ret; > > +} > > + > > +static const struct dm_gpio_ops gpio_pic32_ops = { > > + .direction_input = pic32_gpio_direction_input, > > + .direction_output = pic32_gpio_direction_output, > > + .get_value = pic32_gpio_get_value, > > + .set_value = pic32_gpio_set_value, > > + .get_function = pic32_gpio_get_function, > > + .xlate = pic32_gpio_xlate, > > +}; > > + > > +static int pic32_gpio_probe(struct udevice *dev) > > +{ > > + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); > > + struct pic32_gpio_priv *priv = dev_get_priv(dev); > > + fdt_addr_t addr; > > + fdt_size_t size; > > + char *end; > > + int bank; > > + > > + addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, > > "reg", &size); > > + if (addr == FDT_ADDR_T_NONE) > > + return -EINVAL; > > + > > + priv->regs = ioremap(addr, size); > > + if (!priv->regs) > > + return -EINVAL; > > you can drop this check. ioremap() always returns a mapped address. > > > + > > + uc_priv->gpio_count = MICROCHIP_GPIOS_PER_BANK; > > + end = strrchr(dev->name, '@'); > > + bank = trailing_strtoln(dev->name, end); > > + priv->name[0] = 'A' + bank; > > + uc_priv->bank_name = priv->name; > > + > > + return 0; > > +} > > + > > +static const struct udevice_id pic32_gpio_ids[] = { > > + { .compatible = "microchip,pic32mzda-gpio" }, > > + { } > > +}; > > + > > +U_BOOT_DRIVER(gpio_pic32) = { > > + .name = "gpio_pic32", > > + .id = UCLASS_GPIO, > > + .of_match = pic32_gpio_ids, > > + .ops = &gpio_pic32_ops, > > + .probe = pic32_gpio_probe, > > + .priv_auto_alloc_size = sizeof(struct > > pic32_gpio_priv), > > +}; -- - Daniel _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot