| .. | .. |
|---|
| 17 | 17 | #include <linux/mm.h> |
|---|
| 18 | 18 | #include <linux/seq_file.h> |
|---|
| 19 | 19 | #include <linux/tty.h> |
|---|
| 20 | +#include <linux/clocksource.h> |
|---|
| 20 | 21 | #include <linux/console.h> |
|---|
| 21 | 22 | #include <linux/rtc.h> |
|---|
| 22 | 23 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 31 | 32 | #include <asm/bootinfo-amiga.h> |
|---|
| 32 | 33 | #include <asm/byteorder.h> |
|---|
| 33 | 34 | #include <asm/setup.h> |
|---|
| 34 | | -#include <asm/pgtable.h> |
|---|
| 35 | 35 | #include <asm/amigahw.h> |
|---|
| 36 | 36 | #include <asm/amigaints.h> |
|---|
| 37 | 37 | #include <asm/irq.h> |
|---|
| .. | .. |
|---|
| 95 | 95 | static void amiga_sched_init(irq_handler_t handler); |
|---|
| 96 | 96 | static void amiga_get_model(char *model); |
|---|
| 97 | 97 | static void amiga_get_hardware_list(struct seq_file *m); |
|---|
| 98 | | -/* amiga specific timer functions */ |
|---|
| 99 | | -static u32 amiga_gettimeoffset(void); |
|---|
| 100 | 98 | extern void amiga_mksound(unsigned int count, unsigned int ticks); |
|---|
| 101 | 99 | static void amiga_reset(void); |
|---|
| 102 | 100 | extern void amiga_init_sound(void); |
|---|
| .. | .. |
|---|
| 216 | 214 | |
|---|
| 217 | 215 | switch (amiga_model) { |
|---|
| 218 | 216 | case AMI_UNKNOWN: |
|---|
| 219 | | - goto Generic; |
|---|
| 217 | + break; |
|---|
| 220 | 218 | |
|---|
| 221 | 219 | case AMI_600: |
|---|
| 222 | 220 | case AMI_1200: |
|---|
| 223 | 221 | AMIGAHW_SET(A1200_IDE); |
|---|
| 224 | 222 | AMIGAHW_SET(PCMCIA); |
|---|
| 223 | + fallthrough; |
|---|
| 225 | 224 | case AMI_500: |
|---|
| 226 | 225 | case AMI_500PLUS: |
|---|
| 227 | 226 | case AMI_1000: |
|---|
| 228 | 227 | case AMI_2000: |
|---|
| 229 | 228 | case AMI_2500: |
|---|
| 230 | 229 | AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */ |
|---|
| 231 | | - goto Generic; |
|---|
| 230 | + break; |
|---|
| 232 | 231 | |
|---|
| 233 | 232 | case AMI_3000: |
|---|
| 234 | 233 | case AMI_3000T: |
|---|
| 235 | 234 | AMIGAHW_SET(AMBER_FF); |
|---|
| 236 | 235 | AMIGAHW_SET(MAGIC_REKICK); |
|---|
| 237 | | - /* fall through */ |
|---|
| 236 | + fallthrough; |
|---|
| 238 | 237 | case AMI_3000PLUS: |
|---|
| 239 | 238 | AMIGAHW_SET(A3000_SCSI); |
|---|
| 240 | 239 | AMIGAHW_SET(A3000_CLK); |
|---|
| 241 | 240 | AMIGAHW_SET(ZORRO3); |
|---|
| 242 | | - goto Generic; |
|---|
| 241 | + break; |
|---|
| 243 | 242 | |
|---|
| 244 | 243 | case AMI_4000T: |
|---|
| 245 | 244 | AMIGAHW_SET(A4000_SCSI); |
|---|
| 246 | | - /* fall through */ |
|---|
| 245 | + fallthrough; |
|---|
| 247 | 246 | case AMI_4000: |
|---|
| 248 | 247 | AMIGAHW_SET(A4000_IDE); |
|---|
| 249 | 248 | AMIGAHW_SET(A3000_CLK); |
|---|
| 250 | 249 | AMIGAHW_SET(ZORRO3); |
|---|
| 251 | | - goto Generic; |
|---|
| 250 | + break; |
|---|
| 252 | 251 | |
|---|
| 253 | 252 | case AMI_CDTV: |
|---|
| 254 | 253 | case AMI_CD32: |
|---|
| 255 | 254 | AMIGAHW_SET(CD_ROM); |
|---|
| 256 | 255 | AMIGAHW_SET(A2000_CLK); /* Is this correct? */ |
|---|
| 257 | | - goto Generic; |
|---|
| 258 | | - |
|---|
| 259 | | - Generic: |
|---|
| 260 | | - AMIGAHW_SET(AMI_VIDEO); |
|---|
| 261 | | - AMIGAHW_SET(AMI_BLITTER); |
|---|
| 262 | | - AMIGAHW_SET(AMI_AUDIO); |
|---|
| 263 | | - AMIGAHW_SET(AMI_FLOPPY); |
|---|
| 264 | | - AMIGAHW_SET(AMI_KEYBOARD); |
|---|
| 265 | | - AMIGAHW_SET(AMI_MOUSE); |
|---|
| 266 | | - AMIGAHW_SET(AMI_SERIAL); |
|---|
| 267 | | - AMIGAHW_SET(AMI_PARALLEL); |
|---|
| 268 | | - AMIGAHW_SET(CHIP_RAM); |
|---|
| 269 | | - AMIGAHW_SET(PAULA); |
|---|
| 270 | | - |
|---|
| 271 | | - switch (amiga_chipset) { |
|---|
| 272 | | - case CS_OCS: |
|---|
| 273 | | - case CS_ECS: |
|---|
| 274 | | - case CS_AGA: |
|---|
| 275 | | - switch (amiga_custom.deniseid & 0xf) { |
|---|
| 276 | | - case 0x0c: |
|---|
| 277 | | - AMIGAHW_SET(DENISE_HR); |
|---|
| 278 | | - break; |
|---|
| 279 | | - case 0x08: |
|---|
| 280 | | - AMIGAHW_SET(LISA); |
|---|
| 281 | | - break; |
|---|
| 282 | | - } |
|---|
| 283 | | - break; |
|---|
| 284 | | - default: |
|---|
| 285 | | - AMIGAHW_SET(DENISE); |
|---|
| 286 | | - break; |
|---|
| 287 | | - } |
|---|
| 288 | | - switch ((amiga_custom.vposr>>8) & 0x7f) { |
|---|
| 289 | | - case 0x00: |
|---|
| 290 | | - AMIGAHW_SET(AGNUS_PAL); |
|---|
| 291 | | - break; |
|---|
| 292 | | - case 0x10: |
|---|
| 293 | | - AMIGAHW_SET(AGNUS_NTSC); |
|---|
| 294 | | - break; |
|---|
| 295 | | - case 0x20: |
|---|
| 296 | | - case 0x21: |
|---|
| 297 | | - AMIGAHW_SET(AGNUS_HR_PAL); |
|---|
| 298 | | - break; |
|---|
| 299 | | - case 0x30: |
|---|
| 300 | | - case 0x31: |
|---|
| 301 | | - AMIGAHW_SET(AGNUS_HR_NTSC); |
|---|
| 302 | | - break; |
|---|
| 303 | | - case 0x22: |
|---|
| 304 | | - case 0x23: |
|---|
| 305 | | - AMIGAHW_SET(ALICE_PAL); |
|---|
| 306 | | - break; |
|---|
| 307 | | - case 0x32: |
|---|
| 308 | | - case 0x33: |
|---|
| 309 | | - AMIGAHW_SET(ALICE_NTSC); |
|---|
| 310 | | - break; |
|---|
| 311 | | - } |
|---|
| 312 | | - AMIGAHW_SET(ZORRO); |
|---|
| 313 | 256 | break; |
|---|
| 314 | 257 | |
|---|
| 315 | 258 | case AMI_DRACO: |
|---|
| .. | .. |
|---|
| 318 | 261 | default: |
|---|
| 319 | 262 | panic("Unknown Amiga Model"); |
|---|
| 320 | 263 | } |
|---|
| 264 | + |
|---|
| 265 | + AMIGAHW_SET(AMI_VIDEO); |
|---|
| 266 | + AMIGAHW_SET(AMI_BLITTER); |
|---|
| 267 | + AMIGAHW_SET(AMI_AUDIO); |
|---|
| 268 | + AMIGAHW_SET(AMI_FLOPPY); |
|---|
| 269 | + AMIGAHW_SET(AMI_KEYBOARD); |
|---|
| 270 | + AMIGAHW_SET(AMI_MOUSE); |
|---|
| 271 | + AMIGAHW_SET(AMI_SERIAL); |
|---|
| 272 | + AMIGAHW_SET(AMI_PARALLEL); |
|---|
| 273 | + AMIGAHW_SET(CHIP_RAM); |
|---|
| 274 | + AMIGAHW_SET(PAULA); |
|---|
| 275 | + |
|---|
| 276 | + switch (amiga_chipset) { |
|---|
| 277 | + case CS_OCS: |
|---|
| 278 | + case CS_ECS: |
|---|
| 279 | + case CS_AGA: |
|---|
| 280 | + switch (amiga_custom.deniseid & 0xf) { |
|---|
| 281 | + case 0x0c: |
|---|
| 282 | + AMIGAHW_SET(DENISE_HR); |
|---|
| 283 | + break; |
|---|
| 284 | + case 0x08: |
|---|
| 285 | + AMIGAHW_SET(LISA); |
|---|
| 286 | + break; |
|---|
| 287 | + default: |
|---|
| 288 | + AMIGAHW_SET(DENISE); |
|---|
| 289 | + break; |
|---|
| 290 | + } |
|---|
| 291 | + break; |
|---|
| 292 | + } |
|---|
| 293 | + switch ((amiga_custom.vposr>>8) & 0x7f) { |
|---|
| 294 | + case 0x00: |
|---|
| 295 | + AMIGAHW_SET(AGNUS_PAL); |
|---|
| 296 | + break; |
|---|
| 297 | + case 0x10: |
|---|
| 298 | + AMIGAHW_SET(AGNUS_NTSC); |
|---|
| 299 | + break; |
|---|
| 300 | + case 0x20: |
|---|
| 301 | + case 0x21: |
|---|
| 302 | + AMIGAHW_SET(AGNUS_HR_PAL); |
|---|
| 303 | + break; |
|---|
| 304 | + case 0x30: |
|---|
| 305 | + case 0x31: |
|---|
| 306 | + AMIGAHW_SET(AGNUS_HR_NTSC); |
|---|
| 307 | + break; |
|---|
| 308 | + case 0x22: |
|---|
| 309 | + case 0x23: |
|---|
| 310 | + AMIGAHW_SET(ALICE_PAL); |
|---|
| 311 | + break; |
|---|
| 312 | + case 0x32: |
|---|
| 313 | + case 0x33: |
|---|
| 314 | + AMIGAHW_SET(ALICE_NTSC); |
|---|
| 315 | + break; |
|---|
| 316 | + } |
|---|
| 317 | + AMIGAHW_SET(ZORRO); |
|---|
| 321 | 318 | |
|---|
| 322 | 319 | #define AMIGAHW_ANNOUNCE(name, str) \ |
|---|
| 323 | 320 | if (AMIGAHW_PRESENT(name)) \ |
|---|
| .. | .. |
|---|
| 386 | 383 | mach_init_IRQ = amiga_init_IRQ; |
|---|
| 387 | 384 | mach_get_model = amiga_get_model; |
|---|
| 388 | 385 | mach_get_hardware_list = amiga_get_hardware_list; |
|---|
| 389 | | - arch_gettimeoffset = amiga_gettimeoffset; |
|---|
| 390 | 386 | |
|---|
| 391 | 387 | /* |
|---|
| 392 | 388 | * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI |
|---|
| .. | .. |
|---|
| 464 | 460 | *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80; |
|---|
| 465 | 461 | } |
|---|
| 466 | 462 | |
|---|
| 463 | +static u64 amiga_read_clk(struct clocksource *cs); |
|---|
| 464 | + |
|---|
| 465 | +static struct clocksource amiga_clk = { |
|---|
| 466 | + .name = "ciab", |
|---|
| 467 | + .rating = 250, |
|---|
| 468 | + .read = amiga_read_clk, |
|---|
| 469 | + .mask = CLOCKSOURCE_MASK(32), |
|---|
| 470 | + .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
|---|
| 471 | +}; |
|---|
| 472 | + |
|---|
| 467 | 473 | static unsigned short jiffy_ticks; |
|---|
| 474 | +static u32 clk_total, clk_offset; |
|---|
| 475 | + |
|---|
| 476 | +static irqreturn_t ciab_timer_handler(int irq, void *dev_id) |
|---|
| 477 | +{ |
|---|
| 478 | + irq_handler_t timer_routine = dev_id; |
|---|
| 479 | + |
|---|
| 480 | + clk_total += jiffy_ticks; |
|---|
| 481 | + clk_offset = 0; |
|---|
| 482 | + timer_routine(0, NULL); |
|---|
| 483 | + |
|---|
| 484 | + return IRQ_HANDLED; |
|---|
| 485 | +} |
|---|
| 468 | 486 | |
|---|
| 469 | 487 | static void __init amiga_sched_init(irq_handler_t timer_routine) |
|---|
| 470 | 488 | { |
|---|
| .. | .. |
|---|
| 484 | 502 | * Please don't change this to use ciaa, as it interferes with the |
|---|
| 485 | 503 | * SCSI code. We'll have to take a look at this later |
|---|
| 486 | 504 | */ |
|---|
| 487 | | - if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL)) |
|---|
| 505 | + if (request_irq(IRQ_AMIGA_CIAB_TA, ciab_timer_handler, IRQF_TIMER, |
|---|
| 506 | + "timer", timer_routine)) |
|---|
| 488 | 507 | pr_err("Couldn't register timer interrupt\n"); |
|---|
| 489 | 508 | /* start timer */ |
|---|
| 490 | 509 | ciab.cra |= 0x11; |
|---|
| 510 | + |
|---|
| 511 | + clocksource_register_hz(&amiga_clk, amiga_eclock); |
|---|
| 491 | 512 | } |
|---|
| 492 | 513 | |
|---|
| 493 | | -#define TICK_SIZE 10000 |
|---|
| 494 | | - |
|---|
| 495 | | -/* This is always executed with interrupts disabled. */ |
|---|
| 496 | | -static u32 amiga_gettimeoffset(void) |
|---|
| 514 | +static u64 amiga_read_clk(struct clocksource *cs) |
|---|
| 497 | 515 | { |
|---|
| 498 | 516 | unsigned short hi, lo, hi2; |
|---|
| 499 | | - u32 ticks, offset = 0; |
|---|
| 517 | + unsigned long flags; |
|---|
| 518 | + u32 ticks; |
|---|
| 519 | + |
|---|
| 520 | + local_irq_save(flags); |
|---|
| 500 | 521 | |
|---|
| 501 | 522 | /* read CIA B timer A current value */ |
|---|
| 502 | 523 | hi = ciab.tahi; |
|---|
| .. | .. |
|---|
| 513 | 534 | if (ticks > jiffy_ticks / 2) |
|---|
| 514 | 535 | /* check for pending interrupt */ |
|---|
| 515 | 536 | if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA) |
|---|
| 516 | | - offset = 10000; |
|---|
| 537 | + clk_offset = jiffy_ticks; |
|---|
| 517 | 538 | |
|---|
| 518 | 539 | ticks = jiffy_ticks - ticks; |
|---|
| 519 | | - ticks = (10000 * ticks) / jiffy_ticks; |
|---|
| 540 | + ticks += clk_offset + clk_total; |
|---|
| 520 | 541 | |
|---|
| 521 | | - return (ticks + offset) * 1000; |
|---|
| 542 | + local_irq_restore(flags); |
|---|
| 543 | + |
|---|
| 544 | + return ticks; |
|---|
| 522 | 545 | } |
|---|
| 523 | 546 | |
|---|
| 524 | 547 | static void amiga_reset(void) __noreturn; |
|---|
| .. | .. |
|---|
| 603 | 626 | unsigned long magic2; /* SAVEKMSG_MAGIC2 */ |
|---|
| 604 | 627 | unsigned long magicptr; /* address of magic1 */ |
|---|
| 605 | 628 | unsigned long size; |
|---|
| 606 | | - char data[0]; |
|---|
| 629 | + char data[]; |
|---|
| 607 | 630 | }; |
|---|
| 608 | 631 | |
|---|
| 609 | 632 | static struct savekmsg *savekmsg; |
|---|