On 01/13/2016 07:38 PM, Daniel Schwierzeck wrote: > 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
ack, will add. >>> + 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. ack. will drop. >>> + >>> + 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), >>> +}; _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot