16b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang/* 296f1050d3df105c9ae6c6ac224f370199ea82fcdRobin Getz * IPI management based on arch/arm/kernel/smp.c (Copyright 2002 ARM Limited) 36b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * 496f1050d3df105c9ae6c6ac224f370199ea82fcdRobin Getz * Copyright 2007-2009 Analog Devices Inc. 596f1050d3df105c9ae6c6ac224f370199ea82fcdRobin Getz * Philippe Gerum <rpm@xenomai.org> 66b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * 796f1050d3df105c9ae6c6ac224f370199ea82fcdRobin Getz * Licensed under the GPL-2. 86b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang */ 96b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 106b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/module.h> 116b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/delay.h> 126b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/init.h> 136b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/spinlock.h> 146b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/sched.h> 156b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/interrupt.h> 166b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/cache.h> 17d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu#include <linux/clockchips.h> 186b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/profile.h> 196b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/errno.h> 206b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/mm.h> 216b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/cpu.h> 226b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/smp.h> 239c199b5965c76f90b297e01accb933624dc8d242Graf Yang#include <linux/cpumask.h> 246b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/seq_file.h> 256b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/irq.h> 265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2760063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h> 286b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/cacheflush.h> 296327a574f9ce85f0daab8693913003a456f27f1fMike Frysinger#include <asm/irq_handler.h> 306b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/mmu_context.h> 316b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/pgtable.h> 326b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/pgalloc.h> 336b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/processor.h> 346b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/ptrace.h> 356b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <asm/cpu.h> 361fa9be72b558c39459f98835eb86dbb4ef4da30bGraf Yang#include <asm/time.h> 376b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#include <linux/err.h> 386b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 39555487bbb63f527e63fecbff48c86e2c07ce5024Graf Yang/* 40555487bbb63f527e63fecbff48c86e2c07ce5024Graf Yang * Anomaly notes: 41555487bbb63f527e63fecbff48c86e2c07ce5024Graf Yang * 05000120 - we always define corelock as 32-bit integer in L2 42555487bbb63f527e63fecbff48c86e2c07ce5024Graf Yang */ 436b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstruct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); 446b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 45c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaaSonic Zhang#ifdef CONFIG_ICACHE_FLUSH_L1 46c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaaSonic Zhangunsigned long blackfin_iflush_l1_entry[NR_CPUS]; 47c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaaSonic Zhang#endif 48c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaaSonic Zhang 4913dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakerstruct blackfin_initial_pda initial_pda_coreb; 506b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 5150888469bda11bcff306893bbaff21f25894be0bSteven Miaoenum ipi_message_type { 52150382a53d11256e5666c86525c8bf8d23684532Steven Miao BFIN_IPI_NONE, 5350888469bda11bcff306893bbaff21f25894be0bSteven Miao BFIN_IPI_TIMER, 5450888469bda11bcff306893bbaff21f25894be0bSteven Miao BFIN_IPI_RESCHEDULE, 5550888469bda11bcff306893bbaff21f25894be0bSteven Miao BFIN_IPI_CALL_FUNC, 5650888469bda11bcff306893bbaff21f25894be0bSteven Miao BFIN_IPI_CPU_STOP, 5750888469bda11bcff306893bbaff21f25894be0bSteven Miao}; 586b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 596b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstruct blackfin_flush_data { 606b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned long start; 616b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned long end; 626b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang}; 636b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 646b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid *secondary_stack; 656b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 666b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstatic struct blackfin_flush_data smp_flush_data; 676b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 686b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstatic DEFINE_SPINLOCK(stop_lock); 696b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 7073a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li/* A magic number - stress test shows this is safe for common cases */ 7173a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li#define BFIN_IPI_MSGQ_LEN 5 7273a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li 7373a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li/* Simple FIFO buffer, overflow leads to panic */ 7450888469bda11bcff306893bbaff21f25894be0bSteven Miaostruct ipi_data { 75150382a53d11256e5666c86525c8bf8d23684532Steven Miao atomic_t count; 76150382a53d11256e5666c86525c8bf8d23684532Steven Miao atomic_t bits; 776b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang}; 786b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 7950888469bda11bcff306893bbaff21f25894be0bSteven Miaostatic DEFINE_PER_CPU(struct ipi_data, bfin_ipi); 806b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 816b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstatic void ipi_cpu_stop(unsigned int cpu) 826b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 836b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang spin_lock(&stop_lock); 846b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang printk(KERN_CRIT "CPU%u: stopping\n", cpu); 856b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang dump_stack(); 866b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang spin_unlock(&stop_lock); 876b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 88fecedc807116ed820ca6f3138d6d47a3bc6c5a60KOSAKI Motohiro set_cpu_online(cpu, false); 896b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 906b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang local_irq_disable(); 916b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 926b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang while (1) 936b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang SSYNC(); 946b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 956b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 966b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangstatic void ipi_flush_icache(void *info) 976b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 986b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang struct blackfin_flush_data *fdata = info; 996b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 1006b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang /* Invalidate the memory holding the bounds of the flushed region. */ 1018d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang blackfin_dcache_invalidate_range((unsigned long)fdata, 1028d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang (unsigned long)fdata + sizeof(*fdata)); 1038d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang 1048d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang /* Make sure all write buffers in the data side of the core 1058d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * are flushed before trying to invalidate the icache. This 1068d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * needs to be after the data flush and before the icache 1078d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * flush so that the SSYNC does the right thing in preventing 1088d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * the instruction prefetcher from hitting things in cached 1098d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * memory at the wrong time -- it runs much further ahead than 1108d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * the pipeline. 1118d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang */ 1128d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang SSYNC(); 1138d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang 1148d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang /* ipi_flaush_icache is invoked by generic flush_icache_range, 1158d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang * so call blackfin arch icache flush directly here. 1168d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang */ 1178d50de9ee77b38a239dc5b1d6a63ad92a78f119dSonic Zhang blackfin_icache_flush_range(fdata->start, fdata->end); 1186b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 1196b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 12073a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li/* Use IRQ_SUPPLE_0 to request reschedule. 12173a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li * When returning from interrupt to user space, 12273a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li * there is chance to reschedule */ 12373a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Listatic irqreturn_t ipi_handler_int0(int irq, void *dev_instance) 12473a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li{ 12573a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li unsigned int cpu = smp_processor_id(); 12673a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li 12773a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li platform_clear_ipi(cpu, IRQ_SUPPLE_0); 12873a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li return IRQ_HANDLED; 12973a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li} 13073a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li 131d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob LiuDECLARE_PER_CPU(struct clock_event_device, coretmr_events); 132d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liuvoid ipi_timer(void) 133d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu{ 134d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu int cpu = smp_processor_id(); 135d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu struct clock_event_device *evt = &per_cpu(coretmr_events, cpu); 136d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu evt->event_handler(evt); 137d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu} 138d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu 13973a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Listatic irqreturn_t ipi_handler_int1(int irq, void *dev_instance) 1406b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 14150888469bda11bcff306893bbaff21f25894be0bSteven Miao struct ipi_data *bfin_ipi_data; 1426b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu = smp_processor_id(); 14350888469bda11bcff306893bbaff21f25894be0bSteven Miao unsigned long pending; 14450888469bda11bcff306893bbaff21f25894be0bSteven Miao unsigned long msg; 1456b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 14673a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li platform_clear_ipi(cpu, IRQ_SUPPLE_1); 1476b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 148177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao smp_rmb(); 1497e788ab11d73fbb617973c12a9b3f84f93721e67Christoph Lameter bfin_ipi_data = this_cpu_ptr(&bfin_ipi); 15016fc5bc4c76b9ac335c2b39943f29c5d047a822dSteven Miao while ((pending = atomic_xchg(&bfin_ipi_data->bits, 0)) != 0) { 15150888469bda11bcff306893bbaff21f25894be0bSteven Miao msg = 0; 15250888469bda11bcff306893bbaff21f25894be0bSteven Miao do { 15350888469bda11bcff306893bbaff21f25894be0bSteven Miao msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); 15450888469bda11bcff306893bbaff21f25894be0bSteven Miao switch (msg) { 15550888469bda11bcff306893bbaff21f25894be0bSteven Miao case BFIN_IPI_TIMER: 15650888469bda11bcff306893bbaff21f25894be0bSteven Miao ipi_timer(); 15750888469bda11bcff306893bbaff21f25894be0bSteven Miao break; 15850888469bda11bcff306893bbaff21f25894be0bSteven Miao case BFIN_IPI_RESCHEDULE: 15950888469bda11bcff306893bbaff21f25894be0bSteven Miao scheduler_ipi(); 16050888469bda11bcff306893bbaff21f25894be0bSteven Miao break; 16150888469bda11bcff306893bbaff21f25894be0bSteven Miao case BFIN_IPI_CALL_FUNC: 16250888469bda11bcff306893bbaff21f25894be0bSteven Miao generic_smp_call_function_interrupt(); 16350888469bda11bcff306893bbaff21f25894be0bSteven Miao break; 16450888469bda11bcff306893bbaff21f25894be0bSteven Miao case BFIN_IPI_CPU_STOP: 16550888469bda11bcff306893bbaff21f25894be0bSteven Miao ipi_cpu_stop(cpu); 16650888469bda11bcff306893bbaff21f25894be0bSteven Miao break; 167177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao default: 168177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao goto out; 16950888469bda11bcff306893bbaff21f25894be0bSteven Miao } 170150382a53d11256e5666c86525c8bf8d23684532Steven Miao atomic_dec(&bfin_ipi_data->count); 17150888469bda11bcff306893bbaff21f25894be0bSteven Miao } while (msg < BITS_PER_LONG); 172177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao 1736b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang } 174177a48fdc8a0156b32f96d9d0056361d88203983Steven Miaoout: 1756b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang return IRQ_HANDLED; 1766b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 1776b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 17850888469bda11bcff306893bbaff21f25894be0bSteven Miaostatic void bfin_ipi_init(void) 1796b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 1806b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu; 18150888469bda11bcff306893bbaff21f25894be0bSteven Miao struct ipi_data *bfin_ipi_data; 1826b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang for_each_possible_cpu(cpu) { 18350888469bda11bcff306893bbaff21f25894be0bSteven Miao bfin_ipi_data = &per_cpu(bfin_ipi, cpu); 18416fc5bc4c76b9ac335c2b39943f29c5d047a822dSteven Miao atomic_set(&bfin_ipi_data->bits, 0); 18516fc5bc4c76b9ac335c2b39943f29c5d047a822dSteven Miao atomic_set(&bfin_ipi_data->count, 0); 1866b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang } 1876b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 1886b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 18950888469bda11bcff306893bbaff21f25894be0bSteven Miaovoid send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) 1906b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 1916b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu; 19250888469bda11bcff306893bbaff21f25894be0bSteven Miao struct ipi_data *bfin_ipi_data; 19350888469bda11bcff306893bbaff21f25894be0bSteven Miao unsigned long flags; 19450888469bda11bcff306893bbaff21f25894be0bSteven Miao 19550888469bda11bcff306893bbaff21f25894be0bSteven Miao local_irq_save(flags); 19650888469bda11bcff306893bbaff21f25894be0bSteven Miao for_each_cpu(cpu, cpumask) { 19750888469bda11bcff306893bbaff21f25894be0bSteven Miao bfin_ipi_data = &per_cpu(bfin_ipi, cpu); 198150382a53d11256e5666c86525c8bf8d23684532Steven Miao atomic_set_mask((1 << msg), &bfin_ipi_data->bits); 199150382a53d11256e5666c86525c8bf8d23684532Steven Miao atomic_inc(&bfin_ipi_data->count); 2006b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang } 20150888469bda11bcff306893bbaff21f25894be0bSteven Miao local_irq_restore(flags); 202177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao smp_wmb(); 203177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao for_each_cpu(cpu, cpumask) 204177a48fdc8a0156b32f96d9d0056361d88203983Steven Miao platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); 20573a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li} 20673a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li 20750888469bda11bcff306893bbaff21f25894be0bSteven Miaovoid arch_send_call_function_single_ipi(int cpu) 20873a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li{ 2095e98c0990471fa1ee707f5c3a6f5183355b19828Jiang Liu send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC); 2106b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2116b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 21250888469bda11bcff306893bbaff21f25894be0bSteven Miaovoid arch_send_call_function_ipi_mask(const struct cpumask *mask) 2136b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 21450888469bda11bcff306893bbaff21f25894be0bSteven Miao send_ipi(mask, BFIN_IPI_CALL_FUNC); 2156b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2166b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2176b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid smp_send_reschedule(int cpu) 2186b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 21950888469bda11bcff306893bbaff21f25894be0bSteven Miao send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE); 2206b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2216b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang return; 2226b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2236b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 224d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liuvoid smp_send_msg(const struct cpumask *mask, unsigned long type) 225d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu{ 22650888469bda11bcff306893bbaff21f25894be0bSteven Miao send_ipi(mask, type); 227d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu} 228d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu 229d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liuvoid smp_timer_broadcast(const struct cpumask *mask) 230d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu{ 231d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu smp_send_msg(mask, BFIN_IPI_TIMER); 232d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu} 233d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu 2346b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid smp_send_stop(void) 2356b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 2366b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang cpumask_t callmap; 2376b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 238567ebfc99d7546913408b560ad443a5315bf8a53Sonic Zhang preempt_disable(); 239fecedc807116ed820ca6f3138d6d47a3bc6c5a60KOSAKI Motohiro cpumask_copy(&callmap, cpu_online_mask); 240fecedc807116ed820ca6f3138d6d47a3bc6c5a60KOSAKI Motohiro cpumask_clear_cpu(smp_processor_id(), &callmap); 241fecedc807116ed820ca6f3138d6d47a3bc6c5a60KOSAKI Motohiro if (!cpumask_empty(&callmap)) 24250888469bda11bcff306893bbaff21f25894be0bSteven Miao send_ipi(&callmap, BFIN_IPI_CPU_STOP); 2436b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 244567ebfc99d7546913408b560ad443a5315bf8a53Sonic Zhang preempt_enable(); 2456b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2466b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang return; 2476b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2486b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 24913dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakerint __cpu_up(unsigned int cpu, struct task_struct *idle) 2506b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 2516b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang int ret; 2520b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 2536b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang secondary_stack = task_stack_page(idle) + THREAD_SIZE; 2546b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2556b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang ret = platform_boot_secondary(cpu, idle); 2566b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2576b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang secondary_stack = NULL; 2586b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2596b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang return ret; 2606b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2616b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 26213dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakerstatic void setup_secondary(unsigned int cpu) 2636b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 2646b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned long ilat; 2656b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2666b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang bfin_write_IMASK(0); 2676b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang CSYNC(); 2686b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang ilat = bfin_read_ILAT(); 2696b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang CSYNC(); 2706b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang bfin_write_ILAT(ilat); 2716b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang CSYNC(); 2726b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2736b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang /* Enable interrupt levels IVG7-15. IARs have been already 2746b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * programmed by the boot CPU. */ 275400597842452c02916a61a51f3154dd032c2d569Mike Frysinger bfin_irq_flags |= IMASK_IVG15 | 2766b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | 2776b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; 2786b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 2796b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 28013dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakervoid secondary_start_kernel(void) 2816b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 2826b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu = smp_processor_id(); 2836b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang struct mm_struct *mm = &init_mm; 2846b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 2856b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang if (_bfin_swrst & SWRST_DBL_FAULT_B) { 2866b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n"); 2876b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#ifdef CONFIG_DEBUG_DOUBLEFAULT 288fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n", 289fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger initial_pda_coreb.seqstat_doublefault & SEQSTAT_EXCAUSE, 290fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger initial_pda_coreb.retx_doublefault); 291fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", 292fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger initial_pda_coreb.dcplb_doublefault_addr); 293fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", 294fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger initial_pda_coreb.icplb_doublefault_addr); 2956b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#endif 2966b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", 297fb1d9be5967fff0a3c93b06304fd992e3c438b7fMike Frysinger initial_pda_coreb.retx); 2986b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang } 2996b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3006b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang /* 3016b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * We want the D-cache to be enabled early, in case the atomic 3026b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * support code emulates cache coherence (see 3036b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang * __ARCH_SYNC_CORE_DCACHE). 3046b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang */ 3056b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang init_exception_vectors(); 3066b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3076b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang local_irq_disable(); 3086b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3096b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang /* Attach the new idle task to the global mm. */ 3106b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang atomic_inc(&mm->mm_users); 3116b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang atomic_inc(&mm->mm_count); 3126b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang current->active_mm = mm; 3136b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3146b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang preempt_disable(); 3156b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3166b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang setup_secondary(cpu); 3176b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 318578d36f5e160208821e8f51037ac1038e065ecafYi Li platform_secondary_init(cpu); 3190d152c27e336b5fd777da7dd3e814617e7305afdYi Li /* setup local core timer */ 3200d152c27e336b5fd777da7dd3e814617e7305afdYi Li bfin_local_timer_setup(); 3210d152c27e336b5fd777da7dd3e814617e7305afdYi Li 3226b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang local_irq_enable(); 3236b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 324ab61d2ac5c9d7c9232b8455c8d889216ca9d4814steven miao bfin_setup_caches(cpu); 325ab61d2ac5c9d7c9232b8455c8d889216ca9d4814steven miao 326d0014be47dc90d15adf7d6e09031d06e2aa7ce79Bob Liu notify_cpu_starting(cpu); 327578d36f5e160208821e8f51037ac1038e065ecafYi Li /* 328578d36f5e160208821e8f51037ac1038e065ecafYi Li * Calibrate loops per jiffy value. 329578d36f5e160208821e8f51037ac1038e065ecafYi Li * IRQs need to be enabled here - D-cache can be invalidated 330578d36f5e160208821e8f51037ac1038e065ecafYi Li * in timer irq handler, so core B can read correct jiffies. 331578d36f5e160208821e8f51037ac1038e065ecafYi Li */ 332578d36f5e160208821e8f51037ac1038e065ecafYi Li calibrate_delay(); 3336b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 334150382a53d11256e5666c86525c8bf8d23684532Steven Miao /* We are done with local CPU inits, unblock the boot CPU. */ 335150382a53d11256e5666c86525c8bf8d23684532Steven Miao set_cpu_online(cpu, true); 33625d67f860f3a29d216f8206092a284cacbc6127eThomas Gleixner cpu_startup_entry(CPUHP_ONLINE); 3376b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 3386b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3396b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid __init smp_prepare_boot_cpu(void) 3406b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 3416b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 3426b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3436b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid __init smp_prepare_cpus(unsigned int max_cpus) 3446b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 3456b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang platform_prepare_cpus(max_cpus); 34650888469bda11bcff306893bbaff21f25894be0bSteven Miao bfin_ipi_init(); 34773a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0); 34873a400646b8e26615f3ef1a0a4bc0cd0d5bd284cYi Li platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1); 3496b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 3506b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3516b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid __init smp_cpus_done(unsigned int max_cpus) 3526b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 3536b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned long bogosum = 0; 3546b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu; 3556b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3566b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang for_each_online_cpu(cpu) 357c70c754ff916cedd969a73549799d2167ffefcd6Michael Hennerich bogosum += loops_per_jiffy; 3586b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3596b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang printk(KERN_INFO "SMP: Total of %d processors activated " 3606b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang "(%lu.%02lu BogoMIPS).\n", 3616b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang num_online_cpus(), 3626b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang bogosum / (500000/HZ), 3636b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang (bogosum / (5000/HZ)) % 100); 3646b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 3656b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3666b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid smp_icache_flush_range_others(unsigned long start, unsigned long end) 3676b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 3686b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang smp_flush_data.start = start; 3696b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang smp_flush_data.end = end; 3706b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 371a2eff9dd8bca6d03bc3c87790bac3fdb4fe6dbf0Steven Miao preempt_disable(); 372a2eff9dd8bca6d03bc3c87790bac3fdb4fe6dbf0Steven Miao if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1)) 3736b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n"); 374a2eff9dd8bca6d03bc3c87790bac3fdb4fe6dbf0Steven Miao preempt_enable(); 3756b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 3766b3087c64a92a36ae20d33479b4df6d7afc910d4Graf YangEXPORT_SYMBOL_GPL(smp_icache_flush_range_others); 3776b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 37847e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang#ifdef __ARCH_SYNC_CORE_ICACHE 379718340f62900ed44046d2b0f74d0dec7cf844194Graf Yangunsigned long icache_invld_count[NR_CPUS]; 38047e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhangvoid resync_core_icache(void) 38147e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang{ 38247e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang unsigned int cpu = get_cpu(); 38347e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang blackfin_invalidate_entire_icache(); 384718340f62900ed44046d2b0f74d0dec7cf844194Graf Yang icache_invld_count[cpu]++; 38547e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang put_cpu(); 38647e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang} 38747e9dedb720364e0adff0e99960fa294c6161f71Sonic ZhangEXPORT_SYMBOL(resync_core_icache); 38847e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang#endif 38947e9dedb720364e0adff0e99960fa294c6161f71Sonic Zhang 3906b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#ifdef __ARCH_SYNC_CORE_DCACHE 391718340f62900ed44046d2b0f74d0dec7cf844194Graf Yangunsigned long dcache_invld_count[NR_CPUS]; 3926b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangunsigned long barrier_mask __attribute__ ((__section__(".l2.bss"))); 3936b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang 3946b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yangvoid resync_core_dcache(void) 3956b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang{ 3966b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang unsigned int cpu = get_cpu(); 3976b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang blackfin_invalidate_entire_dcache(); 398718340f62900ed44046d2b0f74d0dec7cf844194Graf Yang dcache_invld_count[cpu]++; 3996b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang put_cpu(); 4006b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang} 4016b3087c64a92a36ae20d33479b4df6d7afc910d4Graf YangEXPORT_SYMBOL(resync_core_dcache); 4026b3087c64a92a36ae20d33479b4df6d7afc910d4Graf Yang#endif 4030b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4040b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang#ifdef CONFIG_HOTPLUG_CPU 40513dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakerint __cpu_disable(void) 4060b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang{ 4070b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang unsigned int cpu = smp_processor_id(); 4080b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4090b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang if (cpu == 0) 4100b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang return -EPERM; 4110b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4120b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang set_cpu_online(cpu, false); 4130b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang return 0; 4140b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang} 4150b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4160b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yangstatic DECLARE_COMPLETION(cpu_killed); 4170b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 41813dff62d80e93f1cc65b4ad2dddedd12de720272Paul Gortmakerint __cpu_die(unsigned int cpu) 4190b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang{ 4200b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang return wait_for_completion_timeout(&cpu_killed, 5000); 4210b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang} 4220b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4230b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yangvoid cpu_die(void) 4240b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang{ 4250b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang complete(&cpu_killed); 4260b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4270b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang atomic_dec(&init_mm.mm_users); 4280b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang atomic_dec(&init_mm.mm_count); 4290b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang 4300b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang local_irq_disable(); 4310b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang platform_cpu_die(); 4320b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang} 4330b39db28b953945232719e7ff6fb802aa8a2be5fGraf Yang#endif 434