2019-05-29 16:58:00 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2006-01-11 22:46:18 +01:00
/*
* vSMPowered ( tm ) systems specific initialization
* Copyright ( C ) 2005 ScaleMP Inc .
*
* Ravikiran Thirumalai < kiran @ scalemp . com > ,
* Shai Fultheim < shai @ scalemp . com >
2008-02-11 17:16:04 -02:00
* Paravirt ops integration : Glauber de Oliveira Costa < gcosta @ redhat . com > ,
* Ravikiran Thirumalai < kiran @ scalemp . com >
2006-01-11 22:46:18 +01:00
*/
# include <linux/init.h>
# include <linux/pci_ids.h>
# include <linux/pci_regs.h>
2012-04-16 10:39:35 +03:00
# include <linux/smp.h>
2012-06-03 01:11:35 +03:00
# include <linux/irq.h>
2008-05-12 15:43:34 +02:00
# include <asm/apic.h>
2006-01-11 22:46:18 +01:00
# include <asm/pci-direct.h>
2006-10-12 12:17:52 -07:00
# include <asm/io.h>
2008-02-11 17:16:04 -02:00
# include <asm/paravirt.h>
2008-05-12 15:43:34 +02:00
# include <asm/setup.h>
2008-02-11 17:16:04 -02:00
2012-04-16 10:39:35 +03:00
# define TOPOLOGY_REGISTER_OFFSET 0x10
2018-11-05 19:31:54 +02:00
# ifdef CONFIG_PCI
static void __init set_vsmp_ctl ( void )
2006-01-11 22:46:18 +01:00
{
2008-10-28 23:05:22 -07:00
void __iomem * address ;
2008-02-11 17:16:03 -02:00
unsigned int cap , ctl , cfg ;
2006-01-11 22:46:18 +01:00
/* set vSMP magic bits to indicate vSMP capable kernel */
2008-02-11 17:16:03 -02:00
cfg = read_pci_config ( 0 , 0x1f , 0 , PCI_BASE_ADDRESS_0 ) ;
address = early_ioremap ( cfg , 8 ) ;
2006-01-11 22:46:18 +01:00
cap = readl ( address ) ;
ctl = readl ( address + 4 ) ;
2008-01-30 13:30:24 +01:00
printk ( KERN_INFO " vSMP CTL: capabilities:0x%08x control:0x%08x \n " ,
cap , ctl ) ;
2012-06-03 01:11:35 +03:00
/* If possible, let the vSMP foundation route the interrupt optimally */
# ifdef CONFIG_SMP
if ( cap & ctl & BIT ( 8 ) ) {
ctl & = ~ BIT ( 8 ) ;
2014-04-28 10:21:37 +03:00
2012-06-14 18:43:08 +03:00
# ifdef CONFIG_PROC_FS
/* Don't let users change irq affinity via procfs */
2012-06-03 01:11:35 +03:00
no_irq_affinity = 1 ;
2012-06-14 18:43:08 +03:00
# endif
2012-06-03 01:11:35 +03:00
}
# endif
writel ( ctl , address + 4 ) ;
ctl = readl ( address + 4 ) ;
pr_info ( " vSMP CTL: control set to:0x%08x \n " , ctl ) ;
2006-01-11 22:46:18 +01:00
2008-02-11 17:16:03 -02:00
early_iounmap ( address , 8 ) ;
2008-03-20 00:41:16 -07:00
}
2008-03-24 14:48:36 -07:00
static int is_vsmp = - 1 ;
2008-03-20 00:41:16 -07:00
2008-03-24 14:48:36 -07:00
static void __init detect_vsmp_box ( void )
2008-03-20 00:41:16 -07:00
{
2008-03-24 14:48:36 -07:00
is_vsmp = 0 ;
2008-03-20 00:41:16 -07:00
if ( ! early_pci_allowed ( ) )
2008-03-24 14:48:36 -07:00
return ;
2008-03-20 00:41:16 -07:00
2008-03-24 14:48:36 -07:00
/* Check if we are running on a ScaleMP vSMPowered box */
2008-03-21 09:55:06 +01:00
if ( read_pci_config ( 0 , 0x1f , 0 , PCI_VENDOR_ID ) = =
( PCI_VENDOR_ID_SCALEMP | ( PCI_DEVICE_ID_SCALEMP_VSMP_CTL < < 16 ) ) )
2008-03-24 14:48:36 -07:00
is_vsmp = 1 ;
}
2008-03-20 00:41:16 -07:00
2014-08-01 14:47:56 -07:00
static int is_vsmp_box ( void )
2008-03-24 14:48:36 -07:00
{
if ( is_vsmp ! = - 1 )
return is_vsmp ;
else {
WARN_ON_ONCE ( 1 ) ;
return 0 ;
}
2008-03-20 00:41:16 -07:00
}
2009-03-23 23:14:29 -07:00
# else
static void __init detect_vsmp_box ( void )
{
}
2014-08-01 14:47:56 -07:00
static int is_vsmp_box ( void )
2009-03-23 23:14:29 -07:00
{
return 0 ;
}
2018-11-05 19:31:54 +02:00
static void __init set_vsmp_ctl ( void )
{
}
2009-03-23 23:14:29 -07:00
# endif
2012-04-16 10:39:35 +03:00
static void __init vsmp_cap_cpus ( void )
{
2018-11-05 19:31:54 +02:00
# if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
2012-04-16 10:39:35 +03:00
void __iomem * address ;
unsigned int cfg , topology , node_shift , maxcpus ;
/*
* CONFIG_X86_VSMP is not configured , so limit the number CPUs to the
* ones present in the first board , unless explicitly overridden by
* setup_max_cpus
*/
if ( setup_max_cpus ! = NR_CPUS )
return ;
/* Read the vSMP Foundation topology register */
cfg = read_pci_config ( 0 , 0x1f , 0 , PCI_BASE_ADDRESS_0 ) ;
address = early_ioremap ( cfg + TOPOLOGY_REGISTER_OFFSET , 4 ) ;
if ( WARN_ON ( ! address ) )
return ;
topology = readl ( address ) ;
node_shift = ( topology > > 16 ) & 0x7 ;
if ( ! node_shift )
/* The value 0 should be decoded as 8 */
node_shift = 8 ;
maxcpus = ( topology & ( ( 1 < < node_shift ) - 1 ) ) + 1 ;
pr_info ( " vSMP CTL: Capping CPUs to %d (CONFIG_X86_VSMP is unset) \n " ,
maxcpus ) ;
setup_max_cpus = maxcpus ;
early_iounmap ( address , 4 ) ;
# endif
}
2012-06-03 01:11:34 +03:00
static int apicid_phys_pkg_id ( int initial_apic_id , int index_msb )
{
return hard_smp_processor_id ( ) > > index_msb ;
}
static void vsmp_apic_post_init ( void )
{
/* need to update phys_pkg_id */
apic - > phys_pkg_id = apicid_phys_pkg_id ;
}
2008-03-20 00:41:16 -07:00
void __init vsmp_init ( void )
{
2008-03-24 14:48:36 -07:00
detect_vsmp_box ( ) ;
2008-03-20 00:41:16 -07:00
if ( ! is_vsmp_box ( ) )
return ;
2012-06-03 01:11:34 +03:00
x86_platform . apic_post_init = vsmp_apic_post_init ;
2012-04-16 10:39:35 +03:00
vsmp_cap_cpus ( ) ;
2018-11-05 19:31:54 +02:00
set_vsmp_ctl ( ) ;
2008-02-11 17:16:02 -02:00
return ;
2006-01-11 22:46:18 +01:00
}