From 4e9f9fd5148004b983b29e15de66918e71da56c0 Mon Sep 17 00:00:00 2001 From: Herbert Valerio Riedel Date: Mon, 26 Nov 2007 18:41:02 +0100 Subject: [ARM] 4668/1: ep93xx: implement new GPIO API Implement new GPIO API for ep93xx platform as defined in Documentation/gpio.txt and provide transitional __deprecated wrappers for the previous gpio_line_* functions. Signed-off-by: Herbert Valerio Riedel Acked-by: Lennert Buytenhek Signed-off-by: Russell King --- include/asm-arm/arch-ep93xx/gpio.h | 76 +++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 10 deletions(-) (limited to 'include/asm-arm') diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h index 1ee14a14cba0..fc1e57db5fac 100644 --- a/include/asm-arm/arch-ep93xx/gpio.h +++ b/include/asm-arm/arch-ep93xx/gpio.h @@ -5,16 +5,6 @@ #ifndef __ASM_ARCH_GPIO_H #define __ASM_ARCH_GPIO_H -#define GPIO_IN 0 -#define GPIO_OUT 1 - -#define EP93XX_GPIO_LOW 0 -#define EP93XX_GPIO_HIGH 1 - -extern void gpio_line_config(int line, int direction); -extern int gpio_line_get(int line); -extern void gpio_line_set(int line, int value); - /* GPIO port A. */ #define EP93XX_GPIO_LINE_A(x) ((x) + 0) #define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) @@ -103,5 +93,71 @@ extern void gpio_line_set(int line, int value); #define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) #define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) +/* new generic GPIO API - see Documentation/gpio.txt */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ + if (gpio > EP93XX_GPIO_LINE_H(7)) + return -EINVAL; + return 0; +} + +static inline void gpio_free(unsigned gpio) +{ +} + +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); + +#include /* cansleep wrappers */ + +/* + * Map GPIO A0..A7 (0..7) to irq 64..71, + * B0..B7 (7..15) to irq 72..79, and + * F0..F7 (40..47) to irq 80..87. + */ + +static inline int gpio_to_irq(unsigned gpio) +{ + if (gpio <= EP93XX_GPIO_LINE_EGPIO15) + return 64 + gpio; + + if (gpio >= EP93XX_GPIO_LINE_F(0) && gpio <= EP93XX_GPIO_LINE_F(7)) + return 80 + (gpio - EP93XX_GPIO_LINE_F(0)); + + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + if (irq >= 64 && irq <= 79) + return irq - 64; + + if (irq >= 80 && irq <= 87) + return (irq - 80) + EP93XX_GPIO_LINE_F(0); + + return -EINVAL; +} + +/* obsolete specific GPIO API */ +#define GPIO_IN 0 +#define GPIO_OUT 1 + +#define EP93XX_GPIO_LOW 0 +#define EP93XX_GPIO_HIGH 1 + +void __deprecated gpio_line_config(int line, int direction); + +static inline int __deprecated gpio_line_get(int line) +{ + return gpio_get_value(line); +} + +static inline void __deprecated gpio_line_set(int line, int value) +{ + gpio_set_value(line, value); +} #endif -- cgit v1.2.3 From 7ca722533979d47563e75a40c86c405153818b83 Mon Sep 17 00:00:00 2001 From: Herbert Valerio Riedel Date: Mon, 26 Nov 2007 18:45:59 +0100 Subject: [ARM] 4669/1: ep93xx: simplify GPIO code and cleanups This patch renumbers the (virtual) GPIO line numbering to have all irq-capable gpio lines <= EP93XX_GPIO_LINE_MAX_IRQ by swapping the port f range with the port c range; This simplifies code such as #define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f)) or if (line >= 0 && line < 16) { /* Port A/B */ } else if (line >= 40 && line < 48) { /* Port F */ } considerably; in addition to the renumbering this patch also introduces macro constants EP93XX_GPIO_LINE_MAX_IRQ and EP93XX_GPIO_LINE_MAX, and replaces most magic numbers by those and invocations of gpio_to_irq()/irq_to_gpio(). Signed-off-by: Herbert Valerio Riedel Acked-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 147 ++++++++++++++++++------------------- include/asm-arm/arch-ep93xx/gpio.h | 27 +++---- include/asm-arm/arch-ep93xx/irqs.h | 6 -- 3 files changed, 82 insertions(+), 98 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8a7340661377..58957d7a5763 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3]; static unsigned char gpio_int_type1[3]; static unsigned char gpio_int_type2[3]; -static void update_gpio_int_params(int abf) +/* Port ordering is: A B F */ +static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; +static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; +static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; +static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c }; + +static void update_gpio_int_params(unsigned port) { - if (abf == 0) { - __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); - __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); - __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); - __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE); - } else if (abf == 1) { - __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); - __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); - __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); - __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE); - } else if (abf == 2) { - __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE); - __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2); - __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1); - __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE); - } else { - BUG(); - } -} + BUG_ON(port > 2); + __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); + + __raw_writeb(gpio_int_type2[port], + EP93XX_GPIO_REG(int_type2_register_offset[port])); + + __raw_writeb(gpio_int_type1[port], + EP93XX_GPIO_REG(int_type1_register_offset[port])); + + __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], + EP93XX_GPIO_REG(int_en_register_offset[port])); +} -static unsigned char data_register_offset[8] = { - 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, +/* Port ordering is: A B F D E C G H */ +static const u8 data_register_offset[8] = { + 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40, }; -static unsigned char data_direction_register_offset[8] = { - 0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44, +static const u8 data_direction_register_offset[8] = { + 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44, }; static void ep93xx_gpio_set_direction(unsigned line, int direction) @@ -199,14 +199,10 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction) local_irq_save(flags); if (direction == GPIO_OUT) { - if (line >= 0 && line < 16) { - /* Port A/B. */ + if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) { + /* Port A/B/F */ gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); update_gpio_int_params(line >> 3); - } else if (line >= 40 && line < 48) { - /* Port F. */ - gpio_int_unmasked[2] &= ~(1 << (line & 7)); - update_gpio_int_params(2); } v = __raw_readb(data_direction_register); @@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config); int gpio_direction_input(unsigned gpio) { - if (gpio > EP93XX_GPIO_LINE_H(7)) + if (gpio > EP93XX_GPIO_LINE_MAX) return -EINVAL; ep93xx_gpio_set_direction(gpio, GPIO_IN); @@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input); int gpio_direction_output(unsigned gpio, int value) { - if (gpio > EP93XX_GPIO_LINE_H(7)) + if (gpio > EP93XX_GPIO_LINE_MAX) return -EINVAL; gpio_set_value(gpio, value); @@ -290,47 +286,50 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); for (i = 0; i < 8; i++) { if (status & (1 << i)) { - desc = irq_desc + IRQ_EP93XX_GPIO(0) + i; - desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc); + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; + desc = irq_desc + gpio_irq; + desc_handle_irq(gpio_irq, desc); } } status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); for (i = 0; i < 8; i++) { if (status & (1 << i)) { - desc = irq_desc + IRQ_EP93XX_GPIO(8) + i; - desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc); + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; + desc = irq_desc + gpio_irq; + desc_handle_irq(gpio_irq, desc); } } } static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) { - int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4); + /* + * map discontiguous hw irq range to continous sw irq range: + * + * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) + */ + int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; desc_handle_irq(gpio_irq, irq_desc + gpio_irq); } static void ep93xx_gpio_irq_mask_ack(unsigned int irq) { - int line = irq - IRQ_EP93XX_GPIO(0); + int line = irq_to_gpio(irq); int port = line >> 3; + int port_mask = 1 << (line & 7); - gpio_int_unmasked[port] &= ~(1 << (line & 7)); + gpio_int_unmasked[port] &= ~port_mask; update_gpio_int_params(port); - if (port == 0) { - __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); - } else if (port == 1) { - __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK); - } else if (port == 2) { - __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK); - } + __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); } static void ep93xx_gpio_irq_mask(unsigned int irq) { - int line = irq - IRQ_EP93XX_GPIO(0); + int line = irq_to_gpio(irq); int port = line >> 3; gpio_int_unmasked[port] &= ~(1 << (line & 7)); @@ -339,7 +338,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq) static void ep93xx_gpio_irq_unmask(unsigned int irq) { - int line = irq - IRQ_EP93XX_GPIO(0); + int line = irq_to_gpio(irq); int port = line >> 3; gpio_int_unmasked[port] |= 1 << (line & 7); @@ -354,37 +353,30 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq) */ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) { - int port; - int line; + const int gpio = irq_to_gpio(irq); + const int port = gpio >> 3; + const int port_mask = 1 << (gpio & 7); - line = irq - IRQ_EP93XX_GPIO(0); - if (line >= 0 && line < 16) { - ep93xx_gpio_set_direction(line, GPIO_IN); - } else { - ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN); - } - - port = line >> 3; - line &= 7; + ep93xx_gpio_set_direction(gpio, GPIO_IN); if (type & IRQT_RISING) { - gpio_int_enabled[port] |= 1 << line; - gpio_int_type1[port] |= 1 << line; - gpio_int_type2[port] |= 1 << line; + gpio_int_enabled[port] |= port_mask; + gpio_int_type1[port] |= port_mask; + gpio_int_type2[port] |= port_mask; } else if (type & IRQT_FALLING) { - gpio_int_enabled[port] |= 1 << line; - gpio_int_type1[port] |= 1 << line; - gpio_int_type2[port] &= ~(1 << line); + gpio_int_enabled[port] |= port_mask; + gpio_int_type1[port] |= port_mask; + gpio_int_type2[port] &= ~port_mask; } else if (type & IRQT_HIGH) { - gpio_int_enabled[port] |= 1 << line; - gpio_int_type1[port] &= ~(1 << line); - gpio_int_type2[port] |= 1 << line; + gpio_int_enabled[port] |= port_mask; + gpio_int_type1[port] &= ~port_mask; + gpio_int_type2[port] |= port_mask; } else if (type & IRQT_LOW) { - gpio_int_enabled[port] |= 1 << line; - gpio_int_type1[port] &= ~(1 << line); - gpio_int_type2[port] &= ~(1 << line); + gpio_int_enabled[port] |= port_mask; + gpio_int_type1[port] &= ~port_mask; + gpio_int_type2[port] &= ~port_mask; } else { - gpio_int_enabled[port] &= ~(1 << line); + gpio_int_enabled[port] &= ~port_mask; } update_gpio_int_params(port); @@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = { void __init ep93xx_init_irq(void) { - int irq; + int gpio_irq; vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); - for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) { - set_irq_chip(irq, &ep93xx_gpio_irq_chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); + for (gpio_irq = gpio_to_irq(0); + gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { + set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip); + set_irq_handler(gpio_irq, handle_level_irq); + set_irq_flags(gpio_irq, IRQF_VALID); } set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h index fc1e57db5fac..cebb64be7e4b 100644 --- a/include/asm-arm/arch-ep93xx/gpio.h +++ b/include/asm-arm/arch-ep93xx/gpio.h @@ -28,7 +28,7 @@ #define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) /* GPIO port C. */ -#define EP93XX_GPIO_LINE_C(x) ((x) + 16) +#define EP93XX_GPIO_LINE_C(x) ((x) + 40) #define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) #define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) #define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) @@ -61,7 +61,7 @@ #define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) /* GPIO port F. */ -#define EP93XX_GPIO_LINE_F(x) ((x) + 40) +#define EP93XX_GPIO_LINE_F(x) ((x) + 16) #define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) #define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) #define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) @@ -93,11 +93,17 @@ #define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) #define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) +/* maximum value for gpio line identifiers */ +#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) + +/* maximum value for irq capable line identifiers */ +#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) + /* new generic GPIO API - see Documentation/gpio.txt */ static inline int gpio_request(unsigned gpio, const char *label) { - if (gpio > EP93XX_GPIO_LINE_H(7)) + if (gpio > EP93XX_GPIO_LINE_MAX) return -EINVAL; return 0; } @@ -116,29 +122,20 @@ void gpio_set_value(unsigned gpio, int value); /* * Map GPIO A0..A7 (0..7) to irq 64..71, * B0..B7 (7..15) to irq 72..79, and - * F0..F7 (40..47) to irq 80..87. + * F0..F7 (16..24) to irq 80..87. */ static inline int gpio_to_irq(unsigned gpio) { - if (gpio <= EP93XX_GPIO_LINE_EGPIO15) + if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ) return 64 + gpio; - if (gpio >= EP93XX_GPIO_LINE_F(0) && gpio <= EP93XX_GPIO_LINE_F(7)) - return 80 + (gpio - EP93XX_GPIO_LINE_F(0)); - return -EINVAL; } static inline int irq_to_gpio(unsigned irq) { - if (irq >= 64 && irq <= 79) - return irq - 64; - - if (irq >= 80 && irq <= 87) - return (irq - 80) + EP93XX_GPIO_LINE_F(0); - - return -EINVAL; + return irq - gpio_to_irq(0); } /* obsolete specific GPIO API */ diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h index 2a8c63638c5e..53d4a68bfc88 100644 --- a/include/asm-arm/arch-ep93xx/irqs.h +++ b/include/asm-arm/arch-ep93xx/irqs.h @@ -67,12 +67,6 @@ #define IRQ_EP93XX_SAI 60 #define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff -/* - * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and - * F0..F7 to 80..87. - */ -#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f)) - #define NR_EP93XX_IRQS (64 + 24) #define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) -- cgit v1.2.3 From 6331acd78f7916db16ec20b50d7838bd4944cd27 Mon Sep 17 00:00:00 2001 From: Herbert Valerio Riedel Date: Mon, 26 Nov 2007 18:50:42 +0100 Subject: [ARM] 4671/1: ep93xx: remove obsolete gpio_line_* operations With the new GPIO methods in place the old gpio_line_* methods are redundant, so this patch finally removes the old legacy gpio_line_* wrappers. Signed-off-by: Herbert Valerio Riedel Acked-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 9 +++------ include/asm-arm/arch-ep93xx/gpio.h | 19 ------------------- 2 files changed, 3 insertions(+), 25 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 2788da06417c..4cb3f742a6a1 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -189,6 +189,9 @@ static const u8 data_direction_register_offset[8] = { 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44, }; +#define GPIO_IN 0 +#define GPIO_OUT 1 + static void ep93xx_gpio_set_direction(unsigned line, int direction) { unsigned int data_direction_register; @@ -217,12 +220,6 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction) local_irq_restore(flags); } -void __deprecated gpio_line_config(int line, int direction) -{ - ep93xx_gpio_set_direction(line, direction); -} -EXPORT_SYMBOL(gpio_line_config); - int gpio_direction_input(unsigned gpio) { if (gpio > EP93XX_GPIO_LINE_MAX) diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h index cebb64be7e4b..9b1864bbd9a8 100644 --- a/include/asm-arm/arch-ep93xx/gpio.h +++ b/include/asm-arm/arch-ep93xx/gpio.h @@ -138,23 +138,4 @@ static inline int irq_to_gpio(unsigned irq) return irq - gpio_to_irq(0); } -/* obsolete specific GPIO API */ -#define GPIO_IN 0 -#define GPIO_OUT 1 - -#define EP93XX_GPIO_LOW 0 -#define EP93XX_GPIO_HIGH 1 - -void __deprecated gpio_line_config(int line, int direction); - -static inline int __deprecated gpio_line_get(int line) -{ - return gpio_get_value(line); -} - -static inline void __deprecated gpio_line_set(int line, int value) -{ - gpio_set_value(line, value); -} - #endif -- cgit v1.2.3 From 20118ff97823822bf4d52ccb528ce2b5042c3057 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 15 Oct 2007 14:27:41 +0100 Subject: [ARM] 4603/1: KS8695: debugfs interface to view pin state This patch adds a debug interface (if CONFIG_DEBUG_FS is selected) to display the basic configuration and current state of the GPIO pins on the Kendin/Micrel KS8695 processor. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-ks8695/gpio.c | 83 +++++++++++++++++++++++++++++++++ include/asm-arm/arch-ks8695/regs-gpio.h | 2 + 2 files changed, 85 insertions(+) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c index b1aa3cb3d4a3..5e46191c0af9 100644 --- a/arch/arm/mach-ks8695/gpio.c +++ b/arch/arm/mach-ks8695/gpio.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -216,3 +218,84 @@ int irq_to_gpio(unsigned int irq) return (irq - KS8695_IRQ_EXTERN0); } EXPORT_SYMBOL(irq_to_gpio); + + +/* .... Debug interface ..................................................... */ + +#ifdef CONFIG_DEBUG_FS + +static int ks8695_gpio_show(struct seq_file *s, void *unused) +{ + unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; + unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; + unsigned long mode, ctrl, data; + int i; + + mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); + data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + + seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); + + for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { + seq_printf(s, "%i:\t", i); + + seq_printf(s, "%s\t", (mode & IOPM_(i)) ? "Output" : "Input"); + + if (i <= KS8695_GPIO_3) { + if (ctrl & enable[i]) { + seq_printf(s, "EXT%i ", i); + + switch ((ctrl & intmask[i]) >> (4 * i)) { + case IOPC_TM_LOW: + seq_printf(s, "(Low)"); break; + case IOPC_TM_HIGH: + seq_printf(s, "(High)"); break; + case IOPC_TM_RISING: + seq_printf(s, "(Rising)"); break; + case IOPC_TM_FALLING: + seq_printf(s, "(Falling)"); break; + case IOPC_TM_EDGE: + seq_printf(s, "(Edges)"); break; + } + } + else + seq_printf(s, "GPIO\t"); + } + else if (i <= KS8695_GPIO_5) { + if (ctrl & enable[i]) + seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); + else + seq_printf(s, "GPIO\t"); + } + else + seq_printf(s, "GPIO\t"); + + seq_printf(s, "\t"); + + seq_printf(s, "%i\n", (data & IOPD_(i)) ? 1 : 0); + } + return 0; +} + +static int ks8695_gpio_open(struct inode *inode, struct file *file) +{ + return single_open(file, ks8695_gpio_show, NULL); +} + +static const struct file_operations ks8695_gpio_operations = { + .open = ks8695_gpio_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init ks8695_gpio_debugfs_init(void) +{ + /* /sys/kernel/debug/ks8695_gpio */ + (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations); + return 0; +} +postcore_initcall(ks8695_gpio_debugfs_init); + +#endif diff --git a/include/asm-arm/arch-ks8695/regs-gpio.h b/include/asm-arm/arch-ks8695/regs-gpio.h index 57fcf9fc82e4..6b95d77aea19 100644 --- a/include/asm-arm/arch-ks8695/regs-gpio.h +++ b/include/asm-arm/arch-ks8695/regs-gpio.h @@ -49,5 +49,7 @@ #define IOPC_TM_FALLING (4) /* Falling Edge Detection */ #define IOPC_TM_EDGE (6) /* Both Edge Detection */ +/* Port Data Register */ +#define IOPD_(x) (1 << (x)) /* Signal Level of GPIO Pin x */ #endif -- cgit v1.2.3 From 3042102a28501510a409fe86962f20369e325cf2 Mon Sep 17 00:00:00 2001 From: Brian Swetland Date: Mon, 26 Nov 2007 04:11:43 -0800 Subject: [ARM] msm: core platform support for ARCH_MSM7X00A - core header files for arch-msm - Kconfig and Makefiles to enable ARCH_MSM7X00A builds - MSM7X00A specific arch_idle - peripheral iomap and irq number definitions Signed-off-by: Brian Swetland --- arch/arm/Kconfig | 11 ++++ arch/arm/Makefile | 1 + arch/arm/mach-msm/Makefile | 2 + arch/arm/mach-msm/Makefile.boot | 3 + arch/arm/mach-msm/idle.S | 36 ++++++++++++ arch/arm/mach-msm/io.c | 85 +++++++++++++++++++++++++++ arch/arm/mm/Kconfig | 3 +- include/asm-arm/arch-msm/board.h | 37 ++++++++++++ include/asm-arm/arch-msm/debug-macro.S | 40 +++++++++++++ include/asm-arm/arch-msm/dma.h | 1 + include/asm-arm/arch-msm/entry-macro.S | 38 ++++++++++++ include/asm-arm/arch-msm/hardware.h | 18 ++++++ include/asm-arm/arch-msm/io.h | 33 +++++++++++ include/asm-arm/arch-msm/irqs.h | 89 ++++++++++++++++++++++++++++ include/asm-arm/arch-msm/memory.h | 27 +++++++++ include/asm-arm/arch-msm/msm_iomap.h | 104 +++++++++++++++++++++++++++++++++ include/asm-arm/arch-msm/system.h | 23 ++++++++ include/asm-arm/arch-msm/timex.h | 20 +++++++ include/asm-arm/arch-msm/uncompress.h | 36 ++++++++++++ include/asm-arm/arch-msm/vmalloc.h | 22 +++++++ 20 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-msm/Makefile create mode 100644 arch/arm/mach-msm/Makefile.boot create mode 100644 arch/arm/mach-msm/idle.S create mode 100644 arch/arm/mach-msm/io.c create mode 100644 include/asm-arm/arch-msm/board.h create mode 100644 include/asm-arm/arch-msm/debug-macro.S create mode 100644 include/asm-arm/arch-msm/dma.h create mode 100644 include/asm-arm/arch-msm/entry-macro.S create mode 100644 include/asm-arm/arch-msm/hardware.h create mode 100644 include/asm-arm/arch-msm/io.h create mode 100644 include/asm-arm/arch-msm/irqs.h create mode 100644 include/asm-arm/arch-msm/memory.h create mode 100644 include/asm-arm/arch-msm/msm_iomap.h create mode 100644 include/asm-arm/arch-msm/system.h create mode 100644 include/asm-arm/arch-msm/timex.h create mode 100644 include/asm-arm/arch-msm/uncompress.h create mode 100644 include/asm-arm/arch-msm/vmalloc.h (limited to 'include/asm-arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a04f507e7f2c..89c3811132c2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -409,6 +409,17 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1 and OMAP2). +config ARCH_MSM7X00A + bool "Qualcomm MSM7X00A" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + help + Support for Qualcomm MSM7X00A based systems. This runs on the ARM11 + apps processor of the MSM7X00A and depends on a shared memory + interface to the ARM9 modem processor which runs the baseband stack + and controls some vital subsystems (clock and power control, etc). + + endchoice source "arch/arm/mach-clps711x/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 35e56c99ad1d..dd220d189843 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -139,6 +139,7 @@ endif machine-$(CONFIG_ARCH_KS8695) := ks8695 incdir-$(CONFIG_ARCH_MXC) := mxc machine-$(CONFIG_ARCH_MX3) := mx3 + machine-$(CONFIG_ARCH_MSM7X00A) := msm ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile new file mode 100644 index 000000000000..feb9e469df9a --- /dev/null +++ b/arch/arm/mach-msm/Makefile @@ -0,0 +1,2 @@ +obj-y += io.o idle.o + diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot new file mode 100644 index 000000000000..24dfbf8c07c4 --- /dev/null +++ b/arch/arm/mach-msm/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x10008000 +params_phys-y := 0x10000100 +initrd_phys-y := 0x10800000 diff --git a/arch/arm/mach-msm/idle.S b/arch/arm/mach-msm/idle.S new file mode 100644 index 000000000000..2b1cb7f16943 --- /dev/null +++ b/arch/arm/mach-msm/idle.S @@ -0,0 +1,36 @@ +/* linux/include/asm-arm/arch-msm/idle.S + * + * Idle processing for MSM7K - work around bugs with SWFI. + * + * Copyright (c) 2007 QUALCOMM Incorporated. + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include + +ENTRY(arch_idle) +#ifdef CONFIG_MSM7X00A_IDLE + mrc p15, 0, r1, c1, c0, 0 /* read current CR */ + bic r0, r1, #(1 << 2) /* clear dcache bit */ + bic r0, r0, #(1 << 12) /* clear icache bit */ + mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */ + + mov r0, #0 /* prepare wfi value */ + mcr p15, 0, r0, c7, c10, 0 /* flush the cache */ + mcr p15, 0, r0, c7, c10, 4 /* memory barrier */ + mcr p15, 0, r0, c7, c0, 4 /* wait for interrupt */ + + mcr p15, 0, r1, c1, c0, 0 /* restore d/i cache */ +#endif + mov pc, lr diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c new file mode 100644 index 000000000000..c39edb994a88 --- /dev/null +++ b/arch/arm/mach-msm/io.c @@ -0,0 +1,85 @@ +/* arch/arm/mach-msm/io.c + * + * MSM7K io support + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define MSM_DEVICE(name) { \ + .virtual = MSM_##name##_BASE, \ + .pfn = __phys_to_pfn(MSM_##name##_PHYS), \ + .length = MSM_##name##_SIZE, \ + .type = MT_DEVICE_NONSHARED, \ + } + +static struct map_desc msm_io_desc[] __initdata = { + MSM_DEVICE(VIC), + MSM_DEVICE(CSR), + MSM_DEVICE(GPT), + MSM_DEVICE(DMOV), + MSM_DEVICE(UART1), + MSM_DEVICE(UART2), + MSM_DEVICE(UART3), + MSM_DEVICE(I2C), + MSM_DEVICE(GPIO1), + MSM_DEVICE(GPIO2), + MSM_DEVICE(HSUSB), + MSM_DEVICE(CLK_CTL), + MSM_DEVICE(PMDH), + MSM_DEVICE(EMDH), + MSM_DEVICE(MDP), + { + .virtual = MSM_SHARED_RAM_BASE, + .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS), + .length = MSM_SHARED_RAM_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init msm_map_common_io(void) +{ + /* Make sure the peripheral register window is closed, since + * we will use PTE flags (TEX[1]=1,B=0,C=1) to determine which + * pages are peripheral interface or not. + */ + asm("mcr p15, 0, %0, c15, c2, 4" : : "r" (0)); + + iotable_init(msm_io_desc, ARRAY_SIZE(msm_io_desc)); +} + +void __iomem * +__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) +{ + if (mtype == MT_DEVICE) { + /* The peripherals in the 88000000 - D0000000 range + * are only accessable by type MT_DEVICE_NONSHARED. + * Adjust mtype as necessary to make this "just work." + */ + if ((phys_addr >= 0x88000000) && (phys_addr < 0xD0000000)) + mtype = MT_DEVICE_NONSHARED; + } + + return __arm_ioremap(phys_addr, size, mtype); +} diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 7868f4dc1d00..bc2ca3c03a48 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -345,8 +345,9 @@ config CPU_XSC3 # ARMv6 config CPU_V6 bool "Support ARM V6 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 + depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM7X00A default y if ARCH_MX3 + default y if ARCH_MSM7X00A select CPU_32v6 select CPU_ABRT_EV6 select CPU_CACHE_V6 diff --git a/include/asm-arm/arch-msm/board.h b/include/asm-arm/arch-msm/board.h new file mode 100644 index 000000000000..763051f8ba14 --- /dev/null +++ b/include/asm-arm/arch-msm/board.h @@ -0,0 +1,37 @@ +/* linux/include/asm-arm/arch-msm/board.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_BOARD_H +#define __ASM_ARCH_MSM_BOARD_H + +#include + +/* platform device data structures */ + +struct msm_mddi_platform_data +{ + void (*panel_power)(int on); + unsigned has_vsync_irq:1; +}; + +/* common init routines for use by arch/arm/mach-msm/board-*.c */ + +void __init msm_add_devices(void); +void __init msm_map_common_io(void); +void __init msm_init_irq(void); +void __init msm_init_gpio(void); + +#endif diff --git a/include/asm-arm/arch-msm/debug-macro.S b/include/asm-arm/arch-msm/debug-macro.S new file mode 100644 index 000000000000..393d5272e506 --- /dev/null +++ b/include/asm-arm/arch-msm/debug-macro.S @@ -0,0 +1,40 @@ +/* include/asm-arm/arch-msm7200/debug-macro.S + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include + + .macro addruart,rx + @ see if the MMU is enabled and select appropriate base address + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, =MSM_UART1_PHYS + ldrne \rx, =MSM_UART1_BASE + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x0C] + .endm + + .macro waituart,rd,rx + @ wait for TX_READY +1: ldr \rd, [\rx, #0x08] + tst \rd, #0x04 + beq 1b + .endm + + .macro busyuart,rd,rx + .endm diff --git a/include/asm-arm/arch-msm/dma.h b/include/asm-arm/arch-msm/dma.h new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/include/asm-arm/arch-msm/dma.h @@ -0,0 +1 @@ + diff --git a/include/asm-arm/arch-msm/entry-macro.S b/include/asm-arm/arch-msm/entry-macro.S new file mode 100644 index 000000000000..ee24aece4cb0 --- /dev/null +++ b/include/asm-arm/arch-msm/entry-macro.S @@ -0,0 +1,38 @@ +/* include/asm-arm/arch-msm7200/entry-macro.S + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + @ enable imprecise aborts + cpsie a + mov \base, #MSM_VIC_BASE + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + @ 0xD0 has irq# or old irq# if the irq has been handled + @ 0xD4 has irq# or -1 if none pending *but* if you just + @ read 0xD4 you never get the first irq for some reason + ldr \irqnr, [\base, #0xD0] + ldr \irqnr, [\base, #0xD4] + cmp \irqnr, #0xffffffff + .endm diff --git a/include/asm-arm/arch-msm/hardware.h b/include/asm-arm/arch-msm/hardware.h new file mode 100644 index 000000000000..89af2b70182f --- /dev/null +++ b/include/asm-arm/arch-msm/hardware.h @@ -0,0 +1,18 @@ +/* linux/include/asm-arm/arch-msm/hardware.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_HARDWARE_H + +#endif diff --git a/include/asm-arm/arch-msm/io.h b/include/asm-arm/arch-msm/io.h new file mode 100644 index 000000000000..4645ae26b62a --- /dev/null +++ b/include/asm-arm/arch-msm/io.h @@ -0,0 +1,33 @@ +/* include/asm-arm/arch-msm/io.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __arch_ioremap __msm_ioremap +#define __arch_iounmap __iounmap + +void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype); + +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)addr; +} +#define __io(a) __io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/include/asm-arm/arch-msm/irqs.h b/include/asm-arm/arch-msm/irqs.h new file mode 100644 index 000000000000..565430cfaa7e --- /dev/null +++ b/include/asm-arm/arch-msm/irqs.h @@ -0,0 +1,89 @@ +/* linux/include/asm-arm/arch-msm/irqs.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_IRQS_H + +/* MSM ARM11 Interrupt Numbers */ +/* See 80-VE113-1 A, pp219-221 */ + +#define INT_A9_M2A_0 0 +#define INT_A9_M2A_1 1 +#define INT_A9_M2A_2 2 +#define INT_A9_M2A_3 3 +#define INT_A9_M2A_4 4 +#define INT_A9_M2A_5 5 +#define INT_A9_M2A_6 6 +#define INT_GP_TIMER_EXP 7 +#define INT_DEBUG_TIMER_EXP 8 +#define INT_UART1 9 +#define INT_UART2 10 +#define INT_UART3 11 +#define INT_UART1_RX 12 +#define INT_UART2_RX 13 +#define INT_UART3_RX 14 +#define INT_USB_OTG 15 +#define INT_MDDI_PRI 16 +#define INT_MDDI_EXT 17 +#define INT_MDDI_CLIENT 18 +#define INT_MDP 19 +#define INT_GRAPHICS 20 +#define INT_ADM_AARM 21 +#define INT_ADSP_A11 22 +#define INT_ADSP_A9_A11 23 +#define INT_SDC1_0 24 +#define INT_SDC1_1 25 +#define INT_SDC2_0 26 +#define INT_SDC2_1 27 +#define INT_KEYSENSE 28 +#define INT_TCHSCRN_SSBI 29 +#define INT_TCHSCRN1 30 +#define INT_TCHSCRN2 31 + +#define INT_GPIO_GROUP1 (32 + 0) +#define INT_GPIO_GROUP2 (32 + 1) +#define INT_PWB_I2C (32 + 2) +#define INT_SOFTRESET (32 + 3) +#define INT_NAND_WR_ER_DONE (32 + 4) +#define INT_NAND_OP_DONE (32 + 5) +#define INT_PBUS_ARM11 (32 + 6) +#define INT_AXI_MPU_SMI (32 + 7) +#define INT_AXI_MPU_EBI1 (32 + 8) +#define INT_AD_HSSD (32 + 9) +#define INT_ARM11_PMU (32 + 10) +#define INT_ARM11_DMA (32 + 11) +#define INT_TSIF_IRQ (32 + 12) +#define INT_UART1DM_IRQ (32 + 13) +#define INT_UART1DM_RX (32 + 14) +#define INT_USB_HS (32 + 15) +#define INT_SDC3_0 (32 + 16) +#define INT_SDC3_1 (32 + 17) +#define INT_SDC4_0 (32 + 18) +#define INT_SDC4_1 (32 + 19) +#define INT_UART2DM_RX (32 + 20) +#define INT_UART2DM_IRQ (32 + 21) + +/* 22-31 are reserved */ + +#define MSM_IRQ_BIT(irq) (1 << ((irq) & 31)) + +#define NR_MSM_IRQS 64 +#define NR_GPIO_IRQS 122 +#define NR_BOARD_IRQS 64 +#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS) + +#define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n)) + +#endif diff --git a/include/asm-arm/arch-msm/memory.h b/include/asm-arm/arch-msm/memory.h new file mode 100644 index 000000000000..b5ce0e9ac86d --- /dev/null +++ b/include/asm-arm/arch-msm/memory.h @@ -0,0 +1,27 @@ +/* linux/include/asm-arm/arch-msm/memory.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* physical offset of RAM */ +#define PHYS_OFFSET UL(0x10000000) + +/* bus address and physical addresses are identical */ +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif + diff --git a/include/asm-arm/arch-msm/msm_iomap.h b/include/asm-arm/arch-msm/msm_iomap.h new file mode 100644 index 000000000000..b8955cc26fec --- /dev/null +++ b/include/asm-arm/arch-msm/msm_iomap.h @@ -0,0 +1,104 @@ +/* linux/include/asm-arm/arch-msm/msm_iomap.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_H +#define __ASM_ARCH_MSM_IOMAP_H + +#include + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM_VIC_BASE 0xE0000000 +#define MSM_VIC_PHYS 0xC0000000 +#define MSM_VIC_SIZE SZ_4K + +#define MSM_CSR_BASE 0xE0001000 +#define MSM_CSR_PHYS 0xC0100000 +#define MSM_CSR_SIZE SZ_4K + +#define MSM_GPT_PHYS MSM_CSR_PHYS +#define MSM_GPT_BASE MSM_CSR_BASE +#define MSM_GPT_SIZE SZ_4K + +#define MSM_DMOV_BASE 0xE0002000 +#define MSM_DMOV_PHYS 0xA9700000 +#define MSM_DMOV_SIZE SZ_4K + +#define MSM_UART1_BASE 0xE0003000 +#define MSM_UART1_PHYS 0xA9A00000 +#define MSM_UART1_SIZE SZ_4K + +#define MSM_UART2_BASE 0xE0004000 +#define MSM_UART2_PHYS 0xA9B00000 +#define MSM_UART2_SIZE SZ_4K + +#define MSM_UART3_BASE 0xE0005000 +#define MSM_UART3_PHYS 0xA9C00000 +#define MSM_UART3_SIZE SZ_4K + +#define MSM_I2C_BASE 0xE0006000 +#define MSM_I2C_PHYS 0xA9900000 +#define MSM_I2C_SIZE SZ_4K + +#define MSM_GPIO1_BASE 0xE0007000 +#define MSM_GPIO1_PHYS 0xA9200000 +#define MSM_GPIO1_SIZE SZ_4K + +#define MSM_GPIO2_BASE 0xE0008000 +#define MSM_GPIO2_PHYS 0xA9300000 +#define MSM_GPIO2_SIZE SZ_4K + +#define MSM_HSUSB_BASE 0xE0009000 +#define MSM_HSUSB_PHYS 0xA0800000 +#define MSM_HSUSB_SIZE SZ_4K + +#define MSM_CLK_CTL_BASE 0xE000A000 +#define MSM_CLK_CTL_PHYS 0xA8600000 +#define MSM_CLK_CTL_SIZE SZ_4K + +#define MSM_PMDH_BASE 0xE000B000 +#define MSM_PMDH_PHYS 0xAA600000 +#define MSM_PMDH_SIZE SZ_4K + +#define MSM_EMDH_BASE 0xE000C000 +#define MSM_EMDH_PHYS 0xAA700000 +#define MSM_EMDH_SIZE SZ_4K + +#define MSM_MDP_BASE 0xE0010000 +#define MSM_MDP_PHYS 0xAA200000 +#define MSM_MDP_SIZE 0x000F0000 + +#define MSM_SHARED_RAM_BASE 0xE0100000 +#define MSM_SHARED_RAM_PHYS 0x01F00000 +#define MSM_SHARED_RAM_SIZE SZ_1M + +#endif diff --git a/include/asm-arm/arch-msm/system.h b/include/asm-arm/arch-msm/system.h new file mode 100644 index 000000000000..7c5544bdd0c7 --- /dev/null +++ b/include/asm-arm/arch-msm/system.h @@ -0,0 +1,23 @@ +/* linux/include/asm-arm/arch-msm/system.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +void arch_idle(void); + +static inline void arch_reset(char mode) +{ + for (;;) ; /* depends on IPC w/ other core */ +} diff --git a/include/asm-arm/arch-msm/timex.h b/include/asm-arm/arch-msm/timex.h new file mode 100644 index 000000000000..154b23fb3599 --- /dev/null +++ b/include/asm-arm/arch-msm/timex.h @@ -0,0 +1,20 @@ +/* linux/include/asm-arm/arch-msm/timex.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_TIMEX_H + +#define CLOCK_TICK_RATE 1000000 + +#endif diff --git a/include/asm-arm/arch-msm/uncompress.h b/include/asm-arm/arch-msm/uncompress.h new file mode 100644 index 000000000000..e91ed786ffec --- /dev/null +++ b/include/asm-arm/arch-msm/uncompress.h @@ -0,0 +1,36 @@ +/* linux/include/asm-arm/arch-msm/uncompress.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_UNCOMPRESS_H + +#include "hardware.h" + +static void putc(int c) +{ +} + +static inline void flush(void) +{ +} + +static inline void arch_decomp_setup(void) +{ +} + +static inline void arch_decomp_wdog(void) +{ +} + +#endif diff --git a/include/asm-arm/arch-msm/vmalloc.h b/include/asm-arm/arch-msm/vmalloc.h new file mode 100644 index 000000000000..60f8d910e825 --- /dev/null +++ b/include/asm-arm/arch-msm/vmalloc.h @@ -0,0 +1,22 @@ +/* linux/include/asm-arm/arch-msm/vmalloc.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_VMALLOC_H +#define __ASM_ARCH_MSM_VMALLOC_H + +#define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#endif + -- cgit v1.2.3 From bfe645adf1a79b873b528556523abb46f281a5dc Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Mon, 26 Nov 2007 04:12:29 -0800 Subject: [ARM] msm: dma support for MSM7X00A Signed-off-by: Brian Swetland --- arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/dma.c | 214 +++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-msm/dma.h | 150 +++++++++++++++++++++++++++++ 3 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-msm/dma.c (limited to 'include/asm-arm') diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index fcca853d6485..d12f23655850 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -1,4 +1,4 @@ -obj-y += io.o idle.o irq.o timer.o +obj-y += io.o idle.o irq.o timer.o dma.o # Common code for board init obj-y += common.o diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c new file mode 100644 index 000000000000..8b0f339b3274 --- /dev/null +++ b/arch/arm/mach-msm/dma.c @@ -0,0 +1,214 @@ +/* linux/arch/arm/mach-msm/dma.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +#define MSM_DMOV_CHANNEL_COUNT 16 + +enum { + MSM_DMOV_PRINT_ERRORS = 1, + MSM_DMOV_PRINT_IO = 2, + MSM_DMOV_PRINT_FLOW = 4 +}; + +static DEFINE_SPINLOCK(msm_dmov_lock); +static struct msm_dmov_cmd active_command; +static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; +static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; +unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS; + +#define MSM_DMOV_DPRINTF(mask, format, args...) \ + do { \ + if ((mask) & msm_dmov_print_mask) \ + printk(KERN_ERR format, args); \ + } while (0) +#define PRINT_ERROR(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_ERRORS, format, args); +#define PRINT_IO(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_IO, format, args); +#define PRINT_FLOW(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args); + +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) +{ + unsigned long irq_flags; + unsigned int status; + + spin_lock_irqsave(&msm_dmov_lock, irq_flags); + status = readl(DMOV_STATUS(id)); + if (list_empty(&ready_commands[id]) && + (status & DMOV_STATUS_CMD_PTR_RDY)) { +#if 0 + if (list_empty(&active_commands[id])) { + PRINT_FLOW("msm_dmov_enqueue_cmd(%d), enable interrupt\n", id); + writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id)); + } +#endif + PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status); + list_add_tail(&cmd->list, &active_commands[id]); + writel(cmd->cmdptr, DMOV_CMD_PTR(id)); + } else { + if (list_empty(&active_commands[id])) + PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status); + + PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status %x\n", id, status); + list_add_tail(&cmd->list, &ready_commands[id]); + } + spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); +} + +struct msm_dmov_exec_cmdptr_cmd { + struct msm_dmov_cmd dmov_cmd; + struct completion complete; + unsigned id; + unsigned int result; + unsigned int flush[6]; +}; + +static void dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, unsigned int result) +{ + struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd); + cmd->result = result; + if (result != 0x80000002) { + cmd->flush[0] = readl(DMOV_FLUSH0(cmd->id)); + cmd->flush[1] = readl(DMOV_FLUSH1(cmd->id)); + cmd->flush[2] = readl(DMOV_FLUSH2(cmd->id)); + cmd->flush[3] = readl(DMOV_FLUSH3(cmd->id)); + cmd->flush[4] = readl(DMOV_FLUSH4(cmd->id)); + cmd->flush[5] = readl(DMOV_FLUSH5(cmd->id)); + } + complete(&cmd->complete); +} + +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) +{ + struct msm_dmov_exec_cmdptr_cmd cmd; + + PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr); + + cmd.dmov_cmd.cmdptr = cmdptr; + cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func; + cmd.id = id; + init_completion(&cmd.complete); + + msm_dmov_enqueue_cmd(id, &cmd.dmov_cmd); + wait_for_completion(&cmd.complete); + + if (cmd.result != 0x80000002) { + PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result); + PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n", + id, cmd.flush[0], cmd.flush[1], cmd.flush[2], cmd.flush[3]); + return -EIO; + } + PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr); + return 0; +} + + +static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id) +{ + unsigned int int_status, mask, id; + unsigned long irq_flags; + unsigned int ch_status; + unsigned int ch_result; + struct msm_dmov_cmd *cmd; + + spin_lock_irqsave(&msm_dmov_lock, irq_flags); + + int_status = readl(DMOV_ISR); /* read and clear interrupt */ + PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status); + + while (int_status) { + mask = int_status & -int_status; + id = fls(mask) - 1; + PRINT_FLOW("msm_datamover_irq_handler %08x %08x id %d\n", int_status, mask, id); + int_status &= ~mask; + ch_status = readl(DMOV_STATUS(id)); + if (!(ch_status & DMOV_STATUS_RSLT_VALID)) { + PRINT_FLOW("msm_datamover_irq_handler id %d, result not valid %x\n", id, ch_status); + continue; + } + do { + ch_result = readl(DMOV_RSLT(id)); + if (list_empty(&active_commands[id])) { + PRINT_ERROR("msm_datamover_irq_handler id %d, got result " + "with no active command, status %x, result %x\n", + id, ch_status, ch_result); + cmd = NULL; + } else + cmd = list_entry(active_commands[id].next, typeof(*cmd), list); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x, result %x\n", id, ch_status, ch_result); + if (ch_result & DMOV_RSLT_DONE) { + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", + id, ch_status); + PRINT_IO("msm_datamover_irq_handler id %d, got result " + "for %p, result %x\n", id, cmd, ch_result); + if (cmd) { + list_del(&cmd->list); + cmd->complete_func(cmd, ch_result); + } + } + if (ch_result & DMOV_RSLT_FLUSH) { + unsigned int flush0 = readl(DMOV_FLUSH0(id)); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, flush0); + if (cmd) { + list_del(&cmd->list); + cmd->complete_func(cmd, ch_result); + } + } + if (ch_result & DMOV_RSLT_ERROR) { + unsigned int flush0 = readl(DMOV_FLUSH0(id)); + PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, flush0); + if (cmd) { + list_del(&cmd->list); + cmd->complete_func(cmd, ch_result); + } + /* this does not seem to work, once we get an error */ + /* the datamover will no longer accept commands */ + writel(0, DMOV_FLUSH0(id)); + } + ch_status = readl(DMOV_STATUS(id)); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) && !list_empty(&ready_commands[id])) { + cmd = list_entry(ready_commands[id].next, typeof(*cmd), list); + list_del(&cmd->list); + list_add_tail(&cmd->list, &active_commands[id]); + PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id); + writel(cmd->cmdptr, DMOV_CMD_PTR(id)); + } + } while (ch_status & DMOV_STATUS_RSLT_VALID); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + } + spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); + return IRQ_HANDLED; +} + +static int __init msm_init_datamover(void) +{ + int i; + for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { + INIT_LIST_HEAD(&ready_commands[i]); + INIT_LIST_HEAD(&active_commands[i]); + writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i)); + } + return request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); +} + +arch_initcall(msm_init_datamover); + diff --git a/include/asm-arm/arch-msm/dma.h b/include/asm-arm/arch-msm/dma.h index 8b137891791f..e4b565b27b35 100644 --- a/include/asm-arm/arch-msm/dma.h +++ b/include/asm-arm/arch-msm/dma.h @@ -1 +1,151 @@ +/* linux/include/asm-arm/arch-msm/dma.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __ASM_ARCH_MSM_DMA_H + +#include +#include + +struct msm_dmov_cmd { + struct list_head list; + unsigned int cmdptr; + void (*complete_func)(struct msm_dmov_cmd *cmd, unsigned int result); +/* void (*user_result_func)(struct msm_dmov_cmd *cmd); */ +}; + +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); +void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd); +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); +/* int msm_dmov_exec_cmd_etc(unsigned id, unsigned int cmdptr, int timeout, int interruptible); */ + + + +#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2)) +#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2)) +#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2)) +#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2)) + +/* only security domain 3 is available to the ARM11 + * SD0 -> mARM trusted, SD1 -> mARM nontrusted, SD2 -> aDSP, SD3 -> aARM + */ + +#define DMOV_CMD_PTR(ch) DMOV_SD3(0x000, ch) +#define DMOV_CMD_LIST (0 << 29) /* does not work */ +#define DMOV_CMD_PTR_LIST (1 << 29) /* works */ +#define DMOV_CMD_INPUT_CFG (2 << 29) /* untested */ +#define DMOV_CMD_OUTPUT_CFG (3 << 29) /* untested */ +#define DMOV_CMD_ADDR(addr) ((addr) >> 3) + +#define DMOV_RSLT(ch) DMOV_SD3(0x040, ch) +#define DMOV_RSLT_VALID (1 << 31) /* 0 == host has empties result fifo */ +#define DMOV_RSLT_ERROR (1 << 3) +#define DMOV_RSLT_FLUSH (1 << 2) +#define DMOV_RSLT_DONE (1 << 1) /* top pointer done */ +#define DMOV_RSLT_USER (1 << 0) /* command with FR force result */ + +#define DMOV_FLUSH0(ch) DMOV_SD3(0x080, ch) +#define DMOV_FLUSH1(ch) DMOV_SD3(0x0C0, ch) +#define DMOV_FLUSH2(ch) DMOV_SD3(0x100, ch) +#define DMOV_FLUSH3(ch) DMOV_SD3(0x140, ch) +#define DMOV_FLUSH4(ch) DMOV_SD3(0x180, ch) +#define DMOV_FLUSH5(ch) DMOV_SD3(0x1C0, ch) + +#define DMOV_STATUS(ch) DMOV_SD3(0x200, ch) +#define DMOV_STATUS_RSLT_COUNT(n) (((n) >> 29)) +#define DMOV_STATUS_CMD_COUNT(n) (((n) >> 27) & 3) +#define DMOV_STATUS_RSLT_VALID (1 << 1) +#define DMOV_STATUS_CMD_PTR_RDY (1 << 0) + +#define DMOV_ISR DMOV_SD3(0x380, 0) + +#define DMOV_CONFIG(ch) DMOV_SD3(0x300, ch) +#define DMOV_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2) +#define DMOV_CONFIG_FORCE_FLUSH_RSLT (1 << 1) +#define DMOV_CONFIG_IRQ_EN (1 << 0) + +/* channel assignments */ + +#define DMOV_NAND_CHAN 7 +#define DMOV_NAND_CRCI_CMD 5 +#define DMOV_NAND_CRCI_DATA 4 + +#define DMOV_SDC1_CHAN 8 +#define DMOV_SDC1_CRCI 6 + +#define DMOV_SDC2_CHAN 8 +#define DMOV_SDC2_CRCI 7 + +#define DMOV_TSIF_CHAN 10 +#define DMOV_TSIF_CRCI 10 + +#define DMOV_USB_CHAN 11 + +/* no client rate control ifc (eg, ram) */ +#define DMOV_NONE_CRCI 0 + + +/* If the CMD_PTR register has CMD_PTR_LIST selected, the data mover + * is going to walk a list of 32bit pointers as described below. Each + * pointer points to a *array* of dmov_s, etc structs. The last pointer + * in the list is marked with CMD_PTR_LP. The last struct in each array + * is marked with CMD_LC (see below). + */ +#define CMD_PTR_ADDR(addr) ((addr) >> 3) +#define CMD_PTR_LP (1 << 31) /* last pointer */ +#define CMD_PTR_PT (3 << 29) /* ? */ + +/* Single Item Mode */ +typedef struct { + unsigned cmd; + unsigned src; + unsigned dst; + unsigned len; +} dmov_s; + +/* Scatter/Gather Mode */ +typedef struct { + unsigned cmd; + unsigned src_dscr; + unsigned dst_dscr; + unsigned _reserved; +} dmov_sg; + +/* bits for the cmd field of the above structures */ + +#define CMD_LC (1 << 31) /* last command */ +#define CMD_FR (1 << 22) /* force result -- does not work? */ +#define CMD_OCU (1 << 21) /* other channel unblock */ +#define CMD_OCB (1 << 20) /* other channel block */ +#define CMD_TCB (1 << 19) /* ? */ +#define CMD_DAH (1 << 18) /* destination address hold -- does not work?*/ +#define CMD_SAH (1 << 17) /* source address hold -- does not work? */ + +#define CMD_MODE_SINGLE (0 << 0) /* dmov_s structure used */ +#define CMD_MODE_SG (1 << 0) /* untested */ +#define CMD_MODE_IND_SG (2 << 0) /* untested */ +#define CMD_MODE_BOX (3 << 0) /* untested */ + +#define CMD_DST_SWAP_BYTES (1 << 14) /* exchange each byte n with byte n+1 */ +#define CMD_DST_SWAP_SHORTS (1 << 15) /* exchange each short n with short n+1 */ +#define CMD_DST_SWAP_WORDS (1 << 16) /* exchange each word n with word n+1 */ + +#define CMD_SRC_SWAP_BYTES (1 << 11) /* exchange each byte n with byte n+1 */ +#define CMD_SRC_SWAP_SHORTS (1 << 12) /* exchange each short n with short n+1 */ +#define CMD_SRC_SWAP_WORDS (1 << 13) /* exchange each word n with word n+1 */ + +#define CMD_DST_CRCI(n) (((n) & 15) << 7) +#define CMD_SRC_CRCI(n) (((n) & 15) << 3) + +#endif -- cgit v1.2.3 From c98929c07a01c9ec2e1e5253456acc7168da8b66 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 22 Nov 2007 18:32:01 +0100 Subject: [ARM] 4582/2: Add support for the common VFP subarchitecture This patch allows the VFP support code to run correctly on CPUs compatible with the common VFP subarchitecture specification (Appendix B in the ARM ARM v7-A and v7-R edition). It implements support for VFP subarchitecture 2 while being backwards compatible with subarchitecture 1. On VFP subarchitecture 1, the arithmetic exceptions are asynchronous (or imprecise as described in the old ARM ARM) unless the FPSCR.IXE bit is 1. The exceptional instructions can be read from FPINST and FPINST2 registers. With VFP subarchitecture 2, the arithmetic exceptions can also be synchronous and marked by the FPEXC.DEX bit (the FPEXC.EX bit is cleared). CPUs implementing the synchronous arithmetic exceptions don't have the FPINST and FPINST2 registers and accessing them would trigger and undefined exception. Note that FPEXC.EX bit has an additional meaning on subarchitecture 1 - if it isn't set, there is no additional information in FPINST and FPINST2 that needs to be saved at context switch or when lazy-loading the VFP state of a different thread. The patch also removes the clearing of the cumulative exception flags in FPSCR when additional exceptions were raised. It is up to the user application to clear these bits. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/vfp/vfphw.S | 38 +++++++++---------- arch/arm/vfp/vfpmodule.c | 98 +++++++++++++++++++++++++++--------------------- include/asm-arm/vfp.h | 30 +++++++-------- 3 files changed, 89 insertions(+), 77 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 0ac022f800a1..53d9f8e8fac3 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -100,10 +100,10 @@ vfp_support_entry: cmp r4, #0 beq no_old_VFP_process VFPFMRX r5, FPSCR @ current status - VFPFMRX r6, FPINST @ FPINST (always there, rev0 onwards) - tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read? - VFPFMRX r8, FPINST2, NE @ FPINST2 if needed - avoids reading - @ nonexistant reg on rev0 + tst r1, #FPEXC_EX @ is there additional state to save? + VFPFMRX r6, FPINST, NE @ FPINST (only if FPEXC.EX is set) + tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? + VFPFMRX r8, FPINST2, NE @ FPINST2 if needed (and present) VFPFSTMIA r4 @ save the working registers stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 @ and point r4 at the word at the @@ -117,10 +117,10 @@ no_old_VFP_process: VFPFLDMIA r10 @ reload the working registers while @ FPEXC is in a safe state ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 - tst r1, #FPEXC_FPV2 @ is there an FPINST2 to write? - VFPFMXR FPINST2, r8, NE @ FPINST2 if needed - avoids writing - @ nonexistant reg on rev0 - VFPFMXR FPINST, r6 + tst r1, #FPEXC_EX @ is there additional state to restore? + VFPFMXR FPINST, r6, NE @ restore FPINST (only if FPEXC.EX is set) + tstne r1, #FPEXC_FP2V @ is there an FPINST2 to write? + VFPFMXR FPINST2, r8, NE @ FPINST2 if needed (and present) VFPFMXR FPSCR, r5 @ restore status check_for_exception: @@ -136,10 +136,14 @@ check_for_exception: look_for_VFP_exceptions: - tst r1, #FPEXC_EX + @ Check for synchronous or asynchronous exception + tst r1, #FPEXC_EX | FPEXC_DEX bne process_exception + @ On some implementations of the VFP subarch 1, setting FPSCR.IXE + @ causes all the CDP instructions to be bounced synchronously without + @ setting the FPEXC.EX bit VFPFMRX r5, FPSCR - tst r5, #FPSCR_IXE @ IXE doesn't set FPEXC_EX ! + tst r5, #FPSCR_IXE bne process_exception @ Fall into hand on to next handler - appropriate coproc instr @@ -150,10 +154,6 @@ look_for_VFP_exceptions: process_exception: DBGSTR "bounce" - sub r2, r2, #4 - str r2, [sp, #S_PC] @ retry the instruction on exit from - @ the imprecise exception handling in - @ the support code mov r2, sp @ nothing stacked - regdump is at TOS mov lr, r9 @ setup for a return to the user code. @@ -161,7 +161,7 @@ process_exception: @ r0 holds the trigger instruction @ r1 holds the FPEXC value @ r2 pointer to register dump - b VFP9_bounce @ we have handled this - the support + b VFP_bounce @ we have handled this - the support @ code will raise an exception if @ required. If not, the user code will @ retry the faulted instruction @@ -175,10 +175,10 @@ vfp_save_state: @ r1 - FPEXC DBGSTR1 "save VFP state %p", r0 VFPFMRX r2, FPSCR @ current status - VFPFMRX r3, FPINST @ FPINST (always there, rev0 onwards) - tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read? - VFPFMRX r12, FPINST2, NE @ FPINST2 if needed - avoids reading - @ nonexistant reg on rev0 + tst r1, #FPEXC_EX @ is there additional state to save? + VFPFMRX r3, FPINST, NE @ FPINST (only if FPEXC.EX is set) + tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? + VFPFMRX r12, FPINST2, NE @ FPINST2 if needed (and present) VFPFSTMIA r0 @ save the working registers stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 mov pc, lr diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index b4e210df92f2..32455c633f1c 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -125,13 +125,13 @@ void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) send_sig_info(SIGFPE, &info, current); } -static void vfp_panic(char *reason) +static void vfp_panic(char *reason, u32 inst) { int i; printk(KERN_ERR "VFP: Error: %s\n", reason); printk(KERN_ERR "VFP: EXC 0x%08x SCR 0x%08x INST 0x%08x\n", - fmrx(FPEXC), fmrx(FPSCR), fmrx(FPINST)); + fmrx(FPEXC), fmrx(FPSCR), inst); for (i = 0; i < 32; i += 2) printk(KERN_ERR "VFP: s%2u: 0x%08x s%2u: 0x%08x\n", i, vfp_get_float(i), i+1, vfp_get_float(i+1)); @@ -147,19 +147,16 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ pr_debug("VFP: raising exceptions %08x\n", exceptions); if (exceptions == VFP_EXCEPTION_ERROR) { - vfp_panic("unhandled bounce"); + vfp_panic("unhandled bounce", inst); vfp_raise_sigfpe(0, regs); return; } /* - * If any of the status flags are set, update the FPSCR. + * Update the FPSCR with the additional exception flags. * Comparison instructions always return at least one of * these flags set. */ - if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) - fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); - fpscr |= exceptions; fmxr(FPSCR, fpscr); @@ -220,35 +217,64 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs) /* * Package up a bounce condition. */ -void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) +void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) { - u32 fpscr, orig_fpscr, exceptions, inst; + u32 fpscr, orig_fpscr, fpsid, exceptions; pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc); /* - * Enable access to the VFP so we can handle the bounce. + * At this point, FPEXC can have the following configuration: + * + * EX DEX IXE + * 0 1 x - synchronous exception + * 1 x 0 - asynchronous exception + * 1 x 1 - sychronous on VFP subarch 1 and asynchronous on later + * 0 0 1 - synchronous on VFP9 (non-standard subarch 1 + * implementation), undefined otherwise + * + * Clear various bits and enable access to the VFP so we can + * handle the bounce. */ - fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_FPV2|FPEXC_INV|FPEXC_UFC|FPEXC_OFC|FPEXC_IOC)); + fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_DEX|FPEXC_FP2V|FPEXC_VV|FPEXC_TRAP_MASK)); + fpsid = fmrx(FPSID); orig_fpscr = fpscr = fmrx(FPSCR); /* - * If we are running with inexact exceptions enabled, we need to - * emulate the trigger instruction. Note that as we're emulating - * the trigger instruction, we need to increment PC. + * Check for the special VFP subarch 1 and FPSCR.IXE bit case */ - if (fpscr & FPSCR_IXE) { - regs->ARM_pc += 4; + if ((fpsid & FPSID_ARCH_MASK) == (1 << FPSID_ARCH_BIT) + && (fpscr & FPSCR_IXE)) { + /* + * Synchronous exception, emulate the trigger instruction + */ goto emulate; } - barrier(); + if (fpexc & FPEXC_EX) { + /* + * Asynchronous exception. The instruction is read from FPINST + * and the interrupted instruction has to be restarted. + */ + trigger = fmrx(FPINST); + regs->ARM_pc -= 4; + } else if (!(fpexc & FPEXC_DEX)) { + /* + * Illegal combination of bits. It can be caused by an + * unallocated VFP instruction but with FPSCR.IXE set and not + * on VFP subarch 1. + */ + vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs); + return; + } /* - * Modify fpscr to indicate the number of iterations remaining + * Modify fpscr to indicate the number of iterations remaining. + * If FPEXC.EX is 0, FPEXC.DEX is 1 and the FPEXC.VV bit indicates + * whether FPEXC.VECITR or FPSCR.LEN is used. */ - if (fpexc & FPEXC_EX) { + if (fpexc & (FPEXC_EX | FPEXC_VV)) { u32 len; len = fpexc + (1 << FPEXC_LENGTH_BIT); @@ -262,15 +288,15 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) * FPEXC bounce reason, but this appears to be unreliable. * Emulate the bounced instruction instead. */ - inst = fmrx(FPINST); - exceptions = vfp_emulate_instruction(inst, fpscr, regs); + exceptions = vfp_emulate_instruction(trigger, fpscr, regs); if (exceptions) - vfp_raise_exceptions(exceptions, inst, orig_fpscr, regs); + vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); /* - * If there isn't a second FP instruction, exit now. + * If there isn't a second FP instruction, exit now. Note that + * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1. */ - if (!(fpexc & FPEXC_FPV2)) + if (fpexc ^ (FPEXC_EX | FPEXC_FP2V)) return; /* @@ -279,10 +305,9 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) */ barrier(); trigger = fmrx(FPINST2); - orig_fpscr = fpscr = fmrx(FPSCR); emulate: - exceptions = vfp_emulate_instruction(trigger, fpscr, regs); + exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs); if (exceptions) vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); } @@ -306,16 +331,9 @@ static int __init vfp_init(void) { unsigned int vfpsid; unsigned int cpu_arch = cpu_architecture(); - u32 access = 0; - if (cpu_arch >= CPU_ARCH_ARMv6) { - access = get_copro_access(); - - /* - * Enable full access to VFP (cp10 and cp11) - */ - set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); - } + if (cpu_arch >= CPU_ARCH_ARMv6) + vfp_enable(NULL); /* * First check that there is a VFP that we can use. @@ -329,15 +347,9 @@ static int __init vfp_init(void) vfp_vector = vfp_null_entry; printk(KERN_INFO "VFP support v0.3: "); - if (VFP_arch) { + if (VFP_arch) printk("not present\n"); - - /* - * Restore the copro access register. - */ - if (cpu_arch >= CPU_ARCH_ARMv6) - set_copro_access(access); - } else if (vfpsid & FPSID_NODOUBLE) { + else if (vfpsid & FPSID_NODOUBLE) { printk("no double precision support\n"); } else { smp_call_function(vfp_enable, NULL, 1, 1); diff --git a/include/asm-arm/vfp.h b/include/asm-arm/vfp.h index bd6be9d7f772..9d474d47b266 100644 --- a/include/asm-arm/vfp.h +++ b/include/asm-arm/vfp.h @@ -8,6 +8,8 @@ #define FPSID cr0 #define FPSCR cr1 #define FPEXC cr8 +#define FPINST cr9 +#define FPINST2 cr10 /* FPSID bits */ #define FPSID_IMPLEMENTER_BIT (24) @@ -28,6 +30,19 @@ /* FPEXC bits */ #define FPEXC_EX (1 << 31) #define FPEXC_EN (1 << 30) +#define FPEXC_DEX (1 << 29) +#define FPEXC_FP2V (1 << 28) +#define FPEXC_VV (1 << 27) +#define FPEXC_TFV (1 << 26) +#define FPEXC_LENGTH_BIT (8) +#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT) +#define FPEXC_IDF (1 << 7) +#define FPEXC_IXF (1 << 4) +#define FPEXC_UFF (1 << 3) +#define FPEXC_OFF (1 << 2) +#define FPEXC_DZF (1 << 1) +#define FPEXC_IOF (1 << 0) +#define FPEXC_TRAP_MASK (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF) /* FPSCR bits */ #define FPSCR_DEFAULT_NAN (1<<25) @@ -55,21 +70,6 @@ #define FPSCR_IXC (1<<4) #define FPSCR_IDC (1<<7) -/* - * VFP9-S specific. - */ -#define FPINST cr9 -#define FPINST2 cr10 - -/* FPEXC bits */ -#define FPEXC_FPV2 (1<<28) -#define FPEXC_LENGTH_BIT (8) -#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT) -#define FPEXC_INV (1 << 7) -#define FPEXC_UFC (1 << 3) -#define FPEXC_OFC (1 << 2) -#define FPEXC_IOC (1 << 0) - /* Bit patterns for decoding the packaged operation descriptors */ #define VFPOPDESC_LENGTH_BIT (9) #define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) -- cgit v1.2.3 From 25ebee020bd34d1f4c5678538204f0b10bf9f6d5 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 25 Sep 2007 15:22:24 +0100 Subject: [ARM] 4583/1: ARMv7: Add VFPv3 support This patch adds the support for VFPv3 (the kernel currently supports VFPv2). The main difference is 32 double registers (compared to 16). Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/Kconfig | 7 ++++++- arch/arm/vfp/vfp.h | 4 ++++ arch/arm/vfp/vfphw.S | 22 ++++++++++++++++++---- arch/arm/vfp/vfpinstr.h | 6 +++--- include/asm-arm/fpstate.h | 9 +++++++-- include/asm-arm/vfp.h | 6 ++++++ include/asm-arm/vfpmacros.h | 18 ++++++++++++++++-- 7 files changed, 60 insertions(+), 12 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a04f507e7f2c..f4eeb03bc6a9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -951,7 +951,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" - depends on CPU_V6 || CPU_ARM926T + depends on CPU_V6 || CPU_ARM926T || CPU_V7 help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. @@ -961,6 +961,11 @@ config VFP Say N if your target does not have VFP hardware. +config VFPv3 + bool + depends on VFP + default y if CPU_V7 + endmenu menu "Userspace binary formats" diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index 791d0238c68f..c85860bad585 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -265,7 +265,11 @@ struct vfp_double { * which returns (double)0.0. This is useful for the compare with * zero instructions. */ +#ifdef CONFIG_VFPv3 +#define VFP_REG_ZERO 32 +#else #define VFP_REG_ZERO 16 +#endif extern u64 vfp_get_double(unsigned int reg); extern void vfp_put_double(u64 val, unsigned int reg); diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 53d9f8e8fac3..353f9e5c7919 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -99,12 +99,12 @@ vfp_support_entry: DBGSTR1 "save old state %p", r4 cmp r4, #0 beq no_old_VFP_process + VFPFSTMIA r4, r5 @ save the working registers VFPFMRX r5, FPSCR @ current status tst r1, #FPEXC_EX @ is there additional state to save? VFPFMRX r6, FPINST, NE @ FPINST (only if FPEXC.EX is set) tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? VFPFMRX r8, FPINST2, NE @ FPINST2 if needed (and present) - VFPFSTMIA r4 @ save the working registers stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 @ and point r4 at the word at the @ start of the register dump @@ -114,7 +114,7 @@ no_old_VFP_process: DBGSTR1 "load state %p", r10 str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer @ Load the saved state back into the VFP - VFPFLDMIA r10 @ reload the working registers while + VFPFLDMIA r10, r5 @ reload the working registers while @ FPEXC is in a safe state ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 tst r1, #FPEXC_EX @ is there additional state to restore? @@ -174,12 +174,12 @@ vfp_save_state: @ r0 - save location @ r1 - FPEXC DBGSTR1 "save VFP state %p", r0 + VFPFSTMIA r0, r2 @ save the working registers VFPFMRX r2, FPSCR @ current status tst r1, #FPEXC_EX @ is there additional state to save? VFPFMRX r3, FPINST, NE @ FPINST (only if FPEXC.EX is set) tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? VFPFMRX r12, FPINST2, NE @ FPINST2 if needed (and present) - VFPFSTMIA r0 @ save the working registers stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 mov pc, lr #endif @@ -217,8 +217,15 @@ vfp_get_double: fmrrd r0, r1, d\dr mov pc, lr .endr +#ifdef CONFIG_VFPv3 + @ d16 - d31 registers + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr + mov pc, lr + .endr +#endif - @ virtual register 16 for compare with zero + @ virtual register 16 (or 32 if VFPv3) for compare with zero mov r0, #0 mov r1, #0 mov pc, lr @@ -231,3 +238,10 @@ vfp_put_double: fmdrr d\dr, r0, r1 mov pc, lr .endr +#ifdef CONFIG_VFPv3 + @ d16 - d31 registers + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr + mov pc, lr + .endr +#endif diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h index 7f343a4beca0..15b95b5ab97e 100644 --- a/arch/arm/vfp/vfpinstr.h +++ b/arch/arm/vfp/vfpinstr.h @@ -52,11 +52,11 @@ #define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) #define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) -#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12) +#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) #define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) -#define vfp_get_dm(inst) ((inst & 0x0000000f)) +#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) #define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) -#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16) +#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) #define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h index f31cda5a55ee..392eb5332323 100644 --- a/include/asm-arm/fpstate.h +++ b/include/asm-arm/fpstate.h @@ -17,14 +17,18 @@ /* * VFP storage area has: * - FPEXC, FPSCR, FPINST and FPINST2. - * - 16 double precision data registers - * - an implementation-dependant word of state for FLDMX/FSTMX + * - 16 or 32 double precision data registers + * - an implementation-dependant word of state for FLDMX/FSTMX (pre-ARMv6) * * FPEXC will always be non-zero once the VFP has been used in this process. */ struct vfp_hard_struct { +#ifdef CONFIG_VFPv3 + __u64 fpregs[32]; +#else __u64 fpregs[16]; +#endif #if __LINUX_ARM_ARCH__ < 6 __u32 fpmx_state; #endif @@ -35,6 +39,7 @@ struct vfp_hard_struct { */ __u32 fpinst; __u32 fpinst2; + #ifdef CONFIG_SMP __u32 cpu; #endif diff --git a/include/asm-arm/vfp.h b/include/asm-arm/vfp.h index 9d474d47b266..5f9a2cb3d452 100644 --- a/include/asm-arm/vfp.h +++ b/include/asm-arm/vfp.h @@ -7,6 +7,8 @@ #define FPSID cr0 #define FPSCR cr1 +#define MVFR1 cr6 +#define MVFR0 cr7 #define FPEXC cr8 #define FPINST cr9 #define FPINST2 cr10 @@ -70,6 +72,10 @@ #define FPSCR_IXC (1<<4) #define FPSCR_IDC (1<<7) +/* MVFR0 bits */ +#define MVFR0_A_SIMD_BIT (0) +#define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) + /* Bit patterns for decoding the packaged operation descriptors */ #define VFPOPDESC_LENGTH_BIT (9) #define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h index 27fe028b4e72..cccb3892e73c 100644 --- a/include/asm-arm/vfpmacros.h +++ b/include/asm-arm/vfpmacros.h @@ -15,19 +15,33 @@ .endm @ read all the working registers back into the VFP - .macro VFPFLDMIA, base + .macro VFPFLDMIA, base, tmp #if __LINUX_ARM_ARCH__ < 6 LDC p11, cr0, [\base],#33*4 @ FLDMIAX \base!, {d0-d15} #else LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15} +#endif +#ifdef CONFIG_VFPv3 + VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 + and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field + cmp \tmp, #2 @ 32 x 64bit registers? + ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addne \base, \base, #32*4 @ step over unused register space #endif .endm @ write all the working registers out of the VFP - .macro VFPFSTMIA, base + .macro VFPFSTMIA, base, tmp #if __LINUX_ARM_ARCH__ < 6 STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15} #else STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15} +#endif +#ifdef CONFIG_VFPv3 + VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 + and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field + cmp \tmp, #2 @ 32 x 64bit registers? + stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addne \base, \base, #32*4 @ step over unused register space #endif .endm -- cgit v1.2.3 From f1a6de9c7efc8e3fb535f1e61848f671f90b5cd5 Mon Sep 17 00:00:00 2001 From: Jan Altenberg Date: Tue, 2 Oct 2007 13:26:43 -0700 Subject: [ARM] Remove at91_lcdc.h include/asm-arm/arch-at91/at91_lcdc.h (which is still present in latest git) has been superseeded by include/video/atmel_lcdc.h, so let's remove it. Signed-off-by: Jan Altenberg Cc: Andrew Victor Cc: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Russell King --- include/asm-arm/arch-at91/at91_lcdc.h | 148 ---------------------------------- 1 file changed, 148 deletions(-) delete mode 100644 include/asm-arm/arch-at91/at91_lcdc.h (limited to 'include/asm-arm') diff --git a/include/asm-arm/arch-at91/at91_lcdc.h b/include/asm-arm/arch-at91/at91_lcdc.h deleted file mode 100644 index ab040a40d37b..000000000000 --- a/include/asm-arm/arch-at91/at91_lcdc.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * include/asm-arm/arch-at91/at91_lcdc.h - * - * LCD Controller (LCDC). - * Based on AT91SAM9261 datasheet revision E. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef AT91_LCDC_H -#define AT91_LCDC_H - -#define AT91_LCDC_DMABADDR1 0x00 /* DMA Base Address Register 1 */ -#define AT91_LCDC_DMABADDR2 0x04 /* DMA Base Address Register 2 */ -#define AT91_LCDC_DMAFRMPT1 0x08 /* DMA Frame Pointer Register 1 */ -#define AT91_LCDC_DMAFRMPT2 0x0c /* DMA Frame Pointer Register 2 */ -#define AT91_LCDC_DMAFRMADD1 0x10 /* DMA Frame Address Register 1 */ -#define AT91_LCDC_DMAFRMADD2 0x14 /* DMA Frame Address Register 2 */ - -#define AT91_LCDC_DMAFRMCFG 0x18 /* DMA Frame Configuration Register */ -#define AT91_LCDC_FRSIZE (0x7fffff << 0) /* Frame Size */ -#define AT91_LCDC_BLENGTH (0x7f << 24) /* Burst Length */ - -#define AT91_LCDC_DMACON 0x1c /* DMA Control Register */ -#define AT91_LCDC_DMAEN (0x1 << 0) /* DMA Enable */ -#define AT91_LCDC_DMARST (0x1 << 1) /* DMA Reset */ -#define AT91_LCDC_DMABUSY (0x1 << 2) /* DMA Busy */ - -#define AT91_LCDC_LCDCON1 0x0800 /* LCD Control Register 1 */ -#define AT91_LCDC_BYPASS (1 << 0) /* Bypass lcd_dotck divider */ -#define AT91_LCDC_CLKVAL (0x1ff << 12) /* Clock Divider */ -#define AT91_LCDC_LINCNT (0x7ff << 21) /* Line Counter */ - -#define AT91_LCDC_LCDCON2 0x0804 /* LCD Control Register 2 */ -#define AT91_LCDC_DISTYPE (3 << 0) /* Display Type */ -#define AT91_LCDC_DISTYPE_STNMONO (0 << 0) -#define AT91_LCDC_DISTYPE_STNCOLOR (1 << 0) -#define AT91_LCDC_DISTYPE_TFT (2 << 0) -#define AT91_LCDC_SCANMOD (1 << 2) /* Scan Mode */ -#define AT91_LCDC_SCANMOD_SINGLE (0 << 2) -#define AT91_LCDC_SCANMOD_DUAL (1 << 2) -#define AT91_LCDC_IFWIDTH (3 << 3) /*Interface Width */ -#define AT91_LCDC_IFWIDTH_4 (0 << 3) -#define AT91_LCDC_IFWIDTH_8 (1 << 3) -#define AT91_LCDC_IFWIDTH_16 (2 << 3) -#define AT91_LCDC_PIXELSIZE (7 << 5) /* Bits per pixel */ -#define AT91_LCDC_PIXELSIZE_1 (0 << 5) -#define AT91_LCDC_PIXELSIZE_2 (1 << 5) -#define AT91_LCDC_PIXELSIZE_4 (2 << 5) -#define AT91_LCDC_PIXELSIZE_8 (3 << 5) -#define AT91_LCDC_PIXELSIZE_16 (4 << 5) -#define AT91_LCDC_PIXELSIZE_24 (5 << 5) -#define AT91_LCDC_INVVD (1 << 8) /* LCD Data polarity */ -#define AT91_LCDC_INVVD_NORMAL (0 << 8) -#define AT91_LCDC_INVVD_INVERTED (1 << 8) -#define AT91_LCDC_INVFRAME (1 << 9 ) /* LCD VSync polarity */ -#define AT91_LCDC_INVFRAME_NORMAL (0 << 9) -#define AT91_LCDC_INVFRAME_INVERTED (1 << 9) -#define AT91_LCDC_INVLINE (1 << 10) /* LCD HSync polarity */ -#define AT91_LCDC_INVLINE_NORMAL (0 << 10) -#define AT91_LCDC_INVLINE_INVERTED (1 << 10) -#define AT91_LCDC_INVCLK (1 << 11) /* LCD dotclk polarity */ -#define AT91_LCDC_INVCLK_NORMAL (0 << 11) -#define AT91_LCDC_INVCLK_INVERTED (1 << 11) -#define AT91_LCDC_INVDVAL (1 << 12) /* LCD dval polarity */ -#define AT91_LCDC_INVDVAL_NORMAL (0 << 12) -#define AT91_LCDC_INVDVAL_INVERTED (1 << 12) -#define AT91_LCDC_CLKMOD (1 << 15) /* LCD dotclk mode */ -#define AT91_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15) -#define AT91_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15) -#define AT91_LCDC_MEMOR (1 << 31) /* Memory Ordering Format */ -#define AT91_LCDC_MEMOR_BIG (0 << 31) -#define AT91_LCDC_MEMOR_LITTLE (1 << 31) - -#define AT91_LCDC_TIM1 0x0808 /* LCD Timing Register 1 */ -#define AT91_LCDC_VFP (0xff << 0) /* Vertical Front Porch */ -#define AT91_LCDC_VBP (0xff << 8) /* Vertical Back Porch */ -#define AT91_LCDC_VPW (0x3f << 16) /* Vertical Synchronization Pulse Width */ -#define AT91_LCDC_VHDLY (0xf << 24) /* Vertical to Horizontal Delay */ - -#define AT91_LCDC_TIM2 0x080c /* LCD Timing Register 2 */ -#define AT91_LCDC_HBP (0xff << 0) /* Horizontal Back Porch */ -#define AT91_LCDC_HPW (0x3f << 8) /* Horizontal Synchronization Pulse Width */ -#define AT91_LCDC_HFP (0x7ff << 21) /* Horizontal Front Porch */ - -#define AT91_LCDC_LCDFRMCFG 0x0810 /* LCD Frame Configuration Register */ -#define AT91_LCDC_LINEVAL (0x7ff << 0) /* Vertical Size of LCD Module */ -#define AT91_LCDC_HOZVAL (0x7ff << 21) /* Horizontal Size of LCD Module */ - -#define AT91_LCDC_FIFO 0x0814 /* LCD FIFO Register */ -#define AT91_LCDC_FIFOTH (0xffff) /* FIFO Threshold */ - -#define AT91_LCDC_DP1_2 0x081c /* Dithering Pattern DP1_2 Register */ -#define AT91_LCDC_DP4_7 0x0820 /* Dithering Pattern DP4_7 Register */ -#define AT91_LCDC_DP3_5 0x0824 /* Dithering Pattern DP3_5 Register */ -#define AT91_LCDC_DP2_3 0x0828 /* Dithering Pattern DP2_3 Register */ -#define AT91_LCDC_DP5_7 0x082c /* Dithering Pattern DP5_7 Register */ -#define AT91_LCDC_DP3_4 0x0830 /* Dithering Pattern DP3_4 Register */ -#define AT91_LCDC_DP4_5 0x0834 /* Dithering Pattern DP4_5 Register */ -#define AT91_LCDC_DP6_7 0x0838 /* Dithering Pattern DP6_7 Register */ -#define AT91_LCDC_DP1_2_VAL (0xff) -#define AT91_LCDC_DP4_7_VAL (0xfffffff) -#define AT91_LCDC_DP3_5_VAL (0xfffff) -#define AT91_LCDC_DP2_3_VAL (0xfff) -#define AT91_LCDC_DP5_7_VAL (0xfffffff) -#define AT91_LCDC_DP3_4_VAL (0xffff) -#define AT91_LCDC_DP4_5_VAL (0xfffff) -#define AT91_LCDC_DP6_7_VAL (0xfffffff) - -#define AT91_LCDC_PWRCON 0x083c /* Power Control Register */ -#define AT91_LCDC_PWR (1 << 0) /* LCD Module Power Control */ -#define AT91_LCDC_GUARDT (0x7f << 1) /* Delay in Frame Period */ -#define AT91_LCDC_BUSY (1 << 31) /* LCD Busy */ - -#define AT91_LCDC_CONTRAST_CTR 0x0840 /* Contrast Control Register */ -#define AT91_LCDC_PS (3 << 0) /* Contrast Counter Prescaler */ -#define AT91_LCDC_PS_DIV1 (0 << 0) -#define AT91_LCDC_PS_DIV2 (1 << 0) -#define AT91_LCDC_PS_DIV4 (2 << 0) -#define AT91_LCDC_PS_DIV8 (3 << 0) -#define AT91_LCDC_POL (1 << 2) /* Polarity of output Pulse */ -#define AT91_LCDC_POL_NEGATIVE (0 << 2) -#define AT91_LCDC_POL_POSITIVE (1 << 2) -#define AT91_LCDC_ENA (1 << 3) /* PWM generator Control */ -#define AT91_LCDC_ENA_PWMDISABLE (0 << 3) -#define AT91_LCDC_ENA_PWMENABLE (1 << 3) - -#define AT91_LCDC_CONTRAST_VAL 0x0844 /* Contrast Value Register */ -#define AT91_LCDC_CVAL (0xff) /* PWM compare value */ - -#define AT91_LCDC_IER 0x0848 /* Interrupt Enable Register */ -#define AT91_LCDC_IDR 0x084c /* Interrupt Disable Register */ -#define AT91_LCDC_IMR 0x0850 /* Interrupt Mask Register */ -#define AT91_LCDC_ISR 0x0854 /* Interrupt Enable Register */ -#define AT91_LCDC_ICR 0x0858 /* Interrupt Clear Register */ -#define AT91_LCDC_LNI (1 << 0) /* Line Interrupt */ -#define AT91_LCDC_LSTLNI (1 << 1) /* Last Line Interrupt */ -#define AT91_LCDC_EOFI (1 << 2) /* DMA End Of Frame Interrupt */ -#define AT91_LCDC_UFLWI (1 << 4) /* FIFO Underflow Interrupt */ -#define AT91_LCDC_OWRI (1 << 5) /* FIFO Overwrite Interrupt */ -#define AT91_LCDC_MERI (1 << 6) /* DMA Memory Error Interrupt */ - -#define AT91_LCDC_LUT_(n) (0x0c00 + ((n)*4)) /* Palette Entry 0..255 */ - -#endif -- cgit v1.2.3 From d2936b1976a9c70d1cce4700c51f26d4b9495e9d Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sun, 25 Nov 2007 02:12:39 +0100 Subject: [ARM] 4666/1: ixp4xx: fix sparse warnings in include/asm-arm/arch-ixp4xx/io.h Don't lose __iomem in casts. Use __force to cast __iomem addresses to integers. Use __force to cast u32 to __le32 and vice versa. Signed-off-by: Pavel Roskin Signed-off-by: Russell King --- include/asm-arm/arch-ixp4xx/io.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include/asm-arm') diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h index eeeea90cd5a9..9c5d2357aff3 100644 --- a/include/asm-arm/arch-ixp4xx/io.h +++ b/include/asm-arm/arch-ixp4xx/io.h @@ -61,13 +61,13 @@ __ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype) if((addr < PCIBIOS_MIN_MEM) || (addr > 0x4fffffff)) return __arm_ioremap(addr, size, mtype); - return (void *)addr; + return (void __iomem *)addr; } static inline void __ixp4xx_iounmap(void __iomem *addr) { - if ((u32)addr >= VMALLOC_START) + if ((__force u32)addr >= VMALLOC_START) __iounmap(addr); } @@ -141,9 +141,9 @@ __ixp4xx_writesw(volatile void __iomem *bus_addr, const u16 *vaddr, int count) static inline void __ixp4xx_writel(u32 value, volatile void __iomem *p) { - u32 addr = (u32)p; + u32 addr = (__force u32)p; if (addr >= VMALLOC_START) { - __raw_writel(value, addr); + __raw_writel(value, p); return; } @@ -208,11 +208,11 @@ __ixp4xx_readsw(const volatile void __iomem *bus_addr, u16 *vaddr, u32 count) static inline unsigned long __ixp4xx_readl(const volatile void __iomem *p) { - u32 addr = (u32)p; + u32 addr = (__force u32)p; u32 data; if (addr >= VMALLOC_START) - return __raw_readl(addr); + return __raw_readl(p); if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data)) return 0xffffffff; @@ -438,7 +438,7 @@ __ixp4xx_ioread32(const void __iomem *addr) return (unsigned int)__ixp4xx_inl(port & PIO_MASK); else { #ifndef CONFIG_IXP4XX_INDIRECT_PCI - return le32_to_cpu(__raw_readl((u32)port)); + return le32_to_cpu((__force __le32)__raw_readl(addr)); #else return (unsigned int)__ixp4xx_readl(addr); #endif @@ -523,7 +523,7 @@ __ixp4xx_iowrite32(u32 value, void __iomem *addr) __ixp4xx_outl(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_writel(cpu_to_le32(value), port); + __raw_writel((u32 __force)cpu_to_le32(value), addr); #else __ixp4xx_writel(value, addr); #endif -- cgit v1.2.3 From 9ebbec27da6d7f4762b73985ac4929acf061d48b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 20 Nov 2007 13:34:56 +0100 Subject: [ARM] 4657/1: AT91: Header definition update Add definitions of registers / bits found on some AT91SAM9 processors Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91/at91_pmc.h | 4 +++- include/asm-arm/arch-at91/at91_twi.h | 11 +++++++++++ include/asm-arm/arch-at91/at91sam9260_matrix.h | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'include/asm-arm') diff --git a/include/asm-arm/arch-at91/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h index 33ff5b6798ee..34804eaab4f2 100644 --- a/include/asm-arm/arch-at91/at91_pmc.h +++ b/include/asm-arm/arch-at91/at91_pmc.h @@ -37,7 +37,9 @@ #define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */ #define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */ -#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register */ +#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [SAM9RL only] */ + +#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register [not on SAM9RL] */ #define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ #define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass [AT91SAM926x only] */ #define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ diff --git a/include/asm-arm/arch-at91/at91_twi.h b/include/asm-arm/arch-at91/at91_twi.h index ca9a90733456..f9f2e3cd95c5 100644 --- a/include/asm-arm/arch-at91/at91_twi.h +++ b/include/asm-arm/arch-at91/at91_twi.h @@ -21,6 +21,8 @@ #define AT91_TWI_STOP (1 << 1) /* Send a Stop Condition */ #define AT91_TWI_MSEN (1 << 2) /* Master Transfer Enable */ #define AT91_TWI_MSDIS (1 << 3) /* Master Transfer Disable */ +#define AT91_TWI_SVEN (1 << 4) /* Slave Transfer Enable [SAM9260 only] */ +#define AT91_TWI_SVDIS (1 << 5) /* Slave Transfer Disable [SAM9260 only] */ #define AT91_TWI_SWRST (1 << 7) /* Software Reset */ #define AT91_TWI_MMR 0x04 /* Master Mode Register */ @@ -32,6 +34,9 @@ #define AT91_TWI_MREAD (1 << 12) /* Master Read Direction */ #define AT91_TWI_DADR (0x7f << 16) /* Device Address */ +#define AT91_TWI_SMR 0x08 /* Slave Mode Register [SAM9260 only] */ +#define AT91_TWI_SADR (0x7f << 16) /* Slave Address */ + #define AT91_TWI_IADR 0x0c /* Internal Address Register */ #define AT91_TWI_CWGR 0x10 /* Clock Waveform Generator Register */ @@ -43,9 +48,15 @@ #define AT91_TWI_TXCOMP (1 << 0) /* Transmission Complete */ #define AT91_TWI_RXRDY (1 << 1) /* Receive Holding Register Ready */ #define AT91_TWI_TXRDY (1 << 2) /* Transmit Holding Register Ready */ +#define AT91_TWI_SVREAD (1 << 3) /* Slave Read [SAM9260 only] */ +#define AT91_TWI_SVACC (1 << 4) /* Slave Access [SAM9260 only] */ +#define AT91_TWI_GACC (1 << 5) /* General Call Access [SAM9260 only] */ #define AT91_TWI_OVRE (1 << 6) /* Overrun Error [AT91RM9200 only] */ #define AT91_TWI_UNRE (1 << 7) /* Underrun Error [AT91RM9200 only] */ #define AT91_TWI_NACK (1 << 8) /* Not Acknowledged */ +#define AT91_TWI_ARBLST (1 << 9) /* Arbitration Lost [SAM9260 only] */ +#define AT91_TWI_SCLWS (1 << 10) /* Clock Wait State [SAM9260 only] */ +#define AT91_TWI_EOSACC (1 << 11) /* End of Slave Address [SAM9260 only] */ #define AT91_TWI_IER 0x24 /* Interrupt Enable Register */ #define AT91_TWI_IDR 0x28 /* Interrupt Disable Register */ diff --git a/include/asm-arm/arch-at91/at91sam9260_matrix.h b/include/asm-arm/arch-at91/at91sam9260_matrix.h index aacb1e976422..a8e9fec6c735 100644 --- a/include/asm-arm/arch-at91/at91sam9260_matrix.h +++ b/include/asm-arm/arch-at91/at91sam9260_matrix.h @@ -67,7 +67,7 @@ #define AT91_MATRIX_CS4A (1 << 4) /* Chip Select 4 Assignment */ #define AT91_MATRIX_CS4A_SMC (0 << 4) #define AT91_MATRIX_CS4A_SMC_CF1 (1 << 4) -#define AT91_MATRIX_CS5A (1 << 5 ) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_CS5A (1 << 5) /* Chip Select 5 Assignment */ #define AT91_MATRIX_CS5A_SMC (0 << 5) #define AT91_MATRIX_CS5A_SMC_CF2 (1 << 5) #define AT91_MATRIX_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ -- cgit v1.2.3 From 156864f806baa4e1aa6eabd28ac45ecc92b31315 Mon Sep 17 00:00:00 2001 From: Marc Pignat Date: Mon, 3 Dec 2007 12:58:24 +0100 Subject: [ARM] 4688/1: at91: speed-up irq processing Save N instructions on every interrupt processing (where N is the number of interrupts processed in any one IRQ exception). Signed-off-by: Marc Pignat Acked-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91/entry-macro.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/asm-arm') diff --git a/include/asm-arm/arch-at91/entry-macro.S b/include/asm-arm/arch-at91/entry-macro.S index cc1d850a0788..1005eee6219b 100644 --- a/include/asm-arm/arch-at91/entry-macro.S +++ b/include/asm-arm/arch-at91/entry-macro.S @@ -17,13 +17,13 @@ .endm .macro get_irqnr_preamble, base, tmp + ldr \base, =(AT91_VA_BASE_SYS + AT91_AIC) @ base virtual address of AIC peripheral .endm .macro arch_ret_to_user, tmp1, tmp2 .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =(AT91_VA_BASE_SYS + AT91_AIC) @ base virtual address of AIC peripheral ldr \irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) ldr \irqstat, [\base, #(AT91_AIC_ISR - AT91_AIC)] @ read interrupt source number teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt -- cgit v1.2.3 From e2920802351b3e01a3e70a26bb1bbb22f29da4cb Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 22 Jan 2008 11:43:26 +0100 Subject: [ARM] 4751/1: [AT91] ISI peripheral on SAM9263 Add support for the Image Sensor Interface (ISI) peripheral integrated in the Atmel AT91SAM9263 processor. Patch from MaLiK Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/at91sam9263_devices.c | 50 ++++++++++++++++++++++++++++++++ include/asm-arm/arch-at91/board.h | 3 ++ 2 files changed, 53 insertions(+) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index ac329a98e959..d50a8dfb916d 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -731,6 +731,56 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} #endif +/* -------------------------------------------------------------------- + * Image Sensor Interface + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_VIDEO_AT91_ISI) || defined(CONFIG_VIDEO_AT91_ISI_MODULE) + +struct resource isi_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_ISI, + .end = AT91SAM9263_BASE_ISI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_ISI, + .end = AT91SAM9263_ID_ISI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_isi_device = { + .name = "at91_isi", + .id = -1, + .resource = isi_resources, + .num_resources = ARRAY_SIZE(isi_resources), +}; + +void __init at91_add_device_isi(void) +{ + at91_set_A_periph(AT91_PIN_PE0, 0); /* ISI_D0 */ + at91_set_A_periph(AT91_PIN_PE1, 0); /* ISI_D1 */ + at91_set_A_periph(AT91_PIN_PE2, 0); /* ISI_D2 */ + at91_set_A_periph(AT91_PIN_PE3, 0); /* ISI_D3 */ + at91_set_A_periph(AT91_PIN_PE4, 0); /* ISI_D4 */ + at91_set_A_periph(AT91_PIN_PE5, 0); /* ISI_D5 */ + at91_set_A_periph(AT91_PIN_PE6, 0); /* ISI_D6 */ + at91_set_A_periph(AT91_PIN_PE7, 0); /* ISI_D7 */ + at91_set_A_periph(AT91_PIN_PE8, 0); /* ISI_PCK */ + at91_set_A_periph(AT91_PIN_PE9, 0); /* ISI_HSYNC */ + at91_set_A_periph(AT91_PIN_PE10, 0); /* ISI_VSYNC */ + at91_set_B_periph(AT91_PIN_PE11, 0); /* ISI_MCK (PCK3) */ + at91_set_B_periph(AT91_PIN_PE12, 0); /* ISI_PD8 */ + at91_set_B_periph(AT91_PIN_PE13, 0); /* ISI_PD9 */ + at91_set_B_periph(AT91_PIN_PE14, 0); /* ISI_PD10 */ + at91_set_B_periph(AT91_PIN_PE15, 0); /* ISI_PD11 */ +} +#else +void __init at91_add_device_isi(void) {} +#endif + + /* -------------------------------------------------------------------- * LEDs * -------------------------------------------------------------------- */ diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index 79054965baa6..762148cc48c1 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -126,6 +126,9 @@ struct atmel_ac97_data { }; extern void __init at91_add_device_ac97(struct atmel_ac97_data *data); + /* ISI */ +extern void __init at91_add_device_isi(void); + /* LEDs */ extern u8 at91_leds_cpu; extern u8 at91_leds_timer; -- cgit v1.2.3 From 884f5a6a8dc8646d5904f166adf3c558be57e1ab Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 23 Jan 2008 09:11:13 +0100 Subject: [ARM] 4752/1: [AT91] RTT, RTC and WDT peripherals on SAM9 Add platform_device and initialization for the RTT (Real Time Timer) and WDT (Watchdog) integrated in the Atmel AT91SAM9 processors. For SAM9263, register both RTT peripherals. [From: David Brownell ] Provide platform_resources for RTT peripherals [From: David Brownell ] Add support for RTC peripheral on AT91SAM9RL (same RTC peripherals as AT91RM9200) [From: David Brownell ] Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/at91sam9260_devices.c | 47 ++++++++++++++++++++++ arch/arm/mach-at91/at91sam9261_devices.c | 47 ++++++++++++++++++++++ arch/arm/mach-at91/at91sam9263_devices.c | 63 +++++++++++++++++++++++++++++ arch/arm/mach-at91/at91sam9rl_devices.c | 68 ++++++++++++++++++++++++++++++++ include/asm-arm/arch-at91/at91_rtt.h | 8 ++-- 5 files changed, 229 insertions(+), 4 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 3091bf47d8c9..1533556fb873 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -538,6 +538,51 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) #endif +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT, + .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9260_rtt_device = { + .name = "at91_rtt", + .id = -1, + .resource = rtt_resources, + .num_resources = ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at91sam9260_rtt_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +static struct platform_device at91sam9260_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91sam9260_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + /* -------------------------------------------------------------------- * LEDs * -------------------------------------------------------------------- */ @@ -898,6 +943,8 @@ void __init at91_add_device_serial(void) {} */ static int __init at91_add_standard_devices(void) { + at91_add_device_rtt(); + at91_add_device_watchdog(); return 0; } diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 1d03844a607a..17f3f6a24796 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -550,6 +550,51 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} #endif +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT, + .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9261_rtt_device = { + .name = "at91_rtt", + .id = -1, + .resource = rtt_resources, + .num_resources = ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at91sam9261_rtt_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +static struct platform_device at91sam9261_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91sam9261_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + /* -------------------------------------------------------------------- * LEDs * -------------------------------------------------------------------- */ @@ -786,6 +831,8 @@ void __init at91_add_device_serial(void) {} */ static int __init at91_add_standard_devices(void) { + at91_add_device_rtt(); + at91_add_device_watchdog(); return 0; } diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index d50a8dfb916d..b4eb21769db9 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -781,6 +781,67 @@ void __init at91_add_device_isi(void) {} #endif +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt0_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT0, + .end = AT91_BASE_SYS + AT91_RTT0 + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9263_rtt0_device = { + .name = "at91_rtt", + .id = 0, + .resource = rtt0_resources, + .num_resources = ARRAY_SIZE(rtt0_resources), +}; + +static struct resource rtt1_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT1, + .end = AT91_BASE_SYS + AT91_RTT1 + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9263_rtt1_device = { + .name = "at91_rtt", + .id = 1, + .resource = rtt1_resources, + .num_resources = ARRAY_SIZE(rtt1_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at91sam9263_rtt0_device); + platform_device_register(&at91sam9263_rtt1_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +static struct platform_device at91sam9263_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91sam9263_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + /* -------------------------------------------------------------------- * LEDs * -------------------------------------------------------------------- */ @@ -1021,6 +1082,8 @@ void __init at91_add_device_serial(void) {} */ static int __init at91_add_standard_devices(void) { + at91_add_device_rtt(); + at91_add_device_watchdog(); return 0; } diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 2bd60a3dc623..19ca71d3faab 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -383,6 +383,71 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} #endif +/* -------------------------------------------------------------------- + * RTC + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE) +static struct platform_device at91sam9rl_rtc_device = { + .name = "at91_rtc", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_rtc(void) +{ + platform_device_register(&at91sam9rl_rtc_device); +} +#else +static void __init at91_add_device_rtc(void) {} +#endif + + +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT, + .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9rl_rtt_device = { + .name = "at91_rtt", + .id = -1, + .resource = rtt_resources, + .num_resources = ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at91sam9rl_rtt_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +static struct platform_device at91sam9rl_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91sam9rl_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + /* -------------------------------------------------------------------- * LEDs * -------------------------------------------------------------------- */ @@ -659,6 +724,9 @@ void __init at91_add_device_serial(void) {} */ static int __init at91_add_standard_devices(void) { + at91_add_device_rtc(); + at91_add_device_rtt(); + at91_add_device_watchdog(); return 0; } diff --git a/include/asm-arm/arch-at91/at91_rtt.h b/include/asm-arm/arch-at91/at91_rtt.h index bae1103fbbb2..39a32633b275 100644 --- a/include/asm-arm/arch-at91/at91_rtt.h +++ b/include/asm-arm/arch-at91/at91_rtt.h @@ -13,19 +13,19 @@ #ifndef AT91_RTT_H #define AT91_RTT_H -#define AT91_RTT_MR (AT91_RTT + 0x00) /* Real-time Mode Register */ +#define AT91_RTT_MR 0x00 /* Real-time Mode Register */ #define AT91_RTT_RTPRES (0xffff << 0) /* Real-time Timer Prescaler Value */ #define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ #define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ #define AT91_RTT_RTTRST (1 << 18) /* Real Time Timer Restart */ -#define AT91_RTT_AR (AT91_RTT + 0x04) /* Real-time Alarm Register */ +#define AT91_RTT_AR 0x04 /* Real-time Alarm Register */ #define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */ -#define AT91_RTT_VR (AT91_RTT + 0x08) /* Real-time Value Register */ +#define AT91_RTT_VR 0x08 /* Real-time Value Register */ #define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */ -#define AT91_RTT_SR (AT91_RTT + 0x0c) /* Real-time Status Register */ +#define AT91_RTT_SR 0x0c /* Real-time Status Register */ #define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ #define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ -- cgit v1.2.3 From bfbc32663d4846039f88c0eccc1956587d89c042 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 23 Jan 2008 09:18:06 +0100 Subject: [ARM] 4754/1: [AT91] SSC library support Core support of the Atmel SSC library for all Atmel AT91 processors. Based on David Brownell's initial patch for the AT91RM9200. Signed-off-by: Andrew Victor Acked-by: David Brownell Signed-off-by: Russell King --- arch/arm/mach-at91/at91rm9200_devices.c | 173 +++++++++++++++++++++++++++++++ arch/arm/mach-at91/at91sam9260_devices.c | 79 ++++++++++++++ arch/arm/mach-at91/at91sam9261_devices.c | 173 +++++++++++++++++++++++++++++++ arch/arm/mach-at91/at91sam9263_devices.c | 129 +++++++++++++++++++++++ arch/arm/mach-at91/at91sam9rl_devices.c | 129 +++++++++++++++++++++++ include/asm-arm/arch-at91/board.h | 17 +++ 6 files changed, 700 insertions(+) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index a601c7c1670e..cebea4168778 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -635,6 +635,179 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SSC0, + .end = AT91RM9200_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC0, + .end = AT91RM9200_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB0, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB1, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB2, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB3, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB4, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB5, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SSC1, + .end = AT91RM9200_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC1, + .end = AT91RM9200_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB6, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB7, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB8, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB9, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB10, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB11, 1); +} + +static u64 ssc2_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc2_resources[] = { + [0] = { + .start = AT91RM9200_BASE_SSC2, + .end = AT91RM9200_BASE_SSC2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_SSC2, + .end = AT91RM9200_ID_SSC2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_ssc2_device = { + .name = "ssc", + .id = 2, + .dev = { + .dma_mask = &ssc2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc2_resources, + .num_resources = ARRAY_SIZE(ssc2_resources), +}; + +static inline void configure_ssc2_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB12, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB13, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB14, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB15, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB16, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB17, 1); +} + +/* + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91RM9200_ID_SSC0: + pdev = &at91rm9200_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "ssc"); + break; + case AT91RM9200_ID_SSC1: + pdev = &at91rm9200_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "ssc"); + break; + case AT91RM9200_ID_SSC2: + pdev = &at91rm9200_ssc2_device; + configure_ssc2_pins(pins); + at91_clock_associate("ssc2_clk", &pdev->dev, "ssc"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index c34fde362ad4..2e3db137bc49 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -606,6 +606,85 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SSC, + .end = AT91SAM9260_BASE_SSC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SSC, + .end = AT91SAM9260_ID_SSC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_ssc_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc_resources, + .num_resources = ARRAY_SIZE(ssc_resources), +}; + +static inline void configure_ssc_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB17, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB16, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB18, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB19, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB20, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB21, 1); +} + +/* + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9260_ID_SSC: + pdev = &at91sam9260_ssc_device; + configure_ssc_pins(pins); + at91_clock_associate("ssc_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index f7f02d15045d..266ccf01be53 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -618,6 +618,179 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC0, + .end = AT91SAM9261_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC0, + .end = AT91SAM9261_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB21, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB22, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB23, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB24, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB25, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB26, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC1, + .end = AT91SAM9261_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC1, + .end = AT91SAM9261_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PA17, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PA18, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PA19, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PA20, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PA21, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PA22, 1); +} + +static u64 ssc2_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc2_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SSC2, + .end = AT91SAM9261_BASE_SSC2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SSC2, + .end = AT91SAM9261_ID_SSC2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_ssc2_device = { + .name = "ssc", + .id = 2, + .dev = { + .dma_mask = &ssc2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc2_resources, + .num_resources = ARRAY_SIZE(ssc2_resources), +}; + +static inline void configure_ssc2_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PC25, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PC26, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PC27, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PC28, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PC29, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PC30, 1); +} + +/* + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9261_ID_SSC0: + pdev = &at91sam9261_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9261_ID_SSC1: + pdev = &at91sam9261_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9261_ID_SSC2: + pdev = &at91sam9261_ssc2_device; + configure_ssc2_pins(pins); + at91_clock_associate("ssc2_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 9bdcf45defcf..f83ef62f2385 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -865,6 +865,135 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SSC0, + .end = AT91SAM9263_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SSC0, + .end = AT91SAM9263_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PB0, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PB1, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PB2, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PB3, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PB4, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PB5, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91SAM9263_BASE_SSC1, + .end = AT91SAM9263_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9263_ID_SSC1, + .end = AT91SAM9263_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9263_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PB6, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PB7, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PB8, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PB9, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PB10, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PB11, 1); +} + +/* + * Return the device node so that board init code can use it as the + * parent for the device node reflecting how it's used on this board. + * + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9263_ID_SSC0: + pdev = &at91sam9263_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9263_ID_SSC1: + pdev = &at91sam9263_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index bec8066f9ba1..e886cdfe919d 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -471,6 +471,135 @@ void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91SAM9RL_BASE_SSC0, + .end = AT91SAM9RL_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9RL_ID_SSC0, + .end = AT91SAM9RL_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9rl_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PC0, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PC1, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PA15, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PA16, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PA10, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PA22, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91SAM9RL_BASE_SSC1, + .end = AT91SAM9RL_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9RL_ID_SSC1, + .end = AT91SAM9RL_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9rl_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_B_periph(AT91_PIN_PA29, 1); + if (pins & ATMEL_SSC_TK) + at91_set_B_periph(AT91_PIN_PA30, 1); + if (pins & ATMEL_SSC_TD) + at91_set_B_periph(AT91_PIN_PA13, 1); + if (pins & ATMEL_SSC_RD) + at91_set_B_periph(AT91_PIN_PA14, 1); + if (pins & ATMEL_SSC_RK) + at91_set_B_periph(AT91_PIN_PA9, 1); + if (pins & ATMEL_SSC_RF) + at91_set_B_periph(AT91_PIN_PA8, 1); +} + +/* + * Return the device node so that board init code can use it as the + * parent for the device node reflecting how it's used on this board. + * + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9RL_ID_SSC0: + pdev = &at91sam9rl_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9RL_ID_SSC1: + pdev = &at91sam9rl_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + /* -------------------------------------------------------------------- * UART * -------------------------------------------------------------------- */ diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index 762148cc48c1..7fefe018833c 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -116,6 +116,23 @@ struct atmel_uart_data { }; extern void __init at91_add_device_serial(void); +/* + * SSC -- accessed through ssc_request(id). Drivers don't bind to SSC + * platform devices. Their SSC ID is part of their configuration data, + * along with information about which SSC signals they should use. + */ +#define ATMEL_SSC_TK 0x01 +#define ATMEL_SSC_TF 0x02 +#define ATMEL_SSC_TD 0x04 +#define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD) + +#define ATMEL_SSC_RK 0x10 +#define ATMEL_SSC_RF 0x20 +#define ATMEL_SSC_RD 0x40 +#define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD) + +extern void __init at91_add_device_ssc(unsigned id, unsigned pins); + /* LCD Controller */ struct atmel_lcdfb_info; extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data); -- cgit v1.2.3 From c8f385a631ef1f49d67a3798ca40dec36ccdf07d Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 23 Jan 2008 09:25:15 +0100 Subject: [ARM] 4757/1: [AT91] UART initialization Modify the UART initialization to allow the board-initialization code to specify which pins are connected, and which pins should therefore be initialized. The current at91_init_serial() will continue to work as-is, but is marked as "deprecated" and will be removed once the board-specific files has been updated to use the new interface. As in the AVR32 code, we assume that the TX and RX pins will always be initialized. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/at91rm9200_devices.c | 114 ++++++++++++++++++++++++------ arch/arm/mach-at91/at91sam9260_devices.c | 115 ++++++++++++++++++++++++++----- arch/arm/mach-at91/at91sam9261_devices.c | 77 ++++++++++++++++++--- arch/arm/mach-at91/at91sam9263_devices.c | 79 +++++++++++++++++---- arch/arm/mach-at91/at91sam9rl_devices.c | 99 ++++++++++++++++++++++---- include/asm-arm/arch-at91/board.h | 12 +++- 6 files changed, 420 insertions(+), 76 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index a2647265c214..23966229ea9a 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -884,17 +884,21 @@ static struct platform_device at91rm9200_uart0_device = { .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ - /* - * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. - * We need to drive the pin manually. Default is off (RTS is active low). - */ - at91_set_gpio_output(AT91_PIN_PA21, 1); + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ + + if (pins & ATMEL_UART_RTS) { + /* + * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. + * We need to drive the pin manually. Default is off (RTS is active low). + */ + at91_set_gpio_output(AT91_PIN_PA21, 1); + } } static struct resource uart1_resources[] = { @@ -929,16 +933,23 @@ static struct platform_device at91rm9200_uart1_device = { .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { - at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ - at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ - at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ - at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ - at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ - at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ + + if (pins & ATMEL_UART_RI) + at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ + if (pins & ATMEL_UART_DTR) + at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ + if (pins & ATMEL_UART_DCD) + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ + if (pins & ATMEL_UART_DSR) + at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ } static struct resource uart2_resources[] = { @@ -973,10 +984,15 @@ static struct platform_device at91rm9200_uart2_device = { .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ + + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA30, 0); /* CTS2 */ + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA31, 0); /* RTS2 */ } static struct resource uart3_resources[] = { @@ -1011,16 +1027,21 @@ static struct platform_device at91rm9200_uart3_device = { .num_resources = ARRAY_SIZE(uart3_resources), }; -static inline void configure_usart3_pins(void) +static inline void configure_usart3_pins(unsigned pins) { at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ + + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PB1, 0); /* CTS3 */ + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PB0, 0); /* RTS3 */ } static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -1028,22 +1049,22 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91rm9200_uart0_device; at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI); at91_uarts[i] = &at91rm9200_uart1_device; at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(0); at91_uarts[i] = &at91rm9200_uart2_device; at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); break; case 3: - configure_usart3_pins(); + configure_usart3_pins(0); at91_uarts[i] = &at91rm9200_uart3_device; at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); break; @@ -1065,6 +1086,53 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91rm9200_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US0: + pdev = &at91rm9200_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US1: + pdev = &at91rm9200_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US2: + pdev = &at91rm9200_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + case AT91RM9200_ID_US3: + pdev = &at91rm9200_uart3_device; + configure_usart3_pins(pins); + at91_clock_associate("usart3_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -1075,7 +1143,9 @@ void __init at91_add_device_serial(void) } } #else -void __init at91_init_serial(struct at91_uart_config *config) {} +void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 8acd62b75cb0..5dd06bdccb00 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -760,16 +760,23 @@ static struct platform_device at91sam9260_uart0_device = { .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */ - at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */ - at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */ - at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */ - at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */ - at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */ + if (pins & ATMEL_UART_DTR) + at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */ + if (pins & ATMEL_UART_DSR) + at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */ + if (pins & ATMEL_UART_DCD) + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */ + if (pins & ATMEL_UART_RI) + at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */ } static struct resource uart1_resources[] = { @@ -804,12 +811,15 @@ static struct platform_device at91sam9260_uart1_device = { .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD1 */ - at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */ - at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */ } static struct resource uart2_resources[] = { @@ -844,10 +854,15 @@ static struct platform_device at91sam9260_uart2_device = { .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD2 */ at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA4, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA5, 0); /* CTS2 */ } static struct resource uart3_resources[] = { @@ -882,10 +897,15 @@ static struct platform_device at91sam9260_uart3_device = { .num_resources = ARRAY_SIZE(uart3_resources), }; -static inline void configure_usart3_pins(void) +static inline void configure_usart3_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD3 */ at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD3 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PC8, 0); /* RTS3 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PC10, 0); /* CTS3 */ } static struct resource uart4_resources[] = { @@ -967,7 +987,7 @@ static inline void configure_usart5_pins(void) static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -975,22 +995,22 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI); at91_uarts[i] = &at91sam9260_uart0_device; at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9260_uart1_device; at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(0); at91_uarts[i] = &at91sam9260_uart2_device; at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart"); break; case 3: - configure_usart3_pins(); + configure_usart3_pins(0); at91_uarts[i] = &at91sam9260_uart3_device; at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart"); break; @@ -1022,6 +1042,63 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91sam9260_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US0: + pdev = &at91sam9260_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US1: + pdev = &at91sam9260_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US2: + pdev = &at91sam9260_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US3: + pdev = &at91sam9260_uart3_device; + configure_usart3_pins(pins); + at91_clock_associate("usart3_clk", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US4: + pdev = &at91sam9260_uart4_device; + configure_usart4_pins(); + at91_clock_associate("usart4_clk", &pdev->dev, "usart"); + break; + case AT91SAM9260_ID_US5: + pdev = &at91sam9260_uart5_device; + configure_usart5_pins(); + at91_clock_associate("usart5_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -1032,7 +1109,9 @@ void __init at91_add_device_serial(void) } } #else -void __init at91_init_serial(struct at91_uart_config *config) {} +void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index ba84ba6f18fb..467a6431d71a 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -867,12 +867,15 @@ static struct platform_device at91sam9261_uart0_device = { .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PC8, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PC9, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */ - at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */ } static struct resource uart1_resources[] = { @@ -907,10 +910,15 @@ static struct platform_device at91sam9261_uart1_device = { .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PC12, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PC13, 0); /* RXD1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA12, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA13, 0); /* CTS1 */ } static struct resource uart2_resources[] = { @@ -945,16 +953,21 @@ static struct platform_device at91sam9261_uart2_device = { .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PC15, 0); /* RXD2 */ at91_set_A_periph(AT91_PIN_PC14, 1); /* TXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA15, 0); /* RTS2*/ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA16, 0); /* CTS2 */ } static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -962,17 +975,17 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9261_uart0_device; at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(0); at91_uarts[i] = &at91sam9261_uart1_device; at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(0); at91_uarts[i] = &at91sam9261_uart2_device; at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart"); break; @@ -994,6 +1007,48 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91sam9261_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91SAM9261_ID_US0: + pdev = &at91sam9261_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91SAM9261_ID_US1: + pdev = &at91sam9261_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91SAM9261_ID_US2: + pdev = &at91sam9261_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -1004,7 +1059,9 @@ void __init at91_add_device_serial(void) } } #else -void __init at91_init_serial(struct at91_uart_config *config) {} +void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index c025f5c5ffaa..a9f35d0c1cb0 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -1071,12 +1071,15 @@ static struct platform_device at91sam9263_uart0_device = { .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ - at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ } static struct resource uart1_resources[] = { @@ -1111,12 +1114,15 @@ static struct platform_device at91sam9263_uart1_device = { .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */ - at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ - at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ } static struct resource uart2_resources[] = { @@ -1151,18 +1157,21 @@ static struct platform_device at91sam9263_uart2_device = { .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */ at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */ - at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ - at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ } static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -1170,17 +1179,17 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9263_uart0_device; at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9263_uart1_device; at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9263_uart2_device; at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart"); break; @@ -1202,6 +1211,48 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91sam9263_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91SAM9263_ID_US0: + pdev = &at91sam9263_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91SAM9263_ID_US1: + pdev = &at91sam9263_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91SAM9263_ID_US2: + pdev = &at91sam9263_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -1213,6 +1264,8 @@ void __init at91_add_device_serial(void) } #else void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index e886cdfe919d..a942b9e35560 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -676,12 +676,23 @@ static struct platform_device at91sam9rl_uart0_device = { .num_resources = ARRAY_SIZE(uart0_resources), }; -static inline void configure_usart0_pins(void) +static inline void configure_usart0_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA6, 1); /* TXD0 */ at91_set_A_periph(AT91_PIN_PA7, 0); /* RXD0 */ - at91_set_A_periph(AT91_PIN_PA9, 0); /* RTS0 */ - at91_set_A_periph(AT91_PIN_PA10, 0); /* CTS0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA9, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA10, 0); /* CTS0 */ + if (pins & ATMEL_UART_DSR) + at91_set_A_periph(AT91_PIN_PD14, 0); /* DSR0 */ + if (pins & ATMEL_UART_DTR) + at91_set_A_periph(AT91_PIN_PD15, 0); /* DTR0 */ + if (pins & ATMEL_UART_DCD) + at91_set_A_periph(AT91_PIN_PD16, 0); /* DCD0 */ + if (pins & ATMEL_UART_RI) + at91_set_A_periph(AT91_PIN_PD17, 0); /* RI0 */ } static struct resource uart1_resources[] = { @@ -716,10 +727,15 @@ static struct platform_device at91sam9rl_uart1_device = { .num_resources = ARRAY_SIZE(uart1_resources), }; -static inline void configure_usart1_pins(void) +static inline void configure_usart1_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA11, 1); /* TXD1 */ at91_set_A_periph(AT91_PIN_PA12, 0); /* RXD1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA18, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA19, 0); /* CTS1 */ } static struct resource uart2_resources[] = { @@ -754,10 +770,15 @@ static struct platform_device at91sam9rl_uart2_device = { .num_resources = ARRAY_SIZE(uart2_resources), }; -static inline void configure_usart2_pins(void) +static inline void configure_usart2_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PA13, 1); /* TXD2 */ at91_set_A_periph(AT91_PIN_PA14, 0); /* RXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA29, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA30, 0); /* CTS2 */ } static struct resource uart3_resources[] = { @@ -792,16 +813,21 @@ static struct platform_device at91sam9rl_uart3_device = { .num_resources = ARRAY_SIZE(uart3_resources), }; -static inline void configure_usart3_pins(void) +static inline void configure_usart3_pins(unsigned pins) { at91_set_A_periph(AT91_PIN_PB0, 1); /* TXD3 */ at91_set_A_periph(AT91_PIN_PB1, 0); /* RXD3 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PD4, 0); /* RTS3 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PD3, 0); /* CTS3 */ } static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ struct platform_device *atmel_default_console_device; /* the serial console device */ -void __init at91_init_serial(struct at91_uart_config *config) +void __init __deprecated at91_init_serial(struct at91_uart_config *config) { int i; @@ -809,22 +835,22 @@ void __init at91_init_serial(struct at91_uart_config *config) for (i = 0; i < config->nr_tty; i++) { switch (config->tty_map[i]) { case 0: - configure_usart0_pins(); + configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS); at91_uarts[i] = &at91sam9rl_uart0_device; at91_clock_associate("usart0_clk", &at91sam9rl_uart0_device.dev, "usart"); break; case 1: - configure_usart1_pins(); + configure_usart1_pins(0); at91_uarts[i] = &at91sam9rl_uart1_device; at91_clock_associate("usart1_clk", &at91sam9rl_uart1_device.dev, "usart"); break; case 2: - configure_usart2_pins(); + configure_usart2_pins(0); at91_uarts[i] = &at91sam9rl_uart2_device; at91_clock_associate("usart2_clk", &at91sam9rl_uart2_device.dev, "usart"); break; case 3: - configure_usart3_pins(); + configure_usart3_pins(0); at91_uarts[i] = &at91sam9rl_uart3_device; at91_clock_associate("usart3_clk", &at91sam9rl_uart3_device.dev, "usart"); break; @@ -846,6 +872,53 @@ void __init at91_init_serial(struct at91_uart_config *config) printk(KERN_INFO "AT91: No default serial console defined.\n"); } +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91sam9rl_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91SAM9RL_ID_US0: + pdev = &at91sam9rl_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91SAM9RL_ID_US1: + pdev = &at91sam9rl_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91SAM9RL_ID_US2: + pdev = &at91sam9rl_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + case AT91SAM9RL_ID_US3: + pdev = &at91sam9rl_uart3_device; + configure_usart3_pins(pins); + at91_clock_associate("usart3_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + void __init at91_add_device_serial(void) { int i; @@ -856,7 +929,9 @@ void __init at91_add_device_serial(void) } } #else -void __init at91_init_serial(struct at91_uart_config *config) {} +void __init __deprecated at91_init_serial(struct at91_uart_config *config) {} +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index 7fefe018833c..3f41ab28b37f 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -101,13 +101,23 @@ extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_de extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices); /* Serial */ +#define ATMEL_UART_CTS 0x01 +#define ATMEL_UART_RTS 0x02 +#define ATMEL_UART_DSR 0x04 +#define ATMEL_UART_DTR 0x08 +#define ATMEL_UART_DCD 0x10 +#define ATMEL_UART_RI 0x20 + +extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins); +extern void __init at91_set_serial_console(unsigned portnr); + struct at91_uart_config { unsigned short console_tty; /* tty number of serial console */ unsigned short nr_tty; /* number of serial tty's */ short tty_map[]; /* map UART to tty number */ }; extern struct platform_device *atmel_default_console_device; -extern void __init at91_init_serial(struct at91_uart_config *config); +extern void __init __deprecated at91_init_serial(struct at91_uart_config *config); struct atmel_uart_data { short use_dma_tx; /* use transmit DMA? */ -- cgit v1.2.3 From a04ff1af9723607f5901b79c559357e37cee6823 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 23 Jan 2008 09:27:06 +0100 Subject: [ARM] 4758/1: [AT91] LEDs Move the LED initialization code out of the various *_devices.c files, and into leds.c. Also add support for NEW_LEDs. Patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/at91rm9200_devices.c | 22 ----------- arch/arm/mach-at91/at91sam9260_devices.c | 22 ----------- arch/arm/mach-at91/at91sam9261_devices.c | 22 ----------- arch/arm/mach-at91/at91sam9263_devices.c | 22 ----------- arch/arm/mach-at91/at91sam9rl_devices.c | 22 ----------- arch/arm/mach-at91/leds.c | 68 +++++++++++++++++++++++++++++++- include/asm-arm/arch-at91/board.h | 4 +- 8 files changed, 70 insertions(+), 114 deletions(-) (limited to 'include/asm-arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index a8a009c2cf7d..529ffb5f3f13 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o obj-$(CONFIG_MACH_AT91EB01) += board-eb01.o # Drivers -obj-$(CONFIG_LEDS) += leds.o +obj-y += leds.o # Power Management obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 23966229ea9a..ea9a952fb877 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -613,28 +613,6 @@ static void __init at91_add_device_watchdog(void) {} #endif -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); - - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - /* -------------------------------------------------------------------- * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 5dd06bdccb00..105f8403860b 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -584,28 +584,6 @@ static void __init at91_add_device_watchdog(void) {} #endif -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); - - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - /* -------------------------------------------------------------------- * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 467a6431d71a..57d7e3bd05db 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -596,28 +596,6 @@ static void __init at91_add_device_watchdog(void) {} #endif -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); - - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - /* -------------------------------------------------------------------- * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index a9f35d0c1cb0..0b12e1adcc8e 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -843,28 +843,6 @@ static void __init at91_add_device_watchdog(void) {} #endif -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); - - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - /* -------------------------------------------------------------------- * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index a942b9e35560..f43b5c33e45d 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -449,28 +449,6 @@ static void __init at91_add_device_watchdog(void) {} #endif -/* -------------------------------------------------------------------- - * LEDs - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_LEDS) -u8 at91_leds_cpu; -u8 at91_leds_timer; - -void __init at91_init_leds(u8 cpu_led, u8 timer_led) -{ - /* Enable GPIO to access the LEDs */ - at91_set_gpio_output(cpu_led, 1); - at91_set_gpio_output(timer_led, 1); - - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; -} -#else -void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} -#endif - - /* -------------------------------------------------------------------- * SSC -- Synchronous Serial Controller * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c index 0d5144973988..9cdcda500fe8 100644 --- a/arch/arm/mach-at91/leds.c +++ b/arch/arm/mach-at91/leds.c @@ -14,11 +14,62 @@ #include #include -#include #include #include +/* ------------------------------------------------------------------------- */ + +#if defined(CONFIG_NEW_LEDS) + +#include + +/* + * New cross-platform LED support. + */ + +static struct gpio_led_platform_data led_data; + +static struct platform_device at91_leds = { + .name = "leds-gpio", + .id = -1, + .dev.platform_data = &led_data, +}; + +void __init at91_gpio_leds(struct gpio_led *leds, int nr) +{ + int i; + + if (!nr) + return; + + for (i = 0; i < nr; i++) + at91_set_gpio_output(leds[i].gpio, leds[i].active_low); + + led_data.leds = leds; + led_data.num_leds = nr; + platform_device_register(&at91_leds); +} + +#else +void __init at91_gpio_leds(struct gpio_led *leds, int nr) {} +#endif + + +/* ------------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) + +#include + +/* + * Old ARM-specific LED framework; not fully functional when generic time is + * in use. + */ + +static u8 at91_leds_cpu; +static u8 at91_leds_timer; + static inline void at91_led_on(unsigned int led) { at91_set_gpio_value(led, 0); @@ -93,3 +144,18 @@ static int __init leds_init(void) } __initcall(leds_init); + + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + /* Enable GPIO to access the LEDs */ + at91_set_gpio_output(cpu_led, 1); + at91_set_gpio_output(timer_led, 1); + + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} + +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index 3f41ab28b37f..e88ad8621c17 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -34,6 +34,7 @@ #include #include #include +#include #include /* USB Device */ @@ -157,9 +158,8 @@ extern void __init at91_add_device_ac97(struct atmel_ac97_data *data); extern void __init at91_add_device_isi(void); /* LEDs */ -extern u8 at91_leds_cpu; -extern u8 at91_leds_timer; extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); +extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); /* FIXME: this needs a better location, but gets stuff building again */ extern int at91_suspend_entering_slow_clock(void); -- cgit v1.2.3 From 2b3b3516b6eeea1464e205b2dde9ebc9b7dd2ec8 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 24 Jan 2008 15:10:39 +0100 Subject: [ARM] 4764/1: [AT91] AT91CAP9 core support Add support for Atmel's AT91CAP9 Customizable Microcontroller family. Signed-off-by: Stelian Pop Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/Kconfig | 4 +- arch/arm/mach-at91/Kconfig | 3 + arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/Makefile.boot | 7 +- arch/arm/mach-at91/at91cap9.c | 365 ++++++++ arch/arm/mach-at91/at91cap9_devices.c | 1066 ++++++++++++++++++++++++ arch/arm/mach-at91/clock.c | 2 + arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/pm.c | 5 + arch/arm/mm/Kconfig | 4 +- drivers/net/Kconfig | 2 +- drivers/usb/gadget/Kconfig | 2 +- drivers/video/Kconfig | 2 +- drivers/video/atmel_lcdfb.c | 2 +- include/asm-arm/arch-at91/at91_pmc.h | 7 +- include/asm-arm/arch-at91/at91cap9.h | 121 +++ include/asm-arm/arch-at91/at91cap9_matrix.h | 132 +++ include/asm-arm/arch-at91/at91sam9263_matrix.h | 2 +- include/asm-arm/arch-at91/at91sam9rl_matrix.h | 2 +- include/asm-arm/arch-at91/board.h | 2 +- include/asm-arm/arch-at91/cpu.h | 9 +- include/asm-arm/arch-at91/hardware.h | 2 + include/asm-arm/arch-at91/timex.h | 5 + include/asm-avr32/arch-at32ap/cpu.h | 1 + 24 files changed, 1735 insertions(+), 15 deletions(-) create mode 100644 arch/arm/mach-at91/at91cap9.c create mode 100644 arch/arm/mach-at91/at91cap9_devices.c create mode 100644 include/asm-arm/arch-at91/at91cap9.h create mode 100644 include/asm-arm/arch-at91/at91cap9_matrix.h (limited to 'include/asm-arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 93e40b65fd0b..0bd479c47651 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -180,8 +180,8 @@ config ARCH_AT91 bool "Atmel AT91" select GENERIC_GPIO help - This enables support for systems based on the Atmel AT91RM9200 - and AT91SAM9xxx processors. + This enables support for systems based on the Atmel AT91RM9200, + AT91SAM9 and AT91CAP9 processors. config ARCH_CLPS7500 bool "Cirrus CL-PS7500FE" diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 214733e897e5..d12c616407d6 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -22,6 +22,9 @@ config ARCH_AT91SAM9263 config ARCH_AT91SAM9RL bool "AT91SAM9RL" +config ARCH_AT91CAP9 + bool "AT91CAP9" + config ARCH_AT91X40 bool "AT91x40" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 529ffb5f3f13..10413c5d3f8a 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_d obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o +obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o # AT91RM9200 board-specific support diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index e667dcc7cd34..071a2506a69f 100644 --- a/arch/arm/mach-at91/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot @@ -3,7 +3,12 @@ # PARAMS_PHYS must be within 4MB of ZRELADDR # INITRD_PHYS must be in RAM +ifeq ($(CONFIG_ARCH_AT91CAP9),y) + zreladdr-y := 0x70008000 +params_phys-y := 0x70000100 +initrd_phys-y := 0x70410000 +else zreladdr-y := 0x20008000 params_phys-y := 0x20000100 initrd_phys-y := 0x20410000 - +endif diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c new file mode 100644 index 000000000000..48d27d8000b0 --- /dev/null +++ b/arch/arm/mach-at91/at91cap9.c @@ -0,0 +1,365 @@ +/* + * arch/arm/mach-at91/at91cap9.c + * + * Copyright (C) 2007 Stelian Pop + * Copyright (C) 2007 Lead Tech Design + * Copyright (C) 2007 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91cap9_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91CAP9_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91CAP9_SRAM_BASE), + .length = AT91CAP9_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioABCD_clk = { + .name = "pioABCD_clk", + .pmc_mask = 1 << AT91CAP9_ID_PIOABCD, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mpb0_clk = { + .name = "mpb0_clk", + .pmc_mask = 1 << AT91CAP9_ID_MPB0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mpb1_clk = { + .name = "mpb1_clk", + .pmc_mask = 1 << AT91CAP9_ID_MPB1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mpb2_clk = { + .name = "mpb2_clk", + .pmc_mask = 1 << AT91CAP9_ID_MPB2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mpb3_clk = { + .name = "mpb3_clk", + .pmc_mask = 1 << AT91CAP9_ID_MPB3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mpb4_clk = { + .name = "mpb4_clk", + .pmc_mask = 1 << AT91CAP9_ID_MPB4, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91CAP9_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91CAP9_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91CAP9_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc0_clk = { + .name = "mci0_clk", + .pmc_mask = 1 << AT91CAP9_ID_MCI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc1_clk = { + .name = "mci1_clk", + .pmc_mask = 1 << AT91CAP9_ID_MCI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk can_clk = { + .name = "can_clk", + .pmc_mask = 1 << AT91CAP9_ID_CAN, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91CAP9_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91CAP9_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91CAP9_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc0_clk = { + .name = "ssc0_clk", + .pmc_mask = 1 << AT91CAP9_ID_SSC0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc1_clk = { + .name = "ssc1_clk", + .pmc_mask = 1 << AT91CAP9_ID_SSC1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ac97_clk = { + .name = "ac97_clk", + .pmc_mask = 1 << AT91CAP9_ID_AC97C, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tcb_clk = { + .name = "tcb_clk", + .pmc_mask = 1 << AT91CAP9_ID_TCB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pwmc_clk = { + .name = "pwmc_clk", + .pmc_mask = 1 << AT91CAP9_ID_PWMC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk macb_clk = { + .name = "macb_clk", + .pmc_mask = 1 << AT91CAP9_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk aestdes_clk = { + .name = "aestdes_clk", + .pmc_mask = 1 << AT91CAP9_ID_AESTDES, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk adc_clk = { + .name = "adc_clk", + .pmc_mask = 1 << AT91CAP9_ID_ADC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91CAP9_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91CAP9_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk dma_clk = { + .name = "dma_clk", + .pmc_mask = 1 << AT91CAP9_ID_DMA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udphs_clk = { + .name = "udphs_clk", + .pmc_mask = 1 << AT91CAP9_ID_UDPHS, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91CAP9_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioABCD_clk, + &mpb0_clk, + &mpb1_clk, + &mpb2_clk, + &mpb3_clk, + &mpb4_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc0_clk, + &mmc1_clk, + &can_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + &ssc0_clk, + &ssc1_clk, + &ac97_clk, + &tcb_clk, + &pwmc_clk, + &macb_clk, + &aestdes_clk, + &adc_clk, + &isi_clk, + &lcdc_clk, + &dma_clk, + &udphs_clk, + &ohci_clk, + // irq0 .. irq1 +}; + +/* + * The four programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +static void __init at91cap9_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91cap9_gpio[] = { + { + .id = AT91CAP9_ID_PIOABCD, + .offset = AT91_PIOA, + .clock = &pioABCD_clk, + }, { + .id = AT91CAP9_ID_PIOABCD, + .offset = AT91_PIOB, + .clock = &pioABCD_clk, + }, { + .id = AT91CAP9_ID_PIOABCD, + .offset = AT91_PIOC, + .clock = &pioABCD_clk, + }, { + .id = AT91CAP9_ID_PIOABCD, + .offset = AT91_PIOD, + .clock = &pioABCD_clk, + } +}; + +static void at91cap9_reset(void) +{ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + +/* -------------------------------------------------------------------- + * AT91CAP9 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91cap9_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc)); + + at91_arch_reset = at91cap9_reset; + at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91cap9_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91cap9_gpio, 4); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91cap9_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller (FIQ) */ + 7, /* System Peripherals */ + 1, /* Parallel IO Controller A, B, C and D */ + 0, /* MP Block Peripheral 0 */ + 0, /* MP Block Peripheral 1 */ + 0, /* MP Block Peripheral 2 */ + 0, /* MP Block Peripheral 3 */ + 0, /* MP Block Peripheral 4 */ + 5, /* USART 0 */ + 5, /* USART 1 */ + 5, /* USART 2 */ + 0, /* Multimedia Card Interface 0 */ + 0, /* Multimedia Card Interface 1 */ + 3, /* CAN */ + 6, /* Two-Wire Interface */ + 5, /* Serial Peripheral Interface 0 */ + 5, /* Serial Peripheral Interface 1 */ + 4, /* Serial Synchronous Controller 0 */ + 4, /* Serial Synchronous Controller 1 */ + 5, /* AC97 Controller */ + 0, /* Timer Counter 0, 1 and 2 */ + 0, /* Pulse Width Modulation Controller */ + 3, /* Ethernet */ + 0, /* Advanced Encryption Standard, Triple DES*/ + 0, /* Analog-to-Digital Converter */ + 0, /* Image Sensor Interface */ + 3, /* LCD Controller */ + 0, /* DMA Controller */ + 2, /* USB Device Port */ + 2, /* USB Host port */ + 0, /* Advanced Interrupt Controller (IRQ0) */ + 0, /* Advanced Interrupt Controller (IRQ1) */ +}; + +void __init at91cap9_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91cap9_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c new file mode 100644 index 000000000000..c50fad9cd143 --- /dev/null +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -0,0 +1,1066 @@ +/* + * arch/arm/mach-at91/at91cap9_devices.c + * + * Copyright (C) 2007 Stelian Pop + * Copyright (C) 2007 Lead Tech Design + * Copyright (C) 2007 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include + +#include +#include +#include + +#include