diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-at91/Makefile | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260_devices.c | 198 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9263.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9263_devices.c | 133 | ||||
-rw-r--r-- | arch/arm/mach-at91/clocksource.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-at91/gpio.c | 181 | ||||
-rw-r--r-- | arch/arm/mach-at91/lowlevel_init.S | 278 | ||||
-rw-r--r-- | arch/arm/mach-at91/sam9_smc.c | 48 |
9 files changed, 803 insertions, 90 deletions
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index cec148c2ed..c848919e57 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,3 +1,7 @@ obj-y += clocksource.o gpio.o -obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam9260_devices.o -obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o + +obj-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += lowlevel_init.o + +# CPU-specific support +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam9260_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o sam9_smc.o diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 04e954b039..1a6e356482 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -5,14 +5,14 @@ static struct at91_gpio_bank at91sam9260_gpio[] = { { - .id = AT91C_ID_PIOA, - .regbase = (void __iomem *)AT91C_BASE_PIOA, + .id = AT91SAM9260_ID_PIOA, + .offset = AT91_PIOA, }, { - .id = AT91C_ID_PIOB, - .regbase = (void __iomem *)AT91C_BASE_PIOB, + .id = AT91SAM9260_ID_PIOB, + .offset = AT91_PIOB, }, { - .id = AT91C_ID_PIOC, - .regbase = (void __iomem *)AT91C_BASE_PIOC, + .id = AT91SAM9260_ID_PIOC, + .offset = AT91_PIOC, } }; diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 04f8f4a922..5e321c1e7b 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -13,6 +13,10 @@ #include <asm/armlinux.h> #include <asm/hardware.h> #include <asm/arch/board.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91sam9260_matrix.h> +#include <asm/arch/gpio.h> +#include <asm/arch/io.h> static struct memory_platform_data sram_pdata = { .name = "sram0", @@ -21,7 +25,7 @@ static struct memory_platform_data sram_pdata = { static struct device_d sdram_dev = { .name = "mem", - .map_base = 0x20000000, + .map_base = AT91_CHIPSELECT_1, .platform_data = &sram_pdata, }; @@ -35,7 +39,7 @@ void at91_add_device_sdram(u32 size) #if defined(CONFIG_DRIVER_NET_MACB) static struct device_d macb_dev = { .name = "macb", - .map_base = AT91C_BASE_EMACB, + .map_base = AT91SAM9260_BASE_EMAC, .size = 0x1000, }; @@ -44,6 +48,29 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) if (!data) return; + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA21, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* EMDC */ + + if (!(data->flags & AT91SAM_ETHER_RMII)) { + at91_set_B_periph(AT91_PIN_PA28, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PA29, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */ + } + macb_dev.platform_data = data; register_device(&macb_dev); } @@ -54,12 +81,34 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) {} #if defined(CONFIG_NAND_ATMEL) static struct device_d nand_dev = { .name = "atmel_nand", - .map_base = 0x40000000, + .map_base = AT91_CHIPSELECT_3, .size = 0x10, }; void at91_add_device_nand(struct atmel_nand_data *data) { + unsigned long csa; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_PIOC); + nand_dev.platform_data = data; register_device(&nand_dev); } @@ -69,18 +118,155 @@ void at91_add_device_nand(struct atmel_nand_data *data) {} static struct device_d dbgu_serial_device = { .name = "atmel_serial", - .map_base = AT91C_BASE_DBGU, + .map_base = AT91_BASE_SYS + AT91_DBGU, + .size = 4096, +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB14, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PB15, 1); /* DTXD */ +} + +static struct device_d uart0_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US0, + .size = 4096, +}; + +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 */ + + 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 device_d uart1_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US1, + .size = 4096, +}; + +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 */ + + 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 device_d uart2_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US2, + .size = 4096, +}; + +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 device_d uart3_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US3, + .size = 4096, +}; + +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 device_d uart4_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US4, .size = 4096, }; -void at91_register_uart(unsigned id) +static inline void configure_usart4_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA31, 1); /* TXD4 */ + at91_set_B_periph(AT91_PIN_PA30, 0); /* RXD4 */ +} + +static struct device_d uart5_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9260_BASE_US5, + .size = 4096, +}; + +static inline void configure_usart5_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB12, 1); /* TXD5 */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */ +} + +void at91_register_uart(unsigned id, unsigned pins) { switch (id) { case 0: /* DBGU */ + configure_dbgu_pins(); + at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_SYS); register_device(&dbgu_serial_device); break; + case AT91SAM9260_ID_US0: + configure_usart0_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US0); + register_device(&uart0_serial_device); + break; + case AT91SAM9260_ID_US1: + configure_usart1_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US1); + register_device(&uart1_serial_device); + break; + case AT91SAM9260_ID_US2: + configure_usart2_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US2); + register_device(&uart2_serial_device); + break; + case AT91SAM9260_ID_US3: + configure_usart3_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US3); + register_device(&uart3_serial_device); + break; + case AT91SAM9260_ID_US4: + configure_usart4_pins(); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US4); + register_device(&uart4_serial_device); + break; + case AT91SAM9260_ID_US5: + configure_usart5_pins(); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US5); + register_device(&uart5_serial_device); + break; default: return; } - } diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 8688b979eb..472b619863 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -5,21 +5,27 @@ static struct at91_gpio_bank at91sam9263_gpio[] = { { - .id = AT91C_ID_PIOA, - .regbase = (void __iomem *)AT91C_BASE_PIOA, + .id = AT91SAM9263_ID_PIOA, + .offset = AT91_PIOA, }, { - .id = AT91C_ID_PIOB, - .regbase = (void __iomem *)AT91C_BASE_PIOB, + .id = AT91SAM9263_ID_PIOB, + .offset = AT91_PIOB, }, { - .id = AT91C_ID_PIOCDE, - .regbase = (void __iomem *)AT91C_BASE_PIOC, + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOC, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOD, + }, { + .id = AT91SAM9263_ID_PIOCDE, + .offset = AT91_PIOE, } }; static int at91sam9263_initialize(void) { /* Register GPIO subsystem */ - at91_gpio_init(at91sam9263_gpio, 3); + at91_gpio_init(at91sam9263_gpio, 5); return 0; } diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 4eb71f8482..83b733f58b 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -12,7 +12,11 @@ #include <common.h> #include <asm/armlinux.h> #include <asm/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91sam9263_matrix.h> #include <asm/arch/board.h> +#include <asm/arch/gpio.h> +#include <asm/arch/io.h> static struct memory_platform_data ram_pdata = { .name = "ram0", @@ -21,7 +25,7 @@ static struct memory_platform_data ram_pdata = { static struct device_d sdram_dev = { .name = "mem", - .map_base = 0x20000000, + .map_base = AT91_CHIPSELECT_1, .platform_data = &ram_pdata, }; @@ -35,7 +39,7 @@ void at91_add_device_sdram(u32 size) #if defined(CONFIG_DRIVER_NET_MACB) static struct device_d macb_dev = { .name = "macb", - .map_base = AT91C_BASE_MACB, + .map_base = AT91SAM9263_BASE_EMAC, .size = 0x1000, }; @@ -44,6 +48,28 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) if (!data) return; + at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */ + at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */ + + if (!(data->flags & AT91SAM_ETHER_RMII)) { + at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */ + } + macb_dev.platform_data = data; register_device(&macb_dev); } @@ -54,12 +80,35 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) {} #if defined(CONFIG_NAND_ATMEL) static struct device_d nand_dev = { .name = "atmel_nand", - .map_base = 0x40000000, + .map_base = AT91_CHIPSELECT_3, .size = 0x10, }; void at91_add_device_nand(struct atmel_nand_data *data) { + unsigned long csa; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBI0CSA); + at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_PIOA | + 1 << AT91SAM9263_ID_PIOCDE); + nand_dev.platform_data = data; register_device(&nand_dev); } @@ -69,16 +118,90 @@ void at91_add_device_nand(struct atmel_nand_data *data) {} static struct device_d dbgu_serial_device = { .name = "atmel_serial", - .map_base = AT91C_BASE_DBGU, + .map_base = (AT91_BASE_SYS + AT91_DBGU), + .size = 4096, +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ +} + +static struct device_d uart0_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9263_BASE_US0, + .size = 4096, +}; + +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 */ + + 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 device_d uart1_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9263_BASE_US1, .size = 4096, }; -void at91_register_uart(unsigned id) +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 */ + + 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 device_d uart2_serial_device = { + .name = "atmel_serial", + .map_base = AT91SAM9263_BASE_US2, + .size = 4096, +}; + +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 */ + + 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 */ +} + +void at91_register_uart(unsigned id, unsigned pins) { switch (id) { case 0: /* DBGU */ + configure_dbgu_pins(); + at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_SYS); register_device(&dbgu_serial_device); break; + case AT91SAM9263_ID_US0: + configure_usart0_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_US0); + register_device(&uart0_serial_device); + break; + case AT91SAM9263_ID_US1: + configure_usart1_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_US1); + register_device(&uart1_serial_device); + break; + case AT91SAM9263_ID_US2: + configure_usart2_pins(pins); + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_US2); + register_device(&uart2_serial_device); + break; default: return; } diff --git a/arch/arm/mach-at91/clocksource.c b/arch/arm/mach-at91/clocksource.c index 86a51d584e..d937e49c38 100644 --- a/arch/arm/mach-at91/clocksource.c +++ b/arch/arm/mach-at91/clocksource.c @@ -33,11 +33,15 @@ #include <init.h> #include <clock.h> #include <asm/hardware.h> +#include <asm/arch/at91_pit.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> +#include <asm/arch/io.h> #include <asm/io.h> uint64_t at91sam9_clocksource_read(void) { - return readl(AT91C_PITC_PIIR); + return at91_sys_read(AT91_PIT_PIIR); } static struct clocksource cs = { @@ -52,10 +56,10 @@ static int clocksource_init (void) * Enable PITC Clock * The clock is already enabled for system controller in boot */ - writel(1 << AT91C_ID_SYS, AT91C_PMC_PCER); + at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_SYS); /* Enable PITC */ - writel(0xfffff | AT91C_PITC_PITEN, AT91C_PITC_PIMR); + at91_sys_write(AT91_PIT_MR, 0xfffff | AT91_PIT_PITEN); cs.mult = clocksource_hz2mult(1000000 * 6, cs.shift); @@ -71,7 +75,8 @@ core_initcall(clocksource_init); */ void reset_cpu (ulong ignored) { - writel((0xa5 << 24) | AT91C_RSTC_PROCRST | AT91C_RSTC_PERRST, - AT91C_RSTC_RCR); + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | + AT91_RSTC_PROCRST | + AT91_RSTC_PERRST); } EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 09894b7fd0..b479a4f83a 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -24,43 +24,15 @@ #include <common.h> #include <errno.h> #include <asm/io.h> +#include <asm/arch/gpio.h> #include <gpio.h> -#define OFS_PIO_PER 0x00 /* Enable Register */ -#define OFS_PIO_PDR 0x04 /* Disable Register */ -#define OFS_PIO_PSR 0x08 /* Status Register */ -#define OFS_PIO_OER 0x10 /* Output Enable Register */ -#define OFS_PIO_ODR 0x14 /* Output Disable Register */ -#define OFS_PIO_OSR 0x18 /* Output Status Register */ -#define OFS_PIO_IFER 0x20 /* Glitch Input Filter Enable */ -#define OFS_PIO_IFDR 0x24 /* Glitch Input Filter Disable */ -#define OFS_PIO_IFSR 0x28 /* Glitch Input Filter Status */ -#define OFS_PIO_SODR 0x30 /* Set Output Data Register */ -#define OFS_PIO_CODR 0x34 /* Clear Output Data Register */ -#define OFS_PIO_ODSR 0x38 /* Output Data Status Register */ -#define OFS_PIO_PDSR 0x3c /* Pin Data Status Register */ -#define OFS_PIO_IER 0x40 /* Interrupt Enable Register */ -#define OFS_PIO_IDR 0x44 /* Interrupt Disable Register */ -#define OFS_PIO_IMR 0x48 /* Interrupt Mask Register */ -#define OFS_PIO_ISR 0x4c /* Interrupt Status Register */ -#define OFS_PIO_MDER 0x50 /* Multi-driver Enable Register */ -#define OFS_PIO_MDDR 0x54 /* Multi-driver Disable Register */ -#define OFS_PIO_MDSR 0x58 /* Multi-driver Status Register */ -#define OFS_PIO_PUDR 0x60 /* Pull-up Disable Register */ -#define OFS_PIO_PUER 0x64 /* Pull-up Enable Register */ -#define OFS_PIO_PUSR 0x68 /* Pull-up Status Register */ -#define OFS_PIO_ASR 0x70 /* Peripheral A Select Register */ -#define OFS_PIO_BSR 0x74 /* Peripheral B Select Register */ -#define OFS_PIO_ABSR 0x78 /* AB Status Register */ -#define OFS_PIO_OWER 0xa0 /* Output Write Enable Register */ -#define OFS_PIO_OWDR 0xa4 /* Output Write Disable Register */ -#define OFS_PIO_OWSR 0xa8 /* Output Write Status Register */ - static int gpio_banks; static struct at91_gpio_bank *gpio; static inline void __iomem *pin_to_controller(unsigned pin) { + pin -= PIN_BASE; pin /= 32; if (likely(pin < gpio_banks)) return gpio[pin].regbase; @@ -70,10 +42,66 @@ static inline void __iomem *pin_to_controller(unsigned pin) static inline unsigned pin_to_mask(unsigned pin) { + pin -= PIN_BASE; return 1 << (pin % 32); } /* + * mux the pin to the "GPIO" peripheral role. + */ +int at91_set_GPIO_periph(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_PER); + return 0; +} +EXPORT_SYMBOL(at91_set_GPIO_periph); + +/* + * mux the pin to the "A" internal peripheral role. + */ +int at91_set_A_periph(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_ASR); + __raw_writel(mask, pio + PIO_PDR); + return 0; +} +EXPORT_SYMBOL(at91_set_A_periph); + +/* + * mux the pin to the "B" internal peripheral role. + */ +int at91_set_B_periph(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_BSR); + __raw_writel(mask, pio + PIO_PDR); + return 0; +} +EXPORT_SYMBOL(at91_set_B_periph); + +/* * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and * configure it for an input. */ @@ -85,10 +113,10 @@ int at91_set_gpio_input(unsigned pin, int use_pullup) if (!pio) return -EINVAL; - writel(mask, pio + OFS_PIO_IDR); - writel(mask, pio + (use_pullup ? OFS_PIO_PUER : OFS_PIO_PUDR)); - writel(mask, pio + OFS_PIO_ODR); - writel(mask, pio + OFS_PIO_PER); + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_ODR); + __raw_writel(mask, pio + PIO_PER); return 0; } EXPORT_SYMBOL(at91_set_gpio_input); @@ -105,61 +133,66 @@ int at91_set_gpio_output(unsigned pin, int value) if (!pio) return -EINVAL; - writel(mask, pio + OFS_PIO_IDR); - writel(mask, pio + OFS_PIO_PUDR); - writel(mask, pio + (value ? OFS_PIO_SODR : OFS_PIO_CODR)); - writel(mask, pio + OFS_PIO_OER); - writel(mask, pio + OFS_PIO_PER); + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + PIO_PUDR); + __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); + __raw_writel(mask, pio + PIO_OER); + __raw_writel(mask, pio + PIO_PER); return 0; } EXPORT_SYMBOL(at91_set_gpio_output); -int gpio_direction_input(unsigned pin) +/* + * enable/disable the glitch filter; mostly used with IRQ handling. + */ +int at91_set_deglitch(unsigned pin, int is_on) { void __iomem *pio = pin_to_controller(pin); unsigned mask = pin_to_mask(pin); - if (!pio || !(readl(pio + OFS_PIO_PSR) & mask)) + if (!pio) return -EINVAL; - writel(mask, pio + OFS_PIO_ODR); + __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); return 0; } -EXPORT_SYMBOL(gpio_direction_input); +EXPORT_SYMBOL(at91_set_deglitch); -int gpio_direction_output(unsigned pin, int value) +/* + * enable/disable the multi-driver; This is only valid for output and + * allows the output pin to run as an open collector output. + */ +int at91_set_multi_drive(unsigned pin, int is_on) { void __iomem *pio = pin_to_controller(pin); unsigned mask = pin_to_mask(pin); - if (!pio || !(readl(pio + OFS_PIO_PSR) & mask)) + if (!pio) return -EINVAL; - writel(mask, pio + (value ? OFS_PIO_SODR : OFS_PIO_CODR)); - writel(mask, pio + OFS_PIO_OER); + + __raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR)); return 0; } -EXPORT_SYMBOL(gpio_direction_output); - -/*--------------------------------------------------------------------------*/ +EXPORT_SYMBOL(at91_set_multi_drive); /* * assuming the pin is muxed as a gpio output, set its value. */ -void gpio_set_value(unsigned pin, int value) +int at91_set_gpio_value(unsigned pin, int value) { void __iomem *pio = pin_to_controller(pin); unsigned mask = pin_to_mask(pin); if (!pio) - return; - writel(mask, pio + (value ? OFS_PIO_SODR : OFS_PIO_CODR)); + return -EINVAL; + __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); + return 0; } -EXPORT_SYMBOL(gpio_set_value); - +EXPORT_SYMBOL(at91_set_gpio_value); /* * read the pin's value (works even if it's not muxed as a gpio). */ -int gpio_get_value(unsigned pin) +int at91_get_gpio_value(unsigned pin) { void __iomem *pio = pin_to_controller(pin); unsigned mask = pin_to_mask(pin); @@ -167,10 +200,37 @@ int gpio_get_value(unsigned pin) if (!pio) return -EINVAL; - pdsr = readl(pio + OFS_PIO_PDSR); + pdsr = __raw_readl(pio + PIO_PDSR); return (pdsr & mask) != 0; } -EXPORT_SYMBOL(gpio_get_value); +EXPORT_SYMBOL(at91_get_gpio_value); + +int gpio_direction_input(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio || !(__raw_readl(pio + PIO_PSR) & mask)) + return -EINVAL; + __raw_writel(mask, pio + PIO_ODR); + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned pin, int value) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio || !(__raw_readl(pio + PIO_PSR) & mask)) + return -EINVAL; + __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); + __raw_writel(mask, pio + PIO_OER); + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +/*--------------------------------------------------------------------------*/ int at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) { @@ -181,7 +241,10 @@ int at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) gpio_banks = nr_banks; for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) { - data->chipbase = i * 32; + data->chipbase = PIN_BASE + i * 32; + data->regbase = data->offset + + (void __iomem *)AT91_BASE_SYS; + /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */ if (last && last->id == data->id) diff --git a/arch/arm/mach-at91/lowlevel_init.S b/arch/arm/mach-at91/lowlevel_init.S new file mode 100644 index 0000000000..fa6577a6ab --- /dev/null +++ b/arch/arm/mach-at91/lowlevel_init.S @@ -0,0 +1,278 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at) + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <linux/autoconf.h> +#include <config.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_pio.h> +#include <asm/arch/at91_rstc.h> +#include <asm/arch/at91_wdt.h> +#include <asm/arch/at91sam9_matrix.h> +#include <asm/arch/at91sam9_sdramc.h> +#include <asm/arch/at91sam9_smc.h> + +_TEXT_BASE: + .word TEXT_BASE + +.globl board_init_lowlevel +.type board_init_lowlevel,function +board_init_lowlevel: + + mov r5, pc /* r5 = POS1 + 4 current */ +POS1: + ldr r0, =POS1 /* r0 = POS1 compile */ + ldr r2, _TEXT_BASE + sub r0, r0, r2 /* r0 = POS1-_TEXT_BASE (POS1 relative) */ + sub r5, r5, r0 /* r0 = TEXT_BASE-1 */ + sub r5, r5, #4 /* r1 = text base - current */ + + /* memory control configuration 1 */ + ldr r0, =SMRDATA + ldr r2, =SMRDATA1 + ldr r1, _TEXT_BASE + sub r0, r0, r1 + sub r2, r2, r1 + add r0, r0, r5 + add r2, r2, r5 +0: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 0b + +/* ---------------------------------------------------------------------------- + * PMC Init Step 1. + * ---------------------------------------------------------------------------- + * - Check if the PLL is already initialized + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_BASE_SYS + AT91_PMC_MCKR) + ldr r0, [r1] + and r0, r0, #3 + cmp r0, #0 + bne PLL_setup_end + +/* --------------------------------------------------------------------------- + * - Enable the Main Oscillator + * --------------------------------------------------------------------------- + */ + ldr r1, =(AT91_BASE_SYS + AT91_CKGR_MOR) + ldr r2, =(AT91_BASE_SYS + AT91_PMC_SR) + /* Main oscillator Enable register PMC_MOR: */ + ldr r0, =CONFIG_SYS_MOR_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Main Oscillator is enabled */ + mov r4, #AT91_PMC_MOSCS +MOSCS_Loop: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_MOSCS + bne MOSCS_Loop + +/* ---------------------------------------------------------------------------- + * PMC Init Step 2. + * ---------------------------------------------------------------------------- + * Setup PLLA + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_BASE_SYS + AT91_CKGR_PLLAR) + ldr r0, =CONFIG_SYS_PLLAR_VAL + str r0, [r1] + + /* Reading the PMC Status register to detect when the PLLA is locked */ + mov r4, #AT91_PMC_LOCKA +MOSCS_Loop1: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_LOCKA + bne MOSCS_Loop1 + +/* ---------------------------------------------------------------------------- + * PMC Init Step 3. + * ---------------------------------------------------------------------------- + * - Switch on the Main Oscillator + * ---------------------------------------------------------------------------- + */ + ldr r1, =(AT91_BASE_SYS + AT91_PMC_MCKR) + + /* -Master Clock Controller register PMC_MCKR */ + ldr r0, =CONFIG_SYS_MCKR1_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Master clock is ready */ + mov r4, #AT91_PMC_MCKRDY +MCKRDY_Loop: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_MCKRDY + bne MCKRDY_Loop + + ldr r0, =CONFIG_SYS_MCKR2_VAL + str r0, [r1] + + /* Reading the PMC Status to detect when the Master clock is ready */ + mov r4, #AT91_PMC_MCKRDY +MCKRDY_Loop1: + ldr r3, [r2] + and r3, r4, r3 + cmp r3, #AT91_PMC_MCKRDY + bne MCKRDY_Loop1 + +PLL_setup_end: + +/* ---------------------------------------------------------------------------- + * - memory control configuration 2 + * ---------------------------------------------------------------------------- + */ + ldr r0, =(AT91_BASE_SYS + AT91_SDRAMC_TR) + ldr r1, [r0] + cmp r1, #0 + bne SDRAM_setup_end + + ldr r0, =SMRDATA1 + ldr r2, =SMRDATA2 + ldr r1, _TEXT_BASE + sub r0, r0, r1 + sub r2, r2, r1 + add r0, r0, r5 + add r2, r2, r5 + +2: + /* the address */ + ldr r1, [r0], #4 + /* the value */ + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 2b + +SDRAM_setup_end: + /* everything is fine now */ + mov pc, lr + + .ltorg + +SMRDATA: + .word (AT91_BASE_SYS + AT91_WDT_MR) + .word CONFIG_SYS_WDTC_WDMR_VAL + + /* configure PIOx as EBI0 D[16-31] */ +#if defined(CONFIG_ARCH_AT91SAM9263) + .word (AT91_BASE_SYS + AT91_PIOD + PIO_PDR) + .word CONFIG_SYS_PIOD_PDR_VAL1 + .word (AT91_BASE_SYS + AT91_PIOD + PIO_PUDR) + .word CONFIG_SYS_PIOD_PPUDR_VAL + .word (AT91_BASE_SYS + AT91_PIOD + PIO_ASR) + .word CONFIG_SYS_PIOD_PPUDR_VAL +#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261) + .word (AT91_BASE_SYS + AT91_PIOC + PIO_PDR) + .word CONFIG_SYS_PIOC_PDR_VAL1 + .word (AT91_BASE_SYS + AT91_PIOC + PIO_PUDR) + .word CONFIG_SYS_PIOC_PPUDR_VAL +#endif + +#if defined(AT91_MATRIX_EBI0CSA) + .word (AT91_BASE_SYS + AT91_MATRIX_EBI0CSA) + .word CONFIG_SYS_MATRIX_EBI0CSA_VAL +#else /* AT91_MATRIX_EBICSA */ + .word (AT91_BASE_SYS + AT91_MATRIX_EBICSA) + .word CONFIG_SYS_MATRIX_EBICSA_VAL +#endif + + /* flash */ + .word (AT91_BASE_SYS + AT91_SMC_MODE(0)) + .word CONFIG_SYS_SMC0_MODE0_VAL + + .word (AT91_BASE_SYS + AT91_SMC_CYCLE(0)) + .word CONFIG_SYS_SMC0_CYCLE0_VAL + + .word (AT91_BASE_SYS + AT91_SMC_PULSE(0)) + .word CONFIG_SYS_SMC0_PULSE0_VAL + + .word (AT91_BASE_SYS + AT91_SMC_SETUP(0)) + .word CONFIG_SYS_SMC0_SETUP0_VAL + +SMRDATA1: + .word (AT91_BASE_SYS + AT91_SDRAMC_MR) + .word CONFIG_SYS_SDRC_MR_VAL1 + .word (AT91_BASE_SYS + AT91_SDRAMC_TR) + .word CONFIG_SYS_SDRC_TR_VAL1 + .word (AT91_BASE_SYS + AT91_SDRAMC_CR) + .word CONFIG_SYS_SDRC_CR_VAL + .word (AT91_BASE_SYS + AT91_SDRAMC_MDR) + .word CONFIG_SYS_SDRC_MDR_VAL + .word (AT91_BASE_SYS + AT91_SDRAMC_MR) + .word CONFIG_SYS_SDRC_MR_VAL2 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL1 + .word (AT91_BASE_SYS + AT91_SDRAMC_MR) + .word CONFIG_SYS_SDRC_MR_VAL3 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL2 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL3 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL4 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL5 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL6 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL7 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL8 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL9 + .word (AT91_BASE_SYS + AT91_SDRAMC_MR) + .word CONFIG_SYS_SDRC_MR_VAL4 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL10 + .word (AT91_BASE_SYS + AT91_SDRAMC_MR) + .word CONFIG_SYS_SDRC_MR_VAL5 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL11 + .word (AT91_BASE_SYS + AT91_SDRAMC_TR) + .word CONFIG_SYS_SDRC_TR_VAL2 + .word AT91_SDRAM_BASE + .word CONFIG_SYS_SDRAM_VAL12 + /* User reset enable*/ + .word (AT91_BASE_SYS + AT91_RSTC_MR) + .word CONFIG_SYS_RSTC_RMR_VAL +#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP + /* MATRIX_MCFG - REMAP all masters */ + .word (AT91_BASE_SYS + AT91_MATRIX_MCFG0) + .word 0x1FF +#endif + +SMRDATA2: + .word 0 diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c new file mode 100644 index 0000000000..f3f885c72b --- /dev/null +++ b/arch/arm/mach-at91/sam9_smc.c @@ -0,0 +1,48 @@ +/* + * linux/arch/arm/mach-at91/sam9_smc.c + * + * Copyright (C) 2008 Andrew Victor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/io.h> + +#include <asm/arch/at91sam9_smc.h> +#include <asm/arch/sam9_smc.h> + +void sam9_smc_configure(int cs, struct sam9_smc_config* config) +{ + /* Setup register */ + at91_sys_write(AT91_SMC_SETUP(cs), + AT91_SMC_NWESETUP_(config->nwe_setup) + | AT91_SMC_NCS_WRSETUP_(config->ncs_write_setup) + | AT91_SMC_NRDSETUP_(config->nrd_setup) + | AT91_SMC_NCS_RDSETUP_(config->ncs_read_setup) + ); + + /* Pulse register */ + at91_sys_write(AT91_SMC_PULSE(cs), + AT91_SMC_NWEPULSE_(config->nwe_pulse) + | AT91_SMC_NCS_WRPULSE_(config->ncs_write_pulse) + | AT91_SMC_NRDPULSE_(config->nrd_pulse) + | AT91_SMC_NCS_RDPULSE_(config->ncs_read_pulse) + ); + + /* Cycle register */ + at91_sys_write(AT91_SMC_CYCLE(cs), + AT91_SMC_NWECYCLE_(config->write_cycle) + | AT91_SMC_NRDCYCLE_(config->read_cycle) + ); + + /* Mode register */ + at91_sys_write(AT91_SMC_MODE(cs), + config->mode + | AT91_SMC_TDF_(config->tdf_cycles) + ); +} |