1/* 2 * linux/arch/arm/mach-integrator/core.c 3 * 4 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2, as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/types.h> 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/device.h> 14#include <linux/spinlock.h> 15#include <linux/interrupt.h> 16#include <linux/irq.h> 17#include <linux/sched.h> 18#include <linux/smp.h> 19#include <linux/termios.h> 20#include <linux/amba/bus.h> 21#include <linux/amba/serial.h> 22 23#include <asm/hardware.h> 24#include <asm/irq.h> 25#include <asm/io.h> 26#include <asm/hardware/arm_timer.h> 27#include <asm/arch/cm.h> 28#include <asm/system.h> 29#include <asm/leds.h> 30#include <asm/mach/time.h> 31 32#include "common.h" 33 34static struct amba_pl010_data integrator_uart_data; 35 36static struct amba_device rtc_device = { 37 .dev = { 38 .bus_id = "mb:15", 39 }, 40 .res = { 41 .start = INTEGRATOR_RTC_BASE, 42 .end = INTEGRATOR_RTC_BASE + SZ_4K - 1, 43 .flags = IORESOURCE_MEM, 44 }, 45 .irq = { IRQ_RTCINT, NO_IRQ }, 46 .periphid = 0x00041030, 47}; 48 49static struct amba_device uart0_device = { 50 .dev = { 51 .bus_id = "mb:16", 52 .platform_data = &integrator_uart_data, 53 }, 54 .res = { 55 .start = INTEGRATOR_UART0_BASE, 56 .end = INTEGRATOR_UART0_BASE + SZ_4K - 1, 57 .flags = IORESOURCE_MEM, 58 }, 59 .irq = { IRQ_UARTINT0, NO_IRQ }, 60 .periphid = 0x0041010, 61}; 62 63static struct amba_device uart1_device = { 64 .dev = { 65 .bus_id = "mb:17", 66 .platform_data = &integrator_uart_data, 67 }, 68 .res = { 69 .start = INTEGRATOR_UART1_BASE, 70 .end = INTEGRATOR_UART1_BASE + SZ_4K - 1, 71 .flags = IORESOURCE_MEM, 72 }, 73 .irq = { IRQ_UARTINT1, NO_IRQ }, 74 .periphid = 0x0041010, 75}; 76 77static struct amba_device kmi0_device = { 78 .dev = { 79 .bus_id = "mb:18", 80 }, 81 .res = { 82 .start = KMI0_BASE, 83 .end = KMI0_BASE + SZ_4K - 1, 84 .flags = IORESOURCE_MEM, 85 }, 86 .irq = { IRQ_KMIINT0, NO_IRQ }, 87 .periphid = 0x00041050, 88}; 89 90static struct amba_device kmi1_device = { 91 .dev = { 92 .bus_id = "mb:19", 93 }, 94 .res = { 95 .start = KMI1_BASE, 96 .end = KMI1_BASE + SZ_4K - 1, 97 .flags = IORESOURCE_MEM, 98 }, 99 .irq = { IRQ_KMIINT1, NO_IRQ }, 100 .periphid = 0x00041050, 101}; 102 103static struct amba_device *amba_devs[] __initdata = { 104 &rtc_device, 105 &uart0_device, 106 &uart1_device, 107 &kmi0_device, 108 &kmi1_device, 109}; 110 111static int __init integrator_init(void) 112{ 113 int i; 114 115 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 116 struct amba_device *d = amba_devs[i]; 117 amba_device_register(d, &iomem_resource); 118 } 119 120 return 0; 121} 122 123arch_initcall(integrator_init); 124 125/* 126 * On the Integrator platform, the port RTS and DTR are provided by 127 * bits in the following SC_CTRLS register bits: 128 * RTS DTR 129 * UART0 7 6 130 * UART1 5 4 131 */ 132#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) 133#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) 134 135static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) 136{ 137 unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; 138 139 if (dev == &uart0_device) { 140 rts_mask = 1 << 4; 141 dtr_mask = 1 << 5; 142 } else { 143 rts_mask = 1 << 6; 144 dtr_mask = 1 << 7; 145 } 146 147 if (mctrl & TIOCM_RTS) 148 ctrlc |= rts_mask; 149 else 150 ctrls |= rts_mask; 151 152 if (mctrl & TIOCM_DTR) 153 ctrlc |= dtr_mask; 154 else 155 ctrls |= dtr_mask; 156 157 __raw_writel(ctrls, SC_CTRLS); 158 __raw_writel(ctrlc, SC_CTRLC); 159} 160 161static struct amba_pl010_data integrator_uart_data = { 162 .set_mctrl = integrator_uart_set_mctrl, 163}; 164 165#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET 166 167static DEFINE_SPINLOCK(cm_lock); 168 169/** 170 * cm_control - update the CM_CTRL register. 171 * @mask: bits to change 172 * @set: bits to set 173 */ 174void cm_control(u32 mask, u32 set) 175{ 176 unsigned long flags; 177 u32 val; 178 179 spin_lock_irqsave(&cm_lock, flags); 180 val = readl(CM_CTRL) & ~mask; 181 writel(val | set, CM_CTRL); 182 spin_unlock_irqrestore(&cm_lock, flags); 183} 184 185EXPORT_SYMBOL(cm_control); 186 187/* 188 * Where is the timer (VA)? 189 */ 190#define TIMER0_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000000) 191#define TIMER1_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000100) 192#define TIMER2_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000200) 193#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) 194 195/* 196 * How long is the timer interval? 197 */ 198#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) 199#if TIMER_INTERVAL >= 0x100000 200#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) 201#elif TIMER_INTERVAL >= 0x10000 202#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) 203#else 204#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 205#endif 206 207static unsigned long timer_reload; 208 209/* 210 * Returns number of ms since last clock interrupt. Note that interrupts 211 * will have been disabled by do_gettimeoffset() 212 */ 213unsigned long integrator_gettimeoffset(void) 214{ 215 unsigned long ticks1, ticks2, status; 216 217 /* 218 * Get the current number of ticks. Note that there is a race 219 * condition between us reading the timer and checking for 220 * an interrupt. We get around this by ensuring that the 221 * counter has not reloaded between our two reads. 222 */ 223 ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; 224 do { 225 ticks1 = ticks2; 226 status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS); 227 ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; 228 } while (ticks2 > ticks1); 229 230 /* 231 * Number of ticks since last interrupt. 232 */ 233 ticks1 = timer_reload - ticks2; 234 235 /* 236 * Interrupt pending? If so, we've reloaded once already. 237 */ 238 if (status & (1 << IRQ_TIMERINT1)) 239 ticks1 += timer_reload; 240 241 /* 242 * Convert the ticks to usecs 243 */ 244 return TICKS2USECS(ticks1); 245} 246 247/* 248 * IRQ handler for the timer 249 */ 250static irqreturn_t 251integrator_timer_interrupt(int irq, void *dev_id) 252{ 253 write_seqlock(&xtime_lock); 254 255 /* 256 * clear the interrupt 257 */ 258 writel(1, TIMER1_VA_BASE + TIMER_INTCLR); 259 260 timer_tick(); 261 262 write_sequnlock(&xtime_lock); 263 264 return IRQ_HANDLED; 265} 266 267static struct irqaction integrator_timer_irq = { 268 .name = "Integrator Timer Tick", 269 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 270 .handler = integrator_timer_interrupt, 271}; 272 273/* 274 * Set up timer interrupt, and return the current time in seconds. 275 */ 276void __init integrator_time_init(unsigned long reload, unsigned int ctrl) 277{ 278 unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; 279 280 timer_reload = reload; 281 timer_ctrl |= ctrl; 282 283 if (timer_reload > 0x100000) { 284 timer_reload >>= 8; 285 timer_ctrl |= TIMER_CTRL_DIV256; 286 } else if (timer_reload > 0x010000) { 287 timer_reload >>= 4; 288 timer_ctrl |= TIMER_CTRL_DIV16; 289 } 290 291 /* 292 * Initialise to a known state (all timers off) 293 */ 294 writel(0, TIMER0_VA_BASE + TIMER_CTRL); 295 writel(0, TIMER1_VA_BASE + TIMER_CTRL); 296 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 297 298 writel(timer_reload, TIMER1_VA_BASE + TIMER_LOAD); 299 writel(timer_reload, TIMER1_VA_BASE + TIMER_VALUE); 300 writel(timer_ctrl, TIMER1_VA_BASE + TIMER_CTRL); 301 302 /* 303 * Make irqs happen for the system timer 304 */ 305 setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); 306} 307