From bd5ce4332328c1fe473690a86b2e6a4157be038f Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 12:06:01 +0800 Subject: [ARM] pxa: introduce plat-pxa for PXA common code and add DMA support 1. introduce folder of 'arch/arm/plat-pxa' for common code across different PXA processor families 2. initially moved DMA code into plat-pxa 3. common code in moved into , new processors should implement its own , provide the following required definitions and '#include ' in the end: - DMAC_REGS_VIRT for mapped virtual address of the DMA registers' physical I/O memory Signed-off-by: Eric Miao --- arch/arm/plat-pxa/Kconfig | 3 + arch/arm/plat-pxa/Makefile | 6 ++ arch/arm/plat-pxa/dma.c | 144 +++++++++++++++++++++++++++++++++++ arch/arm/plat-pxa/include/plat/dma.h | 85 +++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 arch/arm/plat-pxa/Kconfig create mode 100644 arch/arm/plat-pxa/Makefile create mode 100644 arch/arm/plat-pxa/dma.c create mode 100644 arch/arm/plat-pxa/include/plat/dma.h (limited to 'arch/arm/plat-pxa') diff --git a/arch/arm/plat-pxa/Kconfig b/arch/arm/plat-pxa/Kconfig new file mode 100644 index 00000000000..b158e98038e --- /dev/null +++ b/arch/arm/plat-pxa/Kconfig @@ -0,0 +1,3 @@ +if PLAT_PXA + +endif diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile new file mode 100644 index 00000000000..dcc3ceaf717 --- /dev/null +++ b/arch/arm/plat-pxa/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for code common across different PXA processor families +# + +obj-y := dma.o + diff --git a/arch/arm/plat-pxa/dma.c b/arch/arm/plat-pxa/dma.c new file mode 100644 index 00000000000..70aeee407f7 --- /dev/null +++ b/arch/arm/plat-pxa/dma.c @@ -0,0 +1,144 @@ +/* + * linux/arch/arm/plat-pxa/dma.c + * + * PXA DMA registration and IRQ dispatching + * + * Author: Nicolas Pitre + * Created: Nov 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct dma_channel { + char *name; + pxa_dma_prio prio; + void (*irq_handler)(int, void *); + void *data; +}; + +static struct dma_channel *dma_channels; +static int num_dma_channels; + +int pxa_request_dma (char *name, pxa_dma_prio prio, + void (*irq_handler)(int, void *), + void *data) +{ + unsigned long flags; + int i, found = 0; + + /* basic sanity checks */ + if (!name || !irq_handler) + return -EINVAL; + + local_irq_save(flags); + + do { + /* try grabbing a DMA channel with the requested priority */ + for (i = 0; i < num_dma_channels; i++) { + if ((dma_channels[i].prio == prio) && + !dma_channels[i].name) { + found = 1; + break; + } + } + /* if requested prio group is full, try a hier priority */ + } while (!found && prio--); + + if (found) { + DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + dma_channels[i].name = name; + dma_channels[i].irq_handler = irq_handler; + dma_channels[i].data = data; + } else { + printk (KERN_WARNING "No more available DMA channels for %s\n", name); + i = -ENODEV; + } + + local_irq_restore(flags); + return i; +} + +void pxa_free_dma (int dma_ch) +{ + unsigned long flags; + + if (!dma_channels[dma_ch].name) { + printk (KERN_CRIT + "%s: trying to free channel %d which is already freed\n", + __func__, dma_ch); + return; + } + + local_irq_save(flags); + DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + dma_channels[dma_ch].name = NULL; + local_irq_restore(flags); +} + +static irqreturn_t dma_irq_handler(int irq, void *dev_id) +{ + int i, dint = DINT; + + for (i = 0; i < num_dma_channels; i++) { + if (dint & (1 << i)) { + struct dma_channel *channel = &dma_channels[i]; + if (channel->name && channel->irq_handler) { + channel->irq_handler(i, channel->data); + } else { + /* + * IRQ for an unregistered DMA channel: + * let's clear the interrupts and disable it. + */ + printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i); + DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + } + } + } + return IRQ_HANDLED; +} + +int __init pxa_init_dma(int irq, int num_ch) +{ + int i, ret; + + dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL); + if (dma_channels == NULL) + return -ENOMEM; + + /* dma channel priorities on pxa2xx processors: + * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH + * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM + * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW + */ + for (i = 0; i < num_ch; i++) { + DCSR(i) = 0; + dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW); + } + + ret = request_irq(irq, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); + if (ret) { + printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); + kfree(dma_channels); + return ret; + } + + num_dma_channels = num_ch; + return 0; +} + +EXPORT_SYMBOL(pxa_request_dma); +EXPORT_SYMBOL(pxa_free_dma); diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h new file mode 100644 index 00000000000..a7b91dc0685 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/dma.h @@ -0,0 +1,85 @@ +#ifndef __PLAT_DMA_H +#define __PLAT_DMA_H + +#define DMAC_REG(x) (*((volatile u32 *)(DMAC_REGS_VIRT + (x)))) + +#define DCSR(n) DMAC_REG((n) << 2) +#define DALGN DMAC_REG(0x00a0) /* DMA Alignment Register */ +#define DINT DMAC_REG(0x00f0) /* DMA Interrupt Register */ +#define DDADR(n) DMAC_REG(0x0200 + ((n) << 4)) +#define DSADR(n) DMAC_REG(0x0204 + ((n) << 4)) +#define DTADR(n) DMAC_REG(0x0208 + ((n) << 4)) +#define DCMD(n) DMAC_REG(0x020c + ((n) << 4)) +#define DRCMR(n) DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \ + (((n) & 0x3f) << 2)) + +#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ +#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ +#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ +#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ +#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ +#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ +#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ +#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ + +#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ +#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ +#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ +#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ +#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ +#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ +#define DCSR_EORINTR (1 << 9) /* The end of Receive */ + +#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ +#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ + +#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ +#define DDADR_STOP (1 << 0) /* Stop (read / write) */ + +#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ +#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ +#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ +#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ +#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ +#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ +#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ +#define DCMD_BURST8 (1 << 16) /* 8 byte burst */ +#define DCMD_BURST16 (2 << 16) /* 16 byte burst */ +#define DCMD_BURST32 (3 << 16) /* 32 byte burst */ +#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */ +#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */ +#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ +#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ + +/* + * Descriptor structure for PXA's DMA engine + * Note: this structure must always be aligned to a 16-byte boundary. + */ + +typedef struct pxa_dma_desc { + volatile u32 ddadr; /* Points to the next descriptor + flags */ + volatile u32 dsadr; /* DSADR value for the current transfer */ + volatile u32 dtadr; /* DTADR value for the current transfer */ + volatile u32 dcmd; /* DCMD value for the current transfer */ +} pxa_dma_desc; + +typedef enum { + DMA_PRIO_HIGH = 0, + DMA_PRIO_MEDIUM = 1, + DMA_PRIO_LOW = 2 +} pxa_dma_prio; + +/* + * DMA registration + */ + +int __init pxa_init_dma(int irq, int num_ch); + +int pxa_request_dma (char *name, + pxa_dma_prio prio, + void (*irq_handler)(int, void *), + void *data); + +void pxa_free_dma (int dma_ch); + +#endif /* __PLAT_DMA_H */ -- cgit v1.2.3-70-g09d2 From 38f539a608c9a3b40b30f1892bd5f9a38f4e5ffe Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 12:09:06 +0800 Subject: [ARM] pxa: move common GPIO handling code into plat-pxa 1. add common GPIO handling code into [arch/arm/plat-pxa] 2. common code in moved into , new processors should implement its own , provide the following required definitions and '#include ' in the end: - GPIO_REGS_VIRT for mapped virtual address of the GPIO registers' physical I/O memory - macros of GPLR(), GPSR(), GPDR() for constant optimization for functions gpio_{set,get}_value() (so that bit-bang code can still have tolerable performance) - NR_BUILTIN_GPIO for the number of onchip GPIO - definitions of __gpio_is_inverted() and __gpio_is_occupied(), they can be either macros or inlined functions Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/gpio.c | 365 ---------------------------------- arch/arm/mach-pxa/include/mach/gpio.h | 32 +-- arch/arm/plat-pxa/Makefile | 1 + arch/arm/plat-pxa/gpio.c | 337 +++++++++++++++++++++++++++++++ arch/arm/plat-pxa/include/plat/gpio.h | 62 ++++++ 6 files changed, 402 insertions(+), 397 deletions(-) delete mode 100644 arch/arm/mach-pxa/gpio.c create mode 100644 arch/arm/plat-pxa/gpio.c create mode 100644 arch/arm/plat-pxa/include/plat/gpio.h (limited to 'arch/arm/plat-pxa') diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 70b46570c5c..c80e1bac494 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -4,7 +4,7 @@ # Common support (must be linked before board specific support) obj-y += clock.o devices.o generic.o irq.o \ - time.o gpio.o reset.o + time.o reset.o obj-$(CONFIG_PM) += pm.o sleep.o standby.o ifeq ($(CONFIG_CPU_FREQ),y) diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c deleted file mode 100644 index 7c2267036bf..00000000000 --- a/arch/arm/mach-pxa/gpio.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/gpio.c - * - * Generic PXA GPIO handling - * - * Author: Nicolas Pitre - * Created: Jun 15, 2001 - * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include - -int pxa_last_gpio; - -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 - -struct pxa_gpio_chip { - struct gpio_chip chip; - void __iomem *regbase; - char label[10]; - - unsigned long irq_mask; - unsigned long irq_edge_rise; - unsigned long irq_edge_fall; - -#ifdef CONFIG_PM - unsigned long saved_gplr; - unsigned long saved_gpdr; - unsigned long saved_grer; - unsigned long saved_gfer; -#endif -}; - -static DEFINE_SPINLOCK(gpio_lock); -static struct pxa_gpio_chip *pxa_gpio_chips; - -#define for_each_gpio_chip(i, c) \ - for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) - -static inline void __iomem *gpio_chip_base(struct gpio_chip *c) -{ - return container_of(c, struct pxa_gpio_chip, chip)->regbase; -} - -static inline struct pxa_gpio_chip *gpio_to_chip(unsigned gpio) -{ - return &pxa_gpio_chips[gpio_to_bank(gpio)]; -} - -static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t value, mask = 1 << offset; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - value = __raw_readl(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - value |= mask; - else - value &= ~mask; - __raw_writel(value, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - void __iomem *base = gpio_chip_base(chip); - uint32_t tmp, mask = 1 << offset; - unsigned long flags; - - __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); - - spin_lock_irqsave(&gpio_lock, flags); - - tmp = __raw_readl(base + GPDR_OFFSET); - if (__gpio_is_inverted(chip->base + offset)) - tmp &= ~mask; - else - tmp |= mask; - __raw_writel(tmp, base + GPDR_OFFSET); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); -} - -static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - __raw_writel(1 << offset, gpio_chip_base(chip) + - (value ? GPSR_OFFSET : GPCR_OFFSET)); -} - -static int __init pxa_init_gpio_chip(int gpio_end) -{ - int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; - struct pxa_gpio_chip *chips; - - /* this is early, we have to use bootmem allocator, and we really - * want this to be allocated dynamically for different 'gpio_end' - */ - chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip)); - if (chips == NULL) { - pr_err("%s: failed to allocate GPIO chips\n", __func__); - return -ENOMEM; - } - - for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { - struct gpio_chip *c = &chips[i].chip; - - sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = (void __iomem *)GPIO_BANK(i); - - c->base = gpio; - c->label = chips[i].label; - - c->direction_input = pxa_gpio_direction_input; - c->direction_output = pxa_gpio_direction_output; - c->get = pxa_gpio_get; - c->set = pxa_gpio_set; - - /* number of GPIOs on last bank may be less than 32 */ - c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; - gpiochip_add(c); - } - pxa_gpio_chips = chips; - return 0; -} - -static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) -{ - struct pxa_gpio_chip *c; - int gpio = irq_to_gpio(irq); - unsigned long gpdr, mask = GPIO_bit(gpio); - - c = gpio_to_chip(gpio); - - if (type == IRQ_TYPE_PROBE) { - /* Don't mess with enabled GPIOs using preconfigured edges or - * GPIOs set to alternate function or to output during probe - */ - if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) - return 0; - - if (__gpio_is_occupied(gpio)) - return 0; - - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - } - - gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - - if (__gpio_is_inverted(gpio)) - __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); - else - __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); - - if (type & IRQ_TYPE_EDGE_RISING) - c->irq_edge_rise |= mask; - else - c->irq_edge_rise &= ~mask; - - if (type & IRQ_TYPE_EDGE_FALLING) - c->irq_edge_fall |= mask; - else - c->irq_edge_fall &= ~mask; - - __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); - __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); - - pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio, - ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), - ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); - return 0; -} - -static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) -{ - struct pxa_gpio_chip *c; - int loop, gpio, gpio_base, n; - unsigned long gedr; - - do { - loop = 0; - for_each_gpio_chip(gpio, c) { - gpio_base = c->chip.base; - - gedr = __raw_readl(c->regbase + GEDR_OFFSET); - gedr = gedr & c->irq_mask; - __raw_writel(gedr, c->regbase + GEDR_OFFSET); - - n = find_first_bit(&gedr, BITS_PER_LONG); - while (n < BITS_PER_LONG) { - loop = 1; - - generic_handle_irq(gpio_to_irq(gpio_base + n)); - n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); - } - } - } while (loop); -} - -static void pxa_ack_muxed_gpio(unsigned int irq) -{ - int gpio = irq_to_gpio(irq); - struct pxa_gpio_chip *c = gpio_to_chip(gpio); - - __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); -} - -static void pxa_mask_muxed_gpio(unsigned int irq) -{ - int gpio = irq_to_gpio(irq); - struct pxa_gpio_chip *c = gpio_to_chip(gpio); - uint32_t grer, gfer; - - c->irq_mask &= ~GPIO_bit(gpio); - - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); -} - -static void pxa_unmask_muxed_gpio(unsigned int irq) -{ - int gpio = irq_to_gpio(irq); - struct pxa_gpio_chip *c = gpio_to_chip(gpio); - - c->irq_mask |= GPIO_bit(gpio); - __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); - __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); -} - -static struct irq_chip pxa_muxed_gpio_chip = { - .name = "GPIO", - .ack = pxa_ack_muxed_gpio, - .mask = pxa_mask_muxed_gpio, - .unmask = pxa_unmask_muxed_gpio, - .set_type = pxa_gpio_irq_type, -}; - -void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) -{ - struct pxa_gpio_chip *c; - int gpio, irq; - - pxa_last_gpio = end; - - /* Initialize GPIO chips */ - pxa_init_gpio_chip(end); - - /* clear all GPIO edge detects */ - for_each_gpio_chip(gpio, c) { - __raw_writel(0, c->regbase + GFER_OFFSET); - __raw_writel(0, c->regbase + GRER_OFFSET); - __raw_writel(~0,c->regbase + GEDR_OFFSET); - } - - for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { - set_irq_chip(irq, &pxa_muxed_gpio_chip); - set_irq_handler(irq, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - - /* Install handler for GPIO>=2 edge detect interrupts */ - set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler); - pxa_muxed_gpio_chip.set_wake = fn; -} - -#ifdef CONFIG_PM -static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); - c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); - c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); - - /* Clear GPIO transition detect bits */ - __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); - } - return 0; -} - -static int pxa_gpio_resume(struct sys_device *dev) -{ - struct pxa_gpio_chip *c; - int gpio; - - for_each_gpio_chip(gpio, c) { - /* restore level with set/clear */ - __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); - __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); - - __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); - __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); - __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); - } - return 0; -} -#else -#define pxa_gpio_suspend NULL -#define pxa_gpio_resume NULL -#endif - -struct sysdev_class pxa_gpio_sysclass = { - .name = "gpio", - .suspend = pxa_gpio_suspend, - .resume = pxa_gpio_resume, -}; - -static int __init pxa_gpio_init(void) -{ - return sysdev_class_register(&pxa_gpio_sysclass); -} - -core_initcall(pxa_gpio_init); diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index c72c89a2285..b024a8b3743 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -99,40 +99,12 @@ #define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) -/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). - * Those cases currently cause holes in the GPIO number space, the - * actual number of the last GPIO is recorded by 'pxa_last_gpio'. - */ -extern int pxa_last_gpio; - #define NR_BUILTIN_GPIO 128 -static inline int gpio_get_value(unsigned gpio) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) - return GPLR(gpio) & GPIO_bit(gpio); - else - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) { - if (value) - GPSR(gpio) = GPIO_bit(gpio); - else - GPCR(gpio) = GPIO_bit(gpio); - } else { - __gpio_set_value(gpio, value); - } -} - -#define gpio_cansleep __gpio_cansleep #define gpio_to_bank(gpio) ((gpio) >> 5) #define gpio_to_irq(gpio) IRQ_GPIO(gpio) #define irq_to_gpio(irq) IRQ_TO_GPIO(irq) - #ifdef CONFIG_CPU_PXA26x /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, * as well as their Alternate Function value being '1' for GPIO in GAFRx. @@ -165,7 +137,5 @@ static inline int __gpio_is_occupied(unsigned gpio) return GPDR(gpio) & GPIO_bit(gpio); } -typedef int (*set_wake_t)(unsigned int irq, unsigned int on); - -extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); +#include #endif diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index dcc3ceaf717..b837df44048 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -4,3 +4,4 @@ obj-y := dma.o +obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c new file mode 100644 index 00000000000..af819bf21b6 --- /dev/null +++ b/arch/arm/plat-pxa/gpio.c @@ -0,0 +1,337 @@ +/* + * linux/arch/arm/plat-pxa/gpio.c + * + * Generic PXA GPIO handling + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include + +int pxa_last_gpio; + +struct pxa_gpio_chip { + struct gpio_chip chip; + void __iomem *regbase; + char label[10]; + + unsigned long irq_mask; + unsigned long irq_edge_rise; + unsigned long irq_edge_fall; + +#ifdef CONFIG_PM + unsigned long saved_gplr; + unsigned long saved_gpdr; + unsigned long saved_grer; + unsigned long saved_gfer; +#endif +}; + +static DEFINE_SPINLOCK(gpio_lock); +static struct pxa_gpio_chip *pxa_gpio_chips; + +#define for_each_gpio_chip(i, c) \ + for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) + +static inline void __iomem *gpio_chip_base(struct gpio_chip *c) +{ + return container_of(c, struct pxa_gpio_chip, chip)->regbase; +} + +static inline struct pxa_gpio_chip *gpio_to_chip(unsigned gpio) +{ + return &pxa_gpio_chips[gpio_to_bank(gpio)]; +} + +static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *base = gpio_chip_base(chip); + uint32_t value, mask = 1 << offset; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + value = __raw_readl(base + GPDR_OFFSET); + if (__gpio_is_inverted(chip->base + offset)) + value |= mask; + else + value &= ~mask; + __raw_writel(value, base + GPDR_OFFSET); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} + +static int pxa_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem *base = gpio_chip_base(chip); + uint32_t tmp, mask = 1 << offset; + unsigned long flags; + + __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + + spin_lock_irqsave(&gpio_lock, flags); + + tmp = __raw_readl(base + GPDR_OFFSET); + if (__gpio_is_inverted(chip->base + offset)) + tmp &= ~mask; + else + tmp |= mask; + __raw_writel(tmp, base + GPDR_OFFSET); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} + +static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); +} + +static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + __raw_writel(1 << offset, gpio_chip_base(chip) + + (value ? GPSR_OFFSET : GPCR_OFFSET)); +} + +static int __init pxa_init_gpio_chip(int gpio_end) +{ + int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; + struct pxa_gpio_chip *chips; + + /* this is early, we have to use bootmem allocator, and we really + * want this to be allocated dynamically for different 'gpio_end' + */ + chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip)); + if (chips == NULL) { + pr_err("%s: failed to allocate GPIO chips\n", __func__); + return -ENOMEM; + } + + for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { + struct gpio_chip *c = &chips[i].chip; + + sprintf(chips[i].label, "gpio-%d", i); + chips[i].regbase = (void __iomem *)GPIO_BANK(i); + + c->base = gpio; + c->label = chips[i].label; + + c->direction_input = pxa_gpio_direction_input; + c->direction_output = pxa_gpio_direction_output; + c->get = pxa_gpio_get; + c->set = pxa_gpio_set; + + /* number of GPIOs on last bank may be less than 32 */ + c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; + gpiochip_add(c); + } + pxa_gpio_chips = chips; + return 0; +} + +static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) +{ + struct pxa_gpio_chip *c; + int gpio = irq_to_gpio(irq); + unsigned long gpdr, mask = GPIO_bit(gpio); + + c = gpio_to_chip(gpio); + + if (type == IRQ_TYPE_PROBE) { + /* Don't mess with enabled GPIOs using preconfigured edges or + * GPIOs set to alternate function or to output during probe + */ + if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) + return 0; + + if (__gpio_is_occupied(gpio)) + return 0; + + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + + if (__gpio_is_inverted(gpio)) + __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); + else + __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); + + if (type & IRQ_TYPE_EDGE_RISING) + c->irq_edge_rise |= mask; + else + c->irq_edge_rise &= ~mask; + + if (type & IRQ_TYPE_EDGE_FALLING) + c->irq_edge_fall |= mask; + else + c->irq_edge_fall &= ~mask; + + __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); + __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); + + pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio, + ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), + ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); + return 0; +} + +static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + struct pxa_gpio_chip *c; + int loop, gpio, gpio_base, n; + unsigned long gedr; + + do { + loop = 0; + for_each_gpio_chip(gpio, c) { + gpio_base = c->chip.base; + + gedr = __raw_readl(c->regbase + GEDR_OFFSET); + gedr = gedr & c->irq_mask; + __raw_writel(gedr, c->regbase + GEDR_OFFSET); + + n = find_first_bit(&gedr, BITS_PER_LONG); + while (n < BITS_PER_LONG) { + loop = 1; + + generic_handle_irq(gpio_to_irq(gpio_base + n)); + n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); + } + } + } while (loop); +} + +static void pxa_ack_muxed_gpio(unsigned int irq) +{ + int gpio = irq_to_gpio(irq); + struct pxa_gpio_chip *c = gpio_to_chip(gpio); + + __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); +} + +static void pxa_mask_muxed_gpio(unsigned int irq) +{ + int gpio = irq_to_gpio(irq); + struct pxa_gpio_chip *c = gpio_to_chip(gpio); + uint32_t grer, gfer; + + c->irq_mask &= ~GPIO_bit(gpio); + + grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); + gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); + __raw_writel(grer, c->regbase + GRER_OFFSET); + __raw_writel(gfer, c->regbase + GFER_OFFSET); +} + +static void pxa_unmask_muxed_gpio(unsigned int irq) +{ + int gpio = irq_to_gpio(irq); + struct pxa_gpio_chip *c = gpio_to_chip(gpio); + + c->irq_mask |= GPIO_bit(gpio); + __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); + __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); +} + +static struct irq_chip pxa_muxed_gpio_chip = { + .name = "GPIO", + .ack = pxa_ack_muxed_gpio, + .mask = pxa_mask_muxed_gpio, + .unmask = pxa_unmask_muxed_gpio, + .set_type = pxa_gpio_irq_type, +}; + +void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) +{ + struct pxa_gpio_chip *c; + int gpio, irq; + + pxa_last_gpio = end; + + /* Initialize GPIO chips */ + pxa_init_gpio_chip(end); + + /* clear all GPIO edge detects */ + for_each_gpio_chip(gpio, c) { + __raw_writel(0, c->regbase + GFER_OFFSET); + __raw_writel(0, c->regbase + GRER_OFFSET); + __raw_writel(~0,c->regbase + GEDR_OFFSET); + } + + for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { + set_irq_chip(irq, &pxa_muxed_gpio_chip); + set_irq_handler(irq, handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + /* Install handler for GPIO>=2 edge detect interrupts */ + set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler); + pxa_muxed_gpio_chip.set_wake = fn; +} + +#ifdef CONFIG_PM +static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) +{ + struct pxa_gpio_chip *c; + int gpio; + + for_each_gpio_chip(gpio, c) { + c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); + c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); + c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); + + /* Clear GPIO transition detect bits */ + __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); + } + return 0; +} + +static int pxa_gpio_resume(struct sys_device *dev) +{ + struct pxa_gpio_chip *c; + int gpio; + + for_each_gpio_chip(gpio, c) { + /* restore level with set/clear */ + __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); + __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); + + __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); + __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); + __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); + } + return 0; +} +#else +#define pxa_gpio_suspend NULL +#define pxa_gpio_resume NULL +#endif + +struct sysdev_class pxa_gpio_sysclass = { + .name = "gpio", + .suspend = pxa_gpio_suspend, + .resume = pxa_gpio_resume, +}; + +static int __init pxa_gpio_init(void) +{ + return sysdev_class_register(&pxa_gpio_sysclass); +} + +core_initcall(pxa_gpio_init); diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h new file mode 100644 index 00000000000..44248cb926a --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/gpio.h @@ -0,0 +1,62 @@ +#ifndef __PLAT_GPIO_H +#define __PLAT_GPIO_H + +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 + +static inline int gpio_get_value(unsigned gpio) +{ + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) + return GPLR(gpio) & GPIO_bit(gpio); + else + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) { + if (value) + GPSR(gpio) = GPIO_bit(gpio); + else + GPCR(gpio) = GPIO_bit(gpio); + } else + __gpio_set_value(gpio, value); +} + +#define gpio_cansleep __gpio_cansleep + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +typedef int (*set_wake_t)(unsigned int irq, unsigned int on); + +extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); +#endif /* __PLAT_GPIO_H */ -- cgit v1.2.3-70-g09d2 From f8dec04d33b94a4cfa9358fd9666c01480bb164d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 15 Jan 2009 16:42:56 +0800 Subject: [ARM] pxa: move common MFP handling code into plat-pxa Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 2 +- arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa320.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | 130 ++-------- arch/arm/mach-pxa/include/mach/mfp-pxa930.h | 1 - arch/arm/mach-pxa/mfp-pxa3xx.c | 189 +------------- arch/arm/mach-pxa/pxa300.c | 10 +- arch/arm/mach-pxa/pxa320.c | 6 +- arch/arm/mach-pxa/pxa930.c | 6 +- arch/arm/plat-pxa/Makefile | 2 +- arch/arm/plat-pxa/include/plat/mfp.h | 369 ++++++++++++++++++++++++++++ arch/arm/plat-pxa/mfp.c | 278 +++++++++++++++++++++ 14 files changed, 680 insertions(+), 317 deletions(-) create mode 100644 arch/arm/plat-pxa/include/plat/mfp.h create mode 100644 arch/arm/plat-pxa/mfp.c (limited to 'arch/arm/plat-pxa') diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h index a72869b73ee..b13dc0269a6 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h @@ -1,7 +1,6 @@ #ifndef __ASM_ARCH_MFP_PXA25X_H #define __ASM_ARCH_MFP_PXA25X_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index da4f85a4f99..6543c05f47e 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -8,7 +8,6 @@ * specific controller, and this should work in most cases. */ -#include #include /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index 3e9211591e2..658b28ed129 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h @@ -1,7 +1,7 @@ #ifndef __ASM_ARCH_MFP_PXA2XX_H #define __ASM_ARCH_MFP_PXA2XX_H -#include +#include /* * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index 928fbef9cbf..ae8441192ef 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h @@ -15,7 +15,6 @@ #ifndef __ASM_ARCH_MFP_PXA300_H #define __ASM_ARCH_MFP_PXA300_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 80a0da9e092..07897e61d05 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h @@ -15,7 +15,6 @@ #ifndef __ASM_ARCH_MFP_PXA320_H #define __ASM_ARCH_MFP_PXA320_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h index 1f6b35c015d..d375195d982 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h @@ -1,68 +1,9 @@ #ifndef __ASM_ARCH_MFP_PXA3XX_H #define __ASM_ARCH_MFP_PXA3XX_H -#define MFPR_BASE (0x40e10000) -#define MFPR_SIZE (PAGE_SIZE) - -/* MFPR register bit definitions */ -#define MFPR_PULL_SEL (0x1 << 15) -#define MFPR_PULLUP_EN (0x1 << 14) -#define MFPR_PULLDOWN_EN (0x1 << 13) -#define MFPR_SLEEP_SEL (0x1 << 9) -#define MFPR_SLEEP_OE_N (0x1 << 7) -#define MFPR_EDGE_CLEAR (0x1 << 6) -#define MFPR_EDGE_FALL_EN (0x1 << 5) -#define MFPR_EDGE_RISE_EN (0x1 << 4) - -#define MFPR_SLEEP_DATA(x) ((x) << 8) -#define MFPR_DRIVE(x) (((x) & 0x7) << 10) -#define MFPR_AF_SEL(x) (((x) & 0x7) << 0) +#include -#define MFPR_EDGE_NONE (0) -#define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) -#define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) -#define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) - -/* - * Table that determines the low power modes outputs, with actual settings - * used in parentheses for don't-care values. Except for the float output, - * the configured driven and pulled levels match, so if there is a need for - * non-LPM pulled output, the same configuration could probably be used. - * - * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel - * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) - * - * Input 0 X(0) X(0) X(0) 0 - * Drive 0 0 0 0 X(1) 0 - * Drive 1 0 1 X(1) 0 0 - * Pull hi (1) 1 X(1) 1 0 0 - * Pull lo (0) 1 X(0) 0 1 0 - * Z (float) 1 X(0) 0 0 0 - */ -#define MFPR_LPM_INPUT (0) -#define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) -#define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) -#define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) -#define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) -#define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) -#define MFPR_LPM_MASK (0xe080) - -/* - * The pullup and pulldown state of the MFP pin at run mode is by default - * determined by the selected alternate function. In case that some buggy - * devices need to override this default behavior, the definitions below - * indicates the setting of corresponding MFPR bits - * - * Definition pull_sel pullup_en pulldown_en - * MFPR_PULL_NONE 0 0 0 - * MFPR_PULL_LOW 1 0 1 - * MFPR_PULL_HIGH 1 1 0 - * MFPR_PULL_BOTH 1 1 1 - */ -#define MFPR_PULL_NONE (0) -#define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) -#define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) -#define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) +#define MFPR_BASE (0x40e10000) /* PXA3xx common MFP configurations - processor specific ones defined * in mfp-pxa300.h and mfp-pxa320.h @@ -197,56 +138,21 @@ #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) -/* - * each MFP pin will have a MFPR register, since the offset of the - * register varies between processors, the processor specific code - * should initialize the pin offsets by pxa3xx_mfp_init_addr() - * - * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map" - * structure, which represents a range of MFP pins from "start" to - * "end", with the offset begining at "offset", to define a single - * pin, let "end" = -1 - * - * use - * - * MFP_ADDR_X() to define a range of pins - * MFP_ADDR() to define a single pin - * MFP_ADDR_END to signal the end of pin offset definitions - */ -struct pxa3xx_mfp_addr_map { - unsigned int start; - unsigned int end; - unsigned long offset; -}; - -#define MFP_ADDR_X(start, end, offset) \ - { MFP_PIN_##start, MFP_PIN_##end, offset } - -#define MFP_ADDR(pin, offset) \ - { MFP_PIN_##pin, -1, offset } - -#define MFP_ADDR_END { MFP_PIN_INVALID, 0 } - -/* - * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access - * to the MFPR register - */ -unsigned long pxa3xx_mfp_read(int mfp); -void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val); - -/* - * pxa3xx_mfp_config - configure the MFPR registers - * - * used by board specific initialization code - */ -void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num); - -/* - * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin - * index and MFPR register offset - * - * used by processor specific code +/* NOTE: usage of these two functions is not recommended, + * use pxa3xx_mfp_config() instead. */ -void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *); -void __init pxa3xx_init_mfp(void); +static inline unsigned long pxa3xx_mfp_read(int mfp) +{ + return mfp_read(mfp); +} + +static inline void pxa3xx_mfp_write(int mfp, unsigned long val) +{ + mfp_write(mfp, val); +} + +static inline void pxa3xx_mfp_config(unsigned long *mfp_cfg, int num) +{ + mfp_config(mfp_cfg, num); +} #endif /* __ASM_ARCH_MFP_PXA3XX_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index fa73f56a137..0d119d3b922 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_MFP_PXA9xx_H #define __ASM_ARCH_MFP_PXA9xx_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c index eb197a6e8e9..7a270eecd48 100644 --- a/arch/arm/mach-pxa/mfp-pxa3xx.c +++ b/arch/arm/mach-pxa/mfp-pxa3xx.c @@ -20,183 +20,9 @@ #include #include -#include #include #include -/* mfp_spin_lock is used to ensure that MFP register configuration - * (most likely a read-modify-write operation) is atomic, and that - * mfp_table[] is consistent - */ -static DEFINE_SPINLOCK(mfp_spin_lock); - -static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); - -struct pxa3xx_mfp_pin { - unsigned long config; /* -1 for not configured */ - unsigned long mfpr_off; /* MFPRxx Register offset */ - unsigned long mfpr_run; /* Run-Mode Register Value */ - unsigned long mfpr_lpm; /* Low Power Mode Register Value */ -}; - -static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; - -/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ -static const unsigned long mfpr_lpm[] = { - MFPR_LPM_INPUT, - MFPR_LPM_DRIVE_LOW, - MFPR_LPM_DRIVE_HIGH, - MFPR_LPM_PULL_LOW, - MFPR_LPM_PULL_HIGH, - MFPR_LPM_FLOAT, -}; - -/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ -static const unsigned long mfpr_pull[] = { - MFPR_PULL_NONE, - MFPR_PULL_LOW, - MFPR_PULL_HIGH, - MFPR_PULL_BOTH, -}; - -/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ -static const unsigned long mfpr_edge[] = { - MFPR_EDGE_NONE, - MFPR_EDGE_RISE, - MFPR_EDGE_FALL, - MFPR_EDGE_BOTH, -}; - -#define mfpr_readl(off) \ - __raw_readl(mfpr_mmio_base + (off)) - -#define mfpr_writel(off, val) \ - __raw_writel(val, mfpr_mmio_base + (off)) - -#define mfp_configured(p) ((p)->config != -1) - -/* - * perform a read-back of any MFPR register to make sure the - * previous writings are finished - */ -#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) - -static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p) -{ - if (mfp_configured(p)) - mfpr_writel(p->mfpr_off, p->mfpr_run); -} - -static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) -{ - if (mfp_configured(p)) { - unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; - if (mfpr_clr != p->mfpr_run) - mfpr_writel(p->mfpr_off, mfpr_clr); - if (p->mfpr_lpm != mfpr_clr) - mfpr_writel(p->mfpr_off, p->mfpr_lpm); - } -} - -void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&mfp_spin_lock, flags); - - for (i = 0; i < num; i++, mfp_cfgs++) { - unsigned long tmp, c = *mfp_cfgs; - struct pxa3xx_mfp_pin *p; - int pin, af, drv, lpm, edge, pull; - - pin = MFP_PIN(c); - BUG_ON(pin >= MFP_PIN_MAX); - p = &mfp_table[pin]; - - af = MFP_AF(c); - drv = MFP_DS(c); - lpm = MFP_LPM_STATE(c); - edge = MFP_LPM_EDGE(c); - pull = MFP_PULL(c); - - /* run-mode pull settings will conflict with MFPR bits of - * low power mode state, calculate mfpr_run and mfpr_lpm - * individually if pull != MFP_PULL_NONE - */ - tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); - - if (likely(pull == MFP_PULL_NONE)) { - p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; - p->mfpr_lpm = p->mfpr_run; - } else { - p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; - p->mfpr_run = tmp | mfpr_pull[pull]; - } - - p->config = c; __mfp_config_run(p); - } - - mfpr_sync(); - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -unsigned long pxa3xx_mfp_read(int mfp) -{ - unsigned long val, flags; - - BUG_ON(mfp >= MFP_PIN_MAX); - - spin_lock_irqsave(&mfp_spin_lock, flags); - val = mfpr_readl(mfp_table[mfp].mfpr_off); - spin_unlock_irqrestore(&mfp_spin_lock, flags); - - return val; -} - -void pxa3xx_mfp_write(int mfp, unsigned long val) -{ - unsigned long flags; - - BUG_ON(mfp >= MFP_PIN_MAX); - - spin_lock_irqsave(&mfp_spin_lock, flags); - mfpr_writel(mfp_table[mfp].mfpr_off, val); - mfpr_sync(); - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map) -{ - struct pxa3xx_mfp_addr_map *p; - unsigned long offset, flags; - int i; - - spin_lock_irqsave(&mfp_spin_lock, flags); - - for (p = map; p->start != MFP_PIN_INVALID; p++) { - offset = p->offset; - i = p->start; - - do { - mfp_table[i].mfpr_off = offset; - mfp_table[i].mfpr_run = 0; - mfp_table[i].mfpr_lpm = 0; - offset += 4; i++; - } while ((i <= p->end) && (p->end != -1)); - } - - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -void __init pxa3xx_init_mfp(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mfp_table); i++) - mfp_table[i].config = -1; -} - #ifdef CONFIG_PM /* * Configure the MFPs appropriately for suspend/resume. @@ -207,23 +33,13 @@ void __init pxa3xx_init_mfp(void) */ static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) { - int pin; - - for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { - struct pxa3xx_mfp_pin *p = &mfp_table[pin]; - __mfp_config_lpm(p); - } + mfp_config_lpm(); return 0; } static int pxa3xx_mfp_resume(struct sys_device *d) { - int pin; - - for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { - struct pxa3xx_mfp_pin *p = &mfp_table[pin]; - __mfp_config_run(p); - } + mfp_config_run(); /* clear RDH bit when MFP settings are restored * @@ -231,7 +47,6 @@ static int pxa3xx_mfp_resume(struct sys_device *d) * preserve them here in case they will be referenced later */ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); - return 0; } #else diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 37bb12d13ca..4ba6d21f851 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -23,7 +23,7 @@ #include "devices.h" #include "clock.h" -static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), MFP_ADDR_X(GPIO3, GPIO26, 0x027c), @@ -72,7 +72,7 @@ static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { }; /* override pxa300 MFP register addresses */ -static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO30, GPIO98, 0x0418), MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), @@ -98,13 +98,13 @@ static struct clk_lookup pxa310_clkregs[] = { static int __init pxa300_init(void) { if (cpu_is_pxa300() || cpu_is_pxa310()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa300_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa300_mfp_addr_map); clks_register(ARRAY_AND_SIZE(common_clkregs)); } if (cpu_is_pxa310()) { - pxa3xx_mfp_init_addr(pxa310_mfp_addr_map); + mfp_init_addr(pxa310_mfp_addr_map); clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); } diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index e708f4e0eca..8b3d97efada 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -23,7 +23,7 @@ #include "devices.h" #include "clock.h" -static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO4, 0x0124), MFP_ADDR_X(GPIO5, GPIO9, 0x028C), @@ -86,8 +86,8 @@ static struct clk_lookup pxa320_clkregs[] = { static int __init pxa320_init(void) { if (cpu_is_pxa320()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa320_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa320_mfp_addr_map); clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); } diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c index f15dfa55f27..71131742fff 100644 --- a/arch/arm/mach-pxa/pxa930.c +++ b/arch/arm/mach-pxa/pxa930.c @@ -18,7 +18,7 @@ #include -static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa930_mfp_addr_map[] __initdata = { MFP_ADDR(GPIO0, 0x02e0), MFP_ADDR(GPIO1, 0x02dc), @@ -179,8 +179,8 @@ static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { static int __init pxa930_init(void) { if (cpu_is_pxa930()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa930_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa930_mfp_addr_map); } return 0; diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index b837df44048..4be37235f57 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,6 +2,6 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o +obj-y := dma.o mfp.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h new file mode 100644 index 00000000000..a22229cde09 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -0,0 +1,369 @@ +/* + * arch/arm/plat-pxa/include/plat/mfp.h + * + * Common Multi-Function Pin Definitions + * + * Copyright (C) 2007 Marvell International Ltd. + * + * 2007-8-21: eric miao + * initial version + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_PLAT_MFP_H +#define __ASM_PLAT_MFP_H + +#define mfp_to_gpio(m) ((m) % 128) + +/* list of all the configurable MFP pins */ +enum { + MFP_PIN_INVALID = -1, + + MFP_PIN_GPIO0 = 0, + MFP_PIN_GPIO1, + MFP_PIN_GPIO2, + MFP_PIN_GPIO3, + MFP_PIN_GPIO4, + MFP_PIN_GPIO5, + MFP_PIN_GPIO6, + MFP_PIN_GPIO7, + MFP_PIN_GPIO8, + MFP_PIN_GPIO9, + MFP_PIN_GPIO10, + MFP_PIN_GPIO11, + MFP_PIN_GPIO12, + MFP_PIN_GPIO13, + MFP_PIN_GPIO14, + MFP_PIN_GPIO15, + MFP_PIN_GPIO16, + MFP_PIN_GPIO17, + MFP_PIN_GPIO18, + MFP_PIN_GPIO19, + MFP_PIN_GPIO20, + MFP_PIN_GPIO21, + MFP_PIN_GPIO22, + MFP_PIN_GPIO23, + MFP_PIN_GPIO24, + MFP_PIN_GPIO25, + MFP_PIN_GPIO26, + MFP_PIN_GPIO27, + MFP_PIN_GPIO28, + MFP_PIN_GPIO29, + MFP_PIN_GPIO30, + MFP_PIN_GPIO31, + MFP_PIN_GPIO32, + MFP_PIN_GPIO33, + MFP_PIN_GPIO34, + MFP_PIN_GPIO35, + MFP_PIN_GPIO36, + MFP_PIN_GPIO37, + MFP_PIN_GPIO38, + MFP_PIN_GPIO39, + MFP_PIN_GPIO40, + MFP_PIN_GPIO41, + MFP_PIN_GPIO42, + MFP_PIN_GPIO43, + MFP_PIN_GPIO44, + MFP_PIN_GPIO45, + MFP_PIN_GPIO46, + MFP_PIN_GPIO47, + MFP_PIN_GPIO48, + MFP_PIN_GPIO49, + MFP_PIN_GPIO50, + MFP_PIN_GPIO51, + MFP_PIN_GPIO52, + MFP_PIN_GPIO53, + MFP_PIN_GPIO54, + MFP_PIN_GPIO55, + MFP_PIN_GPIO56, + MFP_PIN_GPIO57, + MFP_PIN_GPIO58, + MFP_PIN_GPIO59, + MFP_PIN_GPIO60, + MFP_PIN_GPIO61, + MFP_PIN_GPIO62, + MFP_PIN_GPIO63, + MFP_PIN_GPIO64, + MFP_PIN_GPIO65, + MFP_PIN_GPIO66, + MFP_PIN_GPIO67, + MFP_PIN_GPIO68, + MFP_PIN_GPIO69, + MFP_PIN_GPIO70, + MFP_PIN_GPIO71, + MFP_PIN_GPIO72, + MFP_PIN_GPIO73, + MFP_PIN_GPIO74, + MFP_PIN_GPIO75, + MFP_PIN_GPIO76, + MFP_PIN_GPIO77, + MFP_PIN_GPIO78, + MFP_PIN_GPIO79, + MFP_PIN_GPIO80, + MFP_PIN_GPIO81, + MFP_PIN_GPIO82, + MFP_PIN_GPIO83, + MFP_PIN_GPIO84, + MFP_PIN_GPIO85, + MFP_PIN_GPIO86, + MFP_PIN_GPIO87, + MFP_PIN_GPIO88, + MFP_PIN_GPIO89, + MFP_PIN_GPIO90, + MFP_PIN_GPIO91, + MFP_PIN_GPIO92, + MFP_PIN_GPIO93, + MFP_PIN_GPIO94, + MFP_PIN_GPIO95, + MFP_PIN_GPIO96, + MFP_PIN_GPIO97, + MFP_PIN_GPIO98, + MFP_PIN_GPIO99, + MFP_PIN_GPIO100, + MFP_PIN_GPIO101, + MFP_PIN_GPIO102, + MFP_PIN_GPIO103, + MFP_PIN_GPIO104, + MFP_PIN_GPIO105, + MFP_PIN_GPIO106, + MFP_PIN_GPIO107, + MFP_PIN_GPIO108, + MFP_PIN_GPIO109, + MFP_PIN_GPIO110, + MFP_PIN_GPIO111, + MFP_PIN_GPIO112, + MFP_PIN_GPIO113, + MFP_PIN_GPIO114, + MFP_PIN_GPIO115, + MFP_PIN_GPIO116, + MFP_PIN_GPIO117, + MFP_PIN_GPIO118, + MFP_PIN_GPIO119, + MFP_PIN_GPIO120, + MFP_PIN_GPIO121, + MFP_PIN_GPIO122, + MFP_PIN_GPIO123, + MFP_PIN_GPIO124, + MFP_PIN_GPIO125, + MFP_PIN_GPIO126, + MFP_PIN_GPIO127, + MFP_PIN_GPIO0_2, + MFP_PIN_GPIO1_2, + MFP_PIN_GPIO2_2, + MFP_PIN_GPIO3_2, + MFP_PIN_GPIO4_2, + MFP_PIN_GPIO5_2, + MFP_PIN_GPIO6_2, + MFP_PIN_GPIO7_2, + MFP_PIN_GPIO8_2, + MFP_PIN_GPIO9_2, + MFP_PIN_GPIO10_2, + MFP_PIN_GPIO11_2, + MFP_PIN_GPIO12_2, + MFP_PIN_GPIO13_2, + MFP_PIN_GPIO14_2, + MFP_PIN_GPIO15_2, + MFP_PIN_GPIO16_2, + MFP_PIN_GPIO17_2, + + MFP_PIN_ULPI_STP, + MFP_PIN_ULPI_NXT, + MFP_PIN_ULPI_DIR, + + MFP_PIN_nXCVREN, + MFP_PIN_DF_CLE_nOE, + MFP_PIN_DF_nADV1_ALE, + MFP_PIN_DF_SCLK_E, + MFP_PIN_DF_SCLK_S, + MFP_PIN_nBE0, + MFP_PIN_nBE1, + MFP_PIN_DF_nADV2_ALE, + MFP_PIN_DF_INT_RnB, + MFP_PIN_DF_nCS0, + MFP_PIN_DF_nCS1, + MFP_PIN_nLUA, + MFP_PIN_nLLA, + MFP_PIN_DF_nWE, + MFP_PIN_DF_ALE_nWE, + MFP_PIN_DF_nRE_nOE, + MFP_PIN_DF_ADDR0, + MFP_PIN_DF_ADDR1, + MFP_PIN_DF_ADDR2, + MFP_PIN_DF_ADDR3, + MFP_PIN_DF_IO0, + MFP_PIN_DF_IO1, + MFP_PIN_DF_IO2, + MFP_PIN_DF_IO3, + MFP_PIN_DF_IO4, + MFP_PIN_DF_IO5, + MFP_PIN_DF_IO6, + MFP_PIN_DF_IO7, + MFP_PIN_DF_IO8, + MFP_PIN_DF_IO9, + MFP_PIN_DF_IO10, + MFP_PIN_DF_IO11, + MFP_PIN_DF_IO12, + MFP_PIN_DF_IO13, + MFP_PIN_DF_IO14, + MFP_PIN_DF_IO15, + + /* additional pins on PXA930 */ + MFP_PIN_GSIM_UIO, + MFP_PIN_GSIM_UCLK, + MFP_PIN_GSIM_UDET, + MFP_PIN_GSIM_nURST, + MFP_PIN_PMIC_INT, + MFP_PIN_RDY, + + MFP_PIN_MAX, +}; + +/* + * a possible MFP configuration is represented by a 32-bit integer + * + * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) + * bit 10..12 - Alternate Function Selection + * bit 13..15 - Drive Strength + * bit 16..18 - Low Power Mode State + * bit 19..20 - Low Power Mode Edge Detection + * bit 21..22 - Run Mode Pull State + * + * to facilitate the definition, the following macros are provided + * + * MFP_CFG_DEFAULT - default MFP configuration value, with + * alternate function = 0, + * drive strength = fast 3mA (MFP_DS03X) + * low power mode = default + * edge detection = none + * + * MFP_CFG - default MFPR value with alternate function + * MFP_CFG_DRV - default MFPR value with alternate function and + * pin drive strength + * MFP_CFG_LPM - default MFPR value with alternate function and + * low power mode + * MFP_CFG_X - default MFPR value with alternate function, + * pin drive strength and low power mode + */ + +typedef unsigned long mfp_cfg_t; + +#define MFP_PIN(x) ((x) & 0x3ff) + +#define MFP_AF0 (0x0 << 10) +#define MFP_AF1 (0x1 << 10) +#define MFP_AF2 (0x2 << 10) +#define MFP_AF3 (0x3 << 10) +#define MFP_AF4 (0x4 << 10) +#define MFP_AF5 (0x5 << 10) +#define MFP_AF6 (0x6 << 10) +#define MFP_AF7 (0x7 << 10) +#define MFP_AF_MASK (0x7 << 10) +#define MFP_AF(x) (((x) >> 10) & 0x7) + +#define MFP_DS01X (0x0 << 13) +#define MFP_DS02X (0x1 << 13) +#define MFP_DS03X (0x2 << 13) +#define MFP_DS04X (0x3 << 13) +#define MFP_DS06X (0x4 << 13) +#define MFP_DS08X (0x5 << 13) +#define MFP_DS10X (0x6 << 13) +#define MFP_DS13X (0x7 << 13) +#define MFP_DS_MASK (0x7 << 13) +#define MFP_DS(x) (((x) >> 13) & 0x7) + +#define MFP_LPM_DEFAULT (0x0 << 16) +#define MFP_LPM_DRIVE_LOW (0x1 << 16) +#define MFP_LPM_DRIVE_HIGH (0x2 << 16) +#define MFP_LPM_PULL_LOW (0x3 << 16) +#define MFP_LPM_PULL_HIGH (0x4 << 16) +#define MFP_LPM_FLOAT (0x5 << 16) +#define MFP_LPM_INPUT (0x6 << 16) +#define MFP_LPM_STATE_MASK (0x7 << 16) +#define MFP_LPM_STATE(x) (((x) >> 16) & 0x7) + +#define MFP_LPM_EDGE_NONE (0x0 << 19) +#define MFP_LPM_EDGE_RISE (0x1 << 19) +#define MFP_LPM_EDGE_FALL (0x2 << 19) +#define MFP_LPM_EDGE_BOTH (0x3 << 19) +#define MFP_LPM_EDGE_MASK (0x3 << 19) +#define MFP_LPM_EDGE(x) (((x) >> 19) & 0x3) + +#define MFP_PULL_NONE (0x0 << 21) +#define MFP_PULL_LOW (0x1 << 21) +#define MFP_PULL_HIGH (0x2 << 21) +#define MFP_PULL_BOTH (0x3 << 21) +#define MFP_PULL_MASK (0x3 << 21) +#define MFP_PULL(x) (((x) >> 21) & 0x3) + +#define MFP_CFG_DEFAULT (MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\ + MFP_LPM_EDGE_NONE | MFP_PULL_NONE) + +#define MFP_CFG(pin, af) \ + ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af)) + +#define MFP_CFG_DRV(pin, af, drv) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv)) + +#define MFP_CFG_LPM(pin, af, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm)) + +#define MFP_CFG_X(pin, af, drv, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm)) + +#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP) +/* + * each MFP pin will have a MFPR register, since the offset of the + * register varies between processors, the processor specific code + * should initialize the pin offsets by mfp_init() + * + * mfp_init_base() - accepts a virtual base for all MFPR registers and + * initialize the MFP table to a default state + * + * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which + * represents a range of MFP pins from "start" to "end", with the offset + * begining at "offset", to define a single pin, let "end" = -1. + * + * use + * + * MFP_ADDR_X() to define a range of pins + * MFP_ADDR() to define a single pin + * MFP_ADDR_END to signal the end of pin offset definitions + */ +struct mfp_addr_map { + unsigned int start; + unsigned int end; + unsigned long offset; +}; + +#define MFP_ADDR_X(start, end, offset) \ + { MFP_PIN_##start, MFP_PIN_##end, offset } + +#define MFP_ADDR(pin, offset) \ + { MFP_PIN_##pin, -1, offset } + +#define MFP_ADDR_END { MFP_PIN_INVALID, 0 } + +void __init mfp_init_base(unsigned long mfpr_base); +void __init mfp_init_addr(struct mfp_addr_map *map); + +/* + * mfp_{read, write}() - for direct read/write access to the MFPR register + * mfp_config() - for configuring a group of MFPR registers + * mfp_config_lpm() - configuring all low power MFPR registers for suspend + * mfp_config_run() - configuring all run time MFPR registers after resume + */ +unsigned long mfp_read(int mfp); +void mfp_write(int mfp, unsigned long mfpr_val); +void mfp_config(unsigned long *mfp_cfgs, int num); +void mfp_config_run(void); +void mfp_config_lpm(void); +#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */ + +#endif /* __ASM_PLAT_MFP_H */ diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c new file mode 100644 index 00000000000..e716c622a17 --- /dev/null +++ b/arch/arm/plat-pxa/mfp.c @@ -0,0 +1,278 @@ +/* + * linux/arch/arm/plat-pxa/mfp.c + * + * Multi-Function Pin Support + * + * Copyright (C) 2007 Marvell Internation Ltd. + * + * 2007-08-21: eric miao + * initial version + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include + +#define MFPR_SIZE (PAGE_SIZE) + +/* MFPR register bit definitions */ +#define MFPR_PULL_SEL (0x1 << 15) +#define MFPR_PULLUP_EN (0x1 << 14) +#define MFPR_PULLDOWN_EN (0x1 << 13) +#define MFPR_SLEEP_SEL (0x1 << 9) +#define MFPR_SLEEP_OE_N (0x1 << 7) +#define MFPR_EDGE_CLEAR (0x1 << 6) +#define MFPR_EDGE_FALL_EN (0x1 << 5) +#define MFPR_EDGE_RISE_EN (0x1 << 4) + +#define MFPR_SLEEP_DATA(x) ((x) << 8) +#define MFPR_DRIVE(x) (((x) & 0x7) << 10) +#define MFPR_AF_SEL(x) (((x) & 0x7) << 0) + +#define MFPR_EDGE_NONE (0) +#define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) +#define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) +#define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) + +/* + * Table that determines the low power modes outputs, with actual settings + * used in parentheses for don't-care values. Except for the float output, + * the configured driven and pulled levels match, so if there is a need for + * non-LPM pulled output, the same configuration could probably be used. + * + * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel + * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) + * + * Input 0 X(0) X(0) X(0) 0 + * Drive 0 0 0 0 X(1) 0 + * Drive 1 0 1 X(1) 0 0 + * Pull hi (1) 1 X(1) 1 0 0 + * Pull lo (0) 1 X(0) 0 1 0 + * Z (float) 1 X(0) 0 0 0 + */ +#define MFPR_LPM_INPUT (0) +#define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) +#define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) +#define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) +#define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) +#define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) +#define MFPR_LPM_MASK (0xe080) + +/* + * The pullup and pulldown state of the MFP pin at run mode is by default + * determined by the selected alternate function. In case that some buggy + * devices need to override this default behavior, the definitions below + * indicates the setting of corresponding MFPR bits + * + * Definition pull_sel pullup_en pulldown_en + * MFPR_PULL_NONE 0 0 0 + * MFPR_PULL_LOW 1 0 1 + * MFPR_PULL_HIGH 1 1 0 + * MFPR_PULL_BOTH 1 1 1 + */ +#define MFPR_PULL_NONE (0) +#define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) +#define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) +#define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) + +/* mfp_spin_lock is used to ensure that MFP register configuration + * (most likely a read-modify-write operation) is atomic, and that + * mfp_table[] is consistent + */ +static DEFINE_SPINLOCK(mfp_spin_lock); + +static void __iomem *mfpr_mmio_base; + +struct mfp_pin { + unsigned long config; /* -1 for not configured */ + unsigned long mfpr_off; /* MFPRxx Register offset */ + unsigned long mfpr_run; /* Run-Mode Register Value */ + unsigned long mfpr_lpm; /* Low Power Mode Register Value */ +}; + +static struct mfp_pin mfp_table[MFP_PIN_MAX]; + +/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ +static const unsigned long mfpr_lpm[] = { + MFPR_LPM_INPUT, + MFPR_LPM_DRIVE_LOW, + MFPR_LPM_DRIVE_HIGH, + MFPR_LPM_PULL_LOW, + MFPR_LPM_PULL_HIGH, + MFPR_LPM_FLOAT, +}; + +/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ +static const unsigned long mfpr_pull[] = { + MFPR_PULL_NONE, + MFPR_PULL_LOW, + MFPR_PULL_HIGH, + MFPR_PULL_BOTH, +}; + +/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ +static const unsigned long mfpr_edge[] = { + MFPR_EDGE_NONE, + MFPR_EDGE_RISE, + MFPR_EDGE_FALL, + MFPR_EDGE_BOTH, +}; + +#define mfpr_readl(off) \ + __raw_readl(mfpr_mmio_base + (off)) + +#define mfpr_writel(off, val) \ + __raw_writel(val, mfpr_mmio_base + (off)) + +#define mfp_configured(p) ((p)->config != -1) + +/* + * perform a read-back of any MFPR register to make sure the + * previous writings are finished + */ +#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) + +static inline void __mfp_config_run(struct mfp_pin *p) +{ + if (mfp_configured(p)) + mfpr_writel(p->mfpr_off, p->mfpr_run); +} + +static inline void __mfp_config_lpm(struct mfp_pin *p) +{ + if (mfp_configured(p)) { + unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; + if (mfpr_clr != p->mfpr_run) + mfpr_writel(p->mfpr_off, mfpr_clr); + if (p->mfpr_lpm != mfpr_clr) + mfpr_writel(p->mfpr_off, p->mfpr_lpm); + } +} + +void mfp_config(unsigned long *mfp_cfgs, int num) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&mfp_spin_lock, flags); + + for (i = 0; i < num; i++, mfp_cfgs++) { + unsigned long tmp, c = *mfp_cfgs; + struct mfp_pin *p; + int pin, af, drv, lpm, edge, pull; + + pin = MFP_PIN(c); + BUG_ON(pin >= MFP_PIN_MAX); + p = &mfp_table[pin]; + + af = MFP_AF(c); + drv = MFP_DS(c); + lpm = MFP_LPM_STATE(c); + edge = MFP_LPM_EDGE(c); + pull = MFP_PULL(c); + + /* run-mode pull settings will conflict with MFPR bits of + * low power mode state, calculate mfpr_run and mfpr_lpm + * individually if pull != MFP_PULL_NONE + */ + tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); + + if (likely(pull == MFP_PULL_NONE)) { + p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; + p->mfpr_lpm = p->mfpr_run; + } else { + p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; + p->mfpr_run = tmp | mfpr_pull[pull]; + } + + p->config = c; __mfp_config_run(p); + } + + mfpr_sync(); + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +unsigned long mfp_read(int mfp) +{ + unsigned long val, flags; + + BUG_ON(mfp >= MFP_PIN_MAX); + + spin_lock_irqsave(&mfp_spin_lock, flags); + val = mfpr_readl(mfp_table[mfp].mfpr_off); + spin_unlock_irqrestore(&mfp_spin_lock, flags); + + return val; +} + +void mfp_write(int mfp, unsigned long val) +{ + unsigned long flags; + + BUG_ON(mfp >= MFP_PIN_MAX); + + spin_lock_irqsave(&mfp_spin_lock, flags); + mfpr_writel(mfp_table[mfp].mfpr_off, val); + mfpr_sync(); + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +void __init mfp_init_base(unsigned long mfpr_base) +{ + int i; + + /* initialize the table with default - unconfigured */ + for (i = 0; i < ARRAY_SIZE(mfp_table); i++) + mfp_table[i].config = -1; + + mfpr_mmio_base = (void __iomem *)mfpr_base; +} + +void __init mfp_init_addr(struct mfp_addr_map *map) +{ + struct mfp_addr_map *p; + unsigned long offset, flags; + int i; + + spin_lock_irqsave(&mfp_spin_lock, flags); + + for (p = map; p->start != MFP_PIN_INVALID; p++) { + offset = p->offset; + i = p->start; + + do { + mfp_table[i].mfpr_off = offset; + mfp_table[i].mfpr_run = 0; + mfp_table[i].mfpr_lpm = 0; + offset += 4; i++; + } while ((i <= p->end) && (p->end != -1)); + } + + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +void mfp_config_lpm(void) +{ + struct mfp_pin *p = &mfp_table[0]; + int pin; + + for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) + __mfp_config_lpm(p); +} + +void mfp_config_run(void) +{ + struct mfp_pin *p = &mfp_table[0]; + int pin; + + for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) + __mfp_config_run(p); +} -- cgit v1.2.3-70-g09d2 From 14c6b5e7add9ec393ad61bceb6106b47c7f14bd3 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 12:50:22 +0800 Subject: [ARM] pxa: add base support for Marvell PXA910 Signed-off-by: Bin Yang Signed-off-by: Eric Miao --- arch/arm/Kconfig | 4 +- arch/arm/mach-mmp/Kconfig | 8 +- arch/arm/mach-mmp/Makefile | 1 + arch/arm/mach-mmp/common.h | 2 + arch/arm/mach-mmp/include/mach/cputype.h | 9 ++ arch/arm/mach-mmp/include/mach/devices.h | 10 ++ arch/arm/mach-mmp/include/mach/irqs.h | 61 +++++++++++ arch/arm/mach-mmp/include/mach/mfp-pxa910.h | 157 +++++++++++++++++++++++++++ arch/arm/mach-mmp/include/mach/pxa910.h | 23 ++++ arch/arm/mach-mmp/include/mach/regs-apbc.h | 25 +++++ arch/arm/mach-mmp/pxa910.c | 158 ++++++++++++++++++++++++++++ arch/arm/plat-pxa/include/plat/mfp.h | 30 ++++++ 12 files changed, 485 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-mmp/include/mach/mfp-pxa910.h create mode 100644 arch/arm/mach-mmp/include/mach/pxa910.h create mode 100644 arch/arm/mach-mmp/pxa910.c (limited to 'arch/arm/plat-pxa') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index daf35d77820..cb4486ad0f7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -488,7 +488,7 @@ config ARCH_PXA Support for Intel/Marvell's PXA2xx/PXA3xx processor line. config ARCH_MMP - bool "Marvell PXA168" + bool "Marvell PXA168/910" depends on MMU select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB @@ -499,7 +499,7 @@ config ARCH_MMP select TICK_ONESHOT select PLAT_PXA help - Support for Marvell's PXA168 processor line. + Support for Marvell's PXA168/910 processor line. config ARCH_RPC bool "RiscPC" diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index b5232676355..ba2e377484f 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -1,6 +1,6 @@ if ARCH_MMP -menu "Marvell PXA168 Implmentations" +menu "Marvell PXA168/910 Implmentations" config MACH_ASPENITE bool "Marvell's PXA168 Aspenite Development Board" @@ -24,4 +24,10 @@ config CPU_PXA168 help Select code specific to PXA168 +config CPU_PXA910 + bool + select CPU_MOHAWK + help + Select code specific to PXA910 + endif diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 0ac7644ec99..93d2bc7459d 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -6,6 +6,7 @@ obj-y += common.o clock.o devices.o irq.o time.o # SoC support obj-$(CONFIG_CPU_PXA168) += pxa168.o +obj-$(CONFIG_CPU_PXA910) += pxa910.o # board support obj-$(CONFIG_MACH_ASPENITE) += aspenite.o diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h index bf7a6a492de..c33fbbc4941 100644 --- a/arch/arm/mach-mmp/common.h +++ b/arch/arm/mach-mmp/common.h @@ -5,7 +5,9 @@ struct sys_timer; extern void timer_init(int irq); extern struct sys_timer pxa168_timer; +extern struct sys_timer pxa910_timer; extern void __init pxa168_init_irq(void); +extern void __init pxa910_init_irq(void); extern void __init icu_init_irq(void); extern void __init pxa_map_io(void); diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h index 4ceed7a5075..25e797b0908 100644 --- a/arch/arm/mach-mmp/include/mach/cputype.h +++ b/arch/arm/mach-mmp/include/mach/cputype.h @@ -7,6 +7,7 @@ * CPU Stepping OLD_ID CPU_ID CHIP_ID * * PXA168 A0 0x41159263 0x56158400 0x00A0A333 + * PXA910 Y0 0x41159262 0x56158000 0x00F0C910 */ #ifdef CONFIG_CPU_PXA168 @@ -16,6 +17,14 @@ # define __cpu_is_pxa168(id) (0) #endif +#ifdef CONFIG_CPU_PXA910 +# define __cpu_is_pxa910(id) \ + ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; }) +#else +# define __cpu_is_pxa910(id) (0) +#endif + #define cpu_is_pxa168() ({ __cpu_is_pxa168(read_cpuid_id()); }) +#define cpu_is_pxa910() ({ __cpu_is_pxa910(read_cpuid_id()); }) #endif /* __ASM_MACH_CPUTYPE_H */ diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h index bc03388d5fd..24585397217 100644 --- a/arch/arm/mach-mmp/include/mach/devices.h +++ b/arch/arm/mach-mmp/include/mach/devices.h @@ -24,4 +24,14 @@ struct pxa_device_desc pxa168_device_##_name __initdata = { \ .dma = { _dma }, \ }; +#define PXA910_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...) \ +struct pxa_device_desc pxa910_device_##_name __initdata = { \ + .dev_name = "pxa910-" #_name, \ + .drv_name = _drv, \ + .id = _id, \ + .irq = IRQ_PXA910_##_irq, \ + .start = _start, \ + .size = _size, \ + .dma = { _dma }, \ +}; extern int pxa_register_device(struct pxa_device_desc *, void *, size_t); diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index 91ecb3fbca0..e83e45ebf7a 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -49,6 +49,67 @@ #define IRQ_PXA168_PMU 60 #define IRQ_PXA168_SM_INT 63 +/* + * Interrupt numbers for PXA910 + */ +#define IRQ_PXA910_AIRQ 0 +#define IRQ_PXA910_SSP3 1 +#define IRQ_PXA910_SSP2 2 +#define IRQ_PXA910_SSP1 3 +#define IRQ_PXA910_PMIC_INT 4 +#define IRQ_PXA910_RTC_INT 5 +#define IRQ_PXA910_RTC_ALARM 6 +#define IRQ_PXA910_TWSI0 7 +#define IRQ_PXA910_GPU 8 +#define IRQ_PXA910_KEYPAD 9 +#define IRQ_PXA910_ROTARY 10 +#define IRQ_PXA910_TRACKBALL 11 +#define IRQ_PXA910_ONEWIRE 12 +#define IRQ_PXA910_AP1_TIMER1 13 +#define IRQ_PXA910_AP1_TIMER2 14 +#define IRQ_PXA910_AP1_TIMER3 15 +#define IRQ_PXA910_IPC_AP0 16 +#define IRQ_PXA910_IPC_AP1 17 +#define IRQ_PXA910_IPC_AP2 18 +#define IRQ_PXA910_IPC_AP3 19 +#define IRQ_PXA910_IPC_AP4 20 +#define IRQ_PXA910_IPC_CP0 21 +#define IRQ_PXA910_IPC_CP1 22 +#define IRQ_PXA910_IPC_CP2 23 +#define IRQ_PXA910_IPC_CP3 24 +#define IRQ_PXA910_IPC_CP4 25 +#define IRQ_PXA910_L2_DDR 26 +#define IRQ_PXA910_UART2 27 +#define IRQ_PXA910_UART3 28 +#define IRQ_PXA910_AP2_TIMER1 29 +#define IRQ_PXA910_AP2_TIMER2 30 +#define IRQ_PXA910_CP2_TIMER1 31 +#define IRQ_PXA910_CP2_TIMER2 32 +#define IRQ_PXA910_CP2_TIMER3 33 +#define IRQ_PXA910_GSSP 34 +#define IRQ_PXA910_CP2_WDT 35 +#define IRQ_PXA910_MAIN_PMU 36 +#define IRQ_PXA910_CP_FREQ_CHG 37 +#define IRQ_PXA910_AP_FREQ_CHG 38 +#define IRQ_PXA910_MMC 39 +#define IRQ_PXA910_AEU 40 +#define IRQ_PXA910_LCD 41 +#define IRQ_PXA910_CCIC 42 +#define IRQ_PXA910_IRE 43 +#define IRQ_PXA910_USB1 44 +#define IRQ_PXA910_NAND 45 +#define IRQ_PXA910_HIFI_DMA 46 +#define IRQ_PXA910_DMA_INT0 47 +#define IRQ_PXA910_DMA_INT1 48 +#define IRQ_PXA910_AP_GPIO 49 +#define IRQ_PXA910_AP2_TIMER3 50 +#define IRQ_PXA910_USB2 51 +#define IRQ_PXA910_TWSI1 54 +#define IRQ_PXA910_CP_GPIO 55 +#define IRQ_PXA910_UART1 59 /* Slow UART */ +#define IRQ_PXA910_AP_PMU 60 +#define IRQ_PXA910_SM_INT 63 /* from PinMux */ + #define IRQ_GPIO_START 64 #define IRQ_GPIO_NUM 128 #define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h new file mode 100644 index 00000000000..48a1cbc7c56 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h @@ -0,0 +1,157 @@ +#ifndef __ASM_MACH_MFP_PXA910_H +#define __ASM_MACH_MFP_PXA910_H + +#include + +/* UART2 */ +#define GPIO47_UART2_RXD MFP_CFG(GPIO47, AF6) +#define GPIO48_UART2_TXD MFP_CFG(GPIO48, AF6) + +/* UART3 */ +#define GPIO31_UART3_RXD MFP_CFG(GPIO31, AF4) +#define GPIO32_UART3_TXD MFP_CFG(GPIO32, AF4) + +/*IRDA*/ +#define GPIO51_IRDA_SHDN MFP_CFG(GPIO51, AF0) + +/* SMC */ +#define SM_nCS0_nCS0 MFP_CFG(SM_nCS0, AF0) +#define SM_ADV_SM_ADV MFP_CFG(SM_ADV, AF0) +#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0) +#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0) +#define SM_BE0_SM_BE0 MFP_CFG(SM_BE0, AF1) +#define SM_BE1_SM_BE1 MFP_CFG(SM_BE1, AF1) + +/* I2C */ +#define GPIO53_CI2C_SCL MFP_CFG(GPIO53, AF2) +#define GPIO54_CI2C_SDA MFP_CFG(GPIO54, AF2) + +/* SSP1 (I2S) */ +#define GPIO24_SSP1_SDATA_IN MFP_CFG_DRV(GPIO24, AF1, MEDIUM) +#define GPIO21_SSP1_BITCLK MFP_CFG_DRV(GPIO21, AF1, MEDIUM) +#define GPIO20_SSP1_SYSCLK MFP_CFG_DRV(GPIO20, AF1, MEDIUM) +#define GPIO22_SSP1_SYNC MFP_CFG_DRV(GPIO22, AF1, MEDIUM) +#define GPIO23_SSP1_DATA_OUT MFP_CFG_DRV(GPIO23, AF1, MEDIUM) +#define GPIO124_MN_CLK_OUT MFP_CFG_DRV(GPIO124, AF1, MEDIUM) +#define GPIO123_CLK_REQ MFP_CFG_DRV(GPIO123, AF0, MEDIUM) + +/* DFI */ +#define DF_IO0_ND_IO0 MFP_CFG(DF_IO0, AF0) +#define DF_IO1_ND_IO1 MFP_CFG(DF_IO1, AF0) +#define DF_IO2_ND_IO2 MFP_CFG(DF_IO2, AF0) +#define DF_IO3_ND_IO3 MFP_CFG(DF_IO3, AF0) +#define DF_IO4_ND_IO4 MFP_CFG(DF_IO4, AF0) +#define DF_IO5_ND_IO5 MFP_CFG(DF_IO5, AF0) +#define DF_IO6_ND_IO6 MFP_CFG(DF_IO6, AF0) +#define DF_IO7_ND_IO7 MFP_CFG(DF_IO7, AF0) +#define DF_IO8_ND_IO8 MFP_CFG(DF_IO8, AF0) +#define DF_IO9_ND_IO9 MFP_CFG(DF_IO9, AF0) +#define DF_IO10_ND_IO10 MFP_CFG(DF_IO10, AF0) +#define DF_IO11_ND_IO11 MFP_CFG(DF_IO11, AF0) +#define DF_IO12_ND_IO12 MFP_CFG(DF_IO12, AF0) +#define DF_IO13_ND_IO13 MFP_CFG(DF_IO13, AF0) +#define DF_IO14_ND_IO14 MFP_CFG(DF_IO14, AF0) +#define DF_IO15_ND_IO15 MFP_CFG(DF_IO15, AF0) +#define DF_nCS0_SM_nCS2_nCS0 MFP_CFG(DF_nCS0_SM_nCS2, AF0) +#define DF_ALE_SM_WEn_ND_ALE MFP_CFG(DF_ALE_SM_WEn, AF1) +#define DF_CLE_SM_OEn_ND_CLE MFP_CFG(DF_CLE_SM_OEn, AF0) +#define DF_WEn_DF_WEn MFP_CFG(DF_WEn, AF1) +#define DF_REn_DF_REn MFP_CFG(DF_REn, AF1) +#define DF_RDY0_DF_RDY0 MFP_CFG(DF_RDY0, AF0) + +/*keypad*/ +#define GPIO00_KP_MKIN0 MFP_CFG(GPIO0, AF1) +#define GPIO01_KP_MKOUT0 MFP_CFG(GPIO1, AF1) +#define GPIO02_KP_MKIN1 MFP_CFG(GPIO2, AF1) +#define GPIO03_KP_MKOUT1 MFP_CFG(GPIO3, AF1) +#define GPIO04_KP_MKIN2 MFP_CFG(GPIO4, AF1) +#define GPIO05_KP_MKOUT2 MFP_CFG(GPIO5, AF1) +#define GPIO06_KP_MKIN3 MFP_CFG(GPIO6, AF1) +#define GPIO07_KP_MKOUT3 MFP_CFG(GPIO7, AF1) +#define GPIO08_KP_MKIN4 MFP_CFG(GPIO8, AF1) +#define GPIO09_KP_MKOUT4 MFP_CFG(GPIO9, AF1) +#define GPIO10_KP_MKIN5 MFP_CFG(GPIO10, AF1) +#define GPIO11_KP_MKOUT5 MFP_CFG(GPIO11, AF1) +#define GPIO12_KP_MKIN6 MFP_CFG(GPIO12, AF1) +#define GPIO13_KP_MKOUT6 MFP_CFG(GPIO13, AF1) +#define GPIO14_KP_MKIN7 MFP_CFG(GPIO14, AF1) +#define GPIO15_KP_MKOUT7 MFP_CFG(GPIO15, AF1) +#define GPIO16_KP_DKIN0 MFP_CFG(GPIO16, AF1) +#define GPIO17_KP_DKIN1 MFP_CFG(GPIO17, AF1) +#define GPIO18_KP_DKIN2 MFP_CFG(GPIO18, AF1) +#define GPIO19_KP_DKIN3 MFP_CFG(GPIO19, AF1) + +/* LCD */ +#define GPIO81_LCD_FCLK MFP_CFG(GPIO81, AF1) +#define GPIO82_LCD_LCLK MFP_CFG(GPIO82, AF1) +#define GPIO83_LCD_PCLK MFP_CFG(GPIO83, AF1) +#define GPIO84_LCD_DENA MFP_CFG(GPIO84, AF1) +#define GPIO85_LCD_DD0 MFP_CFG(GPIO85, AF1) +#define GPIO86_LCD_DD1 MFP_CFG(GPIO86, AF1) +#define GPIO87_LCD_DD2 MFP_CFG(GPIO87, AF1) +#define GPIO88_LCD_DD3 MFP_CFG(GPIO88, AF1) +#define GPIO89_LCD_DD4 MFP_CFG(GPIO89, AF1) +#define GPIO90_LCD_DD5 MFP_CFG(GPIO90, AF1) +#define GPIO91_LCD_DD6 MFP_CFG(GPIO91, AF1) +#define GPIO92_LCD_DD7 MFP_CFG(GPIO92, AF1) +#define GPIO93_LCD_DD8 MFP_CFG(GPIO93, AF1) +#define GPIO94_LCD_DD9 MFP_CFG(GPIO94, AF1) +#define GPIO95_LCD_DD10 MFP_CFG(GPIO95, AF1) +#define GPIO96_LCD_DD11 MFP_CFG(GPIO96, AF1) +#define GPIO97_LCD_DD12 MFP_CFG(GPIO97, AF1) +#define GPIO98_LCD_DD13 MFP_CFG(GPIO98, AF1) +#define GPIO100_LCD_DD14 MFP_CFG(GPIO100, AF1) +#define GPIO101_LCD_DD15 MFP_CFG(GPIO101, AF1) +#define GPIO102_LCD_DD16 MFP_CFG(GPIO102, AF1) +#define GPIO103_LCD_DD17 MFP_CFG(GPIO103, AF1) +#define GPIO104_LCD_DD18 MFP_CFG(GPIO104, AF1) +#define GPIO105_LCD_DD19 MFP_CFG(GPIO105, AF1) +#define GPIO106_LCD_DD20 MFP_CFG(GPIO106, AF1) +#define GPIO107_LCD_DD21 MFP_CFG(GPIO107, AF1) +#define GPIO108_LCD_DD22 MFP_CFG(GPIO108, AF1) +#define GPIO109_LCD_DD23 MFP_CFG(GPIO109, AF1) + +#define GPIO104_LCD_SPIDOUT MFP_CFG(GPIO104, AF3) +#define GPIO105_LCD_SPIDIN MFP_CFG(GPIO105, AF3) +#define GPIO107_LCD_CS1 MFP_CFG(GPIO107, AF3) +#define GPIO108_LCD_DCLK MFP_CFG(GPIO108, AF3) + +#define GPIO106_LCD_RESET MFP_CFG(GPIO106, AF0) + +/*smart panel*/ +#define GPIO82_LCD_A0 MFP_CFG(GPIO82, AF0) +#define GPIO83_LCD_WR MFP_CFG(GPIO83, AF0) +#define GPIO103_LCD_CS MFP_CFG(GPIO103, AF0) + +/*1wire*/ +#define GPIO106_1WIRE MFP_CFG(GPIO106, AF3) + +/*CCIC*/ +#define GPIO67_CCIC_IN7 MFP_CFG_DRV(GPIO67, AF1, MEDIUM) +#define GPIO68_CCIC_IN6 MFP_CFG_DRV(GPIO68, AF1, MEDIUM) +#define GPIO69_CCIC_IN5 MFP_CFG_DRV(GPIO69, AF1, MEDIUM) +#define GPIO70_CCIC_IN4 MFP_CFG_DRV(GPIO70, AF1, MEDIUM) +#define GPIO71_CCIC_IN3 MFP_CFG_DRV(GPIO71, AF1, MEDIUM) +#define GPIO72_CCIC_IN2 MFP_CFG_DRV(GPIO72, AF1, MEDIUM) +#define GPIO73_CCIC_IN1 MFP_CFG_DRV(GPIO73, AF1, MEDIUM) +#define GPIO74_CCIC_IN0 MFP_CFG_DRV(GPIO74, AF1, MEDIUM) +#define GPIO75_CAM_HSYNC MFP_CFG_DRV(GPIO75, AF1, MEDIUM) +#define GPIO76_CAM_VSYNC MFP_CFG_DRV(GPIO76, AF1, MEDIUM) +#define GPIO77_CAM_MCLK MFP_CFG_DRV(GPIO77, AF1, MEDIUM) +#define GPIO78_CAM_PCLK MFP_CFG_DRV(GPIO78, AF1, MEDIUM) + +/* MMC1 */ +#define MMC1_DAT7_MMC1_DAT7 MFP_CFG_DRV(MMC1_DAT7, AF0, MEDIUM) +#define MMC1_DAT6_MMC1_DAT6 MFP_CFG_DRV(MMC1_DAT6, AF0, MEDIUM) +#define MMC1_DAT5_MMC1_DAT5 MFP_CFG_DRV(MMC1_DAT5, AF0, MEDIUM) +#define MMC1_DAT4_MMC1_DAT4 MFP_CFG_DRV(MMC1_DAT4, AF0, MEDIUM) +#define MMC1_DAT3_MMC1_DAT3 MFP_CFG_DRV(MMC1_DAT3, AF0, MEDIUM) +#define MMC1_DAT2_MMC1_DAT2 MFP_CFG_DRV(MMC1_DAT2, AF0, MEDIUM) +#define MMC1_DAT1_MMC1_DAT1 MFP_CFG_DRV(MMC1_DAT1, AF0, MEDIUM) +#define MMC1_DAT0_MMC1_DAT0 MFP_CFG_DRV(MMC1_DAT0, AF0, MEDIUM) +#define MMC1_CMD_MMC1_CMD MFP_CFG_DRV(MMC1_CMD, AF0, MEDIUM) +#define MMC1_CLK_MMC1_CLK MFP_CFG_DRV(MMC1_CLK, AF0, MEDIUM) +#define MMC1_CD_MMC1_CD MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM) +#define MMC1_WP_MMC1_WP MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM) + +#endif /* __ASM_MACH MFP_PXA910_H */ diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h new file mode 100644 index 00000000000..b7aeaf574c3 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/pxa910.h @@ -0,0 +1,23 @@ +#ifndef __ASM_MACH_PXA910_H +#define __ASM_MACH_PXA910_H + +#include + +extern struct pxa_device_desc pxa910_device_uart1; +extern struct pxa_device_desc pxa910_device_uart2; + +static inline int pxa910_add_uart(int id) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa910_device_uart1; break; + case 2: d = &pxa910_device_uart2; break; + } + + if (d == NULL) + return -EINVAL; + + return pxa_register_device(d, NULL, 0); +} +#endif /* __ASM_MACH_PXA910_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h index e0ffae59487..c6b8c9dc202 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apbc.h +++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h @@ -42,6 +42,31 @@ #define APBC_PXA168_UART3 APBC_REG(0x070) #define APBC_PXA168_AC97 APBC_REG(0x084) +/* + * APB Clock register offsets for PXA910 + */ +#define APBC_PXA910_UART0 APBC_REG(0x000) +#define APBC_PXA910_UART1 APBC_REG(0x004) +#define APBC_PXA910_GPIO APBC_REG(0x008) +#define APBC_PXA910_PWM0 APBC_REG(0x00c) +#define APBC_PXA910_PWM1 APBC_REG(0x010) +#define APBC_PXA910_PWM2 APBC_REG(0x014) +#define APBC_PXA910_PWM3 APBC_REG(0x018) +#define APBC_PXA910_SSP1 APBC_REG(0x01c) +#define APBC_PXA910_SSP2 APBC_REG(0x020) +#define APBC_PXA910_IPC APBC_REG(0x024) +#define APBC_PXA910_TWSI0 APBC_REG(0x02c) +#define APBC_PXA910_KPC APBC_REG(0x030) +#define APBC_PXA910_TIMERS APBC_REG(0x034) +#define APBC_PXA910_TBROT APBC_REG(0x038) +#define APBC_PXA910_AIB APBC_REG(0x03c) +#define APBC_PXA910_SW_JTAG APBC_REG(0x040) +#define APBC_PXA910_TIMERS1 APBC_REG(0x044) +#define APBC_PXA910_ONEWIRE APBC_REG(0x048) +#define APBC_PXA910_SSP3 APBC_REG(0x04c) +#define APBC_PXA910_ASFAR APBC_REG(0x050) +#define APBC_PXA910_ASSAR APBC_REG(0x054) + /* Common APB clock register bit definitions */ #define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */ #define APBC_FNCLK (1 << 1) /* Functional Clock Enable */ diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c new file mode 100644 index 00000000000..453f8f7758b --- /dev/null +++ b/arch/arm/mach-mmp/pxa910.c @@ -0,0 +1,158 @@ +/* + * linux/arch/arm/mach-mmp/pxa910.c + * + * Code specific to PXA910 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "clock.h" + +#define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000) + +static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata = +{ + MFP_ADDR_X(GPIO0, GPIO54, 0xdc), + MFP_ADDR_X(GPIO67, GPIO98, 0x1b8), + MFP_ADDR_X(GPIO100, GPIO109, 0x238), + + MFP_ADDR(GPIO123, 0xcc), + MFP_ADDR(GPIO124, 0xd0), + + MFP_ADDR(DF_IO0, 0x40), + MFP_ADDR(DF_IO1, 0x3c), + MFP_ADDR(DF_IO2, 0x38), + MFP_ADDR(DF_IO3, 0x34), + MFP_ADDR(DF_IO4, 0x30), + MFP_ADDR(DF_IO5, 0x2c), + MFP_ADDR(DF_IO6, 0x28), + MFP_ADDR(DF_IO7, 0x24), + MFP_ADDR(DF_IO8, 0x20), + MFP_ADDR(DF_IO9, 0x1c), + MFP_ADDR(DF_IO10, 0x18), + MFP_ADDR(DF_IO11, 0x14), + MFP_ADDR(DF_IO12, 0x10), + MFP_ADDR(DF_IO13, 0xc), + MFP_ADDR(DF_IO14, 0x8), + MFP_ADDR(DF_IO15, 0x4), + + MFP_ADDR(DF_nCS0_SM_nCS2, 0x44), + MFP_ADDR(DF_nCS1_SM_nCS3, 0x48), + MFP_ADDR(SM_nCS0, 0x4c), + MFP_ADDR(SM_nCS1, 0x50), + MFP_ADDR(DF_WEn, 0x54), + MFP_ADDR(DF_REn, 0x58), + MFP_ADDR(DF_CLE_SM_OEn, 0x5c), + MFP_ADDR(DF_ALE_SM_WEn, 0x60), + MFP_ADDR(SM_SCLK, 0x64), + MFP_ADDR(DF_RDY0, 0x68), + MFP_ADDR(SM_BE0, 0x6c), + MFP_ADDR(SM_BE1, 0x70), + MFP_ADDR(SM_ADV, 0x74), + MFP_ADDR(DF_RDY1, 0x78), + MFP_ADDR(SM_ADVMUX, 0x7c), + MFP_ADDR(SM_RDY, 0x80), + + MFP_ADDR_X(MMC1_DAT7, MMC1_WP, 0x84), + + MFP_ADDR_END, +}; + +#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) + +static void __init pxa910_init_gpio(void) +{ + int i; + + /* enable GPIO clock */ + __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO); + + /* unmask GPIO edge detection for all 4 banks - APMASKx */ + for (i = 0; i < 4; i++) + __raw_writel(0xffffffff, APMASK(i)); + + pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL); +} + +void __init pxa910_init_irq(void) +{ + icu_init_irq(); + pxa910_init_gpio(); +} + +/* APB peripheral clocks */ +static APBC_CLK(uart1, PXA910_UART0, 1, 14745600); +static APBC_CLK(uart2, PXA910_UART1, 1, 14745600); + +/* device and clock bindings */ +static struct clk_lookup pxa910_clkregs[] = { + INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL), +}; + +static int __init pxa910_init(void) +{ + if (cpu_is_pxa910()) { + mfp_init_base(MFPR_VIRT_BASE); + mfp_init_addr(pxa910_mfp_addr_map); + pxa_init_dma(IRQ_PXA910_DMA_INT0, 32); + clks_register(ARRAY_AND_SIZE(pxa910_clkregs)); + } + + return 0; +} +postcore_initcall(pxa910_init); + +/* system timer - clock enabled, 3.25MHz */ +#define TIMER_CLK_RST (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3)) + +static void __init pxa910_timer_init(void) +{ + /* reset and configure */ + __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA910_TIMERS); + __raw_writel(TIMER_CLK_RST, APBC_PXA910_TIMERS); + + timer_init(IRQ_PXA910_AP1_TIMER1); +} + +struct sys_timer pxa910_timer = { + .init = pxa910_timer_init, +}; + +/* on-chip devices */ + +/* NOTE: there are totally 3 UARTs on PXA910: + * + * UART1 - Slow UART (can be used both by AP and CP) + * UART2/3 - Fast UART + * + * To be backward compatible with the legacy FFUART/BTUART/STUART sequence, + * they are re-ordered as: + * + * pxa910_device_uart1 - UART2 as FFUART + * pxa910_device_uart2 - UART3 as BTUART + * + * UART1 is not used by AP for the moment. + */ +PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22); +PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24); diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h index a22229cde09..64019464c8d 100644 --- a/arch/arm/plat-pxa/include/plat/mfp.h +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -209,6 +209,36 @@ enum { MFP_PIN_DF_IO13, MFP_PIN_DF_IO14, MFP_PIN_DF_IO15, + MFP_PIN_DF_nCS0_SM_nCS2, + MFP_PIN_DF_nCS1_SM_nCS3, + MFP_PIN_SM_nCS0, + MFP_PIN_SM_nCS1, + MFP_PIN_DF_WEn, + MFP_PIN_DF_REn, + MFP_PIN_DF_CLE_SM_OEn, + MFP_PIN_DF_ALE_SM_WEn, + MFP_PIN_DF_RDY0, + MFP_PIN_DF_RDY1, + + MFP_PIN_SM_SCLK, + MFP_PIN_SM_BE0, + MFP_PIN_SM_BE1, + MFP_PIN_SM_ADV, + MFP_PIN_SM_ADVMUX, + MFP_PIN_SM_RDY, + + MFP_PIN_MMC1_DAT7, + MFP_PIN_MMC1_DAT6, + MFP_PIN_MMC1_DAT5, + MFP_PIN_MMC1_DAT4, + MFP_PIN_MMC1_DAT3, + MFP_PIN_MMC1_DAT2, + MFP_PIN_MMC1_DAT1, + MFP_PIN_MMC1_DAT0, + MFP_PIN_MMC1_CMD, + MFP_PIN_MMC1_CLK, + MFP_PIN_MMC1_CD, + MFP_PIN_MMC1_WP, /* additional pins on PXA930 */ MFP_PIN_GSIM_UIO, -- cgit v1.2.3-70-g09d2 From 707b2c247c6c3e8976f94fcf9ab25c85502352d5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 26 Mar 2009 21:04:10 +0800 Subject: [ARM] pxa: build arch/arm/plat-pxa/mfp.c only when PXA3xx or ARCH_MMP defined arch/arm/plat-pxa/mfp.c is not intended to be use by PXA25x/PXA27x, make it explicit here only for use by PXA3xx or ARCH_MMP. Reported-by: Guennadi Liakhovestski Reported-by: Robert Jarzmik Signed-off-by: Eric Miao --- arch/arm/plat-pxa/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-pxa') diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 4be37235f57..8f2c4c7fbd4 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,6 +2,8 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o mfp.o +obj-y := dma.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_PXA3xx) += mfp.o +obj-$(CONFIG_ARCH_MMP) += mfp.o -- cgit v1.2.3-70-g09d2