diff options
| author | Andrew Victor <andrew@sanpeople.com> | 2007-05-11 20:49:56 +0100 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-05-11 21:07:54 +0100 | 
| commit | 877d7720f5f67793b9b6027840d2c88ea25dc4c8 (patch) | |
| tree | 7f906238239dba97f26e9e78da359b958436d7f5 /arch/arm/mach-at91/at91sam9rl.c | |
| parent | 9da7cf23a4f9690ceecfd0184cd050be564416f1 (diff) | |
[ARM] 4370/3: AT91: Support for Atmel AT91SAM9RL processors.
Add support for Atmel's new AT91SAM9RL range of processors.
Includes similar peripherals as other AT91SAM9 processors, but with a
High-speed USB controller and various sizes of internal SRAM.
Signed-off-by: Nicolas Ferre <nicolas.ferre@rfo.atmel.com>
Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-at91/at91sam9rl.c')
| -rw-r--r-- | arch/arm/mach-at91/at91sam9rl.c | 341 | 
1 files changed, 341 insertions, 0 deletions
| diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c new file mode 100644 index 000000000000..4813a35f6cf5 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -0,0 +1,341 @@ +/* + * arch/arm/mach-at91/at91sam9rl.c + * + *  Copyright (C) 2005 SAN People + *  Copyright (C) 2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/arch/cpu.h> +#include <asm/arch/at91sam9rl.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9rl_io_desc[] __initdata = { +	{ +		.virtual	= AT91_VA_BASE_SYS, +		.pfn		= __phys_to_pfn(AT91_BASE_SYS), +		.length		= SZ_16K, +		.type		= MT_DEVICE, +	}, +}; + +static struct map_desc at91sam9rl_sram_desc[] __initdata = { +	{ +		.pfn		= __phys_to_pfn(AT91SAM9RL_SRAM_BASE), +		.type		= MT_DEVICE, +	} +}; + +/* -------------------------------------------------------------------- + *  Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { +	.name		= "pioA_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_PIOA, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { +	.name		= "pioB_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_PIOB, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { +	.name		= "pioC_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_PIOC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pioD_clk = { +	.name		= "pioD_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_PIOD, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { +	.name		= "usart0_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_US0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { +	.name		= "usart1_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_US1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { +	.name		= "usart2_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_US2, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { +	.name		= "usart3_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_US3, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { +	.name		= "mci_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_MCI, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk twi0_clk = { +	.name		= "twi0_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TWI0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk twi1_clk = { +	.name		= "twi1_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TWI1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk spi_clk = { +	.name		= "spi_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_SPI, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc0_clk = { +	.name		= "ssc0_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_SSC0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc1_clk = { +	.name		= "ssc1_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_SSC1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc0_clk = { +	.name		= "tc0_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TC0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc1_clk = { +	.name		= "tc1_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TC1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc2_clk = { +	.name		= "tc2_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TC2, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pwmc_clk = { +	.name		= "pwmc_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_PWMC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tsc_clk = { +	.name		= "tsc_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_TSC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk dma_clk = { +	.name		= "dma_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_DMA, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk udphs_clk = { +	.name		= "udphs_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_UDPHS, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { +	.name		= "lcdc_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_LCDC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ac97_clk = { +	.name		= "ac97_clk", +	.pmc_mask	= 1 << AT91SAM9RL_ID_AC97C, +	.type		= CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { +	&pioA_clk, +	&pioB_clk, +	&pioC_clk, +	&pioD_clk, +	&usart0_clk, +	&usart1_clk, +	&usart2_clk, +	&usart3_clk, +	&mmc_clk, +	&twi0_clk, +	&twi1_clk, +	&spi_clk, +	&ssc0_clk, +	&ssc1_clk, +	&tc0_clk, +	&tc1_clk, +	&tc2_clk, +	&pwmc_clk, +	&tsc_clk, +	&dma_clk, +	&udphs_clk, +	&lcdc_clk, +	&ac97_clk, +	// irq0 +}; + +/* + * The two 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 void __init at91sam9rl_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); +} + +/* -------------------------------------------------------------------- + *  GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9rl_gpio[] = { +	{ +		.id		= AT91SAM9RL_ID_PIOA, +		.offset		= AT91_PIOA, +		.clock		= &pioA_clk, +	}, { +		.id		= AT91SAM9RL_ID_PIOB, +		.offset		= AT91_PIOB, +		.clock		= &pioB_clk, +	}, { +		.id		= AT91SAM9RL_ID_PIOC, +		.offset		= AT91_PIOC, +		.clock		= &pioC_clk, +	}, { +		.id		= AT91SAM9RL_ID_PIOD, +		.offset		= AT91_PIOD, +		.clock		= &pioD_clk, +	} +}; + +static void at91sam9rl_reset(void) +{ +	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + + +/* -------------------------------------------------------------------- + *  AT91SAM9RL processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9rl_initialize(unsigned long main_clock) +{ +	unsigned long cidr, sram_size; + +	/* Map peripherals */ +	iotable_init(at91sam9rl_io_desc, ARRAY_SIZE(at91sam9rl_io_desc)); + +	cidr = at91_sys_read(AT91_DBGU_CIDR); + +	switch (cidr & AT91_CIDR_SRAMSIZ) { +		case AT91_CIDR_SRAMSIZ_32K: +			sram_size = 2 * SZ_16K; +			break; +		case AT91_CIDR_SRAMSIZ_16K: +		default: +			sram_size = SZ_16K; +	} + +	at91sam9rl_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size; +	at91sam9rl_sram_desc->length = sram_size; + +	/* Map SRAM */ +	iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc)); + +	at91_arch_reset = at91sam9rl_reset; +	at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0); + +	/* Init clock subsystem */ +	at91_clock_init(main_clock); + +	/* Register the processor-specific clocks */ +	at91sam9rl_register_clocks(); + +	/* Register GPIO subsystem */ +	at91_gpio_init(at91sam9rl_gpio, 4); +} + +/* -------------------------------------------------------------------- + *  Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = { +	7,	/* Advanced Interrupt Controller */ +	7,	/* System Peripherals */ +	1,	/* Parallel IO Controller A */ +	1,	/* Parallel IO Controller B */ +	1,	/* Parallel IO Controller C */ +	1,	/* Parallel IO Controller D */ +	5,	/* USART 0 */ +	5,	/* USART 1 */ +	5,	/* USART 2 */ +	5,	/* USART 3 */ +	0,	/* Multimedia Card Interface */ +	6,	/* Two-Wire Interface 0 */ +	6,	/* Two-Wire Interface 1 */ +	5,	/* Serial Peripheral Interface */ +	4,	/* Serial Synchronous Controller 0 */ +	4,	/* Serial Synchronous Controller 1 */ +	0,	/* Timer Counter 0 */ +	0,	/* Timer Counter 1 */ +	0,	/* Timer Counter 2 */ +	0, +	0,	/* Touch Screen Controller */ +	0,	/* DMA Controller */ +	2,	/* USB Device High speed port */ +	2,	/* LCD Controller */ +	6,	/* AC97 Controller */ +	0, +	0, +	0, +	0, +	0, +	0, +	0,	/* Advanced Interrupt Controller */ +}; + +void __init at91sam9rl_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ +	if (!priority) +		priority = at91sam9rl_default_irq_priority; + +	/* Initialize the AIC interrupt controller */ +	at91_aic_init(priority); + +	/* Enable GPIO interrupts */ +	at91_gpio_irq_setup(); +} | 
