| .. | .. |
|---|
| 19 | 19 | #include <linux/mm.h> |
|---|
| 20 | 20 | #include <linux/seq_file.h> |
|---|
| 21 | 21 | #include <linux/tty.h> |
|---|
| 22 | +#include <linux/clocksource.h> |
|---|
| 22 | 23 | #include <linux/console.h> |
|---|
| 23 | 24 | #include <linux/linkage.h> |
|---|
| 24 | 25 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 31 | 32 | #include <asm/bootinfo.h> |
|---|
| 32 | 33 | #include <asm/bootinfo-vme.h> |
|---|
| 33 | 34 | #include <asm/byteorder.h> |
|---|
| 34 | | -#include <asm/pgtable.h> |
|---|
| 35 | 35 | #include <asm/setup.h> |
|---|
| 36 | 36 | #include <asm/irq.h> |
|---|
| 37 | 37 | #include <asm/traps.h> |
|---|
| .. | .. |
|---|
| 44 | 44 | |
|---|
| 45 | 45 | static void mvme16x_get_model(char *model); |
|---|
| 46 | 46 | extern void mvme16x_sched_init(irq_handler_t handler); |
|---|
| 47 | | -extern u32 mvme16x_gettimeoffset(void); |
|---|
| 48 | 47 | extern int mvme16x_hwclk (int, struct rtc_time *); |
|---|
| 49 | 48 | extern void mvme16x_reset (void); |
|---|
| 50 | 49 | |
|---|
| .. | .. |
|---|
| 115 | 114 | m68k_setup_user_interrupt(VEC_USER, 192); |
|---|
| 116 | 115 | } |
|---|
| 117 | 116 | |
|---|
| 118 | | -#define pcc2chip ((volatile u_char *)0xfff42000) |
|---|
| 119 | | -#define PccSCCMICR 0x1d |
|---|
| 120 | | -#define PccSCCTICR 0x1e |
|---|
| 121 | | -#define PccSCCRICR 0x1f |
|---|
| 122 | | -#define PccTPIACKR 0x25 |
|---|
| 117 | +#define PCC2CHIP (0xfff42000) |
|---|
| 118 | +#define PCCSCCMICR (PCC2CHIP + 0x1d) |
|---|
| 119 | +#define PCCSCCTICR (PCC2CHIP + 0x1e) |
|---|
| 120 | +#define PCCSCCRICR (PCC2CHIP + 0x1f) |
|---|
| 121 | +#define PCCTPIACKR (PCC2CHIP + 0x25) |
|---|
| 123 | 122 | |
|---|
| 124 | 123 | #ifdef CONFIG_EARLY_PRINTK |
|---|
| 125 | 124 | |
|---|
| .. | .. |
|---|
| 227 | 226 | base_addr[CyIER] = CyTxMpty; |
|---|
| 228 | 227 | |
|---|
| 229 | 228 | while (1) { |
|---|
| 230 | | - if (pcc2chip[PccSCCTICR] & 0x20) |
|---|
| 229 | + if (in_8(PCCSCCTICR) & 0x20) |
|---|
| 231 | 230 | { |
|---|
| 232 | 231 | /* We have a Tx int. Acknowledge it */ |
|---|
| 233 | | - sink = pcc2chip[PccTPIACKR]; |
|---|
| 232 | + sink = in_8(PCCTPIACKR); |
|---|
| 234 | 233 | if ((base_addr[CyLICR] >> 2) == port) { |
|---|
| 235 | 234 | if (i == count) { |
|---|
| 236 | 235 | /* Last char of string is now output */ |
|---|
| .. | .. |
|---|
| 272 | 271 | mach_max_dma_address = 0xffffffff; |
|---|
| 273 | 272 | mach_sched_init = mvme16x_sched_init; |
|---|
| 274 | 273 | mach_init_IRQ = mvme16x_init_IRQ; |
|---|
| 275 | | - arch_gettimeoffset = mvme16x_gettimeoffset; |
|---|
| 276 | 274 | mach_hwclk = mvme16x_hwclk; |
|---|
| 277 | 275 | mach_reset = mvme16x_reset; |
|---|
| 278 | 276 | mach_get_model = mvme16x_get_model; |
|---|
| .. | .. |
|---|
| 345 | 343 | return IRQ_HANDLED; |
|---|
| 346 | 344 | } |
|---|
| 347 | 345 | |
|---|
| 346 | +static u64 mvme16x_read_clk(struct clocksource *cs); |
|---|
| 347 | + |
|---|
| 348 | +static struct clocksource mvme16x_clk = { |
|---|
| 349 | + .name = "pcc", |
|---|
| 350 | + .rating = 250, |
|---|
| 351 | + .read = mvme16x_read_clk, |
|---|
| 352 | + .mask = CLOCKSOURCE_MASK(32), |
|---|
| 353 | + .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
|---|
| 354 | +}; |
|---|
| 355 | + |
|---|
| 356 | +static u32 clk_total; |
|---|
| 357 | + |
|---|
| 358 | +#define PCC_TIMER_CLOCK_FREQ 1000000 |
|---|
| 359 | +#define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ) |
|---|
| 360 | + |
|---|
| 361 | +#define PCCTCMP1 (PCC2CHIP + 0x04) |
|---|
| 362 | +#define PCCTCNT1 (PCC2CHIP + 0x08) |
|---|
| 363 | +#define PCCTOVR1 (PCC2CHIP + 0x17) |
|---|
| 364 | +#define PCCTIC1 (PCC2CHIP + 0x1b) |
|---|
| 365 | + |
|---|
| 366 | +#define PCCTOVR1_TIC_EN 0x01 |
|---|
| 367 | +#define PCCTOVR1_COC_EN 0x02 |
|---|
| 368 | +#define PCCTOVR1_OVR_CLR 0x04 |
|---|
| 369 | + |
|---|
| 370 | +#define PCCTIC1_INT_LEVEL 6 |
|---|
| 371 | +#define PCCTIC1_INT_CLR 0x08 |
|---|
| 372 | +#define PCCTIC1_INT_EN 0x10 |
|---|
| 373 | + |
|---|
| 348 | 374 | static irqreturn_t mvme16x_timer_int (int irq, void *dev_id) |
|---|
| 349 | 375 | { |
|---|
| 350 | 376 | irq_handler_t timer_routine = dev_id; |
|---|
| 351 | 377 | unsigned long flags; |
|---|
| 352 | 378 | |
|---|
| 353 | 379 | local_irq_save(flags); |
|---|
| 354 | | - *(volatile unsigned char *)0xfff4201b |= 8; |
|---|
| 380 | + out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN); |
|---|
| 381 | + out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL); |
|---|
| 382 | + clk_total += PCC_TIMER_CYCLES; |
|---|
| 355 | 383 | timer_routine(0, NULL); |
|---|
| 356 | 384 | local_irq_restore(flags); |
|---|
| 357 | 385 | |
|---|
| .. | .. |
|---|
| 364 | 392 | int irq; |
|---|
| 365 | 393 | |
|---|
| 366 | 394 | /* Using PCCchip2 or MC2 chip tick timer 1 */ |
|---|
| 367 | | - *(volatile unsigned long *)0xfff42008 = 0; |
|---|
| 368 | | - *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */ |
|---|
| 369 | | - *(volatile unsigned char *)0xfff42017 |= 3; |
|---|
| 370 | | - *(volatile unsigned char *)0xfff4201b = 0x16; |
|---|
| 371 | | - if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer", |
|---|
| 395 | + if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer", |
|---|
| 372 | 396 | timer_routine)) |
|---|
| 373 | 397 | panic ("Couldn't register timer int"); |
|---|
| 398 | + |
|---|
| 399 | + out_be32(PCCTCNT1, 0); |
|---|
| 400 | + out_be32(PCCTCMP1, PCC_TIMER_CYCLES); |
|---|
| 401 | + out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN); |
|---|
| 402 | + out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL); |
|---|
| 403 | + |
|---|
| 404 | + clocksource_register_hz(&mvme16x_clk, PCC_TIMER_CLOCK_FREQ); |
|---|
| 374 | 405 | |
|---|
| 375 | 406 | if (brdno == 0x0162 || brdno == 0x172) |
|---|
| 376 | 407 | irq = MVME162_IRQ_ABORT; |
|---|
| .. | .. |
|---|
| 381 | 412 | panic ("Couldn't register abort int"); |
|---|
| 382 | 413 | } |
|---|
| 383 | 414 | |
|---|
| 384 | | - |
|---|
| 385 | | -/* This is always executed with interrupts disabled. */ |
|---|
| 386 | | -u32 mvme16x_gettimeoffset(void) |
|---|
| 415 | +static u64 mvme16x_read_clk(struct clocksource *cs) |
|---|
| 387 | 416 | { |
|---|
| 388 | | - return (*(volatile u32 *)0xfff42008) * 1000; |
|---|
| 417 | + unsigned long flags; |
|---|
| 418 | + u8 overflow, tmp; |
|---|
| 419 | + u32 ticks; |
|---|
| 420 | + |
|---|
| 421 | + local_irq_save(flags); |
|---|
| 422 | + tmp = in_8(PCCTOVR1) >> 4; |
|---|
| 423 | + ticks = in_be32(PCCTCNT1); |
|---|
| 424 | + overflow = in_8(PCCTOVR1) >> 4; |
|---|
| 425 | + if (overflow != tmp) |
|---|
| 426 | + ticks = in_be32(PCCTCNT1); |
|---|
| 427 | + ticks += overflow * PCC_TIMER_CYCLES; |
|---|
| 428 | + ticks += clk_total; |
|---|
| 429 | + local_irq_restore(flags); |
|---|
| 430 | + |
|---|
| 431 | + return ticks; |
|---|
| 389 | 432 | } |
|---|
| 390 | 433 | |
|---|
| 391 | 434 | int bcd2int (unsigned char b) |
|---|