X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-versatile%2Fcore.c;h=bf71507c76fd91602d2513c40f19e06a8740e06b;hb=refs%2Fheads%2Fvserver;hp=239d9897d6745838d0a2a7d97270e405efc61fa2;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 239d9897d..bf71507c7 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -18,30 +18,35 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include +#include #include #include +#include +#include +#include #include #include #include #include #include +#include +#include +#include #include -#include -#include #include #include #include #include #include -#ifdef CONFIG_MMC #include -#endif + +#include "core.h" +#include "clock.h" /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx @@ -49,26 +54,9 @@ * * Setup a VA for the Versatile Vectored Interrupt Controller. */ -#define VA_VIC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) -#define VA_SIC_BASE IO_ADDRESS(VERSATILE_SIC_BASE) - -static void vic_mask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); -} - -static void vic_unmask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE); -} - -static struct irqchip vic_chip = { - .ack = vic_mask_irq, - .mask = vic_mask_irq, - .unmask = vic_unmask_irq, -}; +#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) { @@ -82,19 +70,20 @@ static void sic_unmask_irq(unsigned int irq) writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET); } -static struct irqchip sic_chip = { +static struct irq_chip sic_chip = { + .name = "SIC", .ack = sic_mask_irq, .mask = sic_mask_irq, .unmask = sic_unmask_irq, }; static void -sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) +sic_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, regs); + do_bad_IRQ(irq, desc); return; } @@ -105,63 +94,29 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) irq += IRQ_SIC_START; desc = irq_desc + irq; - desc->handle(irq, desc, regs); + desc_handle_irq(irq, desc); } while (status); } #if 1 #define IRQ_MMCI0A IRQ_VICSOURCE22 -#define IRQ_MMCI1A IRQ_VICSOURCE23 #define IRQ_AACI IRQ_VICSOURCE24 #define IRQ_ETH IRQ_VICSOURCE25 #define PIC_MASK 0xFFD00000 #else #define IRQ_MMCI0A IRQ_SIC_MMCI0A -#define IRQ_MMCI1A IRQ_SIC_MMCI1A #define IRQ_AACI IRQ_SIC_AACI #define IRQ_ETH IRQ_SIC_ETH #define PIC_MASK 0 #endif -static void __init versatile_init_irq(void) +void __init versatile_init_irq(void) { - unsigned int i, value; - - /* Disable all interrupts initially. */ - - writel(0, VA_VIC_BASE + VIC_INT_SELECT); - writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE); - writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); - writel(0, VA_VIC_BASE + VIC_IRQ_STATUS); - writel(0, VA_VIC_BASE + VIC_ITCR); - writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR); + unsigned int i; - /* - * Make sure we clear all existing interrupts - */ - writel(0, VA_VIC_BASE + VIC_VECT_ADDR); - for (i = 0; i < 19; i++) { - value = readl(VA_VIC_BASE + VIC_VECT_ADDR); - writel(value, VA_VIC_BASE + VIC_VECT_ADDR); - } - - for (i = 0; i < 16; i++) { - value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); - writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); - } - - writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR); + vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0); - for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) { - if (i != IRQ_VICSOURCE31) { - set_irq_chip(i, &vic_chip); - set_irq_handler(i, do_level_IRQ); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } - } - - set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); - vic_unmask_irq(IRQ_VICSOURCE31); + set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq); /* Do second interrupt controller */ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); @@ -169,7 +124,7 @@ static void __init versatile_init_irq(void) 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, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } @@ -185,44 +140,114 @@ static void __init versatile_init_irq(void) } static struct map_desc versatile_io_desc[] __initdata = { - { IO_ADDRESS(VERSATILE_SYS_BASE), VERSATILE_SYS_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(VERSATILE_SIC_BASE), VERSATILE_SIC_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(VERSATILE_VIC_BASE), VERSATILE_VIC_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(VERSATILE_SCTL_BASE), VERSATILE_SCTL_BASE, SZ_4K * 9, MT_DEVICE }, + { + .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 - { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE }, + { + .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 -#ifdef FIXME - { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE }, - { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE }, - { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE }, - { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE }, #endif }; -static void __init versatile_map_io(void) +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) +#define VERSATILE_REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) /* - * This is the VersatilePB sched_clock implementation. This has - * a resolution of 41.7ns, and a maximum value of about 179s. + * 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; + unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER)); - v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125; - do_div(v, 3); + /* 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) +#define VERSATILE_FLASHCTRL (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET) static int versatile_flash_init(void) { @@ -266,7 +291,7 @@ static struct flash_platform_data versatile_flash_data = { static struct resource versatile_flash_resource = { .start = VERSATILE_FLASH_BASE, - .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE, + .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1, .flags = IORESOURCE_MEM, }; @@ -300,10 +325,22 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -#define VERSATILE_SYSMCI (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) +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) -#ifdef CONFIG_MMC -static unsigned int mmc_status(struct device *dev) +unsigned int mmc_status(struct device *dev) { struct amba_device *adev = container_of(dev, struct amba_device, dev); u32 mask; @@ -321,20 +358,46 @@ static struct mmc_platform_data mmc0_plat_data = { .status = mmc_status, }; -static struct mmc_platform_data mmc1_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, }; -#endif /* * CLCD support. */ #define SYS_CLCD_MODE_MASK (3 << 0) -#define SYS_CLCD_MODE_5551 (0 << 0) -#define SYS_CLCD_MODE_565 (1 << 0) -#define SYS_CLCD_MODE_888 (2 << 0) -#define SYS_CLCD_MODE_LT (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) @@ -342,6 +405,7 @@ static struct mmc_platform_data mmc1_plat_data = { #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 = { @@ -390,6 +454,29 @@ static struct clcd_panel sanyo_3_8_in = { .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", @@ -421,13 +508,15 @@ static struct clcd_panel epson_2_2_in = { */ static struct clcd_panel *versatile_clcd_panel(void) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; struct clcd_panel *panel = &vga; u32 val; val = readl(sys_clcd) & SYS_CLCD_ID_MASK; if (val == SYS_CLCD_ID_SANYO_3_8) panel = &sanyo_3_8_in; + else if (val == SYS_CLCD_ID_SANYO_2_5) + panel = &sanyo_2_5_in; else if (val == SYS_CLCD_ID_EPSON_2_2) panel = &epson_2_2_in; else if (val == SYS_CLCD_ID_VGA) @@ -435,9 +524,10 @@ static struct clcd_panel *versatile_clcd_panel(void) else { printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); + panel = &vga; } - return &vga; + return panel; } /* @@ -445,12 +535,26 @@ static struct clcd_panel *versatile_clcd_panel(void) */ static void versatile_clcd_disable(struct clcd_fb *fb) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; writel(val, sys_clcd); + +#ifdef CONFIG_MACH_VERSATILE_AB + /* + * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off + */ + if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) { + void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); + unsigned long ctrl; + + ctrl = readl(versatile_ib2_ctrl); + ctrl &= ~0x01; + writel(ctrl, versatile_ib2_ctrl); + } +#endif } /* @@ -458,7 +562,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb) */ static void versatile_clcd_enable(struct clcd_fb *fb) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); @@ -466,19 +570,10 @@ static void versatile_clcd_enable(struct clcd_fb *fb) switch (fb->fb.var.green.length) { case 5: -#if 0 - /* - * For some undocumented reason, we need to select 565 mode - * even when using 555 with VGA. Maybe this is only true - * for the VGA output and needs to be done for LCD panels? - * I can't get an explaination from the people who should - * know. - */ val |= SYS_CLCD_MODE_5551; break; -#endif case 6: - val |= SYS_CLCD_MODE_565; + val |= SYS_CLCD_MODE_565_RLSB; break; case 8: val |= SYS_CLCD_MODE_888; @@ -495,6 +590,20 @@ static void versatile_clcd_enable(struct clcd_fb *fb) */ val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; writel(val, sys_clcd); + +#ifdef CONFIG_MACH_VERSATILE_AB + /* + * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on + */ + if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) { + void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); + unsigned long ctrl; + + ctrl = readl(versatile_ib2_ctrl); + ctrl |= 0x01; + writel(ctrl, versatile_ib2_ctrl); + } +#endif } static unsigned long framesize = SZ_1M; @@ -518,6 +627,14 @@ static int versatile_clcd_setup(struct clcd_fb *fb) return 0; } +static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + static void versatile_clcd_remove(struct clcd_fb *fb) { dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, @@ -525,32 +642,16 @@ static void versatile_clcd_remove(struct clcd_fb *fb) } static struct clcd_board clcd_plat_data = { - .name = "Versatile PB", + .name = "Versatile", .check = clcdfb_check, .decode = clcdfb_decode, .disable = versatile_clcd_disable, .enable = versatile_clcd_enable, .setup = versatile_clcd_setup, + .mmap = versatile_clcd_mmap, .remove = versatile_clcd_remove, }; -#define AMBA_DEVICE(name,busid,base,plat) \ -static struct amba_device name##_device = { \ - .dev = { \ - .coherent_dma_mask = ~0, \ - .bus_id = busid, \ - .platform_data = plat, \ - }, \ - .res = { \ - .start = VERSATILE_##base##_BASE, \ - .end = (VERSATILE_##base##_BASE) + SZ_4K - 1,\ - .flags = IORESOURCE_MEM, \ - }, \ - .dma_mask = ~0, \ - .irq = base##_IRQ, \ - /* .dma = base##_DMA,*/ \ -} - #define AACI_IRQ { IRQ_AACI, NO_IRQ } #define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B } @@ -559,12 +660,6 @@ static struct amba_device name##_device = { \ #define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ } #define KMI1_DMA { 0, 0 } -#define UART3_IRQ { IRQ_SIC_UART3, NO_IRQ } -#define UART3_DMA { 0x86, 0x87 } -#define SCI1_IRQ { IRQ_SIC_SCI3, NO_IRQ } -#define SCI1_DMA { 0x88, 0x89 } -#define MMCI1_IRQ { IRQ_MMCI1A, IRQ_SIC_MMCI1B } -#define MMCI1_DMA { 0x85, 0 } /* * These devices are connected directly to the multi-layer AHB switch @@ -589,10 +684,6 @@ static struct amba_device name##_device = { \ #define GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ } #define GPIO1_DMA { 0, 0 } -#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } -#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define RTC_IRQ { IRQ_RTCINT, NO_IRQ } #define RTC_DMA { 0, 0 } @@ -612,16 +703,9 @@ static struct amba_device name##_device = { \ /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); -#ifdef CONFIG_MMC AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &mmc0_plat_data); -#endif AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL); AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL); -AMBA_DEVICE(uart3, "fpga:09", UART3, NULL); -AMBA_DEVICE(sci1, "fpga:0a", SCI1, NULL); -#ifdef CONFIG_MMC -AMBA_DEVICE(mmc1, "fpga:0b", MMCI1, &mmc1_plat_data); -#endif /* DevChip Primecells */ AMBA_DEVICE(smc, "dev:00", SMC, NULL); @@ -632,8 +716,6 @@ AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL); AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL); AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL); AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL); -AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL); -AMBA_DEVICE(gpio3, "dev:e7", GPIO3, NULL); AMBA_DEVICE(rtc, "dev:e8", RTC, NULL); AMBA_DEVICE(sci0, "dev:f0", SCI, NULL); AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); @@ -646,7 +728,6 @@ static struct amba_device *amba_devs[] __initdata = { &uart0_device, &uart1_device, &uart2_device, - &uart3_device, &smc_device, &mpmc_device, &clcd_device, @@ -654,24 +735,17 @@ static struct amba_device *amba_devs[] __initdata = { &wdog_device, &gpio0_device, &gpio1_device, - &gpio2_device, - &gpio3_device, &rtc_device, &sci0_device, &ssp0_device, &aaci_device, -#ifdef CONFIG_MMC &mmc0_device, -#endif &kmi0_device, &kmi1_device, - &sci1_device, -#ifdef CONFIG_MMC - &mmc1_device, -#endif }; -#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) +#ifdef CONFIG_LEDS +#define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) static void versatile_leds_event(led_event_t ledevt) { @@ -705,12 +779,16 @@ static void versatile_leds_event(led_event_t ledevt) writel(val, VA_LEDS_BASE); local_irq_restore(flags); } +#endif /* CONFIG_LEDS */ -static void __init versatile_init(void) +void __init versatile_init(void) { int i; + clk_register(&versatile_clcd_clk); + platform_device_register(&versatile_flash_device); + platform_device_register(&versatile_i2c_device); platform_device_register(&smc91x_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { @@ -718,57 +796,44 @@ static void __init versatile_init(void) amba_device_register(d, &iomem_resource); } +#ifdef CONFIG_LEDS leds_event = versatile_leds_event; +#endif } /* * Where is the timer (VA)? */ -#define TIMER0_VA_BASE IO_ADDRESS(VERSATILE_TIMER0_1_BASE) -#define TIMER1_VA_BASE (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20) -#define TIMER2_VA_BASE IO_ADDRESS(VERSATILE_TIMER2_3_BASE) -#define TIMER3_VA_BASE (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20) -#define VA_IC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) +#define TIMER0_VA_BASE __io_address(VERSATILE_TIMER0_1_BASE) +#define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20) +#define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE) +#define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20) +#define VA_IC_BASE __io_address(VERSATILE_VIC_BASE) /* * How long is the timer interval? */ #define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) #if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) /* Divide by 256 */ -#define TIMER_CTRL 0x88 /* Enable, Clock / 256 */ +#define TIMER_RELOAD (TIMER_INTERVAL >> 8) +#define TIMER_DIVISOR (TIMER_CTRL_DIV256) #define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) #elif TIMER_INTERVAL >= 0x10000 #define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_CTRL 0x84 /* Enable, Clock / 16 */ +#define TIMER_DIVISOR (TIMER_CTRL_DIV16) #define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) #else #define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_CTRL 0x80 /* Enable */ +#define TIMER_DIVISOR (TIMER_CTRL_DIV1) #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) #endif -#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ - -/* - * What does it look like? - */ -typedef struct TimerStruct { - unsigned long TimerLoad; - unsigned long TimerValue; - unsigned long TimerControl; - unsigned long TimerClear; -} TimerStruct_t; - -extern unsigned long (*gettimeoffset)(void); - /* * Returns number of ms since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() */ static unsigned long versatile_gettimeoffset(void) { - volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE; unsigned long ticks1, ticks2, status; /* @@ -777,11 +842,11 @@ static unsigned long versatile_gettimeoffset(void) * an interrupt. We get around this by ensuring that the * counter has not reloaded between our two reads. */ - ticks2 = timer0->TimerValue & 0xffff; + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; do { ticks1 = ticks2; - status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); - ticks2 = timer0->TimerValue & 0xffff; + status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS); + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; } while (ticks2 > ticks1); /* @@ -806,68 +871,65 @@ static unsigned long versatile_gettimeoffset(void) /* * IRQ handler for the timer */ -static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) { - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; + write_seqlock(&xtime_lock); // ...clear the interrupt - timer0->TimerClear = 1; + writel(1, TIMER0_VA_BASE + TIMER_INTCLR); - timer_tick(regs); + timer_tick(); + + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } static struct irqaction versatile_timer_irq = { .name = "Versatile Timer Tick", - .flags = SA_INTERRUPT, - .handler = versatile_timer_interrupt + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = versatile_timer_interrupt, }; /* * Set up timer interrupt, and return the current time in seconds. */ -void __init versatile_init_time(void) +static void __init versatile_timer_init(void) { - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; - volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; - volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; - volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE; + u32 val; /* * set clock frequency: * VERSATILE_REFCLK is 32KHz * VERSATILE_TIMCLK is 1MHz */ - *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= - ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | - (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel)); + val = readl(__io_address(VERSATILE_SCTL_BASE)); + writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, + __io_address(VERSATILE_SCTL_BASE)); /* * Initialise to a known state (all timers off) */ - timer0->TimerControl = 0; - timer1->TimerControl = 0; - timer2->TimerControl = 0; - timer3->TimerControl = 0; + writel(0, TIMER0_VA_BASE + TIMER_CTRL); + writel(0, TIMER1_VA_BASE + TIMER_CTRL); + writel(0, TIMER2_VA_BASE + TIMER_CTRL); + writel(0, TIMER3_VA_BASE + TIMER_CTRL); - timer0->TimerLoad = TIMER_RELOAD; - timer0->TimerValue = TIMER_RELOAD; - timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */ + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE); + writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC | + TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL); /* * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); - gettimeoffset = versatile_gettimeoffset; } -MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") - MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") - BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000) - BOOT_PARAMS(0x00000100) - MAPIO(versatile_map_io) - INITIRQ(versatile_init_irq) - INITTIME(versatile_init_time) - INIT_MACHINE(versatile_init) -MACHINE_END +struct sys_timer versatile_timer = { + .init = versatile_timer_init, + .offset = versatile_gettimeoffset, +};