2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-03-21 14:44:08 +04:00
/*
* Copyright ( C ) 2010 , 2011 , 2012 , Lemote , Inc .
* Author : Chen Huacai , chenhc @ lemote . com
*/
2020-03-25 06:55:00 +03:00
# include <irq.h>
2014-03-21 14:44:08 +04:00
# include <linux/init.h>
# include <linux/cpu.h>
# include <linux/sched.h>
2017-02-08 20:51:36 +03:00
# include <linux/sched/hotplug.h>
2017-02-08 20:51:37 +03:00
# include <linux/sched/task_stack.h>
2014-03-21 14:44:08 +04:00
# include <linux/smp.h>
# include <linux/cpufreq.h>
2018-09-12 00:49:21 +03:00
# include <linux/kexec.h>
2014-03-21 14:44:08 +04:00
# include <asm/processor.h>
2023-02-16 21:42:52 +03:00
# include <asm/smp.h>
2014-03-21 14:44:08 +04:00
# include <asm/time.h>
# include <asm/tlbflush.h>
2014-03-21 14:44:09 +04:00
# include <asm/cacheflush.h>
2014-03-21 14:44:08 +04:00
# include <loongson.h>
2019-09-21 16:50:28 +03:00
# include <loongson_regs.h>
2014-11-04 09:13:27 +03:00
# include <workarounds.h>
2014-03-21 14:44:08 +04:00
# include "smp.h"
2014-03-21 14:44:09 +04:00
DEFINE_PER_CPU ( int , cpu_state ) ;
2020-03-25 06:55:00 +03:00
# define LS_IPI_IRQ (MIPS_CPU_IRQ_BASE + 6)
2023-02-21 16:16:54 +03:00
static void __iomem * ipi_set0_regs [ 16 ] ;
static void __iomem * ipi_clear0_regs [ 16 ] ;
static void __iomem * ipi_status0_regs [ 16 ] ;
static void __iomem * ipi_en0_regs [ 16 ] ;
static void __iomem * ipi_mailbox_buf [ 16 ] ;
2016-01-21 16:09:49 +03:00
static uint32_t core0_c0count [ NR_CPUS ] ;
2014-06-26 07:41:30 +04:00
2021-05-27 14:52:53 +03:00
static u32 ( * ipi_read_clear ) ( int cpu ) ;
static void ( * ipi_write_action ) ( int cpu , u32 action ) ;
static void ( * ipi_write_enable ) ( int cpu ) ;
static void ( * ipi_clear_buf ) ( int cpu ) ;
static void ( * ipi_write_buf ) ( int cpu , struct task_struct * idle ) ;
2020-11-03 10:12:03 +03:00
/* send mail via Mail_Send register for 3A4000+ CPU */
static void csr_mail_send ( uint64_t data , int cpu , int mailbox )
{
uint64_t val ;
/* send high 32 bits */
val = CSR_MAIL_SEND_BLOCK ;
val | = ( CSR_MAIL_SEND_BOX_HIGH ( mailbox ) < < CSR_MAIL_SEND_BOX_SHIFT ) ;
val | = ( cpu < < CSR_MAIL_SEND_CPU_SHIFT ) ;
val | = ( data & CSR_MAIL_SEND_H32_MASK ) ;
csr_writeq ( val , LOONGSON_CSR_MAIL_SEND ) ;
/* send low 32 bits */
val = CSR_MAIL_SEND_BLOCK ;
val | = ( CSR_MAIL_SEND_BOX_LOW ( mailbox ) < < CSR_MAIL_SEND_BOX_SHIFT ) ;
val | = ( cpu < < CSR_MAIL_SEND_CPU_SHIFT ) ;
val | = ( data < < CSR_MAIL_SEND_BUF_SHIFT ) ;
csr_writeq ( val , LOONGSON_CSR_MAIL_SEND ) ;
} ;
2019-09-21 16:50:28 +03:00
static u32 csr_ipi_read_clear ( int cpu )
{
u32 action ;
/* Load the ipi register to figure out what we're supposed to do */
action = csr_readl ( LOONGSON_CSR_IPI_STATUS ) ;
/* Clear the ipi register to clear the interrupt */
csr_writel ( action , LOONGSON_CSR_IPI_CLEAR ) ;
return action ;
}
static void csr_ipi_write_action ( int cpu , u32 action )
{
unsigned int irq = 0 ;
while ( ( irq = ffs ( action ) ) ) {
uint32_t val = CSR_IPI_SEND_BLOCK ;
val | = ( irq - 1 ) ;
val | = ( cpu < < CSR_IPI_SEND_CPU_SHIFT ) ;
csr_writel ( val , LOONGSON_CSR_IPI_SEND ) ;
action & = ~ BIT ( irq - 1 ) ;
}
}
2020-11-03 10:12:03 +03:00
static void csr_ipi_write_enable ( int cpu )
{
csr_writel ( 0xffffffff , LOONGSON_CSR_IPI_EN ) ;
}
static void csr_ipi_clear_buf ( int cpu )
{
csr_writeq ( 0 , LOONGSON_CSR_MAIL_BUF0 ) ;
}
static void csr_ipi_write_buf ( int cpu , struct task_struct * idle )
{
unsigned long startargs [ 4 ] ;
/* startargs[] are initial PC, SP and GP for secondary CPU */
startargs [ 0 ] = ( unsigned long ) & smp_bootstrap ;
startargs [ 1 ] = ( unsigned long ) __KSTK_TOS ( idle ) ;
startargs [ 2 ] = ( unsigned long ) task_thread_info ( idle ) ;
startargs [ 3 ] = 0 ;
pr_debug ( " CPU#%d, func_pc=%lx, sp=%lx, gp=%lx \n " ,
cpu , startargs [ 0 ] , startargs [ 1 ] , startargs [ 2 ] ) ;
csr_mail_send ( startargs [ 3 ] , cpu_logical_map ( cpu ) , 3 ) ;
csr_mail_send ( startargs [ 2 ] , cpu_logical_map ( cpu ) , 2 ) ;
csr_mail_send ( startargs [ 1 ] , cpu_logical_map ( cpu ) , 1 ) ;
csr_mail_send ( startargs [ 0 ] , cpu_logical_map ( cpu ) , 0 ) ;
}
2019-09-21 16:50:28 +03:00
static u32 legacy_ipi_read_clear ( int cpu )
{
u32 action ;
/* Load the ipi register to figure out what we're supposed to do */
2023-02-21 16:16:56 +03:00
action = readl_relaxed ( ipi_status0_regs [ cpu_logical_map ( cpu ) ] ) ;
2019-09-21 16:50:28 +03:00
/* Clear the ipi register to clear the interrupt */
2023-02-21 16:16:56 +03:00
writel_relaxed ( action , ipi_clear0_regs [ cpu_logical_map ( cpu ) ] ) ;
nudge_writes ( ) ;
2019-09-21 16:50:28 +03:00
return action ;
}
static void legacy_ipi_write_action ( int cpu , u32 action )
{
2023-02-21 16:16:56 +03:00
writel_relaxed ( ( u32 ) action , ipi_set0_regs [ cpu ] ) ;
nudge_writes ( ) ;
2019-09-21 16:50:28 +03:00
}
2020-11-03 10:12:03 +03:00
static void legacy_ipi_write_enable ( int cpu )
{
2023-02-21 16:16:56 +03:00
writel_relaxed ( 0xffffffff , ipi_en0_regs [ cpu_logical_map ( cpu ) ] ) ;
2020-11-03 10:12:03 +03:00
}
static void legacy_ipi_clear_buf ( int cpu )
{
2023-02-21 16:16:56 +03:00
writeq_relaxed ( 0 , ipi_mailbox_buf [ cpu_logical_map ( cpu ) ] + 0x0 ) ;
2020-11-03 10:12:03 +03:00
}
static void legacy_ipi_write_buf ( int cpu , struct task_struct * idle )
{
unsigned long startargs [ 4 ] ;
/* startargs[] are initial PC, SP and GP for secondary CPU */
startargs [ 0 ] = ( unsigned long ) & smp_bootstrap ;
startargs [ 1 ] = ( unsigned long ) __KSTK_TOS ( idle ) ;
startargs [ 2 ] = ( unsigned long ) task_thread_info ( idle ) ;
startargs [ 3 ] = 0 ;
pr_debug ( " CPU#%d, func_pc=%lx, sp=%lx, gp=%lx \n " ,
cpu , startargs [ 0 ] , startargs [ 1 ] , startargs [ 2 ] ) ;
2023-02-21 16:16:56 +03:00
writeq_relaxed ( startargs [ 3 ] ,
2020-11-03 10:12:03 +03:00
ipi_mailbox_buf [ cpu_logical_map ( cpu ) ] + 0x18 ) ;
2023-02-21 16:16:56 +03:00
writeq_relaxed ( startargs [ 2 ] ,
2020-11-03 10:12:03 +03:00
ipi_mailbox_buf [ cpu_logical_map ( cpu ) ] + 0x10 ) ;
2023-02-21 16:16:56 +03:00
writeq_relaxed ( startargs [ 1 ] ,
2020-11-03 10:12:03 +03:00
ipi_mailbox_buf [ cpu_logical_map ( cpu ) ] + 0x8 ) ;
2023-02-21 16:16:56 +03:00
writeq_relaxed ( startargs [ 0 ] ,
2020-11-03 10:12:03 +03:00
ipi_mailbox_buf [ cpu_logical_map ( cpu ) ] + 0x0 ) ;
2023-02-21 16:16:56 +03:00
nudge_writes ( ) ;
2020-11-03 10:12:03 +03:00
}
2019-09-21 16:50:28 +03:00
static void csr_ipi_probe ( void )
{
if ( cpu_has_csr ( ) & & csr_readl ( LOONGSON_CSR_FEATURES ) & LOONGSON_CSRF_IPI ) {
ipi_read_clear = csr_ipi_read_clear ;
ipi_write_action = csr_ipi_write_action ;
2020-11-03 10:12:03 +03:00
ipi_write_enable = csr_ipi_write_enable ;
ipi_clear_buf = csr_ipi_clear_buf ;
ipi_write_buf = csr_ipi_write_buf ;
2019-09-21 16:50:28 +03:00
} else {
ipi_read_clear = legacy_ipi_read_clear ;
ipi_write_action = legacy_ipi_write_action ;
2020-11-03 10:12:03 +03:00
ipi_write_enable = legacy_ipi_write_enable ;
ipi_clear_buf = legacy_ipi_clear_buf ;
ipi_write_buf = legacy_ipi_write_buf ;
2019-09-21 16:50:28 +03:00
}
}
2014-06-26 07:41:30 +04:00
static void ipi_set0_regs_init ( void )
{
ipi_set0_regs [ 0 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0 ) ;
ipi_set0_regs [ 1 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0 ) ;
ipi_set0_regs [ 2 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0 ) ;
ipi_set0_regs [ 3 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0 ) ;
ipi_set0_regs [ 4 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0 ) ;
ipi_set0_regs [ 5 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0 ) ;
ipi_set0_regs [ 6 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0 ) ;
ipi_set0_regs [ 7 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0 ) ;
ipi_set0_regs [ 8 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0 ) ;
ipi_set0_regs [ 9 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0 ) ;
ipi_set0_regs [ 10 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0 ) ;
ipi_set0_regs [ 11 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0 ) ;
ipi_set0_regs [ 12 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0 ) ;
ipi_set0_regs [ 13 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0 ) ;
ipi_set0_regs [ 14 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0 ) ;
ipi_set0_regs [ 15 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0 ) ;
}
2014-03-21 14:44:08 +04:00
2014-06-26 07:41:30 +04:00
static void ipi_clear0_regs_init ( void )
{
ipi_clear0_regs [ 0 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 1 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 2 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 3 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 4 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 5 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 6 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 7 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 8 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 9 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 10 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 11 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 12 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 13 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 14 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0 ) ;
ipi_clear0_regs [ 15 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0 ) ;
}
2014-03-21 14:44:08 +04:00
2014-06-26 07:41:30 +04:00
static void ipi_status0_regs_init ( void )
{
ipi_status0_regs [ 0 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 1 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 2 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 3 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 4 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 5 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 6 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 7 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 8 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 9 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 10 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 11 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 12 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 13 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 14 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0 ) ;
ipi_status0_regs [ 15 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0 ) ;
}
2014-03-21 14:44:08 +04:00
2014-06-26 07:41:30 +04:00
static void ipi_en0_regs_init ( void )
{
ipi_en0_regs [ 0 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0 ) ;
ipi_en0_regs [ 1 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0 ) ;
ipi_en0_regs [ 2 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0 ) ;
ipi_en0_regs [ 3 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0 ) ;
ipi_en0_regs [ 4 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0 ) ;
ipi_en0_regs [ 5 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0 ) ;
ipi_en0_regs [ 6 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0 ) ;
ipi_en0_regs [ 7 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0 ) ;
ipi_en0_regs [ 8 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0 ) ;
ipi_en0_regs [ 9 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0 ) ;
ipi_en0_regs [ 10 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0 ) ;
ipi_en0_regs [ 11 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0 ) ;
ipi_en0_regs [ 12 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0 ) ;
ipi_en0_regs [ 13 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0 ) ;
ipi_en0_regs [ 14 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0 ) ;
ipi_en0_regs [ 15 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0 ) ;
}
2014-03-21 14:44:08 +04:00
2014-06-26 07:41:30 +04:00
static void ipi_mailbox_buf_init ( void )
{
ipi_mailbox_buf [ 0 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF ) ;
ipi_mailbox_buf [ 1 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF ) ;
ipi_mailbox_buf [ 2 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF ) ;
ipi_mailbox_buf [ 3 ] = ( void * )
( SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF ) ;
ipi_mailbox_buf [ 4 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF ) ;
ipi_mailbox_buf [ 5 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF ) ;
ipi_mailbox_buf [ 6 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF ) ;
ipi_mailbox_buf [ 7 ] = ( void * )
( SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF ) ;
ipi_mailbox_buf [ 8 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF ) ;
ipi_mailbox_buf [ 9 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF ) ;
ipi_mailbox_buf [ 10 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF ) ;
ipi_mailbox_buf [ 11 ] = ( void * )
( SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF ) ;
ipi_mailbox_buf [ 12 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF ) ;
ipi_mailbox_buf [ 13 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF ) ;
ipi_mailbox_buf [ 14 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF ) ;
ipi_mailbox_buf [ 15 ] = ( void * )
( SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF ) ;
}
2014-03-21 14:44:08 +04:00
/*
* Simple enough , just poke the appropriate ipi register
*/
static void loongson3_send_ipi_single ( int cpu , unsigned int action )
{
2019-09-21 16:50:28 +03:00
ipi_write_action ( cpu_logical_map ( cpu ) , ( u32 ) action ) ;
2014-03-21 14:44:08 +04:00
}
static void
loongson3_send_ipi_mask ( const struct cpumask * mask , unsigned int action )
{
unsigned int i ;
for_each_cpu ( i , mask )
2019-09-21 16:50:28 +03:00
ipi_write_action ( cpu_logical_map ( i ) , ( u32 ) action ) ;
2014-03-21 14:44:08 +04:00
}
2017-06-22 18:06:52 +03:00
2020-03-25 06:55:00 +03:00
static irqreturn_t loongson3_ipi_interrupt ( int irq , void * dev_id )
2014-03-21 14:44:08 +04:00
{
2014-03-21 14:44:09 +04:00
int i , cpu = smp_processor_id ( ) ;
2020-03-25 06:55:00 +03:00
unsigned int action , c0count ;
2014-03-21 14:44:08 +04:00
2019-09-21 16:50:28 +03:00
action = ipi_read_clear ( cpu ) ;
2014-03-21 14:44:08 +04:00
if ( action & SMP_RESCHEDULE_YOURSELF )
scheduler_ipi ( ) ;
2015-07-24 18:57:49 +03:00
if ( action & SMP_CALL_FUNCTION ) {
irq_enter ( ) ;
generic_smp_call_function_interrupt ( ) ;
irq_exit ( ) ;
}
2014-03-21 14:44:09 +04:00
if ( action & SMP_ASK_C0COUNT ) {
BUG_ON ( cpu ! = 0 ) ;
c0count = read_c0_count ( ) ;
2016-01-21 16:09:49 +03:00
c0count = c0count ? c0count : 1 ;
for ( i = 1 ; i < nr_cpu_ids ; i + + )
core0_c0count [ i ] = c0count ;
2023-02-21 16:16:55 +03:00
nudge_writes ( ) ; /* Let others see the result ASAP */
2014-03-21 14:44:09 +04:00
}
2017-06-22 18:06:52 +03:00
2020-03-25 06:55:00 +03:00
return IRQ_HANDLED ;
2014-03-21 14:44:08 +04:00
}
2016-01-21 16:09:49 +03:00
# define MAX_LOOPS 800
2014-03-21 14:44:08 +04:00
/*
* SMP init and finish on secondary CPUs
*/
static void loongson3_init_secondary ( void )
{
int i ;
2014-03-21 14:44:09 +04:00
uint32_t initcount ;
unsigned int cpu = smp_processor_id ( ) ;
2014-03-21 14:44:08 +04:00
unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
STATUSF_IP3 | STATUSF_IP2 ;
/* Set interrupt mask, but don't enable */
change_c0_status ( ST0_IM , imask ) ;
2020-11-03 10:12:03 +03:00
ipi_write_enable ( cpu ) ;
2014-03-21 14:44:09 +04:00
per_cpu ( cpu_state , cpu ) = CPU_ONLINE ;
2017-08-13 05:49:35 +03:00
cpu_set_core ( & cpu_data [ cpu ] ,
cpu_logical_map ( cpu ) % loongson_sysconf . cores_per_package ) ;
2014-11-04 09:13:26 +03:00
cpu_data [ cpu ] . package =
cpu_logical_map ( cpu ) / loongson_sysconf . cores_per_package ;
2014-03-21 14:44:09 +04:00
i = 0 ;
2016-01-21 16:09:49 +03:00
core0_c0count [ cpu ] = 0 ;
2014-03-21 14:44:09 +04:00
loongson3_send_ipi_single ( 0 , SMP_ASK_C0COUNT ) ;
2016-01-21 16:09:49 +03:00
while ( ! core0_c0count [ cpu ] ) {
2014-03-21 14:44:09 +04:00
i + + ;
cpu_relax ( ) ;
}
if ( i > MAX_LOOPS )
i = MAX_LOOPS ;
2016-01-21 16:09:49 +03:00
if ( cpu_data [ cpu ] . package )
initcount = core0_c0count [ cpu ] + i ;
else /* Local access is faster for loops */
initcount = core0_c0count [ cpu ] + i / 2 ;
2014-03-21 14:44:09 +04:00
write_c0_count ( initcount ) ;
2014-03-21 14:44:08 +04:00
}
static void loongson3_smp_finish ( void )
{
2014-11-04 09:13:26 +03:00
int cpu = smp_processor_id ( ) ;
2014-03-21 14:44:08 +04:00
write_c0_compare ( read_c0_count ( ) + mips_hpt_frequency / HZ ) ;
local_irq_enable ( ) ;
2020-11-03 10:12:03 +03:00
ipi_clear_buf ( cpu ) ;
2014-03-21 14:44:08 +04:00
pr_info ( " CPU#%d finished, CP0_ST=%x \n " ,
smp_processor_id ( ) , read_c0_status ( ) ) ;
}
static void __init loongson3_smp_setup ( void )
{
2014-11-04 09:13:26 +03:00
int i = 0 , num = 0 ; /* i: physical id, num: logical id */
2014-03-21 14:44:08 +04:00
init_cpu_possible ( cpu_none_mask ) ;
/* For unified kernel, NR_CPUS is the maximum possible value,
2020-12-22 11:37:00 +03:00
* loongson_sysconf . nr_cpus is the really present value
*/
2014-11-04 09:13:26 +03:00
while ( i < loongson_sysconf . nr_cpus ) {
if ( loongson_sysconf . reserved_cpus_mask & ( 1 < < i ) ) {
/* Reserved physical CPU cores */
__cpu_number_map [ i ] = - 1 ;
} else {
__cpu_number_map [ i ] = num ;
__cpu_logical_map [ num ] = i ;
set_cpu_possible ( num , true ) ;
2020-12-30 06:39:49 +03:00
/* Loongson processors are always grouped by 4 */
cpu_set_cluster ( & cpu_data [ num ] , i / 4 ) ;
2014-11-04 09:13:26 +03:00
num + + ;
}
i + + ;
2014-03-21 14:44:08 +04:00
}
2014-11-04 09:13:26 +03:00
pr_info ( " Detected %i available CPU(s) \n " , num ) ;
while ( num < loongson_sysconf . nr_cpus ) {
__cpu_logical_map [ num ] = - 1 ;
num + + ;
}
2019-09-21 16:50:28 +03:00
csr_ipi_probe ( ) ;
2014-06-26 07:41:30 +04:00
ipi_set0_regs_init ( ) ;
ipi_clear0_regs_init ( ) ;
ipi_status0_regs_init ( ) ;
ipi_en0_regs_init ( ) ;
ipi_mailbox_buf_init ( ) ;
2020-11-03 10:12:03 +03:00
ipi_write_enable ( 0 ) ;
2017-08-13 05:49:35 +03:00
cpu_set_core ( & cpu_data [ 0 ] ,
cpu_logical_map ( 0 ) % loongson_sysconf . cores_per_package ) ;
2014-11-04 09:13:26 +03:00
cpu_data [ 0 ] . package = cpu_logical_map ( 0 ) / loongson_sysconf . cores_per_package ;
2014-03-21 14:44:08 +04:00
}
static void __init loongson3_prepare_cpus ( unsigned int max_cpus )
{
2020-03-25 06:55:00 +03:00
if ( request_irq ( LS_IPI_IRQ , loongson3_ipi_interrupt ,
IRQF_PERCPU | IRQF_NO_SUSPEND , " SMP_IPI " , NULL ) )
pr_err ( " Failed to request IPI IRQ \n " ) ;
2014-03-21 14:44:09 +04:00
init_cpu_present ( cpu_possible_mask ) ;
per_cpu ( cpu_state , smp_processor_id ( ) ) = CPU_ONLINE ;
2014-03-21 14:44:08 +04:00
}
/*
* Setup the PC , SP , and GP of a secondary processor and start it runing !
*/
2017-08-13 05:49:40 +03:00
static int loongson3_boot_secondary ( int cpu , struct task_struct * idle )
2014-03-21 14:44:08 +04:00
{
pr_info ( " Booting CPU#%d... \n " , cpu ) ;
2020-11-03 10:12:03 +03:00
ipi_write_buf ( cpu , idle ) ;
2014-03-21 14:44:08 +04:00
2017-08-13 05:49:40 +03:00
return 0 ;
2014-03-21 14:44:08 +04:00
}
2014-03-21 14:44:09 +04:00
# ifdef CONFIG_HOTPLUG_CPU
static int loongson3_cpu_disable ( void )
{
unsigned long flags ;
unsigned int cpu = smp_processor_id ( ) ;
set_cpu_online ( cpu , false ) ;
2016-07-13 16:12:45 +03:00
calculate_cpu_foreign_map ( ) ;
2014-03-21 14:44:09 +04:00
local_irq_save ( flags ) ;
2020-03-25 06:55:00 +03:00
clear_c0_status ( ST0_IM ) ;
2014-03-21 14:44:09 +04:00
local_irq_restore ( flags ) ;
local_flush_tlb_all ( ) ;
return 0 ;
}
static void loongson3_cpu_die ( unsigned int cpu )
{
while ( per_cpu ( cpu_state , cpu ) ! = CPU_DEAD )
cpu_relax ( ) ;
mb ( ) ;
}
/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
* flush all L1 entries at first . Then , another core ( usually Core 0 ) can
* safely disable the clock of the target core . loongson3_play_dead ( ) is
2020-12-22 11:37:00 +03:00
* called via CKSEG1 ( uncached and unmmaped )
*/
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
static void loongson3_type1_play_dead ( int * state_addr )
2014-03-21 14:44:09 +04:00
{
register int val ;
register long cpuid , core , node , count ;
register void * addr , * base , * initfunc ;
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" li %[addr], 0x80000000 \n " /* KSEG0 */
" 1: cache 0, 0(%[addr]) \n " /* flush L1 ICache */
" cache 0, 1(%[addr]) \n "
" cache 0, 2(%[addr]) \n "
" cache 0, 3(%[addr]) \n "
" cache 1, 0(%[addr]) \n " /* flush L1 DCache */
" cache 1, 1(%[addr]) \n "
" cache 1, 2(%[addr]) \n "
" cache 1, 3(%[addr]) \n "
" addiu %[sets], %[sets], -1 \n "
" bnez %[sets], 1b \n "
" addiu %[addr], %[addr], 0x20 \n "
" li %[val], 0x7 \n " /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n "
" sync \n "
" cache 21, (%[state_addr]) \n " /* flush entry of *state_addr */
" .set pop \n "
: [ addr ] " =&r " ( addr ) , [ val ] " =&r " ( val )
: [ state_addr ] " r " ( state_addr ) ,
[ sets ] " r " ( cpu_data [ smp_processor_id ( ) ] . dcache . sets ) ) ;
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" .set mips64 \n "
" mfc0 %[cpuid], $15, 1 \n "
" andi %[cpuid], 0x3ff \n "
" dli %[base], 0x900000003ff01000 \n "
" andi %[core], %[cpuid], 0x3 \n "
" sll %[core], 8 \n " /* get core id */
" or %[base], %[base], %[core] \n "
" andi %[node], %[cpuid], 0xc \n "
" dsll %[node], 42 \n " /* get node id */
" or %[base], %[base], %[node] \n "
" 1: li %[count], 0x100 \n " /* wait for init loop */
" 2: bnez %[count], 2b \n " /* limit mailbox access */
" addiu %[count], -1 \n "
" ld %[initfunc], 0x20(%[base]) \n " /* get PC via mailbox */
" beqz %[initfunc], 1b \n "
" nop \n "
" ld $sp, 0x28(%[base]) \n " /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n " /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n "
" jr %[initfunc] \n " /* jump to initial PC */
" nop \n "
" .set pop \n "
: [ core ] " =&r " ( core ) , [ node ] " =&r " ( node ) ,
[ base ] " =&r " ( base ) , [ cpuid ] " =&r " ( cpuid ) ,
[ count ] " =&r " ( count ) , [ initfunc ] " =&r " ( initfunc )
: /* No Input */
: " a1 " ) ;
}
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
static void loongson3_type2_play_dead ( int * state_addr )
2016-03-03 04:45:09 +03:00
{
register int val ;
register long cpuid , core , node , count ;
register void * addr , * base , * initfunc ;
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" li %[addr], 0x80000000 \n " /* KSEG0 */
" 1: cache 0, 0(%[addr]) \n " /* flush L1 ICache */
" cache 0, 1(%[addr]) \n "
" cache 0, 2(%[addr]) \n "
" cache 0, 3(%[addr]) \n "
" cache 1, 0(%[addr]) \n " /* flush L1 DCache */
" cache 1, 1(%[addr]) \n "
" cache 1, 2(%[addr]) \n "
" cache 1, 3(%[addr]) \n "
" addiu %[sets], %[sets], -1 \n "
" bnez %[sets], 1b \n "
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
" addiu %[addr], %[addr], 0x20 \n "
2016-03-03 04:45:09 +03:00
" li %[val], 0x7 \n " /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n "
" sync \n "
" cache 21, (%[state_addr]) \n " /* flush entry of *state_addr */
" .set pop \n "
: [ addr ] " =&r " ( addr ) , [ val ] " =&r " ( val )
: [ state_addr ] " r " ( state_addr ) ,
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
[ sets ] " r " ( cpu_data [ smp_processor_id ( ) ] . dcache . sets ) ) ;
2016-03-03 04:45:09 +03:00
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" .set mips64 \n "
" mfc0 %[cpuid], $15, 1 \n "
" andi %[cpuid], 0x3ff \n "
" dli %[base], 0x900000003ff01000 \n "
" andi %[core], %[cpuid], 0x3 \n "
" sll %[core], 8 \n " /* get core id */
" or %[base], %[base], %[core] \n "
" andi %[node], %[cpuid], 0xc \n "
" dsll %[node], 42 \n " /* get node id */
" or %[base], %[base], %[node] \n "
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
" dsrl %[node], 30 \n " /* 15:14 */
" or %[base], %[base], %[node] \n "
2016-03-03 04:45:09 +03:00
" 1: li %[count], 0x100 \n " /* wait for init loop */
" 2: bnez %[count], 2b \n " /* limit mailbox access */
" addiu %[count], -1 \n "
" ld %[initfunc], 0x20(%[base]) \n " /* get PC via mailbox */
" beqz %[initfunc], 1b \n "
" nop \n "
" ld $sp, 0x28(%[base]) \n " /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n " /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n "
" jr %[initfunc] \n " /* jump to initial PC */
" nop \n "
" .set pop \n "
: [ core ] " =&r " ( core ) , [ node ] " =&r " ( node ) ,
[ base ] " =&r " ( base ) , [ cpuid ] " =&r " ( cpuid ) ,
[ count ] " =&r " ( count ) , [ initfunc ] " =&r " ( initfunc )
: /* No Input */
: " a1 " ) ;
}
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
static void loongson3_type3_play_dead ( int * state_addr )
2014-06-26 07:41:30 +04:00
{
register int val ;
register long cpuid , core , node , count ;
register void * addr , * base , * initfunc ;
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" li %[addr], 0x80000000 \n " /* KSEG0 */
" 1: cache 0, 0(%[addr]) \n " /* flush L1 ICache */
" cache 0, 1(%[addr]) \n "
" cache 0, 2(%[addr]) \n "
" cache 0, 3(%[addr]) \n "
" cache 1, 0(%[addr]) \n " /* flush L1 DCache */
" cache 1, 1(%[addr]) \n "
" cache 1, 2(%[addr]) \n "
" cache 1, 3(%[addr]) \n "
" addiu %[sets], %[sets], -1 \n "
" bnez %[sets], 1b \n "
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
" addiu %[addr], %[addr], 0x40 \n "
" li %[addr], 0x80000000 \n " /* KSEG0 */
" 2: cache 2, 0(%[addr]) \n " /* flush L1 VCache */
" cache 2, 1(%[addr]) \n "
" cache 2, 2(%[addr]) \n "
" cache 2, 3(%[addr]) \n "
" cache 2, 4(%[addr]) \n "
" cache 2, 5(%[addr]) \n "
" cache 2, 6(%[addr]) \n "
" cache 2, 7(%[addr]) \n "
" cache 2, 8(%[addr]) \n "
" cache 2, 9(%[addr]) \n "
" cache 2, 10(%[addr]) \n "
" cache 2, 11(%[addr]) \n "
" cache 2, 12(%[addr]) \n "
" cache 2, 13(%[addr]) \n "
" cache 2, 14(%[addr]) \n "
" cache 2, 15(%[addr]) \n "
" addiu %[vsets], %[vsets], -1 \n "
" bnez %[vsets], 2b \n "
" addiu %[addr], %[addr], 0x40 \n "
2014-06-26 07:41:30 +04:00
" li %[val], 0x7 \n " /* *state_addr = CPU_DEAD; */
" sw %[val], (%[state_addr]) \n "
" sync \n "
" cache 21, (%[state_addr]) \n " /* flush entry of *state_addr */
" .set pop \n "
: [ addr ] " =&r " ( addr ) , [ val ] " =&r " ( val )
: [ state_addr ] " r " ( state_addr ) ,
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
[ sets ] " r " ( cpu_data [ smp_processor_id ( ) ] . dcache . sets ) ,
[ vsets ] " r " ( cpu_data [ smp_processor_id ( ) ] . vcache . sets ) ) ;
2014-06-26 07:41:30 +04:00
__asm__ __volatile__ (
" .set push \n "
" .set noreorder \n "
" .set mips64 \n "
" mfc0 %[cpuid], $15, 1 \n "
" andi %[cpuid], 0x3ff \n "
" dli %[base], 0x900000003ff01000 \n "
" andi %[core], %[cpuid], 0x3 \n "
" sll %[core], 8 \n " /* get core id */
" or %[base], %[base], %[core] \n "
" andi %[node], %[cpuid], 0xc \n "
" dsll %[node], 42 \n " /* get node id */
" or %[base], %[base], %[node] \n "
" 1: li %[count], 0x100 \n " /* wait for init loop */
" 2: bnez %[count], 2b \n " /* limit mailbox access */
" addiu %[count], -1 \n "
2020-11-03 10:12:04 +03:00
" lw %[initfunc], 0x20(%[base]) \n " /* check lower 32-bit as jump indicator */
2014-06-26 07:41:30 +04:00
" beqz %[initfunc], 1b \n "
" nop \n "
2020-11-03 10:12:04 +03:00
" ld %[initfunc], 0x20(%[base]) \n " /* get PC (whole 64-bit) via mailbox */
2014-06-26 07:41:30 +04:00
" ld $sp, 0x28(%[base]) \n " /* get SP via mailbox */
" ld $gp, 0x30(%[base]) \n " /* get GP via mailbox */
" ld $a1, 0x38(%[base]) \n "
" jr %[initfunc] \n " /* jump to initial PC */
" nop \n "
" .set pop \n "
: [ core ] " =&r " ( core ) , [ node ] " =&r " ( node ) ,
[ base ] " =&r " ( base ) , [ cpuid ] " =&r " ( cpuid ) ,
[ count ] " =&r " ( count ) , [ initfunc ] " =&r " ( initfunc )
: /* No Input */
: " a1 " ) ;
}
2014-03-21 14:44:09 +04:00
void play_dead ( void )
{
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
int prid_imp , prid_rev , * state_addr ;
2014-03-21 14:44:09 +04:00
unsigned int cpu = smp_processor_id ( ) ;
void ( * play_dead_at_ckseg1 ) ( int * ) ;
idle_task_exit ( ) ;
2023-05-13 00:07:37 +03:00
cpuhp_ap_report_dead ( ) ;
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
prid_imp = read_c0_prid ( ) & PRID_IMP_MASK ;
prid_rev = read_c0_prid ( ) & PRID_REV_MASK ;
if ( prid_imp = = PRID_IMP_LOONGSON_64G ) {
play_dead_at_ckseg1 =
( void * ) CKSEG1ADDR ( ( unsigned long ) loongson3_type3_play_dead ) ;
goto out ;
}
switch ( prid_rev ) {
2016-03-03 04:45:09 +03:00
case PRID_REV_LOONGSON3A_R1 :
2014-06-26 07:41:30 +04:00
default :
play_dead_at_ckseg1 =
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
( void * ) CKSEG1ADDR ( ( unsigned long ) loongson3_type1_play_dead ) ;
break ;
case PRID_REV_LOONGSON3B_R1 :
case PRID_REV_LOONGSON3B_R2 :
play_dead_at_ckseg1 =
( void * ) CKSEG1ADDR ( ( unsigned long ) loongson3_type2_play_dead ) ;
2016-03-03 04:45:09 +03:00
break ;
2018-11-15 10:53:52 +03:00
case PRID_REV_LOONGSON3A_R2_0 :
case PRID_REV_LOONGSON3A_R2_1 :
2018-04-28 06:21:25 +03:00
case PRID_REV_LOONGSON3A_R3_0 :
case PRID_REV_LOONGSON3A_R3_1 :
2016-03-03 04:45:09 +03:00
play_dead_at_ckseg1 =
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
( void * ) CKSEG1ADDR ( ( unsigned long ) loongson3_type3_play_dead ) ;
2014-06-26 07:41:30 +04:00
break ;
}
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 16:50:27 +03:00
out :
2014-03-21 14:44:09 +04:00
state_addr = & per_cpu ( cpu_state , cpu ) ;
mb ( ) ;
play_dead_at_ckseg1 ( state_addr ) ;
2023-02-14 10:05:44 +03:00
BUG ( ) ;
2014-03-21 14:44:09 +04:00
}
2016-09-06 20:04:52 +03:00
static int loongson3_disable_clock ( unsigned int cpu )
2014-06-26 07:41:30 +04:00
{
2017-08-13 05:49:35 +03:00
uint64_t core_id = cpu_core ( & cpu_data [ cpu ] ) ;
2014-06-26 07:41:30 +04:00
uint64_t package_id = cpu_data [ cpu ] . package ;
2016-03-03 04:45:09 +03:00
if ( ( read_c0_prid ( ) & PRID_REV_MASK ) = = PRID_REV_LOONGSON3A_R1 ) {
2014-06-26 07:41:30 +04:00
LOONGSON_CHIPCFG ( package_id ) & = ~ ( 1 < < ( 12 + core_id ) ) ;
2016-03-03 04:45:09 +03:00
} else {
2014-11-04 09:13:27 +03:00
if ( ! ( loongson_sysconf . workarounds & WORKAROUND_CPUHOTPLUG ) )
2014-06-26 07:41:30 +04:00
LOONGSON_FREQCTRL ( package_id ) & = ~ ( 1 < < ( core_id * 4 + 3 ) ) ;
}
2016-09-06 20:04:52 +03:00
return 0 ;
2014-06-26 07:41:30 +04:00
}
2016-09-06 20:04:52 +03:00
static int loongson3_enable_clock ( unsigned int cpu )
2014-06-26 07:41:30 +04:00
{
2017-08-13 05:49:35 +03:00
uint64_t core_id = cpu_core ( & cpu_data [ cpu ] ) ;
2014-06-26 07:41:30 +04:00
uint64_t package_id = cpu_data [ cpu ] . package ;
2016-03-03 04:45:09 +03:00
if ( ( read_c0_prid ( ) & PRID_REV_MASK ) = = PRID_REV_LOONGSON3A_R1 ) {
2014-06-26 07:41:30 +04:00
LOONGSON_CHIPCFG ( package_id ) | = 1 < < ( 12 + core_id ) ;
2016-03-03 04:45:09 +03:00
} else {
2014-11-04 09:13:27 +03:00
if ( ! ( loongson_sysconf . workarounds & WORKAROUND_CPUHOTPLUG ) )
2014-06-26 07:41:30 +04:00
LOONGSON_FREQCTRL ( package_id ) | = 1 < < ( core_id * 4 + 3 ) ;
}
2016-09-06 20:04:52 +03:00
return 0 ;
2014-03-21 14:44:09 +04:00
}
static int register_loongson3_notifier ( void )
{
2016-09-06 20:04:52 +03:00
return cpuhp_setup_state_nocalls ( CPUHP_MIPS_SOC_PREPARE ,
" mips/loongson:prepare " ,
loongson3_enable_clock ,
loongson3_disable_clock ) ;
2014-03-21 14:44:09 +04:00
}
early_initcall ( register_loongson3_notifier ) ;
# endif
2017-07-19 11:21:03 +03:00
const struct plat_smp_ops loongson3_smp_ops = {
2014-03-21 14:44:08 +04:00
. send_ipi_single = loongson3_send_ipi_single ,
. send_ipi_mask = loongson3_send_ipi_mask ,
. init_secondary = loongson3_init_secondary ,
. smp_finish = loongson3_smp_finish ,
. boot_secondary = loongson3_boot_secondary ,
. smp_setup = loongson3_smp_setup ,
. prepare_cpus = loongson3_prepare_cpus ,
2014-03-21 14:44:09 +04:00
# ifdef CONFIG_HOTPLUG_CPU
. cpu_disable = loongson3_cpu_disable ,
. cpu_die = loongson3_cpu_die ,
# endif
2018-09-12 00:49:21 +03:00
# ifdef CONFIG_KEXEC
. kexec_nonboot_cpu = kexec_nonboot_cpu_jump ,
# endif
2014-03-21 14:44:08 +04:00
} ;