summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvert Pap <evert.pap@sintecs.nl>2016-03-31 13:54:38 (GMT)
committervojo <joris.van.vossen@sintecs.nl>2017-08-23 08:06:41 (GMT)
commita5deb669f027575829326eb5f07e8a47bc870005 (patch)
treee5ad6cf8e5e5c4712c0797e9af08f2b84a5831e0
parentbc5d0384458466ed5b3608d326eec03cd4f13016 (diff)
downloadu-boot-fsl-qoriq-a5deb669f027575829326eb5f07e8a47bc870005.tar.xz
dm: gpio: Add DM GPIO driver for MPC8xxx platforms
This driver adds DM GPIO support for the NXP QorIQ T10xx series. ported from the linux kernel 4.5 * (b562e44f507e863c6792946e4e1b1449fbbac85d) * and removed the interrupt functionallity. This driver could also support the older platforms, as well as the new LayerScape (ARM) based platforms, but these platforms are not supported at this time.
-rw-r--r--arch/powerpc/include/asm/arch-mpc85xx/gpio.h8
-rw-r--r--arch/powerpc/include/asm/immap_85xx.h10
-rw-r--r--arch/powerpc/include/asm/mpc8xxx_gpio.h100
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/Makefile4
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c178
-rw-r--r--include/dm/platform_data/gpio_mpc8xxx.h21
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