diff options
author | Yutang Jiang <yutang.jiang@nxp.com> | 2016-10-29 00:14:32 +0800 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2016-10-31 17:00:10 +0100 |
commit | c6c731fe311f7da42777ffd31804a4f6aa3f8e19 (patch) | |
tree | d92c7296f82d46d1b2da30933a97595f6cb8ad66 /target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch | |
parent | a34f96d6cf80c7c3c425076714d9c4caa67e3670 (diff) | |
download | upstream-c6c731fe311f7da42777ffd31804a4f6aa3f8e19.tar.gz upstream-c6c731fe311f7da42777ffd31804a4f6aa3f8e19.tar.bz2 upstream-c6c731fe311f7da42777ffd31804a4f6aa3f8e19.zip |
layerscape: add 64b/32b target for ls1043ardb device
Add support for NXP layerscape ls1043ardb 64b/32b Dev board.
LS1043a is an SoC with 4x64-bit up to 1.6 GHz ARMv8 A53 cores.
ls1043ardb support features as: 2GB DDR4, 128MB NOR/512MB NAND, USB3.0, eSDHC,
I2C, GPIO, PCIe/Mini-PCIe, 6x1G/1x10G network port, etc.
64b/32b ls1043ardb target is using 4.4 kernel, and rcw/u-boot/fman images from
NXP QorIQ SDK release.
All of 4.4 kernel patches porting from SDK release or upstream.
QorIQ SDK ISOs can be downloaded from this location:
http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX
Signed-off-by: Yutang Jiang <yutang.jiang@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch b/target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch new file mode 100644 index 0000000000..101f4505fe --- /dev/null +++ b/target/linux/layerscape/patches-4.4/8042-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch @@ -0,0 +1,289 @@ +From c2d0a12b5cfa61e43494483f5d1ee466b4998830 Mon Sep 17 00:00:00 2001 +From: Liu Gang <Gang.Liu@nxp.com> +Date: Thu, 14 Jan 2016 19:48:09 +0800 +Subject: [PATCH 42/70] drivers/gpio: Port gpio driver to support layerscape + platform + +Layerscape has the same ip block/controller as +GPIO on powerpc platform(MPC8XXX). + +So use portable i/o accessors, as in_be32/out_be32 +accessors are Power architecture specific whereas +ioread32/iowrite32 and ioread32be/iowrite32be are +available in other architectures. + +Layerscape GPIO controller's registers may be big +or little endian, so the code needs to get the +endian property from DTB, then make additional +functions to fit right register read/write +operations. + +Currently the code can support ls2080a GPIO with +little endian registers. And it can also work well +on other layerscape platform with big endian GPIO +registers. + +Signed-off-by: Liu Gang <Gang.Liu@nxp.com> +--- + drivers/gpio/Kconfig | 7 ++-- + drivers/gpio/gpio-mpc8xxx.c | 87 +++++++++++++++++++++++++++++++------------ + 2 files changed, 68 insertions(+), 26 deletions(-) + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -281,12 +281,13 @@ config GPIO_MPC5200 + depends on PPC_MPC52xx + + config GPIO_MPC8XXX +- bool "MPC512x/MPC8xxx GPIO support" ++ bool "MPC512x/MPC8xxx/QorIQ GPIO support" + depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ +- FSL_SOC_BOOKE || PPC_86xx ++ FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \ ++ COMPILE_TEST + help + Say Y here if you're going to use hardware that connects to the +- MPC512x/831x/834x/837x/8572/8610 GPIOs. ++ MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. + + config GPIO_MVEBU + def_bool y +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -1,5 +1,5 @@ + /* +- * GPIOs on MPC512x/8349/8572/8610 and compatible ++ * GPIOs on MPC512x/8349/8572/8610/QorIQ and compatible + * + * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> + * +@@ -19,6 +19,7 @@ + #include <linux/gpio.h> + #include <linux/slab.h> + #include <linux/irq.h> ++#include <linux/irqdomain.h> + + #define MPC8XXX_GPIO_PINS 32 + +@@ -44,6 +45,27 @@ struct mpc8xxx_gpio_chip { + const void *of_dev_id_data; + }; + ++static bool gpio_little_endian; ++static inline u32 gpio_in32(void __iomem *addr) ++{ ++ u32 val; ++ ++ if (gpio_little_endian) ++ val = ioread32(addr); ++ else ++ val = ioread32be(addr); ++ ++ return val; ++} ++ ++static inline void gpio_out32(u32 val, void __iomem *addr) ++{ ++ if (gpio_little_endian) ++ iowrite32(val, addr); ++ else ++ iowrite32be(val, addr); ++} ++ + static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) + { + return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); +@@ -59,9 +81,17 @@ static void mpc8xxx_gpio_save_regs(struc + { + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + +- mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); ++ mpc8xxx_gc->data = gpio_in32(mm->regs + GPIO_DAT); + } + ++/* Generic set and clear bits accessor ports */ ++#define bgpio_setbits32(_addr, _v) \ ++ gpio_out32(gpio_in32(_addr) | (_v), (_addr)) ++#define bgpio_clrbits32(_addr, _v) \ ++ gpio_out32(gpio_in32(_addr) & ~(_v), (_addr)) ++#define bgpio_clrsetbits32(addr, clear, set) \ ++ gpio_out32((gpio_in32(addr) & ~(clear)) | (set), (addr)) ++ + /* 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 +@@ -74,9 +104,9 @@ static int mpc8572_gpio_get(struct gpio_ + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + u32 out_mask, out_shadow; + +- out_mask = in_be32(mm->regs + GPIO_DIR); ++ out_mask = gpio_in32(mm->regs + GPIO_DIR); + +- val = in_be32(mm->regs + GPIO_DAT) & ~out_mask; ++ val = gpio_in32(mm->regs + GPIO_DAT) & ~out_mask; + out_shadow = mpc8xxx_gc->data & out_mask; + + return (val | out_shadow) & mpc8xxx_gpio2mask(gpio); +@@ -86,7 +116,7 @@ static int mpc8xxx_gpio_get(struct gpio_ + { + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + +- return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); ++ return gpio_in32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); + } + + static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +@@ -102,7 +132,7 @@ static void mpc8xxx_gpio_set(struct gpio + else + mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); + +- out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); ++ gpio_out32(mpc8xxx_gc->data, mm->regs + GPIO_DAT); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -128,7 +158,7 @@ static void mpc8xxx_gpio_set_multiple(st + } + } + +- out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); ++ gpio_out32(mpc8xxx_gc->data, mm->regs + GPIO_DAT); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -141,7 +171,7 @@ static int mpc8xxx_gpio_dir_in(struct gp + + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); ++ bgpio_clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +@@ -158,7 +188,7 @@ static int mpc8xxx_gpio_dir_out(struct g + + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); ++ bgpio_setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +@@ -201,7 +231,8 @@ static void mpc8xxx_gpio_irq_cascade(str + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; + unsigned int mask; + +- mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR); ++ mask = gpio_in32(mm->regs + GPIO_IER) ++ & gpio_in32(mm->regs + GPIO_IMR); + if (mask) + generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, + 32 - ffs(mask))); +@@ -217,7 +248,8 @@ static void mpc8xxx_irq_unmask(struct ir + + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_setbits32(mm->regs + GPIO_IMR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -230,7 +262,8 @@ static void mpc8xxx_irq_mask(struct irq_ + + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_clrbits32(mm->regs + GPIO_IMR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -240,7 +273,7 @@ static void mpc8xxx_irq_ack(struct irq_d + struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; + +- out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ gpio_out32(mpc8xxx_gpio2mask(irqd_to_hwirq(d)), mm->regs + GPIO_IER); + } + + static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) +@@ -252,15 +285,15 @@ static int mpc8xxx_irq_set_type(struct i + switch (flow_type) { + case IRQ_TYPE_EDGE_FALLING: + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- setbits32(mm->regs + GPIO_ICR, +- mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_setbits32(mm->regs + GPIO_ICR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_BOTH: + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrbits32(mm->regs + GPIO_ICR, +- mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_clrbits32(mm->regs + GPIO_ICR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + +@@ -292,20 +325,20 @@ static int mpc512x_irq_set_type(struct i + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_LEVEL_LOW: + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrsetbits_be32(reg, 3 << shift, 2 << shift); ++ bgpio_clrsetbits32(reg, 3 << shift, 2 << shift); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_LEVEL_HIGH: + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrsetbits_be32(reg, 3 << shift, 1 << shift); ++ bgpio_clrsetbits32(reg, 3 << shift, 1 << shift); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_BOTH: + raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrbits32(reg, 3 << shift); ++ bgpio_clrbits32(reg, 3 << shift); + raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + +@@ -398,6 +431,14 @@ static int mpc8xxx_probe(struct platform + mm_gc = &mpc8xxx_gc->mm_gc; + gc = &mm_gc->gc; + ++ if (of_property_read_bool(np, "little-endian")) { ++ gpio_little_endian = true; ++ dev_dbg(&pdev->dev, "GPIO REGISTERS are LITTLE endian\n"); ++ } else { ++ gpio_little_endian = false; ++ dev_dbg(&pdev->dev, "GPIO REGISTERS are BIG endian\n"); ++ } ++ + mm_gc->save_regs = mpc8xxx_gpio_save_regs; + gc->ngpio = MPC8XXX_GPIO_PINS; + gc->direction_input = mpc8xxx_gpio_dir_in; +@@ -422,7 +463,7 @@ static int mpc8xxx_probe(struct platform + return ret; + + mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0); +- if (mpc8xxx_gc->irqn == NO_IRQ) ++ if (mpc8xxx_gc->irqn == 0) + return 0; + + mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS, +@@ -435,8 +476,8 @@ static int mpc8xxx_probe(struct platform + mpc8xxx_gc->of_dev_id_data = id->data; + + /* ack and mask all irqs */ +- out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); +- out_be32(mm_gc->regs + GPIO_IMR, 0); ++ gpio_out32(0xffffffff, mm_gc->regs + GPIO_IER); ++ gpio_out32(0, mm_gc->regs + GPIO_IMR); + + irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, + mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); |