📄 core.c
字号:
.right_margin = 2, .upper_margin = 1, .lower_margin = 0, .hsync_len = 3, .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,};/* * Detect which LCD panel is connected, and return the appropriate * clcd_panel structure. Note: we do not have any information on * the required timings for the 8.4in panel, so we presently assume * VGA timings. */static struct clcd_panel *versatile_clcd_panel(void){ 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) panel = &vga; else { printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); panel = &vga; } return panel;}/* * Disable all display connectors on the interface module. */static void versatile_clcd_disable(struct clcd_fb *fb){ 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}/* * Enable the relevant connector on the interface module. */static void versatile_clcd_enable(struct clcd_fb *fb){ void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); val &= ~SYS_CLCD_MODE_MASK; switch (fb->fb.var.green.length) { case 5: val |= SYS_CLCD_MODE_5551; break; case 6: val |= SYS_CLCD_MODE_565_RLSB; break; case 8: val |= SYS_CLCD_MODE_888; break; } /* * Set the MUX */ writel(val, sys_clcd); /* * And now enable the PSUs */ 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;static int versatile_clcd_setup(struct clcd_fb *fb){ dma_addr_t dma; fb->panel = versatile_clcd_panel(); fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, &dma, GFP_KERNEL); if (!fb->fb.screen_base) { printk(KERN_ERR "CLCD: unable to map framebuffer\n"); return -ENOMEM; } fb->fb.fix.smem_start = dma; fb->fb.fix.smem_len = framesize; 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, fb->fb.screen_base, fb->fb.fix.smem_start);}static struct clcd_board clcd_plat_data = { .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 AACI_IRQ { IRQ_AACI, NO_IRQ }#define AACI_DMA { 0x80, 0x81 }#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B }#define MMCI0_DMA { 0x84, 0 }#define KMI0_IRQ { IRQ_SIC_KMI0, NO_IRQ }#define KMI0_DMA { 0, 0 }#define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ }#define KMI1_DMA { 0, 0 }/* * These devices are connected directly to the multi-layer AHB switch */#define SMC_IRQ { NO_IRQ, NO_IRQ }#define SMC_DMA { 0, 0 }#define MPMC_IRQ { NO_IRQ, NO_IRQ }#define MPMC_DMA { 0, 0 }#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }#define CLCD_DMA { 0, 0 }#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }#define DMAC_DMA { 0, 0 }/* * These devices are connected via the core APB bridge */#define SCTL_IRQ { NO_IRQ, NO_IRQ }#define SCTL_DMA { 0, 0 }#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }#define WATCHDOG_DMA { 0, 0 }#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }#define GPIO0_DMA { 0, 0 }#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }#define GPIO1_DMA { 0, 0 }#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }#define RTC_DMA { 0, 0 }/* * These devices are connected via the DMA APB bridge */#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }#define SCI_DMA { 7, 6 }#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }#define UART0_DMA { 15, 14 }#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }#define UART1_DMA { 13, 12 }#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }#define UART2_DMA { 11, 10 }#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }#define SSP_DMA { 9, 8 }/* FPGA Primecells */AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &mmc0_plat_data);AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);/* DevChip Primecells */AMBA_DEVICE(smc, "dev:00", SMC, NULL);AMBA_DEVICE(mpmc, "dev:10", MPMC, NULL);AMBA_DEVICE(clcd, "dev:20", CLCD, &clcd_plat_data);AMBA_DEVICE(dmac, "dev:30", DMAC, NULL);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(rtc, "dev:e8", RTC, NULL);AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);AMBA_DEVICE(uart1, "dev:f2", UART1, NULL);AMBA_DEVICE(uart2, "dev:f3", UART2, NULL);AMBA_DEVICE(ssp0, "dev:f4", SSP, NULL);static struct amba_device *amba_devs[] __initdata = { &dmac_device, &uart0_device, &uart1_device, &uart2_device, &smc_device, &mpmc_device, &clcd_device, &sctl_device, &wdog_device, &gpio0_device, &gpio1_device, &rtc_device, &sci0_device, &ssp0_device, &aaci_device, &mmc0_device, &kmi0_device, &kmi1_device,};#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){ unsigned long flags; u32 val; local_irq_save(flags); val = readl(VA_LEDS_BASE); switch (ledevt) { case led_idle_start: val = val & ~VERSATILE_SYS_LED0; break; case led_idle_end: val = val | VERSATILE_SYS_LED0; break; case led_timer: val = val ^ VERSATILE_SYS_LED1; break; case led_halted: val = 0; break; default: break; } writel(val, VA_LEDS_BASE); local_irq_restore(flags);}#endif /* CONFIG_LEDS */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++) { struct amba_device *d = amba_devs[i]; 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) /* * How long is the timer interval? */#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)#if TIMER_INTERVAL >= 0x100000#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_DIVISOR (TIMER_CTRL_DIV16)#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)#else#define TIMER_RELOAD (TIMER_INTERVAL)#define TIMER_DIVISOR (TIMER_CTRL_DIV1)#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)#endifstatic void timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk){ unsigned long ctrl; switch(mode) { case CLOCK_EVT_MODE_PERIODIC: writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); ctrl = TIMER_CTRL_PERIODIC; ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE; break; case CLOCK_EVT_MODE_ONESHOT: /* period set, and timer enabled in 'next_event' hook */ ctrl = TIMER_CTRL_ONESHOT; ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE; break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: default: ctrl = 0; } writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);}static int timer_set_next_event(unsigned long evt, struct clock_event_device *unused){ unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL); writel(evt, TIMER0_VA_BASE + TIMER_LOAD); writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL); return 0;}static struct clock_event_device timer0_clockevent = { .name = "timer0", .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = timer_set_mode, .set_next_event = timer_set_next_event,};/* * IRQ handler for the timer */static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id){ struct clock_event_device *evt = &timer0_clockevent; writel(1, TIMER0_VA_BASE + TIMER_INTCLR); evt->event_handler(evt); return IRQ_HANDLED;}static struct irqaction versatile_timer_irq = { .name = "Versatile Timer Tick", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .handler = versatile_timer_interrupt,};static cycle_t versatile_get_cycles(void){ return ~readl(TIMER3_VA_BASE + TIMER_VALUE);}static struct clocksource clocksource_versatile = { .name = "timer3", .rating = 200, .read = versatile_get_cycles, .mask = CLOCKSOURCE_MASK(32), .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS,};static int __init versatile_clocksource_init(void){ /* setup timer3 as free-running clocksource */ writel(0, TIMER3_VA_BASE + TIMER_CTRL); writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD); writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE); writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, TIMER3_VA_BASE + TIMER_CTRL); clocksource_versatile.mult = clocksource_khz2mult(1000, clocksource_versatile.shift); clocksource_register(&clocksource_versatile); return 0;}/* * Set up timer interrupt, and return the current time in seconds. */static void __init versatile_timer_init(void){ u32 val; /* * set clock frequency: * VERSATILE_REFCLK is 32KHz * VERSATILE_TIMCLK is 1MHz */ 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) */ 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); /* * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); versatile_clocksource_init(); timer0_clockevent.mult = div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); timer0_clockevent.max_delta_ns = clockevent_delta2ns(0xffffffff, &timer0_clockevent); timer0_clockevent.min_delta_ns = clockevent_delta2ns(0xf, &timer0_clockevent); timer0_clockevent.cpumask = cpumask_of_cpu(0); clockevents_register_device(&timer0_clockevent);}struct sys_timer versatile_timer = { .init = versatile_timer_init,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -