Path: blob/master/arch/arm/mach-at91/at91sam9g45.c
10817 views
/*1* Chip-specific setup code for the AT91SAM9G45 family2*3* Copyright (C) 2009 Atmel Corporation.4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10*/1112#include <linux/module.h>13#include <linux/pm.h>1415#include <asm/irq.h>16#include <asm/mach/arch.h>17#include <asm/mach/map.h>18#include <mach/at91sam9g45.h>19#include <mach/at91_pmc.h>20#include <mach/at91_rstc.h>21#include <mach/at91_shdwc.h>22#include <mach/cpu.h>2324#include "generic.h"25#include "clock.h"2627static struct map_desc at91sam9g45_io_desc[] __initdata = {28{29.virtual = AT91_VA_BASE_SYS,30.pfn = __phys_to_pfn(AT91_BASE_SYS),31.length = SZ_16K,32.type = MT_DEVICE,33}, {34.virtual = AT91_IO_VIRT_BASE - AT91SAM9G45_SRAM_SIZE,35.pfn = __phys_to_pfn(AT91SAM9G45_SRAM_BASE),36.length = AT91SAM9G45_SRAM_SIZE,37.type = MT_DEVICE,38}39};4041/* --------------------------------------------------------------------42* Clocks43* -------------------------------------------------------------------- */4445/*46* The peripheral clocks.47*/48static struct clk pioA_clk = {49.name = "pioA_clk",50.pmc_mask = 1 << AT91SAM9G45_ID_PIOA,51.type = CLK_TYPE_PERIPHERAL,52};53static struct clk pioB_clk = {54.name = "pioB_clk",55.pmc_mask = 1 << AT91SAM9G45_ID_PIOB,56.type = CLK_TYPE_PERIPHERAL,57};58static struct clk pioC_clk = {59.name = "pioC_clk",60.pmc_mask = 1 << AT91SAM9G45_ID_PIOC,61.type = CLK_TYPE_PERIPHERAL,62};63static struct clk pioDE_clk = {64.name = "pioDE_clk",65.pmc_mask = 1 << AT91SAM9G45_ID_PIODE,66.type = CLK_TYPE_PERIPHERAL,67};68static struct clk usart0_clk = {69.name = "usart0_clk",70.pmc_mask = 1 << AT91SAM9G45_ID_US0,71.type = CLK_TYPE_PERIPHERAL,72};73static struct clk usart1_clk = {74.name = "usart1_clk",75.pmc_mask = 1 << AT91SAM9G45_ID_US1,76.type = CLK_TYPE_PERIPHERAL,77};78static struct clk usart2_clk = {79.name = "usart2_clk",80.pmc_mask = 1 << AT91SAM9G45_ID_US2,81.type = CLK_TYPE_PERIPHERAL,82};83static struct clk usart3_clk = {84.name = "usart3_clk",85.pmc_mask = 1 << AT91SAM9G45_ID_US3,86.type = CLK_TYPE_PERIPHERAL,87};88static struct clk mmc0_clk = {89.name = "mci0_clk",90.pmc_mask = 1 << AT91SAM9G45_ID_MCI0,91.type = CLK_TYPE_PERIPHERAL,92};93static struct clk twi0_clk = {94.name = "twi0_clk",95.pmc_mask = 1 << AT91SAM9G45_ID_TWI0,96.type = CLK_TYPE_PERIPHERAL,97};98static struct clk twi1_clk = {99.name = "twi1_clk",100.pmc_mask = 1 << AT91SAM9G45_ID_TWI1,101.type = CLK_TYPE_PERIPHERAL,102};103static struct clk spi0_clk = {104.name = "spi0_clk",105.pmc_mask = 1 << AT91SAM9G45_ID_SPI0,106.type = CLK_TYPE_PERIPHERAL,107};108static struct clk spi1_clk = {109.name = "spi1_clk",110.pmc_mask = 1 << AT91SAM9G45_ID_SPI1,111.type = CLK_TYPE_PERIPHERAL,112};113static struct clk ssc0_clk = {114.name = "ssc0_clk",115.pmc_mask = 1 << AT91SAM9G45_ID_SSC0,116.type = CLK_TYPE_PERIPHERAL,117};118static struct clk ssc1_clk = {119.name = "ssc1_clk",120.pmc_mask = 1 << AT91SAM9G45_ID_SSC1,121.type = CLK_TYPE_PERIPHERAL,122};123static struct clk tcb0_clk = {124.name = "tcb0_clk",125.pmc_mask = 1 << AT91SAM9G45_ID_TCB,126.type = CLK_TYPE_PERIPHERAL,127};128static struct clk pwm_clk = {129.name = "pwm_clk",130.pmc_mask = 1 << AT91SAM9G45_ID_PWMC,131.type = CLK_TYPE_PERIPHERAL,132};133static struct clk tsc_clk = {134.name = "tsc_clk",135.pmc_mask = 1 << AT91SAM9G45_ID_TSC,136.type = CLK_TYPE_PERIPHERAL,137};138static struct clk dma_clk = {139.name = "dma_clk",140.pmc_mask = 1 << AT91SAM9G45_ID_DMA,141.type = CLK_TYPE_PERIPHERAL,142};143static struct clk uhphs_clk = {144.name = "uhphs_clk",145.pmc_mask = 1 << AT91SAM9G45_ID_UHPHS,146.type = CLK_TYPE_PERIPHERAL,147};148static struct clk lcdc_clk = {149.name = "lcdc_clk",150.pmc_mask = 1 << AT91SAM9G45_ID_LCDC,151.type = CLK_TYPE_PERIPHERAL,152};153static struct clk ac97_clk = {154.name = "ac97_clk",155.pmc_mask = 1 << AT91SAM9G45_ID_AC97C,156.type = CLK_TYPE_PERIPHERAL,157};158static struct clk macb_clk = {159.name = "macb_clk",160.pmc_mask = 1 << AT91SAM9G45_ID_EMAC,161.type = CLK_TYPE_PERIPHERAL,162};163static struct clk isi_clk = {164.name = "isi_clk",165.pmc_mask = 1 << AT91SAM9G45_ID_ISI,166.type = CLK_TYPE_PERIPHERAL,167};168static struct clk udphs_clk = {169.name = "udphs_clk",170.pmc_mask = 1 << AT91SAM9G45_ID_UDPHS,171.type = CLK_TYPE_PERIPHERAL,172};173static struct clk mmc1_clk = {174.name = "mci1_clk",175.pmc_mask = 1 << AT91SAM9G45_ID_MCI1,176.type = CLK_TYPE_PERIPHERAL,177};178179/* Video decoder clock - Only for sam9m10/sam9m11 */180static struct clk vdec_clk = {181.name = "vdec_clk",182.pmc_mask = 1 << AT91SAM9G45_ID_VDEC,183.type = CLK_TYPE_PERIPHERAL,184};185186static struct clk *periph_clocks[] __initdata = {187&pioA_clk,188&pioB_clk,189&pioC_clk,190&pioDE_clk,191&usart0_clk,192&usart1_clk,193&usart2_clk,194&usart3_clk,195&mmc0_clk,196&twi0_clk,197&twi1_clk,198&spi0_clk,199&spi1_clk,200&ssc0_clk,201&ssc1_clk,202&tcb0_clk,203&pwm_clk,204&tsc_clk,205&dma_clk,206&uhphs_clk,207&lcdc_clk,208&ac97_clk,209&macb_clk,210&isi_clk,211&udphs_clk,212&mmc1_clk,213// irq0214};215216static struct clk_lookup periph_clocks_lookups[] = {217/* One additional fake clock for ohci */218CLKDEV_CON_ID("ohci_clk", &uhphs_clk),219CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),220CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),221CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),222CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),223CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),224CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),225CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),226CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),227CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),228CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),229CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),230};231232static struct clk_lookup usart_clocks_lookups[] = {233CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),234CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),235CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),236CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),237CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),238};239240/*241* The two programmable clocks.242* You must configure pin multiplexing to bring these signals out.243*/244static struct clk pck0 = {245.name = "pck0",246.pmc_mask = AT91_PMC_PCK0,247.type = CLK_TYPE_PROGRAMMABLE,248.id = 0,249};250static struct clk pck1 = {251.name = "pck1",252.pmc_mask = AT91_PMC_PCK1,253.type = CLK_TYPE_PROGRAMMABLE,254.id = 1,255};256257static void __init at91sam9g45_register_clocks(void)258{259int i;260261for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)262clk_register(periph_clocks[i]);263264clkdev_add_table(periph_clocks_lookups,265ARRAY_SIZE(periph_clocks_lookups));266clkdev_add_table(usart_clocks_lookups,267ARRAY_SIZE(usart_clocks_lookups));268269if (cpu_is_at91sam9m10() || cpu_is_at91sam9m11())270clk_register(&vdec_clk);271272clk_register(&pck0);273clk_register(&pck1);274}275276static struct clk_lookup console_clock_lookup;277278void __init at91sam9g45_set_console_clock(int id)279{280if (id >= ARRAY_SIZE(usart_clocks_lookups))281return;282283console_clock_lookup.con_id = "usart";284console_clock_lookup.clk = usart_clocks_lookups[id].clk;285clkdev_add(&console_clock_lookup);286}287288/* --------------------------------------------------------------------289* GPIO290* -------------------------------------------------------------------- */291292static struct at91_gpio_bank at91sam9g45_gpio[] = {293{294.id = AT91SAM9G45_ID_PIOA,295.offset = AT91_PIOA,296.clock = &pioA_clk,297}, {298.id = AT91SAM9G45_ID_PIOB,299.offset = AT91_PIOB,300.clock = &pioB_clk,301}, {302.id = AT91SAM9G45_ID_PIOC,303.offset = AT91_PIOC,304.clock = &pioC_clk,305}, {306.id = AT91SAM9G45_ID_PIODE,307.offset = AT91_PIOD,308.clock = &pioDE_clk,309}, {310.id = AT91SAM9G45_ID_PIODE,311.offset = AT91_PIOE,312.clock = &pioDE_clk,313}314};315316static void at91sam9g45_reset(void)317{318at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);319}320321static void at91sam9g45_poweroff(void)322{323at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);324}325326327/* --------------------------------------------------------------------328* AT91SAM9G45 processor initialization329* -------------------------------------------------------------------- */330331void __init at91sam9g45_map_io(void)332{333/* Map peripherals */334iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc));335}336337void __init at91sam9g45_initialize(unsigned long main_clock)338{339at91_arch_reset = at91sam9g45_reset;340pm_power_off = at91sam9g45_poweroff;341at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0);342343/* Init clock subsystem */344at91_clock_init(main_clock);345346/* Register the processor-specific clocks */347at91sam9g45_register_clocks();348349/* Register GPIO subsystem */350at91_gpio_init(at91sam9g45_gpio, 5);351}352353/* --------------------------------------------------------------------354* Interrupt initialization355* -------------------------------------------------------------------- */356357/*358* The default interrupt priority levels (0 = lowest, 7 = highest).359*/360static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {3617, /* Advanced Interrupt Controller (FIQ) */3627, /* System Peripherals */3631, /* Parallel IO Controller A */3641, /* Parallel IO Controller B */3651, /* Parallel IO Controller C */3661, /* Parallel IO Controller D and E */3670,3685, /* USART 0 */3695, /* USART 1 */3705, /* USART 2 */3715, /* USART 3 */3720, /* Multimedia Card Interface 0 */3736, /* Two-Wire Interface 0 */3746, /* Two-Wire Interface 1 */3755, /* Serial Peripheral Interface 0 */3765, /* Serial Peripheral Interface 1 */3774, /* Serial Synchronous Controller 0 */3784, /* Serial Synchronous Controller 1 */3790, /* Timer Counter 0, 1, 2, 3, 4 and 5 */3800, /* Pulse Width Modulation Controller */3810, /* Touch Screen Controller */3820, /* DMA Controller */3832, /* USB Host High Speed port */3843, /* LDC Controller */3855, /* AC97 Controller */3863, /* Ethernet */3870, /* Image Sensor Interface */3882, /* USB Device High speed port */3890,3900, /* Multimedia Card Interface 1 */3910,3920, /* Advanced Interrupt Controller (IRQ0) */393};394395void __init at91sam9g45_init_interrupts(unsigned int priority[NR_AIC_IRQS])396{397if (!priority)398priority = at91sam9g45_default_irq_priority;399400/* Initialize the AIC interrupt controller */401at91_aic_init(priority);402403/* Enable GPIO interrupts */404at91_gpio_irq_setup();405}406407408