Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: EXYNOS4: convert MCT to percpu interrupt API

MCT recently gained per cpu interrupts, and missed the fact that
ARM has moved to a genirq based implementation.

This patch converts the driver to the new API.

Boot tested on Origen.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>

authored by

Marc Zyngier and committed by
Kukjin Kim
e700e41d d8633c1d

+27 -13
+27 -13
arch/arm/mach-exynos4/mct.c
··· 44 44 char name[10]; 45 45 }; 46 46 47 - struct mct_clock_event_device mct_tick[NR_CPUS]; 47 + static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); 48 48 49 49 static void exynos4_mct_write(unsigned int value, void *addr) 50 50 { ··· 302 302 static int exynos4_tick_set_next_event(unsigned long cycles, 303 303 struct clock_event_device *evt) 304 304 { 305 - struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; 305 + struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); 306 306 307 307 exynos4_mct_tick_start(cycles, mevt); 308 308 ··· 312 312 static inline void exynos4_tick_set_mode(enum clock_event_mode mode, 313 313 struct clock_event_device *evt) 314 314 { 315 - struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()]; 315 + struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); 316 316 317 317 exynos4_mct_tick_stop(mevt); 318 318 ··· 376 376 377 377 static void exynos4_mct_tick_init(struct clock_event_device *evt) 378 378 { 379 + struct mct_clock_event_device *mevt; 379 380 unsigned int cpu = smp_processor_id(); 380 381 381 - mct_tick[cpu].evt = evt; 382 + mevt = this_cpu_ptr(&percpu_mct_tick); 383 + mevt->evt = evt; 382 384 383 - mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu); 384 - sprintf(mct_tick[cpu].name, "mct_tick%d", cpu); 385 + mevt->base = EXYNOS4_MCT_L_BASE(cpu); 386 + sprintf(mevt->name, "mct_tick%d", cpu); 385 387 386 - evt->name = mct_tick[cpu].name; 388 + evt->name = mevt->name; 387 389 evt->cpumask = cpumask_of(cpu); 388 390 evt->set_next_event = exynos4_tick_set_next_event; 389 391 evt->set_mode = exynos4_tick_set_mode; ··· 400 398 401 399 clockevents_register_device(evt); 402 400 403 - exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET); 401 + exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET); 404 402 405 403 if (mct_int_type == MCT_INT_SPI) { 406 404 if (cpu == 0) { 407 - mct_tick0_event_irq.dev_id = &mct_tick[cpu]; 405 + mct_tick0_event_irq.dev_id = mevt; 408 406 evt->irq = IRQ_MCT_L0; 409 407 setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); 410 408 } else { 411 - mct_tick1_event_irq.dev_id = &mct_tick[cpu]; 409 + mct_tick1_event_irq.dev_id = mevt; 412 410 evt->irq = IRQ_MCT_L1; 413 411 setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); 414 412 irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); 415 413 } 416 414 } else { 417 - gic_enable_ppi(IRQ_MCT_LOCALTIMER); 415 + enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0); 418 416 } 419 417 } 420 418 ··· 429 427 void local_timer_stop(struct clock_event_device *evt) 430 428 { 431 429 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); 432 - disable_irq(evt->irq); 430 + if (mct_int_type == MCT_INT_SPI) 431 + disable_irq(evt->irq); 432 + else 433 + disable_percpu_irq(IRQ_MCT_LOCALTIMER); 433 434 } 434 - 435 435 #endif /* CONFIG_LOCAL_TIMERS */ 436 436 437 437 static void __init exynos4_timer_resources(void) ··· 442 438 mct_clk = clk_get(NULL, "xtal"); 443 439 444 440 clk_rate = clk_get_rate(mct_clk); 441 + 442 + if (mct_int_type == MCT_INT_PPI) { 443 + int err; 444 + 445 + err = request_percpu_irq(IRQ_MCT_LOCALTIMER, 446 + exynos4_mct_tick_isr, "MCT", 447 + &percpu_mct_tick); 448 + WARN(err, "MCT: can't request IRQ %d (%d)\n", 449 + IRQ_MCT_LOCALTIMER, err); 450 + } 445 451 } 446 452 447 453 static void __init exynos4_timer_init(void)