2006-01-09 20:05:41 +03:00
/*
2007-02-05 13:42:07 +03:00
* arch / arm / mach - at91 / at91rm9200 . c
2006-01-09 20:05:41 +03:00
*
* Copyright ( C ) 2005 SAN People
*
* 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 <linux/module.h>
# include <asm/mach/arch.h>
# include <asm/mach/map.h>
2006-11-30 12:01:47 +03:00
# include <asm/arch/at91rm9200.h>
2006-11-30 19:16:43 +03:00
# include <asm/arch/at91_pmc.h>
# include <asm/arch/at91_st.h>
2006-01-09 20:05:41 +03:00
2006-06-19 18:26:51 +04:00
# include "generic.h"
2006-09-27 13:50:59 +04:00
# include "clock.h"
2006-01-09 20:05:41 +03:00
static struct map_desc at91rm9200_io_desc [ ] __initdata = {
{
. virtual = AT91_VA_BASE_SYS ,
. pfn = __phys_to_pfn ( AT91_BASE_SYS ) ,
. length = SZ_4K ,
. type = MT_DEVICE ,
} , {
. virtual = AT91_VA_BASE_EMAC ,
2006-09-27 12:44:11 +04:00
. pfn = __phys_to_pfn ( AT91RM9200_BASE_EMAC ) ,
2006-01-09 20:05:41 +03:00
. length = SZ_16K ,
. type = MT_DEVICE ,
} , {
2006-12-01 13:51:19 +03:00
. virtual = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE ,
2006-09-27 12:44:11 +04:00
. pfn = __phys_to_pfn ( AT91RM9200_SRAM_BASE ) ,
. length = AT91RM9200_SRAM_SIZE ,
2006-06-19 18:26:51 +04:00
. type = MT_DEVICE ,
2006-01-09 20:05:41 +03:00
} ,
} ;
2006-09-27 13:50:59 +04:00
/* --------------------------------------------------------------------
* Clocks
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* The peripheral clocks .
*/
static struct clk udc_clk = {
. name = " udc_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_UDP ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk ohci_clk = {
. name = " ohci_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_UHP ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk ether_clk = {
. name = " ether_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_EMAC ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk mmc_clk = {
. name = " mci_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_MCI ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk twi_clk = {
. name = " twi_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TWI ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk usart0_clk = {
. name = " usart0_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_US0 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk usart1_clk = {
. name = " usart1_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_US1 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk usart2_clk = {
. name = " usart2_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_US2 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk usart3_clk = {
. name = " usart3_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_US3 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk spi_clk = {
. name = " spi_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_SPI ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk pioA_clk = {
. name = " pioA_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_PIOA ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk pioB_clk = {
. name = " pioB_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_PIOB ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk pioC_clk = {
. name = " pioC_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_PIOC ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk pioD_clk = {
. name = " pioD_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_PIOD ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
2007-05-02 20:14:57 +04:00
static struct clk ssc0_clk = {
. name = " ssc0_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_SSC0 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk ssc1_clk = {
. name = " ssc1_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_SSC1 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk ssc2_clk = {
. name = " ssc2_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_SSC2 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
2007-02-08 12:25:38 +03:00
static struct clk tc0_clk = {
. name = " tc0_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC0 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk tc1_clk = {
. name = " tc1_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC1 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk tc2_clk = {
. name = " tc2_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC2 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk tc3_clk = {
. name = " tc3_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC3 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk tc4_clk = {
. name = " tc4_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC4 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
static struct clk tc5_clk = {
. name = " tc5_clk " ,
. pmc_mask = 1 < < AT91RM9200_ID_TC5 ,
. type = CLK_TYPE_PERIPHERAL ,
} ;
2006-09-27 13:50:59 +04:00
static struct clk * periph_clocks [ ] __initdata = {
& pioA_clk ,
& pioB_clk ,
& pioC_clk ,
& pioD_clk ,
& usart0_clk ,
& usart1_clk ,
& usart2_clk ,
& usart3_clk ,
& mmc_clk ,
& udc_clk ,
& twi_clk ,
& spi_clk ,
2007-05-02 20:14:57 +04:00
& ssc0_clk ,
& ssc1_clk ,
& ssc2_clk ,
2007-02-08 12:25:38 +03:00
& tc0_clk ,
& tc1_clk ,
& tc2_clk ,
& tc3_clk ,
& tc4_clk ,
& tc5_clk ,
2006-09-27 13:50:59 +04:00
& ohci_clk ,
& ether_clk ,
// irq0 .. irq6
} ;
/*
* 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 at91rm9200_register_clocks ( void )
2006-01-09 20:05:41 +03:00
{
2006-09-27 13:50:59 +04:00
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 ) ;
}
2006-09-27 16:23:00 +04:00
/* --------------------------------------------------------------------
* GPIO
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static struct at91_gpio_bank at91rm9200_gpio [ ] = {
{
. id = AT91RM9200_ID_PIOA ,
. offset = AT91_PIOA ,
. clock = & pioA_clk ,
} , {
. id = AT91RM9200_ID_PIOB ,
. offset = AT91_PIOB ,
. clock = & pioB_clk ,
} , {
. id = AT91RM9200_ID_PIOC ,
. offset = AT91_PIOC ,
. clock = & pioC_clk ,
} , {
. id = AT91RM9200_ID_PIOD ,
. offset = AT91_PIOD ,
. clock = & pioD_clk ,
}
} ;
2006-09-27 13:50:59 +04:00
2006-11-30 12:01:47 +03:00
static void at91rm9200_reset ( void )
{
/*
* Perform a hardware reset with the use of the Watchdog timer .
*/
at91_sys_write ( AT91_ST_WDMR , AT91_ST_RSTEN | AT91_ST_EXTEN | 1 ) ;
at91_sys_write ( AT91_ST_CR , AT91_ST_WDRST ) ;
}
2006-09-27 13:50:59 +04:00
/* --------------------------------------------------------------------
* AT91RM9200 processor initialization
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2006-09-27 16:23:00 +04:00
void __init at91rm9200_initialize ( unsigned long main_clock , unsigned short banks )
2006-09-27 13:50:59 +04:00
{
/* Map peripherals */
2006-01-09 20:05:41 +03:00
iotable_init ( at91rm9200_io_desc , ARRAY_SIZE ( at91rm9200_io_desc ) ) ;
2006-09-27 13:50:59 +04:00
2006-11-30 12:01:47 +03:00
at91_arch_reset = at91rm9200_reset ;
at91_extern_irq = ( 1 < < AT91RM9200_ID_IRQ0 ) | ( 1 < < AT91RM9200_ID_IRQ1 )
| ( 1 < < AT91RM9200_ID_IRQ2 ) | ( 1 < < AT91RM9200_ID_IRQ3 )
| ( 1 < < AT91RM9200_ID_IRQ4 ) | ( 1 < < AT91RM9200_ID_IRQ5 )
| ( 1 < < AT91RM9200_ID_IRQ6 ) ;
2006-09-27 13:50:59 +04:00
/* Init clock subsystem */
at91_clock_init ( main_clock ) ;
/* Register the processor-specific clocks */
at91rm9200_register_clocks ( ) ;
2006-09-27 16:23:00 +04:00
/* Initialize GPIO subsystem */
at91_gpio_init ( at91rm9200_gpio , banks ) ;
2006-01-09 20:05:41 +03:00
}
2006-09-27 16:23:00 +04:00
/* --------------------------------------------------------------------
* Interrupt initialization
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2006-07-05 20:22:52 +04:00
/*
* The default interrupt priority levels ( 0 = lowest , 7 = highest ) .
*/
static unsigned int at91rm9200_default_irq_priority [ NR_AIC_IRQS ] __initdata = {
7 , /* Advanced Interrupt Controller (FIQ) */
7 , /* System Peripherals */
0 , /* Parallel IO Controller A */
0 , /* Parallel IO Controller B */
0 , /* Parallel IO Controller C */
0 , /* Parallel IO Controller D */
6 , /* USART 0 */
6 , /* USART 1 */
6 , /* USART 2 */
6 , /* USART 3 */
0 , /* Multimedia Card Interface */
4 , /* USB Device Port */
0 , /* Two-Wire Interface */
6 , /* Serial Peripheral Interface */
5 , /* Serial Synchronous Controller 0 */
5 , /* Serial Synchronous Controller 1 */
5 , /* Serial Synchronous Controller 2 */
0 , /* Timer Counter 0 */
0 , /* Timer Counter 1 */
0 , /* Timer Counter 2 */
0 , /* Timer Counter 3 */
0 , /* Timer Counter 4 */
0 , /* Timer Counter 5 */
3 , /* USB Host port */
3 , /* Ethernet MAC */
0 , /* Advanced Interrupt Controller (IRQ0) */
0 , /* Advanced Interrupt Controller (IRQ1) */
0 , /* Advanced Interrupt Controller (IRQ2) */
0 , /* Advanced Interrupt Controller (IRQ3) */
0 , /* Advanced Interrupt Controller (IRQ4) */
0 , /* Advanced Interrupt Controller (IRQ5) */
0 /* Advanced Interrupt Controller (IRQ6) */
} ;
2006-09-27 16:23:00 +04:00
void __init at91rm9200_init_interrupts ( unsigned int priority [ NR_AIC_IRQS ] )
2006-07-05 20:22:52 +04:00
{
if ( ! priority )
priority = at91rm9200_default_irq_priority ;
2006-09-27 16:23:00 +04:00
/* Initialize the AIC interrupt controller */
2006-07-05 20:22:52 +04:00
at91_aic_init ( priority ) ;
2006-09-27 16:23:00 +04:00
/* Enable GPIO interrupts */
at91_gpio_irq_setup ( ) ;
2006-07-05 20:22:52 +04:00
}