diff options
-rw-r--r-- | arch/powerpc/include/asm/arch-mpc85xx/gpio.h | 8 | ||||
-rw-r--r-- | arch/powerpc/include/asm/immap_85xx.h | 10 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mpc8xxx_gpio.h | 100 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 9 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 178 | ||||
-rw-r--r-- | include/dm/platform_data/gpio_mpc8xxx.h | 21 |
7 files changed, 330 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h index 76faa22..0c72c71 100644 --- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h +++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h @@ -14,6 +14,7 @@ #ifndef __ASM_ARCH_MX85XX_GPIO_H #define __ASM_ARCH_MX85XX_GPIO_H +<<<<<<< bc5d0384458466ed5b3608d326eec03cd4f13016 #ifndef CONFIG_MPC85XX_GPIO #include <asm/mpc85xx_gpio.h> #endif @@ -23,5 +24,12 @@ struct mpc85xx_gpio_plat { unsigned long size; uint ngpios; }; +======= +#ifdef CONFIG_MPC8XXX_GPIO +#include <asm/mpc8xxx_gpio.h> +#else +#include <asm/mpc85xx_gpio.h> +#endif +>>>>>>> dm: gpio: Add DM GPIO driver for MPC8xxx platforms #endif diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index ee537f4..184ff5a 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -3200,4 +3200,14 @@ struct ccsr_scfg { u32 res4[60]; u32 sparecr[8]; /* 0x500 Spare Control register(0-7) */ }; + +#if defined(CONFIG_PPC_T1013) || defined(CONFIG_PPC_T1014) ||\ + defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022) ||\ + defined(CONFIG_PPC_T1023) || defined(CONFIG_PPC_T1024) ||\ + defined(CONFIG_PPC_T1040) || defined(CONFIG_PPC_T1042) ||\ +#define CONFIG_SYS_MPC8XXX_GPIO1_ADDR (CONFIG_SYS_IMMR + 0x130000) +#define CONFIG_SYS_MPC8XXX_GPIO2_ADDR (CONFIG_SYS_IMMR + 0x131000) +#define CONFIG_SYS_MPC8XXX_GPIO3_ADDR (CONFIG_SYS_IMMR + 0x132000) +#define CONFIG_SYS_MPC8XXX_GPIO4_ADDR (CONFIG_SYS_IMMR + 0x133000) +#endif #endif /*__IMMAP_85xx__*/ diff --git a/arch/powerpc/include/asm/mpc8xxx_gpio.h b/arch/powerpc/include/asm/mpc8xxx_gpio.h new file mode 100644 index 0000000..d4a5b7c --- /dev/null +++ b/arch/powerpc/include/asm/mpc8xxx_gpio.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 Scalys B.V. <u-boot@scalys.com> + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _POWERPC_ASM_MPC8XXX_GPIO_H +#define _POWERPC_ASM_MPC8XXX_GPIO_H + +#define MPC8XXX_GPIO_NR(port, pin) ((((port)-1)*32)+((pin)&31)) +#define MPC8XXX_GPIO_TO_PORT(gpio) (gpio/32) +#define MPC8XXX_GPIO_TO_PIN(gpio) (gpio&31) + +static inline void mpc8xxx_gpio_set(uint32_t gpio, int value) +{ + int port, pin; + ccsr_gpio_t *gpio_regs; + uint32_t regval; + + port = MPC8XXX_GPIO_TO_PORT(gpio); + pin = MPC8XXX_GPIO_TO_PIN(gpio); + + switch (port) { +#ifdef CONFIG_SYS_MPC8XXX_GPIO1_ADDR + case 0: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO1_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO2_ADDR + case 1: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO2_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO3_ADDR + case 2: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO3_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO4_ADDR + case 3: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO4_ADDR; + break; +#endif + default: + return; + } + + /* Set output */ + regval = in_be32(&(gpio_regs->gpdat)); + regval |= (0x80000000 >> pin); + out_be32(&(gpio_regs->gpdat), regval); + + /* Set direction to acivate gpio pin */ + regval = in_be32(&(gpio_regs->gpdir)); + regval |= (0x80000000 >> pin); + out_be32(&(gpio_regs->gpdir), regval); +} + +static inline int mpc8xxx_gpio_get(uint32_t gpio, int value) +{ + int port, pin; + ccsr_gpio_t *gpio_regs; + uint32_t regval; + + port = MPC8XXX_GPIO_TO_PORT(gpio); + pin = MPC8XXX_GPIO_TO_PIN(gpio); + + switch (port) { +#ifdef CONFIG_SYS_MPC8XXX_GPIO1_ADDR + case 0: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO1_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO2_ADDR + case 1: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO2_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO3_ADDR + case 2: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO3_ADDR; + break; +#endif +#ifdef CONFIG_SYS_MPC8XXX_GPIO4_ADDR + case 3: + gpio_regs = (ccsr_gpio_t *) CONFIG_SYS_MPC8XXX_GPIO4_ADDR; + break; +#endif + default: + return; + } + + /* Get inputs */ + regval = in_be32(&(gpio_regs->gpdat)); + regval <<= pin; + regval &= 1; + + return regval; +} + +#endif /* _POWERPC_ASM_MPC8XXX_GPIO_H */ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ffeda94..34c4a40 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -34,6 +34,7 @@ config DWAPB_GPIO help Support for the Designware APB GPIO driver. +<<<<<<< bc5d0384458466ed5b3608d326eec03cd4f13016 config AT91_GPIO bool "AT91 PIO GPIO driver" depends on DM_GPIO @@ -46,6 +47,14 @@ config AT91_GPIO The assignment to a function of an embedded peripheral is the responsibility of AT91 Pinctrl driver. This driver is responsible for the general-purpose I/O. +======= +config MPC8XXX_GPIO + bool "NXP (Freescale) MPC8xxx driver" + depends on DM_GPIO + default n + help + Support for the NXP (Freescale) MPC/QorIQ GPIO controller +>>>>>>> dm: gpio: Add DM GPIO driver for MPC8xxx platforms config ATMEL_PIO4 bool "ATMEL PIO4 driver" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1396467..3209071 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -37,7 +37,11 @@ obj-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o obj-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o obj-$(CONFIG_ALTERA_PIO) += altera_pio.o obj-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o +<<<<<<< bc5d0384458466ed5b3608d326eec03cd4f13016 obj-$(CONFIG_MPC85XX_GPIO) += mpc85xx_gpio.o +======= +obj-$(CONFIG_MPC8XXX_GPIO) += gpio-mpc8xxx.o +>>>>>>> dm: gpio: Add DM GPIO driver for MPC8xxx platforms obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c new file mode 100644 index 0000000..c5d72ef --- /dev/null +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -0,0 +1,178 @@ + +/* + * GPIOs on MPC512x/8349/8572/8610/T-series and compatible + * + * Driver ported from the linux kernel 4.5 (b562e44f507e863c6792946e4e1b1449fbbac85d) + * and removed the interrupt functionallity. + * + * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> + * Copyright (c) 2016 Scalys B.V. <u-boot@scalys.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <malloc.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/gpio.h> +#include <dm/platform_data/gpio_mpc8xxx.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define MPC8XXX_GPIO_PINS 32 + +static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) +{ + return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); +} + +static int mpc8xxx_dm_gpio_set(struct udevice *dev, unsigned pin, int val) +{ + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + +#if defined(CONFIG_MPC8572) || defined(CONFIG_MPC8536) + + if (val) { + plat->data |= mpc8xxx_gpio2mask(pin); + } else { + plat->data &= ~mpc8xxx_gpio2mask(pin); + } + + out_be32(&(plat->regs->gpdat), plat->data); +#else + if (val) { + setbits_be32(&(plat->regs->gpdat), mpc8xxx_gpio2mask(pin)); + } else { + clrbits_be32(&(plat->regs->gpdat), mpc8xxx_gpio2mask(pin)); + } +#endif + return 0; +} + +static int mpc8xxx_dm_gpio_dir_in(struct udevice *dev, unsigned int gpio) +{ + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + + clrbits_be32(&(plat->regs->gpdir), mpc8xxx_gpio2mask(gpio)); + + return 0; +} + +static int mpc8xxx_dm_gpio_dir_out(struct udevice *dev, unsigned int gpio, + int val) +{ + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + + mpc8xxx_dm_gpio_set(dev, gpio, val); + + setbits_be32(&(plat->regs->gpdir), mpc8xxx_gpio2mask(gpio)); + + return 0; +} + +static int mpc8xxx_dm_gpio_get(struct udevice *dev, unsigned int gpio) +{ + int ret = 0; + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + +#if defined(CONFIG_MPC8572) || defined(CONFIG_MPC8536) + uint32_t data_val, out_mask, out_shadow; + + /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs + * defined as output cannot be determined by reading GPDAT register, + * so we use shadow data register instead. The status of input pins + * is determined by reading GPDAT register. + */ + out_mask = in_be32(&plat->regs->gpdir); + + data_val = in_be32(&plat->regs->gpdat) & ~out_mask; + out_shadow = plat->data & out_mask; + + ret = ! !((data_val | out_shadow) & mpc8xxx_gpio2mask(gpio)); +#else + if (in_be32(&plat->regs->gpdat) & mpc8xxx_gpio2mask(gpio)) { + ret = 1; + } else { + ret = 0; + } +#endif + return ret; +} + +static int mpc8xxx_dm_gpio_get_function(struct udevice *dev, unsigned gpio) +{ + int ret = GPIOF_UNUSED; + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + + if (in_be32(&plat->regs->gpdir) & mpc8xxx_gpio2mask(gpio)) { + ret = GPIOF_OUTPUT; + } else { + ret = GPIOF_INPUT; + } + return ret; +} + +static const struct udevice_id mpc8xxx_gpio_ids[] = { + {.compatible = "fsl,mpc8349-gpio",}, + {.compatible = "fsl,mpc8572-gpio",}, + {.compatible = "fsl,mpc8610-gpio",}, + {.compatible = "fsl,mpc5121-gpio",}, + {.compatible = "fsl,mpc5125-gpio",}, + {.compatible = "fsl,pq3-gpio",}, + {.compatible = "fsl,qoriq-gpio",}, + {} +}; + +static const struct dm_gpio_ops mpc8xxx_gpio_ops = { + .direction_input = mpc8xxx_dm_gpio_dir_in, + .direction_output = mpc8xxx_dm_gpio_dir_out, + .get_value = mpc8xxx_dm_gpio_get, + .set_value = mpc8xxx_dm_gpio_set, + .get_function = mpc8xxx_dm_gpio_get_function, +}; + +#ifdef SPL_OF_CONTROL +static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev) +{ + int register_address; + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + + register_address = + fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1); + if (register_address == -1) { + debug("%s: Invalid register offset %d\n", __func__, + register_address); + return -EINVAL; + } + plat->regs = map_physmem(register_address, sizeof(ccsr_gpio_t), + MAP_NOCACHE); + plat->gpio_count = MPC8XXX_GPIO_PINS; + plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset, + "bank-name", NULL); + + return 0; +} +#endif + +static int mpc8xxx_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct mpc8xxx_gpio_platdata *plat = dev_get_platdata(dev); + + uc_priv->gpio_count = MPC8XXX_GPIO_PINS; + uc_priv->bank_name = plat->bank_name; + + return 0; +} + +U_BOOT_DRIVER(gpio_mpc8xxx) = { + .name = "gpio-mpc8xxx",.id = UCLASS_GPIO,.of_match = + mpc8xxx_gpio_ids,.ops = &mpc8xxx_gpio_ops, +#ifdef SPL_OF_CONTROL + .ofdata_to_platdata = mpc8xxx_gpio_ofdata_to_platdata, +#endif +.platdata_auto_alloc_size = + sizeof(struct mpc8xxx_gpio_platdata),.probe = mpc8xxx_gpio_probe,}; diff --git a/include/dm/platform_data/gpio_mpc8xxx.h b/include/dm/platform_data/gpio_mpc8xxx.h new file mode 100644 index 0000000..37e5241 --- /dev/null +++ b/include/dm/platform_data/gpio_mpc8xxx.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 Scalys B.V. <u-boot@scalys.com> + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MPC8XXX_GPIO_H +#define _MPC8XXX_GPIO_H + +struct mpc8xxx_gpio_platdata { + const char *bank_name; + ccsr_gpio_t *regs; + int gpio_count; +#if defined(CONFIG_MPC8572) || defined(CONFIG_MPC8536) + /* shadowed data register used to work around errata on + * MPC8572 and MPC8535 where it is not possible to read the + * state of an output pin */ + uint32_t data; +#endif +}; + +#endif |