📄 core.c
字号:
/* * linux/arch/arm/mach-versatile/core.c * * Copyright (C) 1999 - 2003 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd * * 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/init.h>#include <linux/device.h>#include <linux/dma-mapping.h>#include <linux/platform_device.h>#include <linux/sysdev.h>#include <linux/interrupt.h>#include <linux/amba/bus.h>#include <linux/amba/clcd.h>#include <linux/clocksource.h>#include <linux/clockchips.h>#include <asm/cnt32_to_63.h>#include <asm/system.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/leds.h>#include <asm/hardware/arm_timer.h>#include <asm/hardware/icst307.h>#include <asm/hardware/vic.h>#include <asm/mach-types.h>#include <asm/mach/arch.h>#include <asm/mach/flash.h>#include <asm/mach/irq.h>#include <asm/mach/time.h>#include <asm/mach/map.h>#include <asm/mach/mmc.h>#include "core.h"#include "clock.h"/* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx * is the (PA >> 12). * * Setup a VA for the Versatile Vectored Interrupt Controller. */#define __io_address(n) __io(IO_ADDRESS(n))#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE)#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE)static void sic_mask_irq(unsigned int irq){ irq -= IRQ_SIC_START; writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);}static void sic_unmask_irq(unsigned int irq){ irq -= IRQ_SIC_START; writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);}static struct irq_chip sic_chip = { .name = "SIC", .ack = sic_mask_irq, .mask = sic_mask_irq, .unmask = sic_unmask_irq,};static voidsic_handle_irq(unsigned int irq, struct irq_desc *desc){ unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS); if (status == 0) { do_bad_IRQ(irq, desc); return; } do { irq = ffs(status) - 1; status &= ~(1 << irq); irq += IRQ_SIC_START; desc = irq_desc + irq; desc_handle_irq(irq, desc); } while (status);}#if 1#define IRQ_MMCI0A IRQ_VICSOURCE22#define IRQ_AACI IRQ_VICSOURCE24#define IRQ_ETH IRQ_VICSOURCE25#define PIC_MASK 0xFFD00000#else#define IRQ_MMCI0A IRQ_SIC_MMCI0A#define IRQ_AACI IRQ_SIC_AACI#define IRQ_ETH IRQ_SIC_ETH#define PIC_MASK 0#endifvoid __init versatile_init_irq(void){ unsigned int i; vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0); set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq); /* Do second interrupt controller */ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) { set_irq_chip(i, &sic_chip); set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } /* * Interrupts on secondary controller from 0 to 8 are routed to * source 31 on PIC. * Interrupts from 21 to 31 are routed directly to the VIC on * the corresponding number on primary controller. This is controlled * by setting PIC_ENABLEx. */ writel(PIC_MASK, VA_SIC_BASE + SIC_INT_PIC_ENABLE);}static struct map_desc versatile_io_desc[] __initdata = { { .virtual = IO_ADDRESS(VERSATILE_SYS_BASE), .pfn = __phys_to_pfn(VERSATILE_SYS_BASE), .length = SZ_4K, .type = MT_DEVICE }, { .virtual = IO_ADDRESS(VERSATILE_SIC_BASE), .pfn = __phys_to_pfn(VERSATILE_SIC_BASE), .length = SZ_4K, .type = MT_DEVICE }, { .virtual = IO_ADDRESS(VERSATILE_VIC_BASE), .pfn = __phys_to_pfn(VERSATILE_VIC_BASE), .length = SZ_4K, .type = MT_DEVICE }, { .virtual = IO_ADDRESS(VERSATILE_SCTL_BASE), .pfn = __phys_to_pfn(VERSATILE_SCTL_BASE), .length = SZ_4K * 9, .type = MT_DEVICE },#ifdef CONFIG_MACH_VERSATILE_AB { .virtual = IO_ADDRESS(VERSATILE_GPIO0_BASE), .pfn = __phys_to_pfn(VERSATILE_GPIO0_BASE), .length = SZ_4K, .type = MT_DEVICE }, { .virtual = IO_ADDRESS(VERSATILE_IB2_BASE), .pfn = __phys_to_pfn(VERSATILE_IB2_BASE), .length = SZ_64M, .type = MT_DEVICE },#endif#ifdef CONFIG_DEBUG_LL { .virtual = IO_ADDRESS(VERSATILE_UART0_BASE), .pfn = __phys_to_pfn(VERSATILE_UART0_BASE), .length = SZ_4K, .type = MT_DEVICE },#endif#ifdef CONFIG_PCI { .virtual = IO_ADDRESS(VERSATILE_PCI_CORE_BASE), .pfn = __phys_to_pfn(VERSATILE_PCI_CORE_BASE), .length = SZ_4K, .type = MT_DEVICE }, { .virtual = (unsigned long)VERSATILE_PCI_VIRT_BASE, .pfn = __phys_to_pfn(VERSATILE_PCI_BASE), .length = VERSATILE_PCI_BASE_SIZE, .type = MT_DEVICE }, { .virtual = (unsigned long)VERSATILE_PCI_CFG_VIRT_BASE, .pfn = __phys_to_pfn(VERSATILE_PCI_CFG_BASE), .length = VERSATILE_PCI_CFG_BASE_SIZE, .type = MT_DEVICE },#if 0 { .virtual = VERSATILE_PCI_VIRT_MEM_BASE0, .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE0), .length = SZ_16M, .type = MT_DEVICE }, { .virtual = VERSATILE_PCI_VIRT_MEM_BASE1, .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE1), .length = SZ_16M, .type = MT_DEVICE }, { .virtual = VERSATILE_PCI_VIRT_MEM_BASE2, .pfn = __phys_to_pfn(VERSATILE_PCI_MEM_BASE2), .length = SZ_16M, .type = MT_DEVICE },#endif#endif};void __init versatile_map_io(void){ iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));}#define VERSATILE_REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)/* * This is the Versatile sched_clock implementation. This has * a resolution of 41.7ns, and a maximum value of about 35583 days. * * The return value is guaranteed to be monotonic in that range as * long as there is always less than 89 seconds between successive * calls to this function. */unsigned long long sched_clock(void){ unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER)); /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ v *= 125<<1; do_div(v, 3<<1); return v;}#define VERSATILE_FLASHCTRL (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)static int versatile_flash_init(void){ u32 val; val = __raw_readl(VERSATILE_FLASHCTRL); val &= ~VERSATILE_FLASHPROG_FLVPPEN; __raw_writel(val, VERSATILE_FLASHCTRL); return 0;}static void versatile_flash_exit(void){ u32 val; val = __raw_readl(VERSATILE_FLASHCTRL); val &= ~VERSATILE_FLASHPROG_FLVPPEN; __raw_writel(val, VERSATILE_FLASHCTRL);}static void versatile_flash_set_vpp(int on){ u32 val; val = __raw_readl(VERSATILE_FLASHCTRL); if (on) val |= VERSATILE_FLASHPROG_FLVPPEN; else val &= ~VERSATILE_FLASHPROG_FLVPPEN; __raw_writel(val, VERSATILE_FLASHCTRL);}static struct flash_platform_data versatile_flash_data = { .map_name = "cfi_probe", .width = 4, .init = versatile_flash_init, .exit = versatile_flash_exit, .set_vpp = versatile_flash_set_vpp,};static struct resource versatile_flash_resource = { .start = VERSATILE_FLASH_BASE, .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1, .flags = IORESOURCE_MEM,};static struct platform_device versatile_flash_device = { .name = "armflash", .id = 0, .dev = { .platform_data = &versatile_flash_data, }, .num_resources = 1, .resource = &versatile_flash_resource,};static struct resource smc91x_resources[] = { [0] = { .start = VERSATILE_ETH_BASE, .end = VERSATILE_ETH_BASE + SZ_64K - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_ETH, .end = IRQ_ETH, .flags = IORESOURCE_IRQ, },};static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources,};static struct resource versatile_i2c_resource = { .start = VERSATILE_I2C_BASE, .end = VERSATILE_I2C_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM,};static struct platform_device versatile_i2c_device = { .name = "versatile-i2c", .id = -1, .num_resources = 1, .resource = &versatile_i2c_resource,};#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)unsigned int mmc_status(struct device *dev){ struct amba_device *adev = container_of(dev, struct amba_device, dev); u32 mask; if (adev->res.start == VERSATILE_MMCI0_BASE) mask = 1; else mask = 2; return readl(VERSATILE_SYSMCI) & mask;}static struct mmc_platform_data mmc0_plat_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .status = mmc_status,};/* * Clock handling */static const struct icst307_params versatile_oscvco_params = { .ref = 24000, .vco_max = 200000, .vd_min = 4 + 8, .vd_max = 511 + 8, .rd_min = 1 + 2, .rd_max = 127 + 2,};static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco){ void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET; u32 val; val = readl(sys_osc) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, sys_lock); writel(val, sys_osc); writel(0, sys_lock);}static struct clk versatile_clcd_clk = { .name = "CLCDCLK", .params = &versatile_oscvco_params, .setvco = versatile_oscvco_set,};/* * CLCD support. */#define SYS_CLCD_MODE_MASK (3 << 0)#define SYS_CLCD_MODE_888 (0 << 0)#define SYS_CLCD_MODE_5551 (1 << 0)#define SYS_CLCD_MODE_565_RLSB (2 << 0)#define SYS_CLCD_MODE_565_BLSB (3 << 0)#define SYS_CLCD_NLCDIOON (1 << 2)#define SYS_CLCD_VDDPOSSWITCH (1 << 3)#define SYS_CLCD_PWR3V5SWITCH (1 << 4)#define SYS_CLCD_ID_MASK (0x1f << 8)#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)#define SYS_CLCD_ID_VGA (0x1f << 8)static struct clcd_panel vga = { .mode = { .name = "VGA", .refresh = 60, .xres = 640, .yres = 480, .pixclock = 39721, .left_margin = 40, .right_margin = 24, .upper_margin = 32, .lower_margin = 11, .hsync_len = 96, .vsync_len = 2, .sync = 0, .vmode = FB_VMODE_NONINTERLACED, }, .width = -1, .height = -1, .tim2 = TIM2_BCD | TIM2_IPC, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), .bpp = 16,};static struct clcd_panel sanyo_3_8_in = { .mode = { .name = "Sanyo QVGA", .refresh = 116, .xres = 320, .yres = 240, .pixclock = 100000, .left_margin = 6, .right_margin = 6, .upper_margin = 5, .lower_margin = 5, .hsync_len = 6, .vsync_len = 6, .sync = 0, .vmode = FB_VMODE_NONINTERLACED, }, .width = -1, .height = -1, .tim2 = TIM2_BCD, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), .bpp = 16,};static struct clcd_panel sanyo_2_5_in = { .mode = { .name = "Sanyo QVGA Portrait", .refresh = 116, .xres = 240, .yres = 320, .pixclock = 100000, .left_margin = 20, .right_margin = 10, .upper_margin = 2, .lower_margin = 2, .hsync_len = 10, .vsync_len = 2, .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED, }, .width = -1, .height = -1, .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), .bpp = 16,};static struct clcd_panel epson_2_2_in = { .mode = { .name = "Epson QCIF", .refresh = 390, .xres = 176, .yres = 220, .pixclock = 62500, .left_margin = 3,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -