1300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* 2300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * Copyright (C) 2010, 2011, 2012, Lemote, Inc. 3300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * Author: Chen Huacai, chenhc@lemote.com 4300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * 5300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * This program is free software; you can redistribute it and/or 6300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * modify it under the terms of the GNU General Public License 7300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * as published by the Free Software Foundation; either version 2 8300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * of the License, or (at your option) any later version. 9300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * 10300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * This program is distributed in the hope that it will be useful, 11300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * but WITHOUT ANY WARRANTY; without even the implied warranty of 12300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * GNU General Public License for more details. 14300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * 15300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen */ 16300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 17300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <linux/init.h> 18300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <linux/cpu.h> 19300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <linux/sched.h> 20300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <linux/smp.h> 21300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <linux/cpufreq.h> 22300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <asm/processor.h> 23300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <asm/time.h> 24300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <asm/clock.h> 25300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <asm/tlbflush.h> 26c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#include <asm/cacheflush.h> 27300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include <loongson.h> 28300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 29300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#include "smp.h" 30300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 31c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai ChenDEFINE_PER_CPU(int, cpu_state); 32c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai ChenDEFINE_PER_CPU(uint32_t, core0_c0count); 33c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 34e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void *ipi_set0_regs[16]; 35e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void *ipi_clear0_regs[16]; 36e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void *ipi_status0_regs[16]; 37e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void *ipi_en0_regs[16]; 38e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void *ipi_mailbox_buf[16]; 39e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 40300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* read a 32bit value from ipi register */ 41300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#define loongson3_ipi_read32(addr) readl(addr) 42300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* read a 64bit value from ipi register */ 43300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#define loongson3_ipi_read64(addr) readq(addr) 44300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* write a 32bit value to ipi register */ 45300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#define loongson3_ipi_write32(action, addr) \ 46300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen do { \ 47300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen writel(action, addr); \ 48300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __wbflush(); \ 49300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen } while (0) 50300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* write a 64bit value to ipi register */ 51300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen#define loongson3_ipi_write64(action, addr) \ 52300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen do { \ 53300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen writeq(action, addr); \ 54300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __wbflush(); \ 55300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen } while (0) 56300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 57e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void ipi_set0_regs_init(void) 58e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 59e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[0] = (void *) 60e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0); 61e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[1] = (void *) 62e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0); 63e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[2] = (void *) 64e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0); 65e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[3] = (void *) 66e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0); 67e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[4] = (void *) 68e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0); 69e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[5] = (void *) 70e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0); 71e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[6] = (void *) 72e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0); 73e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[7] = (void *) 74e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0); 75e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[8] = (void *) 76e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0); 77e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[9] = (void *) 78e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0); 79e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[10] = (void *) 80e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0); 81e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[11] = (void *) 82e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0); 83e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[12] = (void *) 84e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0); 85e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[13] = (void *) 86e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0); 87e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[14] = (void *) 88e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0); 89e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs[15] = (void *) 90e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0); 91e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 92300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 93e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void ipi_clear0_regs_init(void) 94e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 95e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[0] = (void *) 96e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0); 97e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[1] = (void *) 98e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0); 99e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[2] = (void *) 100e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0); 101e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[3] = (void *) 102e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0); 103e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[4] = (void *) 104e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0); 105e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[5] = (void *) 106e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0); 107e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[6] = (void *) 108e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0); 109e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[7] = (void *) 110e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0); 111e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[8] = (void *) 112e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0); 113e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[9] = (void *) 114e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0); 115e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[10] = (void *) 116e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0); 117e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[11] = (void *) 118e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0); 119e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[12] = (void *) 120e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0); 121e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[13] = (void *) 122e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0); 123e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[14] = (void *) 124e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0); 125e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs[15] = (void *) 126e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0); 127e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 128300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 129e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void ipi_status0_regs_init(void) 130e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 131e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[0] = (void *) 132e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0); 133e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[1] = (void *) 134e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0); 135e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[2] = (void *) 136e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0); 137e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[3] = (void *) 138e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0); 139e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[4] = (void *) 140e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0); 141e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[5] = (void *) 142e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0); 143e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[6] = (void *) 144e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0); 145e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[7] = (void *) 146e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0); 147e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[8] = (void *) 148e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0); 149e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[9] = (void *) 150e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0); 151e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[10] = (void *) 152e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0); 153e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[11] = (void *) 154e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0); 155e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[12] = (void *) 156e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0); 157e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[13] = (void *) 158e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0); 159e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[14] = (void *) 160e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0); 161e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs[15] = (void *) 162e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0); 163e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 164300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 165e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void ipi_en0_regs_init(void) 166e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 167e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[0] = (void *) 168e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0); 169e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[1] = (void *) 170e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0); 171e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[2] = (void *) 172e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0); 173e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[3] = (void *) 174e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0); 175e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[4] = (void *) 176e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0); 177e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[5] = (void *) 178e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0); 179e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[6] = (void *) 180e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0); 181e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[7] = (void *) 182e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0); 183e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[8] = (void *) 184e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0); 185e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[9] = (void *) 186e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0); 187e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[10] = (void *) 188e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0); 189e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[11] = (void *) 190e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0); 191e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[12] = (void *) 192e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0); 193e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[13] = (void *) 194e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0); 195e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[14] = (void *) 196e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0); 197e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs[15] = (void *) 198e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0); 199e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 200300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 201e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void ipi_mailbox_buf_init(void) 202e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 203e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[0] = (void *) 204e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF); 205e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[1] = (void *) 206e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF); 207e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[2] = (void *) 208e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF); 209e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[3] = (void *) 210e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF); 211e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[4] = (void *) 212e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF); 213e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[5] = (void *) 214e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF); 215e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[6] = (void *) 216e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF); 217e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[7] = (void *) 218e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF); 219e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[8] = (void *) 220e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF); 221e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[9] = (void *) 222e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF); 223e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[10] = (void *) 224e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF); 225e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[11] = (void *) 226e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF); 227e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[12] = (void *) 228e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF); 229e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[13] = (void *) 230e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF); 231e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[14] = (void *) 232e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF); 233e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf[15] = (void *) 234e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF); 235e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 236300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 237300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* 238300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * Simple enough, just poke the appropriate ipi register 239300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen */ 240300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void loongson3_send_ipi_single(int cpu, unsigned int action) 241300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 242300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]); 243300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 244300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 245300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void 246300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenloongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action) 247300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 248300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen unsigned int i; 249300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 250300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen for_each_cpu(i, mask) 251300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write32((u32)action, ipi_set0_regs[i]); 252300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 253300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 254300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenvoid loongson3_ipi_interrupt(struct pt_regs *regs) 255300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 256c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen int i, cpu = smp_processor_id(); 257c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned int action, c0count; 258300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 259300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen /* Load the ipi register to figure out what we're supposed to do */ 260300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen action = loongson3_ipi_read32(ipi_status0_regs[cpu]); 261300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 262300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen /* Clear the ipi register to clear the interrupt */ 263300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]); 264300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 265300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen if (action & SMP_RESCHEDULE_YOURSELF) 266300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen scheduler_ipi(); 267300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 268300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen if (action & SMP_CALL_FUNCTION) 269300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen smp_call_function_interrupt(); 270c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 271c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen if (action & SMP_ASK_C0COUNT) { 272c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen BUG_ON(cpu != 0); 273c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen c0count = read_c0_count(); 274c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen for (i = 1; i < loongson_sysconf.nr_cpus; i++) 275c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen per_cpu(core0_c0count, i) = c0count; 276c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen } 277300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 278300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 279c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#define MAX_LOOPS 1111 280300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* 281300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * SMP init and finish on secondary CPUs 282300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen */ 283300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void loongson3_init_secondary(void) 284300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 285300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen int i; 286c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen uint32_t initcount; 287c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned int cpu = smp_processor_id(); 288300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen unsigned int imask = STATUSF_IP7 | STATUSF_IP6 | 289300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen STATUSF_IP3 | STATUSF_IP2; 290300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 291300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen /* Set interrupt mask, but don't enable */ 292300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen change_c0_status(ST0_IM, imask); 293300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 294300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen for (i = 0; i < loongson_sysconf.nr_cpus; i++) 295300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); 296c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 297c46173183657bbdbe0d54a981c28807581648422Huacai Chen cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package; 298c46173183657bbdbe0d54a981c28807581648422Huacai Chen cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package; 299c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen per_cpu(cpu_state, cpu) = CPU_ONLINE; 300c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 301c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen i = 0; 30235898716b4d3382791d219be317faace580b6a41Christoph Lameter __this_cpu_write(core0_c0count, 0); 303c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen loongson3_send_ipi_single(0, SMP_ASK_C0COUNT); 30435898716b4d3382791d219be317faace580b6a41Christoph Lameter while (!__this_cpu_read(core0_c0count)) { 305c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen i++; 306c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen cpu_relax(); 307c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen } 308c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 309c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen if (i > MAX_LOOPS) 310c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen i = MAX_LOOPS; 31135898716b4d3382791d219be317faace580b6a41Christoph Lameter initcount = __this_cpu_read(core0_c0count) + i; 312c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen write_c0_count(initcount); 313300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 314300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 315300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void loongson3_smp_finish(void) 316300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 317300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); 318300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen local_irq_enable(); 319300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write64(0, 320300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen (void *)(ipi_mailbox_buf[smp_processor_id()]+0x0)); 321300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen pr_info("CPU#%d finished, CP0_ST=%x\n", 322300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen smp_processor_id(), read_c0_status()); 323300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 324300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 325300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void __init loongson3_smp_setup(void) 326300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 327300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen int i, num; 328300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 329300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen init_cpu_possible(cpu_none_mask); 330300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen set_cpu_possible(0, true); 331300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 332300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __cpu_number_map[0] = 0; 333300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __cpu_logical_map[0] = 0; 334300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 335300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen /* For unified kernel, NR_CPUS is the maximum possible value, 336300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * loongson_sysconf.nr_cpus is the really present value */ 337300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) { 338300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen set_cpu_possible(i, true); 339300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __cpu_number_map[i] = ++num; 340300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen __cpu_logical_map[num] = i; 341300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen } 342e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_set0_regs_init(); 343e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_clear0_regs_init(); 344e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_status0_regs_init(); 345e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_en0_regs_init(); 346e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen ipi_mailbox_buf_init(); 347300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen pr_info("Detected %i available secondary CPU(s)\n", num); 348300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 349300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 350300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void __init loongson3_prepare_cpus(unsigned int max_cpus) 351300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 352c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen init_cpu_present(cpu_possible_mask); 353c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; 354300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 355300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 356300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen/* 357300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen * Setup the PC, SP, and GP of a secondary processor and start it runing! 358300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen */ 359300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstatic void loongson3_boot_secondary(int cpu, struct task_struct *idle) 360300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen{ 361300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen unsigned long startargs[4]; 362300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 363300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen pr_info("Booting CPU#%d...\n", cpu); 364300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 365300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen /* startargs[] are initial PC, SP and GP for secondary CPU */ 366300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen startargs[0] = (unsigned long)&smp_bootstrap; 367300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen startargs[1] = (unsigned long)__KSTK_TOS(idle); 368300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen startargs[2] = (unsigned long)task_thread_info(idle); 369300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen startargs[3] = 0; 370300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 371300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", 372300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen cpu, startargs[0], startargs[1], startargs[2]); 373300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 374300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18)); 375300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10)); 376300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8)); 377300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0)); 378300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen} 379300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen 380c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#ifdef CONFIG_HOTPLUG_CPU 381c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 382c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenstatic int loongson3_cpu_disable(void) 383c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 384c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned long flags; 385c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned int cpu = smp_processor_id(); 386c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 387c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen if (cpu == 0) 388c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen return -EBUSY; 389c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 390c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen set_cpu_online(cpu, false); 391c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen cpu_clear(cpu, cpu_callin_map); 392c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen local_irq_save(flags); 393c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen fixup_irqs(); 394c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen local_irq_restore(flags); 395c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen flush_cache_all(); 396c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen local_flush_tlb_all(); 397c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 398c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen return 0; 399c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 400c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 401c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 402c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenstatic void loongson3_cpu_die(unsigned int cpu) 403c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 404c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen while (per_cpu(cpu_state, cpu) != CPU_DEAD) 405c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen cpu_relax(); 406c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 407c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen mb(); 408c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 409c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 410c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and 411c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen * flush all L1 entries at first. Then, another core (usually Core 0) can 412c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen * safely disable the clock of the target core. loongson3_play_dead() is 413c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen * called via CKSEG1 (uncached and unmmaped) */ 414e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void loongson3a_play_dead(int *state_addr) 415c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 416c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen register int val; 417c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen register long cpuid, core, node, count; 418c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen register void *addr, *base, *initfunc; 419c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 420c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen __asm__ __volatile__( 421c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set push \n" 422c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set noreorder \n" 423c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " li %[addr], 0x80000000 \n" /* KSEG0 */ 424c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ 425c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 0, 1(%[addr]) \n" 426c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 0, 2(%[addr]) \n" 427c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 0, 3(%[addr]) \n" 428c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ 429c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 1, 1(%[addr]) \n" 430c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 1, 2(%[addr]) \n" 431c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 1, 3(%[addr]) \n" 432c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " addiu %[sets], %[sets], -1 \n" 433c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " bnez %[sets], 1b \n" 434c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " addiu %[addr], %[addr], 0x20 \n" 435c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ 436c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " sw %[val], (%[state_addr]) \n" 437c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " sync \n" 438c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ 439c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set pop \n" 440c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen : [addr] "=&r" (addr), [val] "=&r" (val) 441c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen : [state_addr] "r" (state_addr), 442c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen [sets] "r" (cpu_data[smp_processor_id()].dcache.sets)); 443c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 444c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen __asm__ __volatile__( 445c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set push \n" 446c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set noreorder \n" 447c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set mips64 \n" 448c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " mfc0 %[cpuid], $15, 1 \n" 449c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " andi %[cpuid], 0x3ff \n" 450c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " dli %[base], 0x900000003ff01000 \n" 451c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " andi %[core], %[cpuid], 0x3 \n" 452c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " sll %[core], 8 \n" /* get core id */ 453c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " or %[base], %[base], %[core] \n" 454c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " andi %[node], %[cpuid], 0xc \n" 455c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " dsll %[node], 42 \n" /* get node id */ 456c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " or %[base], %[base], %[node] \n" 457c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen "1: li %[count], 0x100 \n" /* wait for init loop */ 458c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen "2: bnez %[count], 2b \n" /* limit mailbox access */ 459c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " addiu %[count], -1 \n" 460c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ 461c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " beqz %[initfunc], 1b \n" 462c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " nop \n" 463c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ 464c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ 465c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " ld $a1, 0x38(%[base]) \n" 466c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " jr %[initfunc] \n" /* jump to initial PC */ 467c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " nop \n" 468c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen " .set pop \n" 469c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen : [core] "=&r" (core), [node] "=&r" (node), 470c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen [base] "=&r" (base), [cpuid] "=&r" (cpuid), 471c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen [count] "=&r" (count), [initfunc] "=&r" (initfunc) 472c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen : /* No Input */ 473c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen : "a1"); 474c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 475c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 476e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenstatic void loongson3b_play_dead(int *state_addr) 477e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 478e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen register int val; 479e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen register long cpuid, core, node, count; 480e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen register void *addr, *base, *initfunc; 481e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 482e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen __asm__ __volatile__( 483e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set push \n" 484e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set noreorder \n" 485e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " li %[addr], 0x80000000 \n" /* KSEG0 */ 486e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ 487e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 0, 1(%[addr]) \n" 488e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 0, 2(%[addr]) \n" 489e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 0, 3(%[addr]) \n" 490e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ 491e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 1, 1(%[addr]) \n" 492e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 1, 2(%[addr]) \n" 493e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 1, 3(%[addr]) \n" 494e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " addiu %[sets], %[sets], -1 \n" 495e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " bnez %[sets], 1b \n" 496e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " addiu %[addr], %[addr], 0x20 \n" 497e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ 498e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " sw %[val], (%[state_addr]) \n" 499e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " sync \n" 500e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ 501e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set pop \n" 502e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen : [addr] "=&r" (addr), [val] "=&r" (val) 503e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen : [state_addr] "r" (state_addr), 504e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen [sets] "r" (cpu_data[smp_processor_id()].dcache.sets)); 505e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 506e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen __asm__ __volatile__( 507e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set push \n" 508e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set noreorder \n" 509e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set mips64 \n" 510e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " mfc0 %[cpuid], $15, 1 \n" 511e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " andi %[cpuid], 0x3ff \n" 512e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " dli %[base], 0x900000003ff01000 \n" 513e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " andi %[core], %[cpuid], 0x3 \n" 514e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " sll %[core], 8 \n" /* get core id */ 515e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " or %[base], %[base], %[core] \n" 516e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " andi %[node], %[cpuid], 0xc \n" 517e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " dsll %[node], 42 \n" /* get node id */ 518e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " or %[base], %[base], %[node] \n" 519e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " dsrl %[node], 30 \n" /* 15:14 */ 520e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " or %[base], %[base], %[node] \n" 521e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen "1: li %[count], 0x100 \n" /* wait for init loop */ 522e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen "2: bnez %[count], 2b \n" /* limit mailbox access */ 523e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " addiu %[count], -1 \n" 524e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ 525e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " beqz %[initfunc], 1b \n" 526e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " nop \n" 527e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ 528e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ 529e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " ld $a1, 0x38(%[base]) \n" 530e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " jr %[initfunc] \n" /* jump to initial PC */ 531e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " nop \n" 532e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen " .set pop \n" 533e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen : [core] "=&r" (core), [node] "=&r" (node), 534e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen [base] "=&r" (base), [cpuid] "=&r" (cpuid), 535e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen [count] "=&r" (count), [initfunc] "=&r" (initfunc) 536e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen : /* No Input */ 537e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen : "a1"); 538e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 539e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 540c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenvoid play_dead(void) 541c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 542c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen int *state_addr; 543c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned int cpu = smp_processor_id(); 544c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen void (*play_dead_at_ckseg1)(int *); 545c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 546c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen idle_task_exit(); 547e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen switch (loongson_sysconf.cputype) { 548e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen case Loongson_3A: 549e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen default: 550e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen play_dead_at_ckseg1 = 551e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead); 552e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen break; 553e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen case Loongson_3B: 554e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen play_dead_at_ckseg1 = 555e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead); 556e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen break; 557e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen } 558c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen state_addr = &per_cpu(cpu_state, cpu); 559c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen mb(); 560c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen play_dead_at_ckseg1(state_addr); 561c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 562c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 563e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenvoid loongson3_disable_clock(int cpu) 564e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 565e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen uint64_t core_id = cpu_data[cpu].core; 566e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen uint64_t package_id = cpu_data[cpu].package; 567e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 568e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen if (loongson_sysconf.cputype == Loongson_3A) { 569e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); 570e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen } else if (loongson_sysconf.cputype == Loongson_3B) { 571e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen if (!cpuhotplug_workaround) 572e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); 573e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen } 574e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 575e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 576e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chenvoid loongson3_enable_clock(int cpu) 577e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen{ 578e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen uint64_t core_id = cpu_data[cpu].core; 579e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen uint64_t package_id = cpu_data[cpu].package; 580e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 581e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen if (loongson_sysconf.cputype == Loongson_3A) { 582e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); 583e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen } else if (loongson_sysconf.cputype == Loongson_3B) { 584e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen if (!cpuhotplug_workaround) 585e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); 586e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen } 587e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen} 588e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen 589c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN) 590c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenstatic int loongson3_cpu_callback(struct notifier_block *nfb, 591c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned long action, void *hcpu) 592c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 593c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen unsigned int cpu = (unsigned long)hcpu; 594c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 595c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen switch (action) { 596c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen case CPU_POST_DEAD: 597c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen case CPU_POST_DEAD_FROZEN: 598c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen pr_info("Disable clock for CPU#%d\n", cpu); 599e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen loongson3_disable_clock(cpu); 600c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen break; 601c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen case CPU_UP_PREPARE: 602c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen case CPU_UP_PREPARE_FROZEN: 603c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen pr_info("Enable clock for CPU#%d\n", cpu); 604e7841be50fe2b8751a51a068b8cdcdcb6611e354Huacai Chen loongson3_enable_clock(cpu); 605c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen break; 606c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen } 607c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 608c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen return NOTIFY_OK; 609c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 610c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 611c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenstatic int register_loongson3_notifier(void) 612c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen{ 613c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen hotcpu_notifier(loongson3_cpu_callback, 0); 614c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen return 0; 615c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen} 616c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chenearly_initcall(register_loongson3_notifier); 617c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 618c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#endif 619c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen 620300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chenstruct plat_smp_ops loongson3_smp_ops = { 621300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .send_ipi_single = loongson3_send_ipi_single, 622300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .send_ipi_mask = loongson3_send_ipi_mask, 623300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .init_secondary = loongson3_init_secondary, 624300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .smp_finish = loongson3_smp_finish, 625300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .boot_secondary = loongson3_boot_secondary, 626300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .smp_setup = loongson3_smp_setup, 627300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen .prepare_cpus = loongson3_prepare_cpus, 628c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#ifdef CONFIG_HOTPLUG_CPU 629c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen .cpu_disable = loongson3_cpu_disable, 630c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen .cpu_die = loongson3_cpu_die, 631c4a987db1b3cd89207cece4b8121c09cbfbc978aHuacai Chen#endif 632300459d558725cdada5ddebbe52c24ef6e1853d3Huacai Chen}; 633