Path: blob/master/arch/arm/mach-integrator/integrator_cp.c
10817 views
/*1* linux/arch/arm/mach-integrator/integrator_cp.c2*3* Copyright (C) 2003 Deep Blue Solutions Ltd4*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.8*/9#include <linux/types.h>10#include <linux/kernel.h>11#include <linux/init.h>12#include <linux/list.h>13#include <linux/platform_device.h>14#include <linux/dma-mapping.h>15#include <linux/string.h>16#include <linux/sysdev.h>17#include <linux/amba/bus.h>18#include <linux/amba/kmi.h>19#include <linux/amba/clcd.h>20#include <linux/amba/mmci.h>21#include <linux/io.h>22#include <linux/gfp.h>23#include <linux/clkdev.h>24#include <linux/mtd/physmap.h>2526#include <mach/hardware.h>27#include <mach/platform.h>28#include <asm/irq.h>29#include <asm/setup.h>30#include <asm/mach-types.h>31#include <asm/hardware/arm_timer.h>32#include <asm/hardware/icst.h>3334#include <mach/cm.h>35#include <mach/lm.h>3637#include <asm/mach/arch.h>38#include <asm/mach/irq.h>39#include <asm/mach/map.h>40#include <asm/mach/time.h>4142#include <asm/hardware/timer-sp.h>4344#include <plat/clcd.h>45#include <plat/fpga-irq.h>46#include <plat/sched_clock.h>4748#include "common.h"4950#define INTCP_PA_FLASH_BASE 0x2400000051#define INTCP_FLASH_SIZE SZ_32M5253#define INTCP_PA_CLCD_BASE 0xc00000005455#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)56#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)57#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)5859#define INTCP_ETH_SIZE 0x106061#define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE)62#define INTCP_FLASHPROG 0x0463#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)64#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1)6566/*67* Logical Physical68* f1000000 10000000 Core module registers69* f1100000 11000000 System controller registers70* f1200000 12000000 EBI registers71* f1300000 13000000 Counter/Timer72* f1400000 14000000 Interrupt controller73* f1600000 16000000 UART 074* f1700000 17000000 UART 175* f1a00000 1a000000 Debug LEDs76* fc900000 c9000000 GPIO77* fca00000 ca000000 SIC78* fcb00000 cb000000 CP system control79*/8081static struct map_desc intcp_io_desc[] __initdata = {82{83.virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE),84.pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE),85.length = SZ_4K,86.type = MT_DEVICE87}, {88.virtual = IO_ADDRESS(INTEGRATOR_SC_BASE),89.pfn = __phys_to_pfn(INTEGRATOR_SC_BASE),90.length = SZ_4K,91.type = MT_DEVICE92}, {93.virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE),94.pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE),95.length = SZ_4K,96.type = MT_DEVICE97}, {98.virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),99.pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),100.length = SZ_4K,101.type = MT_DEVICE102}, {103.virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),104.pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),105.length = SZ_4K,106.type = MT_DEVICE107}, {108.virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),109.pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),110.length = SZ_4K,111.type = MT_DEVICE112}, {113.virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE),114.pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE),115.length = SZ_4K,116.type = MT_DEVICE117}, {118.virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE),119.pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE),120.length = SZ_4K,121.type = MT_DEVICE122}, {123.virtual = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE),124.pfn = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE),125.length = SZ_4K,126.type = MT_DEVICE127}, {128.virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),129.pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),130.length = SZ_4K,131.type = MT_DEVICE132}, {133.virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),134.pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),135.length = SZ_4K,136.type = MT_DEVICE137}138};139140static void __init intcp_map_io(void)141{142iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));143}144145static struct fpga_irq_data cic_irq_data = {146.base = INTCP_VA_CIC_BASE,147.irq_start = IRQ_CIC_START,148.chip.name = "CIC",149};150151static struct fpga_irq_data pic_irq_data = {152.base = INTCP_VA_PIC_BASE,153.irq_start = IRQ_PIC_START,154.chip.name = "PIC",155};156157static struct fpga_irq_data sic_irq_data = {158.base = INTCP_VA_SIC_BASE,159.irq_start = IRQ_SIC_START,160.chip.name = "SIC",161};162163static void __init intcp_init_irq(void)164{165u32 pic_mask, sic_mask;166167pic_mask = ~((~0u) << (11 - IRQ_PIC_START));168pic_mask |= (~((~0u) << (29 - 22))) << 22;169sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));170171/*172* Disable all interrupt sources173*/174writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);175writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);176writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);177writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);178writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);179writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);180181fpga_irq_init(-1, pic_mask, &pic_irq_data);182183fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),184&cic_irq_data);185186fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);187}188189/*190* Clock handling191*/192#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)193#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)194195static const struct icst_params cp_auxvco_params = {196.ref = 24000000,197.vco_max = ICST525_VCO_MAX_5V,198.vco_min = ICST525_VCO_MIN,199.vd_min = 8,200.vd_max = 263,201.rd_min = 3,202.rd_max = 65,203.s2div = icst525_s2div,204.idx2s = icst525_idx2s,205};206207static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)208{209u32 val;210211val = readl(clk->vcoreg) & ~0x7ffff;212val |= vco.v | (vco.r << 9) | (vco.s << 16);213214writel(0xa05f, CM_LOCK);215writel(val, clk->vcoreg);216writel(0, CM_LOCK);217}218219static const struct clk_ops cp_auxclk_ops = {220.round = icst_clk_round,221.set = icst_clk_set,222.setvco = cp_auxvco_set,223};224225static struct clk cp_auxclk = {226.ops = &cp_auxclk_ops,227.params = &cp_auxvco_params,228.vcoreg = CM_AUXOSC,229};230231static struct clk sp804_clk = {232.rate = 1000000,233};234235static struct clk_lookup cp_lookups[] = {236{ /* CLCD */237.dev_id = "mb:c0",238.clk = &cp_auxclk,239}, { /* SP804 timers */240.dev_id = "sp804",241.clk = &sp804_clk,242},243};244245/*246* Flash handling.247*/248static int intcp_flash_init(struct platform_device *dev)249{250u32 val;251252val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);253val |= CINTEGRATOR_FLASHPROG_FLWREN;254writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);255256return 0;257}258259static void intcp_flash_exit(struct platform_device *dev)260{261u32 val;262263val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);264val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);265writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);266}267268static void intcp_flash_set_vpp(struct platform_device *pdev, int on)269{270u32 val;271272val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);273if (on)274val |= CINTEGRATOR_FLASHPROG_FLVPPEN;275else276val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;277writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);278}279280static struct physmap_flash_data intcp_flash_data = {281.width = 4,282.init = intcp_flash_init,283.exit = intcp_flash_exit,284.set_vpp = intcp_flash_set_vpp,285};286287static struct resource intcp_flash_resource = {288.start = INTCP_PA_FLASH_BASE,289.end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,290.flags = IORESOURCE_MEM,291};292293static struct platform_device intcp_flash_device = {294.name = "physmap-flash",295.id = 0,296.dev = {297.platform_data = &intcp_flash_data,298},299.num_resources = 1,300.resource = &intcp_flash_resource,301};302303static struct resource smc91x_resources[] = {304[0] = {305.start = INTEGRATOR_CP_ETH_BASE,306.end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,307.flags = IORESOURCE_MEM,308},309[1] = {310.start = IRQ_CP_ETHINT,311.end = IRQ_CP_ETHINT,312.flags = IORESOURCE_IRQ,313},314};315316static struct platform_device smc91x_device = {317.name = "smc91x",318.id = 0,319.num_resources = ARRAY_SIZE(smc91x_resources),320.resource = smc91x_resources,321};322323static struct platform_device *intcp_devs[] __initdata = {324&intcp_flash_device,325&smc91x_device,326};327328/*329* It seems that the card insertion interrupt remains active after330* we've acknowledged it. We therefore ignore the interrupt, and331* rely on reading it from the SIC. This also means that we must332* clear the latched interrupt.333*/334static unsigned int mmc_status(struct device *dev)335{336unsigned int status = readl(IO_ADDRESS(0xca000000 + 4));337writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8));338339return status & 8;340}341342static struct mmci_platform_data mmc_data = {343.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,344.status = mmc_status,345.gpio_wp = -1,346.gpio_cd = -1,347};348349static struct amba_device mmc_device = {350.dev = {351.init_name = "mb:1c",352.platform_data = &mmc_data,353},354.res = {355.start = INTEGRATOR_CP_MMC_BASE,356.end = INTEGRATOR_CP_MMC_BASE + SZ_4K - 1,357.flags = IORESOURCE_MEM,358},359.irq = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 },360.periphid = 0,361};362363static struct amba_device aaci_device = {364.dev = {365.init_name = "mb:1d",366},367.res = {368.start = INTEGRATOR_CP_AACI_BASE,369.end = INTEGRATOR_CP_AACI_BASE + SZ_4K - 1,370.flags = IORESOURCE_MEM,371},372.irq = { IRQ_CP_AACIINT, NO_IRQ },373.periphid = 0,374};375376377/*378* CLCD support379*/380/*381* Ensure VGA is selected.382*/383static void cp_clcd_enable(struct clcd_fb *fb)384{385struct fb_var_screeninfo *var = &fb->fb.var;386u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;387388if (var->bits_per_pixel <= 8 ||389(var->bits_per_pixel == 16 && var->green.length == 5))390/* Pseudocolor, RGB555, BGR555 */391val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;392else if (fb->fb.var.bits_per_pixel <= 16)393/* truecolor RGB565 */394val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;395else396val = 0; /* no idea for this, don't trust the docs */397398cm_control(CM_CTRL_LCDMUXSEL_MASK|399CM_CTRL_LCDEN0|400CM_CTRL_LCDEN1|401CM_CTRL_STATIC1|402CM_CTRL_STATIC2|403CM_CTRL_STATIC|404CM_CTRL_n24BITEN, val);405}406407static int cp_clcd_setup(struct clcd_fb *fb)408{409fb->panel = versatile_clcd_get_panel("VGA");410if (!fb->panel)411return -EINVAL;412413return versatile_clcd_setup_dma(fb, SZ_1M);414}415416static struct clcd_board clcd_data = {417.name = "Integrator/CP",418.caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,419.check = clcdfb_check,420.decode = clcdfb_decode,421.enable = cp_clcd_enable,422.setup = cp_clcd_setup,423.mmap = versatile_clcd_mmap_dma,424.remove = versatile_clcd_remove_dma,425};426427static struct amba_device clcd_device = {428.dev = {429.init_name = "mb:c0",430.coherent_dma_mask = ~0,431.platform_data = &clcd_data,432},433.res = {434.start = INTCP_PA_CLCD_BASE,435.end = INTCP_PA_CLCD_BASE + SZ_4K - 1,436.flags = IORESOURCE_MEM,437},438.dma_mask = ~0,439.irq = { IRQ_CP_CLCDCINT, NO_IRQ },440.periphid = 0,441};442443static struct amba_device *amba_devs[] __initdata = {444&mmc_device,445&aaci_device,446&clcd_device,447};448449#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)450451static void __init intcp_init_early(void)452{453clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));454455integrator_init_early();456457#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK458versatile_sched_clock_init(REFCOUNTER, 24000000);459#endif460}461462static void __init intcp_init(void)463{464int i;465466platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));467468for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {469struct amba_device *d = amba_devs[i];470amba_device_register(d, &iomem_resource);471}472}473474#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)475#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)476#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)477478static void __init intcp_timer_init(void)479{480writel(0, TIMER0_VA_BASE + TIMER_CTRL);481writel(0, TIMER1_VA_BASE + TIMER_CTRL);482writel(0, TIMER2_VA_BASE + TIMER_CTRL);483484sp804_clocksource_init(TIMER2_VA_BASE, "timer2");485sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");486}487488static struct sys_timer cp_timer = {489.init = intcp_timer_init,490};491492MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")493/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */494.boot_params = 0x00000100,495.reserve = integrator_reserve,496.map_io = intcp_map_io,497.init_early = intcp_init_early,498.init_irq = intcp_init_irq,499.timer = &cp_timer,500.init_machine = intcp_init,501MACHINE_END502503504