2009-08-29 14:54:20 +02:00
/*
2013-10-17 15:35:27 -07:00
* intel - mid . c : Intel MID platform setup code
2009-08-29 14:54:20 +02:00
*
2013-10-17 15:35:27 -07:00
* ( C ) Copyright 2008 , 2012 Intel Corporation
2009-08-29 14:54:20 +02:00
* Author : Jacob Pan ( jacob . jun . pan @ intel . com )
2013-10-17 15:35:27 -07:00
* Author : Sathyanarayanan Kuppuswamy < sathyanarayanan . kuppuswamy @ intel . com >
2009-08-29 14:54:20 +02:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; version 2
* of the License .
*/
2010-11-09 11:22:58 +00:00
2013-10-17 15:35:29 -07:00
# define pr_fmt(fmt) "intel_mid: " fmt
2010-11-09 11:22:58 +00:00
2009-08-29 14:54:20 +02:00
# include <linux/init.h>
2010-02-12 03:08:30 -08:00
# include <linux/kernel.h>
2011-08-26 11:25:14 +01:00
# include <linux/interrupt.h>
2016-07-09 16:45:29 +03:00
# include <linux/regulator/machine.h>
2011-08-26 11:25:14 +01:00
# include <linux/scatterlist.h>
2010-02-12 03:08:30 -08:00
# include <linux/sfi.h>
# include <linux/irq.h>
2016-07-13 20:18:58 -04:00
# include <linux/export.h>
2011-09-07 16:06:51 +03:00
# include <linux/notifier.h>
2009-08-29 14:54:20 +02:00
# include <asm/setup.h>
2010-02-12 03:08:30 -08:00
# include <asm/mpspec_def.h>
# include <asm/hw_irq.h>
# include <asm/apic.h>
# include <asm/io_apic.h>
2013-10-17 15:35:27 -07:00
# include <asm/intel-mid.h>
# include <asm/intel_mid_vrtc.h>
2010-02-12 02:29:11 -08:00
# include <asm/io.h>
# include <asm/i8259.h>
2010-11-09 11:22:58 +00:00
# include <asm/intel_scu_ipc.h>
2010-02-12 05:01:12 -08:00
# include <asm/apb_timer.h>
2010-11-10 16:50:08 +00:00
# include <asm/reboot.h>
2009-08-29 14:54:20 +02:00
2010-05-19 12:01:25 -07:00
/*
* the clockevent devices on Moorestown / Medfield can be APBT or LAPIC clock ,
2013-10-17 15:35:29 -07:00
* cmdline option x86_intel_mid_timer can be used to override the configuration
2010-05-19 12:01:25 -07:00
* to prefer one or the other .
* at runtime , there are basically three timer configurations :
* 1. per cpu apbt clock only
* 2. per cpu always - on lapic clocks only , this is Penwell / Medfield only
* 3. per cpu lapic clock ( C3STOP ) and one apbt clock , with broadcast .
*
* by default ( without cmdline option ) , platform code first detects cpu type
* to see if we are on lincroft or penwell , then set up both lapic or apbt
* clocks accordingly .
* i . e . by default , medfield uses configuration # 2 , moorestown uses # 1.
* config # 3 is supported but not recommended on medfield .
*
* rating and feature summary :
* lapic ( with C3STOP ) - - - - - - - - - 100
* apbt ( always - on ) - - - - - - - - - - - - 110
* lapic ( always - on , ARAT ) - - - - - - 150
*/
2013-10-17 15:35:29 -07:00
enum intel_mid_timer_options intel_mid_timer_options ;
2010-05-19 12:01:25 -07:00
2013-10-17 15:35:29 -07:00
enum intel_mid_cpu_type __intel_mid_cpu_chip ;
EXPORT_SYMBOL_GPL ( __intel_mid_cpu_chip ) ;
2010-05-19 12:01:24 -07:00
2013-12-16 12:07:37 -08:00
static void intel_mid_power_off ( void )
{
2016-09-07 15:39:55 +03:00
/* Shut down South Complex via PWRMU */
intel_mid_pwr_power_off ( ) ;
/* Only for Tangier, the rest will ignore this command */
intel_scu_ipc_simple_command ( IPCMSG_COLD_OFF , 1 ) ;
2013-12-16 12:07:37 -08:00
} ;
2013-10-17 15:35:29 -07:00
static void intel_mid_reboot ( void )
2011-11-16 16:07:22 +00:00
{
2018-02-28 11:40:49 +02:00
intel_scu_ipc_simple_command ( IPCMSG_COLD_RESET , 0 ) ;
2011-11-16 16:07:22 +00:00
}
2015-04-13 14:11:51 +08:00
static void __init intel_mid_setup_bp_timer ( void )
{
apbt_time_init ( ) ;
setup_boot_APIC_clock ( ) ;
}
2013-10-17 15:35:29 -07:00
static void __init intel_mid_time_init ( void )
2010-02-12 05:01:12 -08:00
{
2010-11-09 11:28:43 +00:00
sfi_table_parse ( SFI_SIG_MTMR , NULL , NULL , sfi_parse_mtmr ) ;
2015-04-13 14:11:51 +08:00
2013-10-17 15:35:29 -07:00
switch ( intel_mid_timer_options ) {
case INTEL_MID_TIMER_APBT_ONLY :
2010-05-19 12:01:25 -07:00
break ;
2013-10-17 15:35:29 -07:00
case INTEL_MID_TIMER_LAPIC_APBT :
2015-04-13 14:11:51 +08:00
/* Use apbt and local apic */
x86_init . timers . setup_percpu_clockev = intel_mid_setup_bp_timer ;
2010-05-19 12:01:25 -07:00
x86_cpuinit . setup_percpu_clockev = setup_secondary_APIC_clock ;
2015-04-13 14:11:51 +08:00
return ;
2010-05-19 12:01:25 -07:00
default :
if ( ! boot_cpu_has ( X86_FEATURE_ARAT ) )
break ;
2015-04-13 14:11:51 +08:00
/* Lapic only, no apbt */
2010-05-19 12:01:25 -07:00
x86_init . timers . setup_percpu_clockev = setup_boot_APIC_clock ;
x86_cpuinit . setup_percpu_clockev = setup_secondary_APIC_clock ;
return ;
}
2015-04-13 14:11:51 +08:00
x86_init . timers . setup_percpu_clockev = apbt_time_init ;
2010-02-12 05:01:12 -08:00
}
2013-11-07 13:34:50 -05:00
static void intel_mid_arch_setup ( void )
2010-02-12 05:01:12 -08:00
{
2013-12-16 12:07:37 -08:00
if ( boot_cpu_data . x86 ! = 6 ) {
2012-01-26 17:33:30 +00:00
pr_err ( " Unknown Intel MID CPU (%d:%d), default to Penwell \n " ,
2010-05-19 12:01:24 -07:00
boot_cpu_data . x86 , boot_cpu_data . x86_model ) ;
2013-10-17 15:35:29 -07:00
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL ;
2013-12-16 12:07:37 -08:00
goto out ;
}
switch ( boot_cpu_data . x86_model ) {
case 0x35 :
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_CLOVERVIEW ;
break ;
2013-12-16 12:07:38 -08:00
case 0x3C :
case 0x4A :
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_TANGIER ;
2018-06-29 22:31:13 +03:00
x86_platform . legacy . rtc = 1 ;
2013-12-16 12:07:38 -08:00
break ;
2013-12-16 12:07:37 -08:00
case 0x27 :
default :
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL ;
break ;
2010-05-19 12:01:24 -07:00
}
2013-12-16 12:07:37 -08:00
out :
2016-07-09 16:45:29 +03:00
/*
* Intel MID platforms are using explicitly defined regulators .
*
* Let the regulator core know that we do not have any additional
* regulators left . This lets it substitute unprovided regulators with
* dummy ones :
*/
regulator_has_full_constraints ( ) ;
2010-05-19 12:01:24 -07:00
}
2010-02-12 05:01:12 -08:00
2011-11-10 13:43:05 +00:00
/*
* Moorestown does not have external NMI source nor port 0x61 to report
* NMI status . The possible NMI sources are from pmu as a result of NMI
* watchdog or lock debug . Reading io port 0x61 results in 0xff which
* misled NMI handler .
*/
2013-10-17 15:35:29 -07:00
static unsigned char intel_mid_get_nmi_reason ( void )
2011-11-10 13:43:05 +00:00
{
return 0 ;
}
2009-08-29 14:54:20 +02:00
/*
* Moorestown specific x86_init function overrides and early setup
* calls .
*/
2013-10-17 15:35:29 -07:00
void __init x86_intel_mid_early_setup ( void )
2009-08-29 14:54:20 +02:00
{
x86_init . resources . probe_roms = x86_init_noop ;
x86_init . resources . reserve_resources = x86_init_noop ;
2010-02-12 02:29:11 -08:00
2013-10-17 15:35:29 -07:00
x86_init . timers . timer_init = intel_mid_time_init ;
2010-05-19 12:01:25 -07:00
x86_init . timers . setup_percpu_clockev = x86_init_noop ;
2017-07-24 20:33:09 +03:00
x86_init . timers . wallclock_init = intel_mid_rtc_init ;
2010-02-12 05:01:12 -08:00
x86_init . irqs . pre_vector_init = x86_init_noop ;
2013-10-17 15:35:29 -07:00
x86_init . oem . arch_setup = intel_mid_arch_setup ;
2010-05-19 12:01:24 -07:00
2010-05-19 12:01:25 -07:00
x86_cpuinit . setup_percpu_clockev = apbt_setup_secondary_clock ;
2010-02-12 05:01:12 -08:00
2013-10-17 15:35:29 -07:00
x86_platform . get_nmi_reason = intel_mid_get_nmi_reason ;
2011-11-10 13:43:05 +00:00
2018-01-17 19:34:08 +02:00
x86_init . pci . arch_init = intel_mid_pci_init ;
2010-02-12 10:31:47 -08:00
x86_init . pci . fixup_irqs = x86_init_noop ;
2010-02-12 02:29:11 -08:00
legacy_pic = & null_legacy_pic ;
2010-05-14 14:41:20 -07:00
2018-02-20 20:05:06 +02:00
/*
* Do nothing for now as everything needed done in
* x86_intel_mid_early_setup ( ) below .
*/
x86_init . acpi . reduced_hw_early_init = x86_init_noop ;
2013-10-17 15:35:29 -07:00
pm_power_off = intel_mid_power_off ;
machine_ops . emergency_restart = intel_mid_reboot ;
2010-11-10 16:50:08 +00:00
2010-05-14 14:41:20 -07:00
/* Avoid searching for BIOS MP tables */
x86_init . mpparse . find_smp_config = x86_init_noop ;
x86_init . mpparse . get_smp_config = x86_init_uint_noop ;
2011-04-08 11:23:00 -07:00
set_bit ( MP_BUS_ISA , mp_bus_not_pci ) ;
2009-08-29 14:54:20 +02:00
}
2010-05-19 12:01:25 -07:00
/*
* if user does not want to use per CPU apb timer , just give it a lower rating
* than local apic timer and skip the late per cpu timer init .
*/
2013-10-17 15:35:29 -07:00
static inline int __init setup_x86_intel_mid_timer ( char * arg )
2010-05-19 12:01:25 -07:00
{
if ( ! arg )
return - EINVAL ;
if ( strcmp ( " apbt_only " , arg ) = = 0 )
2013-10-17 15:35:29 -07:00
intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY ;
2010-05-19 12:01:25 -07:00
else if ( strcmp ( " lapic_and_apbt " , arg ) = = 0 )
2013-10-17 15:35:29 -07:00
intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT ;
2010-05-19 12:01:25 -07:00
else {
2016-01-15 22:11:08 +02:00
pr_warn ( " X86 INTEL_MID timer option %s not recognised use x86_intel_mid_timer=apbt_only or lapic_and_apbt \n " ,
arg ) ;
2010-05-19 12:01:25 -07:00
return - EINVAL ;
}
return 0 ;
}
2013-10-17 15:35:29 -07:00
__setup ( " x86_intel_mid_timer= " , setup_x86_intel_mid_timer ) ;