Commit c4fbde84 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sfi-removal-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull Simple Firmware Interface (SFI) support removal from Rafael Wysocki:
 "Drop support for depercated platforms using SFI, drop the entire
  support for SFI that has been long deprecated too and make some
  janitorial changes on top of that (Andy Shevchenko)"

* tag 'sfi-removal-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  x86/platform/intel-mid: Update Copyright year and drop file names
  x86/platform/intel-mid: Remove unused header inclusion in intel-mid.h
  x86/platform/intel-mid: Drop unused __intel_mid_cpu_chip and Co.
  x86/platform/intel-mid: Get rid of intel_scu_ipc_legacy.h
  x86/PCI: Describe @reg for type1_access_ok()
  x86/PCI: Get rid of custom x86 model comparison
  sfi: Remove framework for deprecated firmware
  cpufreq: sfi-cpufreq: Remove driver for deprecated firmware
  media: atomisp: Remove unused header
  mfd: intel_msic: Remove driver for deprecated platform
  x86/apb_timer: Remove driver for deprecated platform
  x86/platform/intel-mid: Remove unused leftovers (vRTC)
  x86/platform/intel-mid: Remove unused leftovers (msic)
  x86/platform/intel-mid: Remove unused leftovers (msic_thermal)
  x86/platform/intel-mid: Remove unused leftovers (msic_power_btn)
  x86/platform/intel-mid: Remove unused leftovers (msic_gpio)
  x86/platform/intel-mid: Remove unused leftovers (msic_battery)
  x86/platform/intel-mid: Remove unused leftovers (msic_ocd)
  x86/platform/intel-mid: Remove unused leftovers (msic_audio)
  platform/x86: intel_scu_wdt: Drop mistakenly added const
parents e229b429 c9c26882
What: /sys/firmware/sfi/tables/
Date: May 2010
Contact: Len Brown <lenb@kernel.org>
Description:
SFI defines a number of small static memory tables
so the kernel can get platform information from firmware.
The tables are defined in the latest SFI specification:
http://simplefirmware.org/documentation
While the tables are used by the kernel, user-space
can observe them this way::
# cd /sys/firmware/sfi/tables
# cat $TABLENAME > $TABLENAME.bin
......@@ -7,7 +7,7 @@ Description:
is connected. example: "/dev/ttyS0".
The device name flows down to architecture specific board
initialization file from the SFI/ATAGS bootloader
initialization file from the ATAGS bootloader
firmware. The name exposed is read from the user-space
dameon and opens the device when install is requested.
......
......@@ -5990,12 +5990,6 @@
default x2apic cluster mode on platforms
supporting x2apic.
x86_intel_mid_timer= [X86-32,APBT]
Choose timer option for x86 Intel MID platform.
Two valid options are apbt timer only and lapic timer
plus one apbt timer for broadcast timer.
x86_intel_mid_timer=apbt_only | lapic_and_apbt
xen_512gb_limit [KNL,X86-64,XEN]
Restricts the kernel running paravirtualized under Xen
to use only up to 512 GB of RAM. The reason to do so is
......
......@@ -9122,9 +9122,7 @@ F: drivers/gpio/gpio-*cove.c
INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
M: Andy Shevchenko <andy@kernel.org>
S: Maintained
F: drivers/mfd/intel_msic.c
F: drivers/mfd/intel_soc_pmic*
F: include/linux/mfd/intel_msic.h
F: include/linux/mfd/intel_soc_pmic*
INTEL PMT DRIVER
......@@ -16322,13 +16320,6 @@ S: Maintained
F: Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
F: drivers/i3c/master/svc-i3c-master.c
SIMPLE FIRMWARE INTERFACE (SFI)
S: Obsolete
W: http://simplefirmware.org/
F: arch/x86/platform/sfi/
F: drivers/sfi/
F: include/linux/sfi*.h
SIMPLEFB FB DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-fbdev@vger.kernel.org
......
......@@ -448,7 +448,7 @@ config X86_X2APIC
If you don't know what to do here, say N.
config X86_MPPARSE
bool "Enable MPS table" if ACPI || SFI
bool "Enable MPS table" if ACPI
default y
depends on X86_LOCAL_APIC
help
......@@ -607,7 +607,6 @@ config X86_INTEL_MID
depends on PCI
depends on X86_64 || (PCI_GOANY && X86_32)
depends on X86_IO_APIC
select SFI
select I2C
select DW_APB_TIMER
select APB_TIMER
......@@ -896,18 +895,6 @@ config HPET_EMULATE_RTC
def_bool y
depends on HPET_TIMER && (RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
config APB_TIMER
def_bool y if X86_INTEL_MID
prompt "Intel MID APB Timer Support" if X86_INTEL_MID
select DW_APB_TIMER
depends on X86_INTEL_MID && SFI
help
APB timer is the replacement for 8254, HPET on X86 MID platforms.
The APBT provides a stable time base on SMP
systems, unlike the TSC, but it is more expensive to access,
as it is off-chip. APB timers are always running regardless of CPU
C states, they are used as per CPU clockevent device when possible.
# Mark as expert because too many people got it wrong.
# The code disables itself when not needed.
config DMI
......@@ -2469,8 +2456,6 @@ source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"
source "drivers/sfi/Kconfig"
config X86_APM_BOOT
def_bool y
depends on APM
......@@ -2657,7 +2642,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool "Support mmconfig PCI config space access" if X86_64
default y
depends on PCI && (ACPI || SFI || JAILHOUSE_GUEST)
depends on PCI && (ACPI || JAILHOUSE_GUEST)
depends on X86_64 || (PCI_GOANY || PCI_GOMMCONFIG)
config PCI_OLPC
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* apb_timer.h: Driver for Langwell APB timer based on Synopsis DesignWare
*
* (C) Copyright 2009 Intel Corporation
* Author: Jacob Pan (jacob.jun.pan@intel.com)
*
* Note:
*/
#ifndef ASM_X86_APBT_H
#define ASM_X86_APBT_H
#include <linux/sfi.h>
#ifdef CONFIG_APB_TIMER
/* default memory mapped register base */
#define LNW_SCU_ADDR 0xFF100000
#define LNW_EXT_TIMER_OFFSET 0x1B800
#define APBT_DEFAULT_BASE (LNW_SCU_ADDR+LNW_EXT_TIMER_OFFSET)
#define LNW_EXT_TIMER_PGOFFSET 0x800
/* APBT clock speed range from PCLK to fabric base, 25-100MHz */
#define APBT_MAX_FREQ 50000000
#define APBT_MIN_FREQ 1000000
#define APBT_MMAP_SIZE 1024
extern void apbt_time_init(void);
extern void apbt_setup_secondary_clock(void);
extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
extern int sfi_mtimer_num;
#else /* CONFIG_APB_TIMER */
static inline void apbt_time_init(void) { }
#endif
#endif /* ASM_X86_APBT_H */
......@@ -108,9 +108,6 @@ enum fixed_addresses {
#ifdef CONFIG_PARAVIRT_XXL
FIX_PARAVIRT_BOOTMAP,
#endif
#ifdef CONFIG_X86_INTEL_MID
FIX_LNW_VRTC,
#endif
#ifdef CONFIG_ACPI_APEI_GHES
/* Used for GHES mapping from assorted contexts */
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* intel-mid.h: Intel MID specific setup code
* Intel MID specific setup code
*
* (C) Copyright 2009 Intel Corporation
* (C) Copyright 2009, 2021 Intel Corporation
*/
#ifndef _ASM_X86_INTEL_MID_H
#define _ASM_X86_INTEL_MID_H
#include <linux/sfi.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
extern int intel_mid_pci_init(void);
extern int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
......@@ -22,93 +20,18 @@ extern void intel_mid_pwr_power_off(void);
extern int intel_mid_pwr_get_lss_id(struct pci_dev *pdev);
extern int get_gpio_by_name(const char *name);
extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
extern int __init sfi_parse_mtmr(struct sfi_table_header *table);
extern int sfi_mrtc_num;
extern struct sfi_rtc_table_entry sfi_mrtc_array[];
/*
* Here defines the array of devices platform data that IAFW would export
* through SFI "DEVS" table, we use name and type to match the device and
* its platform data.
*/
struct devs_id {
char name[SFI_NAME_LEN + 1];
u8 type;
u8 delay;
u8 msic;
void *(*get_platform_data)(void *info);
};
#define sfi_device(i) \
static const struct devs_id *const __intel_mid_sfi_##i##_dev __used \
__section(".x86_intel_mid_dev.init") = &i
/**
* struct mid_sd_board_info - template for SD device creation
* @name: identifies the driver
* @bus_num: board-specific identifier for a given SD controller
* @max_clk: the maximum frequency device supports
* @platform_data: the particular data stored there is driver-specific
*/
struct mid_sd_board_info {
char name[SFI_NAME_LEN];
int bus_num;
unsigned short addr;
u32 max_clk;
void *platform_data;
};
/*
* Medfield is the follow-up of Moorestown, it combines two chip solution into
* one. Other than that it also added always-on and constant tsc and lapic
* timers. Medfield is the platform name, and the chip name is called Penwell
* we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
* identified via MSRs.
*/
enum intel_mid_cpu_type {
/* 1 was Moorestown */
INTEL_MID_CPU_CHIP_PENWELL = 2,
INTEL_MID_CPU_CHIP_CLOVERVIEW,
INTEL_MID_CPU_CHIP_TANGIER,
};
extern enum intel_mid_cpu_type __intel_mid_cpu_chip;
#ifdef CONFIG_X86_INTEL_MID
static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void)
{
return __intel_mid_cpu_chip;
}
static inline bool intel_mid_has_msic(void)
{
return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL);
}
extern void intel_scu_devices_create(void);
extern void intel_scu_devices_destroy(void);
#else /* !CONFIG_X86_INTEL_MID */
#define intel_mid_identify_cpu() 0
#define intel_mid_has_msic() 0
static inline void intel_scu_devices_create(void) { }
static inline void intel_scu_devices_destroy(void) { }
#endif /* !CONFIG_X86_INTEL_MID */
enum intel_mid_timer_options {
INTEL_MID_TIMER_DEFAULT,
INTEL_MID_TIMER_APBT_ONLY,
INTEL_MID_TIMER_LAPIC_APBT,
};
extern enum intel_mid_timer_options intel_mid_timer_options;
/* Bus Select SoC Fuse value */
#define BSEL_SOC_FUSE_MASK 0x7
/* FSB 133MHz */
......@@ -118,16 +41,4 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
/* FSB 83MHz */
#define BSEL_SOC_FUSE_111 0x7
#define SFI_MTMR_MAX_NUM 8
#define SFI_MRTC_MAX 8
/* VRTC timer */
#define MRST_VRTC_MAP_SZ 1024
/* #define MRST_VRTC_PGOFFSET 0xc00 */
extern void intel_mid_rtc_init(void);
/* The offset for the mapping of global gpio pin to irq */
#define INTEL_MID_IRQ_OFFSET 0x100
#endif /* _ASM_X86_INTEL_MID_H */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _INTEL_MID_VRTC_H
#define _INTEL_MID_VRTC_H
extern unsigned char vrtc_cmos_read(unsigned char reg);
extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
extern void vrtc_get_time(struct timespec64 *now);
extern int vrtc_set_mmss(const struct timespec64 *now);
#endif
......@@ -65,6 +65,4 @@ static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int c
inlen, out, outlen);
}
#include <asm/intel_scu_ipc_legacy.h>
#endif
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_INTEL_SCU_IPC_LEGACY_H_
#define _ASM_X86_INTEL_SCU_IPC_LEGACY_H_
#include <linux/notifier.h>
#define IPCMSG_INDIRECT_READ 0x02
#define IPCMSG_INDIRECT_WRITE 0x05
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
#define IPCMSG_WARM_RESET 0xF0
#define IPCMSG_COLD_RESET 0xF1
#define IPCMSG_SOFT_RESET 0xF2
#define IPCMSG_COLD_BOOT 0xF3
#define IPCMSG_VRTC 0xFA /* Set vRTC device */
/* Command id associated with message IPCMSG_VRTC */
#define IPC_CMD_VRTC_SETTIME 1 /* Set time */
#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */
/* Don't call these in new code - they will be removed eventually */
/* Read single register */
static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data)
{
return intel_scu_ipc_dev_ioread8(NULL, addr, data);
}
/* Read a vector */
static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len)
{
return intel_scu_ipc_dev_readv(NULL, addr, data, len);
}
/* Write single register */
static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data)
{
return intel_scu_ipc_dev_iowrite8(NULL, addr, data);
}
/* Write a vector */
static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)
{
return intel_scu_ipc_dev_writev(NULL, addr, data, len);
}
/* Update single register based on the mask */
static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask)
{
return intel_scu_ipc_dev_update(NULL, addr, data, mask);
}
/* Issue commands to the SCU with or without data */
static inline int intel_scu_ipc_simple_command(int cmd, int sub)
{
return intel_scu_ipc_dev_simple_command(NULL, cmd, sub);
}
static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
u32 *out, int outlen)
{
/* New API takes both inlen and outlen as bytes so convert here */
size_t inbytes = inlen * sizeof(u32);
size_t outbytes = outlen * sizeof(u32);
return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes,
inlen, out, outbytes);
}
extern struct blocking_notifier_head intel_scu_notifier;
static inline void intel_scu_notifier_add(struct notifier_block *nb)
{
blocking_notifier_chain_register(&intel_scu_notifier, nb);
}
static inline void intel_scu_notifier_remove(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
}
static inline int intel_scu_notifier_post(unsigned long v, void *p)
{
return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
}
#define SCU_AVAILABLE 1
#define SCU_DOWN 2
#endif
......@@ -10,8 +10,6 @@
#ifndef _PLATFORM_SST_AUDIO_H_
#define _PLATFORM_SST_AUDIO_H_
#include <linux/sfi.h>
#define MAX_NUM_STREAMS_MRFLD 25
#define MAX_NUM_STREAMS MAX_NUM_STREAMS_MRFLD
......
......@@ -116,7 +116,6 @@ obj-$(CONFIG_VM86) += vm86_32.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_APB_TIMER) += apb_timer.o
obj-$(CONFIG_AMD_NB) += amd_nb.o
obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* apb_timer.c: Driver for Langwell APB timers
*
* (C) Copyright 2009 Intel Corporation
* Author: Jacob Pan (jacob.jun.pan@intel.com)
*
* Note:
* Langwell is the south complex of Intel Moorestown MID platform. There are
* eight external timers in total that can be used by the operating system.
* The timer information, such as frequency and addresses, is provided to the
* OS via SFI tables.
* Timer interrupts are routed via FW/HW emulated IOAPIC independently via
* individual redirection table entries (RTE).
* Unlike HPET, there is no master counter, therefore one of the timers are
* used as clocksource. The overall allocation looks like:
* - timer 0 - NR_CPUs for per cpu timer
* - one timer for clocksource
* - one timer for watchdog driver.
* It is also worth notice that APB timer does not support true one-shot mode,
* free-running mode will be used here to emulate one-shot mode.
* APB timer can also be used as broadcast timer along with per cpu local APIC
* timer, but by default APB timer has higher rating than local APIC timers.
*/
#include <linux/delay.h>
#include <linux/dw_apb_timer.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/sfi.h>
#include <linux/interrupt.h>
#include <linux/cpu.h>
#include <linux/irq.h>
#include <asm/fixmap.h>
#include <asm/apb_timer.h>
#include <asm/intel-mid.h>
#include <asm/time.h>
#define APBT_CLOCKEVENT_RATING 110
#define APBT_CLOCKSOURCE_RATING 250
#define APBT_CLOCKEVENT0_NUM (0)
#define APBT_CLOCKSOURCE_NUM (2)
static phys_addr_t apbt_address;
static int apb_timer_block_enabled;
static void __iomem *apbt_virt_address;
/*
* Common DW APB timer info
*/
static unsigned long apbt_freq;
struct apbt_dev {
struct dw_apb_clock_event_device *timer;
unsigned int num;
int cpu;
unsigned int irq;
char name[10];
};
static struct dw_apb_clocksource *clocksource_apbt;
static inline void __iomem *adev_virt_addr(struct apbt_dev *adev)
{
return apbt_virt_address + adev->num * APBTMRS_REG_SIZE;
}
static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
#ifdef CONFIG_SMP
static unsigned int apbt_num_timers_used;
#endif
static inline void apbt_set_mapping(void)
{
struct sfi_timer_table_entry *mtmr;
int phy_cs_timer_id = 0;
if (apbt_virt_address) {
pr_debug("APBT base already mapped\n");
return;
}
mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
if (mtmr == NULL) {
printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
APBT_CLOCKEVENT0_NUM);
return;
}
apbt_address = (phys_addr_t)mtmr->phys_addr;
if (!apbt_address) {
printk(KERN_WARNING "No timer base from SFI, use default\n");
apbt_address = APBT_DEFAULT_BASE;
}
apbt_virt_address = ioremap(apbt_address, APBT_MMAP_SIZE);
if (!apbt_virt_address) {
pr_debug("Failed mapping APBT phy address at %lu\n",\
(unsigned long)apbt_address);
goto panic_noapbt;
}
apbt_freq = mtmr->freq_hz;
sfi_free_mtmr(mtmr);
/* Now figure out the physical timer id for clocksource device */
mtmr = sfi_get_mtmr(APBT_CLOCKSOURCE_NUM);
if (mtmr == NULL)
goto panic_noapbt;
/* Now figure out the physical timer id */
pr_debug("Use timer %d for clocksource\n",
(int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE);
phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) /
APBTMRS_REG_SIZE;
clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING,
"apbt0", apbt_virt_address + phy_cs_timer_id *
APBTMRS_REG_SIZE, apbt_freq);
return;
panic_noapbt:
panic("Failed to setup APB system timer\n");
}
static inline void apbt_clear_mapping(void)
{
iounmap(apbt_virt_address);
apbt_virt_address = NULL;
}
static int __init apbt_clockevent_register(void)
{
struct sfi_timer_table_entry *mtmr;
struct apbt_dev *adev = this_cpu_ptr(&cpu_apbt_dev);
mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
if (mtmr == NULL) {
printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
APBT_CLOCKEVENT0_NUM);
return -ENODEV;
}
adev->num = smp_processor_id();
adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ?
APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
adev_virt_addr(adev), 0, apbt_freq);
/* Firmware does EOI handling for us. */
adev->timer->eoi = NULL;
if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
global_clock_event = &adev->timer->ced;
printk(KERN_DEBUG "%s clockevent registered as global\n",
global_clock_event->name);
}
dw_apb_clockevent_register(adev->timer);
sfi_free_mtmr(mtmr);
return 0;
}
#ifdef CONFIG_SMP
static void apbt_setup_irq(struct apbt_dev *adev)
{
irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
}
/* Should be called with per cpu */
void apbt_setup_secondary_clock(void)
{
struct apbt_dev *adev;
int cpu;
/* Don't register boot CPU clockevent */
cpu = smp_processor_id();
if (!cpu)
return;
adev = this_cpu_ptr(&cpu_apbt_dev);
if (!adev->timer) {
adev->timer = dw_apb_clockevent_init(cpu, adev->name,
APBT_CLOCKEVENT_RATING, adev_virt_addr(adev),
adev->irq, apbt_freq);
adev->timer->eoi = NULL;
} else {
dw_apb_clockevent_resume(adev->timer);
}
printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n",
cpu, adev->name, adev->cpu);
apbt_setup_irq(adev);
dw_apb_clockevent_register(adev->timer);
return;
}
/*
* this notify handler process CPU hotplug events. in case of S0i3, nonboot
* cpus are disabled/enabled frequently, for performance reasons, we keep the
* per cpu timer irq registered so that we do need to do free_irq/request_irq.
*
* TODO: it might be more reliable to directly disable percpu clockevent device
* without the notifier chain. currently, cpu 0 may get interrupts from other
* cpu timers during the offline process due to the ordering of notification.
* the extra interrupt is harmless.
*/
static int apbt_cpu_dead(unsigned int cpu)
{
struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu);
dw_apb_clockevent_pause(adev->timer);
if (system_state == SYSTEM_RUNNING) {
pr_debug("skipping APBT CPU %u offline\n", cpu);
} else {
pr_debug("APBT clockevent for cpu %u offline\n", cpu);
dw_apb_clockevent_stop(adev->timer);
}
return 0;
}
static __init int apbt_late_init(void)
{
if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||
!apb_timer_block_enabled)
return 0;
return cpuhp_setup_state(CPUHP_X86_APB_DEAD, "x86/apb:dead", NULL,
apbt_cpu_dead);
}
fs_initcall(apbt_late_init);
#else
void apbt_setup_secondary_clock(void) {}
#endif /* CONFIG_SMP */
static int apbt_clocksource_register(void)
{
u64 start, now;
u64 t1;
/* Start the counter, use timer 2 as source, timer 0/1 for event */
dw_apb_clocksource_start(clocksource_apbt);
/* Verify whether apbt counter works */
t1 = dw_apb_clocksource_read(clocksource_apbt);
start = rdtsc();
/*
* We don't know the TSC frequency yet, but waiting for
* 200000 TSC cycles is safe:
* 4 GHz == 50us
* 1 GHz == 200us
*/
do {
rep_nop();
now = rdtsc();
} while ((now - start) < 200000UL);
/* APBT is the only always on clocksource, it has to work! */
if (t1 == dw_apb_clocksource_read(clocksource_apbt))
panic("APBT counter not counting. APBT disabled\n");
dw_apb_clocksource_register(clocksource_apbt);
return 0;
}
/*
* Early setup the APBT timer, only use timer 0 for booting then switch to
* per CPU timer if possible.
* returns 1 if per cpu apbt is setup
* returns 0 if no per cpu apbt is chosen
* panic if set up failed, this is the only platform timer on Moorestown.
*/
void __init apbt_time_init(void)
{
#ifdef CONFIG_SMP
int i;
struct sfi_timer_table_entry *p_mtmr;
struct apbt_dev *adev;
#endif
if (apb_timer_block_enabled)
return;
apbt_set_mapping();
if (!apbt_virt_address)
goto out_noapbt;
/*
* Read the frequency and check for a sane value, for ESL model
* we extend the possible clock range to allow time scaling.
*/
if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq);
goto out_noapbt;
}
if (apbt_clocksource_register()) {
pr_debug("APBT has failed to register clocksource\n");
goto out_noapbt;
}
if (!apbt_clockevent_register())
apb_timer_block_enabled = 1;
else {
pr_debug("APBT has failed to register clockevent\n");
goto out_noapbt;
}
#ifdef CONFIG_SMP
/* kernel cmdline disable apb timer, so we will use lapic timers */
if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
printk(KERN_INFO "apbt: disabled per cpu timer\n");
return;
}
pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus());
if (num_possible_cpus() <= sfi_mtimer_num)
apbt_num_timers_used = num_possible_cpus();
else
apbt_num_timers_used = 1;
pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
/* here we set up per CPU timer data structure */
for (i = 0; i < apbt_num_timers_used; i++) {
adev = &per_cpu(cpu_apbt_dev, i);
adev->num = i;
adev->cpu = i;
p_mtmr = sfi_get_mtmr(i);
if (p_mtmr)
adev->irq = p_mtmr->irq;
else
printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i);
}
#endif
return;
out_noapbt:
apbt_clear_mapping();
apb_timer_block_enabled = 0;
panic("failed to enable APB timer\n");
}
......@@ -198,7 +198,7 @@ static int __init parse_noapic(char *str)
}
early_param("noapic", parse_noapic);
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
/* Will be called in mpparse/ACPI codes for saving IRQ info */
void mp_save_irq(struct mpc_intsrc *m)
{
int i;
......@@ -2863,7 +2863,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
/*
* If mp_register_ioapic() is called during early boot stage when
* walking ACPI/SFI/DT tables, it's too early to create irqdomain,
* walking ACPI/DT tables, it's too early to create irqdomain,
* we are still using bootmem allocator. So delay it to setup_IO_APIC().
*/
if (hotplug) {
......
......@@ -16,7 +16,6 @@
#include <linux/memblock.h>
#include <linux/pci.h>
#include <linux/root_dev.h>
#include <linux/sfi.h>
#include <linux/hugetlb.h>
#include <linux/tboot.h>
#include <linux/usb/xhci-dbgp.h>
......@@ -1185,7 +1184,6 @@ void __init setup_arch(char **cmdline_p)
* Read APIC and some other early information from ACPI tables.
*/
acpi_boot_init();
sfi_init();
x86_dtb_init();
/*
......
......@@ -28,10 +28,12 @@
#include <linux/io.h>
#include <linux/smp.h>
#include <asm/cpu_device_id.h>
#include <asm/segment.h>
#include <asm/pci_x86.h>
#include <asm/hw_irq.h>
#include <asm/io_apic.h>
#include <asm/intel-family.h>
#include <asm/intel-mid.h>
#include <asm/acpi.h>
......@@ -140,6 +142,7 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
* type1_access_ok - check whether to use type 1
* @bus: bus number
* @devfn: device & function in question
* @reg: configuration register offset
*
* If the bus is on a Lincroft chip and it exists, or is not on a Lincroft at
* all, the we can go ahead with any reads & writes. If it's on a Lincroft,
......@@ -212,10 +215,17 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
where, size, value);
}
static const struct x86_cpu_id intel_mid_cpu_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, NULL),
{}
};
static int intel_mid_pci_irq_enable(struct pci_dev *dev)
{
const struct x86_cpu_id *id;
struct irq_alloc_info info;
bool polarity_low;
u16 model = 0;
int ret;
u8 gsi;
......@@ -228,8 +238,12 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
return ret;
}
switch (intel_mid_identify_cpu()) {
case INTEL_MID_CPU_CHIP_TANGIER:
id = x86_match_cpu(intel_mid_cpu_ids);
if (id)
model = id->model;
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT_MID:
polarity_low = false;
/* Special treatment for IRQ0 */
......
......@@ -11,9 +11,9 @@
* themselves.
*/
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/sfi_acpi.h>
#include <linux/bitmap.h>
#include <linux/dmi.h>
#include <linux/slab.h>
......@@ -665,7 +665,7 @@ void __init pci_mmcfg_early_init(void)
if (pci_mmcfg_check_hostbridge())
known_bridge = 1;
else
acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
__pci_mmcfg_init(1);
set_apei_filter();
......@@ -683,7 +683,7 @@ void __init pci_mmcfg_late_init(void)
/* MMCONFIG hasn't been enabled yet, try again */
if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) {
acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
__pci_mmcfg_init(0);
}
}
......
......@@ -10,6 +10,5 @@ obj-y += intel-mid/
obj-y += intel-quark/
obj-y += olpc/
obj-y += scx200/
obj-y += sfi/
obj-y += ts5500/
obj-y += uv/
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o pwr.o
# SFI specific code
ifdef CONFIG_X86_INTEL_MID
obj-$(CONFIG_SFI) += sfi.o device_libs/
endif
obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o pwr.o
# SPDX-License-Identifier: GPL-2.0
# Family-Level Interface Shim (FLIS)
obj-$(subst m,y,$(CONFIG_PINCTRL_MERRIFIELD)) += platform_mrfld_pinctrl.o
# SDHCI Devices
obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += platform_mrfld_sd.o
# WiFi + BT
obj-$(subst m,y,$(CONFIG_BRCMFMAC_SDIO)) += platform_bcm43xx.o
obj-$(subst m,y,$(CONFIG_BT_HCIUART_BCM)) += platform_bt.o
# IPC Devices
obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o
obj-$(subst m,y,$(CONFIG_SND_MFLD_MACHINE)) += platform_msic_audio.o
obj-$(subst m,y,$(CONFIG_GPIO_MSIC)) += platform_msic_gpio.o
obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_ocd.o
obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_battery.o
obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
# SPI Devices
obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o
# I2C Devices
obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
obj-$(subst m,y,$(CONFIG_MPU3050_I2C)) += platform_mpu3050.o
obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o
obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o
# I2C GPIO Expanders
obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_max7315.o
obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_pcal9555a.o
obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o
# MISC Devices
obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o
obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_mrfld_power_btn.o
obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_bcm43xx.c: bcm43xx platform data initialization file
*
* (C) Copyright 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/sfi.h>
#include <asm/intel-mid.h>
#define WLAN_SFI_GPIO_IRQ_NAME "WLAN-interrupt"
#define WLAN_SFI_GPIO_ENABLE_NAME "WLAN-enable"
#define WLAN_DEV_NAME "0000:00:01.3"
static struct regulator_consumer_supply bcm43xx_vmmc_supply = {
.dev_name = WLAN_DEV_NAME,
.supply = "vmmc",
};
static struct regulator_init_data bcm43xx_vmmc_data = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &bcm43xx_vmmc_supply,
};
static struct fixed_voltage_config bcm43xx_vmmc = {
.supply_name = "bcm43xx-vmmc-regulator",
/*
* Announce 2.0V here to be compatible with SDIO specification. The
* real voltage and signaling are still 1.8V.
*/
.microvolts = 2000000, /* 1.8V */
.startup_delay = 250 * 1000, /* 250ms */
.enabled_at_boot = 0, /* disabled at boot */
.init_data = &bcm43xx_vmmc_data,
};
static struct platform_device bcm43xx_vmmc_regulator = {
.name = "reg-fixed-voltage",
.id = PLATFORM_DEVID_AUTO,
.dev = {
.platform_data = &bcm43xx_vmmc,
},
};
static struct gpiod_lookup_table bcm43xx_vmmc_gpio_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("0000:00:0c.0", -1, NULL, GPIO_ACTIVE_LOW),
{}
},
};
static int __init bcm43xx_regulator_register(void)
{
struct gpiod_lookup_table *table = &bcm43xx_vmmc_gpio_table;
struct gpiod_lookup *lookup = table->table;
int ret;
lookup[0].chip_hwnum = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);
gpiod_add_lookup_table(table);
ret = platform_device_register(&bcm43xx_vmmc_regulator);
if (ret) {
pr_err("%s: vmmc regulator register failed\n", __func__);
return ret;
}
return 0;
}
static void __init *bcm43xx_platform_data(void *info)
{
int ret;
ret = bcm43xx_regulator_register();
if (ret)
return NULL;
pr_info("Using generic wifi platform data\n");
/* For now it's empty */
return NULL;
}
static const struct devs_id bcm43xx_clk_vmmc_dev_id __initconst = {
.name = "bcm43xx_clk_vmmc",
.type = SFI_DEV_TYPE_SD,
.get_platform_data = &bcm43xx_platform_data,
};
sfi_device(bcm43xx_clk_vmmc_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_bma023.c: bma023 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
*/
#include <asm/intel-mid.h>
static const struct devs_id bma023_dev_id __initconst = {
.name = "bma023",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
};
sfi_device(bma023_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* Bluetooth platform data initialization file
*
* (C) Copyright 2017 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/gpio/machine.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/intel-mid.h>
struct bt_sfi_data {
struct device *dev;
const char *name;
int (*setup)(struct bt_sfi_data *ddata);
};
static struct gpiod_lookup_table tng_bt_sfi_gpio_table = {
.dev_id = "hci_bcm",
.table = {
GPIO_LOOKUP("0000:00:0c.0", -1, "device-wakeup", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "shutdown", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "host-wakeup", GPIO_ACTIVE_HIGH),
{ },
},
};
#define TNG_BT_SFI_GPIO_DEVICE_WAKEUP "bt_wakeup"
#define TNG_BT_SFI_GPIO_SHUTDOWN "BT-reset"
#define TNG_BT_SFI_GPIO_HOST_WAKEUP "bt_uart_enable"
static int __init tng_bt_sfi_setup(struct bt_sfi_data *ddata)
{
struct gpiod_lookup_table *table = &tng_bt_sfi_gpio_table;
struct gpiod_lookup *lookup = table->table;
struct pci_dev *pdev;
/* Connected to /dev/ttyS0 */
pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(4, 1));
if (!pdev)
return -ENODEV;
ddata->dev = &pdev->dev;
ddata->name = table->dev_id;
lookup[0].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_DEVICE_WAKEUP);
lookup[1].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_SHUTDOWN);
lookup[2].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_HOST_WAKEUP);
gpiod_add_lookup_table(table);
return 0;
}
static struct bt_sfi_data tng_bt_sfi_data __initdata = {
.setup = tng_bt_sfi_setup,
};
static const struct x86_cpu_id bt_sfi_cpu_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tng_bt_sfi_data),
{}
};
static int __init bt_sfi_init(void)
{
struct platform_device_info info;
struct platform_device *pdev;
const struct x86_cpu_id *id;
struct bt_sfi_data *ddata;
int ret;
id = x86_match_cpu(bt_sfi_cpu_ids);
if (!id)
return -ENODEV;
ddata = (struct bt_sfi_data *)id->driver_data;
if (!ddata)
return -ENODEV;
ret = ddata->setup(ddata);
if (ret)
return ret;
memset(&info, 0, sizeof(info));
info.fwnode = ddata->dev->fwnode;
info.parent = ddata->dev;
info.name = ddata->name;
info.id = PLATFORM_DEVID_NONE;
pdev = platform_device_register_full(&info);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
dev_info(ddata->dev, "Registered Bluetooth device: %s\n", ddata->name);
return 0;
}
device_initcall(bt_sfi_init);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_emc1403.c: emc1403 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <asm/intel-mid.h>
static void __init *emc1403_platform_data(void *info)
{
static short intr2nd_pdata;
struct i2c_board_info *i2c_info = info;
int intr = get_gpio_by_name("thermal_int");
int intr2nd = get_gpio_by_name("thermal_alert");
if (intr < 0)
return NULL;
if (intr2nd < 0)
return NULL;
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
return &intr2nd_pdata;
}
static const struct devs_id emc1403_dev_id __initconst = {
.name = "emc1403",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &emc1403_platform_data,
};
sfi_device(emc1403_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_gpio_keys.c: gpio_keys platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/input.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/platform_device.h>
#include <asm/intel-mid.h>
#define DEVICE_NAME "gpio-keys"
/*
* we will search these buttons in SFI GPIO table (by name)
* and register them dynamically. Please add all possible
* buttons here, we will shrink them if no GPIO found.
*/
static struct gpio_keys_button gpio_button[] = {
{KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000},
{KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20},
{KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20},
{SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20},
{KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20},
{KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20},
{KEY_MUTE, -1, 1, "mute_enable", EV_KEY, 0, 20},
{KEY_VOLUMEUP, -1, 1, "volume_up", EV_KEY, 0, 20},
{KEY_VOLUMEDOWN, -1, 1, "volume_down", EV_KEY, 0, 20},
{KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20},
{KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20},
{SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20},
{SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20},
};
static struct gpio_keys_platform_data gpio_keys = {
.buttons = gpio_button,
.rep = 1,
.nbuttons = -1, /* will fill it after search */
};
static struct platform_device pb_device = {
.name = DEVICE_NAME,
.id = -1,
.dev = {
.platform_data = &gpio_keys,
},
};
/*
* Shrink the non-existent buttons, register the gpio button
* device if there is some
*/
static int __init pb_keys_init(void)
{
struct gpio_keys_button *gb = gpio_button;
int i, good = 0;
for (i = 0; i < ARRAY_SIZE(gpio_button); i++) {
gb[i].gpio = get_gpio_by_name(gb[i].desc);
pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc,
gb[i].gpio);
if (gb[i].gpio < 0)
continue;
if (i != good)
gb[good] = gb[i];
good++;
}
if (good) {
gpio_keys.nbuttons = good;
return platform_device_register(&pb_device);
}
return 0;
}
late_initcall(pb_keys_init);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_lis331.c: lis331 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <asm/intel-mid.h>
static void __init *lis331dl_platform_data(void *info)
{
static short intr2nd_pdata;
struct i2c_board_info *i2c_info = info;
int intr = get_gpio_by_name("accel_int");
int intr2nd = get_gpio_by_name("accel_2");
if (intr < 0)
return NULL;
if (intr2nd < 0)
return NULL;
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
return &intr2nd_pdata;
}
static const struct devs_id lis331dl_dev_id __initconst = {
.name = "i2c_accel",
.type = SFI_DEV_TYPE_I2C,
.get_platform_data = &lis331dl_platform_data,
};
sfi_device(lis331dl_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_max7315.c: max7315 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
#include <asm/intel-mid.h>
#define MAX7315_NUM 2
static void __init *max7315_platform_data(void *info)
{
static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
static int nr;
struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
struct i2c_board_info *i2c_info = info;
int gpio_base, intr;
char base_pin_name[SFI_NAME_LEN + 1];
char intr_pin_name[SFI_NAME_LEN + 1];
if (nr == MAX7315_NUM) {
pr_err("too many max7315s, we only support %d\n",
MAX7315_NUM);
return NULL;
}
/* we have several max7315 on the board, we only need load several
* instances of the same pca953x driver to cover them
*/
strcpy(i2c_info->type, "max7315");
if (nr++) {
snprintf(base_pin_name, sizeof(base_pin_name),
"max7315_%d_base", nr);
snprintf(intr_pin_name, sizeof(intr_pin_name),
"max7315_%d_int", nr);
} else {
strcpy(base_pin_name, "max7315_base");
strcpy(intr_pin_name, "max7315_int");
}
gpio_base = get_gpio_by_name(base_pin_name);
intr = get_gpio_by_name(intr_pin_name);
if (gpio_base < 0)
return NULL;
max7315->gpio_base = gpio_base;
if (intr != -1) {
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
} else {
i2c_info->irq = -1;
max7315->irq_base = -1;
}
return max7315;
}
static const struct devs_id max7315_dev_id __initconst = {
.name = "i2c_max7315",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &max7315_platform_data,
};
static const struct devs_id max7315_2_dev_id __initconst = {
.name = "i2c_max7315_2",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &max7315_platform_data,
};
sfi_device(max7315_dev_id);
sfi_device(max7315_2_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_mpu3050.c: mpu3050 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <asm/intel-mid.h>
static void *mpu3050_platform_data(void *info)
{
struct i2c_board_info *i2c_info = info;
int intr = get_gpio_by_name("mpu3050_int");
if (intr < 0)
return NULL;
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
return NULL;
}
static const struct devs_id mpu3050_dev_id __initconst = {
.name = "mpu3050",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &mpu3050_platform_data,
};
sfi_device(mpu3050_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel Merrifield FLIS platform device initialization file
*
* Copyright (C) 2016, Intel Corporation
*
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <asm/intel-mid.h>
#define FLIS_BASE_ADDR 0xff0c0000
#define FLIS_LENGTH 0x8000
static struct resource mrfld_pinctrl_mmio_resource = {
.start = FLIS_BASE_ADDR,
.end = FLIS_BASE_ADDR + FLIS_LENGTH - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device mrfld_pinctrl_device = {
.name = "pinctrl-merrifield",
.id = PLATFORM_DEVID_NONE,
.resource = &mrfld_pinctrl_mmio_resource,
.num_resources = 1,
};
static int __init mrfld_pinctrl_init(void)
{
if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
return platform_device_register(&mrfld_pinctrl_device);
return -ENODEV;
}
arch_initcall(mrfld_pinctrl_init);
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel Merrifield power button support
*
* (C) Copyright 2017 Intel Corporation
*
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/sfi.h>
#include <asm/intel-mid.h>
#include <asm/intel_scu_ipc.h>
static struct resource mrfld_power_btn_resources[] = {
{
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device mrfld_power_btn_dev = {
.name = "msic_power_btn",
.id = PLATFORM_DEVID_NONE,
.num_resources = ARRAY_SIZE(mrfld_power_btn_resources),
.resource = mrfld_power_btn_resources,
};
static int mrfld_power_btn_scu_status_change(struct notifier_block *nb,
unsigned long code, void *data)
{
if (code == SCU_DOWN) {
platform_device_unregister(&mrfld_power_btn_dev);
return 0;
}
return platform_device_register(&mrfld_power_btn_dev);
}
static struct notifier_block mrfld_power_btn_scu_notifier = {
.notifier_call = mrfld_power_btn_scu_status_change,
};
static int __init register_mrfld_power_btn(void)
{
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
return -ENODEV;
/*
* We need to be sure that the SCU IPC is ready before
* PMIC power button device can be registered:
*/
intel_scu_notifier_add(&mrfld_power_btn_scu_notifier);
return 0;
}
arch_initcall(register_mrfld_power_btn);
static void __init *mrfld_power_btn_platform_data(void *info)
{
struct resource *res = mrfld_power_btn_resources;
struct sfi_device_table_entry *pentry = info;
res->start = res->end = pentry->irq;
return NULL;
}
static const struct devs_id mrfld_power_btn_dev_id __initconst = {
.name = "bcove_power_btn",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &mrfld_power_btn_platform_data,
};
sfi_device(mrfld_power_btn_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel Merrifield legacy RTC initialization file
*
* (C) Copyright 2017 Intel Corporation
*
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/init.h>
#include <asm/hw_irq.h>
#include <asm/intel-mid.h>
#include <asm/io_apic.h>
#include <asm/time.h>
#include <asm/x86_init.h>
static int __init mrfld_legacy_rtc_alloc_irq(void)
{
struct irq_alloc_info info;
int ret;
if (!x86_platform.legacy.rtc)
return -ENODEV;
ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, 0);
ret = mp_map_gsi_to_irq(RTC_IRQ, IOAPIC_MAP_ALLOC, &info);
if (ret < 0) {
pr_info("Failed to allocate RTC interrupt. Disabling RTC\n");
x86_platform.legacy.rtc = 0;
return ret;
}
return 0;
}
static int __init mrfld_legacy_rtc_init(void)
{
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
return -ENODEV;
return mrfld_legacy_rtc_alloc_irq();
}
arch_initcall(mrfld_legacy_rtc_init);
// SPDX-License-Identifier: GPL-2.0-only
/*
* SDHCI platform data initilisation file
*
* (C) Copyright 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/mmc/sdhci-pci-data.h>
#include <asm/intel-mid.h>
#define INTEL_MRFLD_SD 2
#define INTEL_MRFLD_SD_CD_GPIO 77
static struct sdhci_pci_data mrfld_sdhci_pci_data = {
.rst_n_gpio = -EINVAL,
.cd_gpio = INTEL_MRFLD_SD_CD_GPIO,
};
static struct sdhci_pci_data *
mrfld_sdhci_pci_get_data(struct pci_dev *pdev, int slotno)
{
unsigned int func = PCI_FUNC(pdev->devfn);
if (func == INTEL_MRFLD_SD)
return &mrfld_sdhci_pci_data;
return NULL;
}
static int __init mrfld_sd_init(void)
{
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
return -ENODEV;
sdhci_pci_get_data = mrfld_sdhci_pci_get_data;
return 0;
}
arch_initcall(mrfld_sd_init);
// SPDX-License-Identifier: GPL-2.0-only
/*
* spidev platform data initialization file
*
* (C) Copyright 2014, 2016 Intel Corporation
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Dan O'Donovan <dan@emutex.com>
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/spi.h>
#include <asm/intel-mid.h>
#define MRFLD_SPI_DEFAULT_DMA_BURST 8
#define MRFLD_SPI_DEFAULT_TIMEOUT 500
/* GPIO pin for spidev chipselect */
#define MRFLD_SPIDEV_GPIO_CS 111
static struct pxa2xx_spi_chip spidev_spi_chip = {
.dma_burst_size = MRFLD_SPI_DEFAULT_DMA_BURST,
.timeout = MRFLD_SPI_DEFAULT_TIMEOUT,
.gpio_cs = MRFLD_SPIDEV_GPIO_CS,
};
static void __init *spidev_platform_data(void *info)
{
struct spi_board_info *spi_info = info;
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
return ERR_PTR(-ENODEV);
spi_info->mode = SPI_MODE_0;
spi_info->controller_data = &spidev_spi_chip;
return NULL;
}
static const struct devs_id spidev_dev_id __initconst = {
.name = "spidev",
.type = SFI_DEV_TYPE_SPI,
.delay = 0,
.get_platform_data = &spidev_platform_data,
};
sfi_device(spidev_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic.c: MSIC platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel_scu_ipc.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
struct intel_msic_platform_data msic_pdata;
static struct resource msic_resources[] = {
{
.start = INTEL_MSIC_IRQ_PHYS_BASE,
.end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device msic_device = {
.name = "intel_msic",
.id = -1,
.dev = {
.platform_data = &msic_pdata,
},
.num_resources = ARRAY_SIZE(msic_resources),
.resource = msic_resources,
};
static int msic_scu_status_change(struct notifier_block *nb,
unsigned long code, void *data)
{
if (code == SCU_DOWN) {
platform_device_unregister(&msic_device);
return 0;
}
return platform_device_register(&msic_device);
}
static int __init msic_init(void)
{
static struct notifier_block msic_scu_notifier = {
.notifier_call = msic_scu_status_change,
};
/*
* We need to be sure that the SCU IPC is ready before MSIC device
* can be registered.
*/
if (intel_mid_has_msic())
intel_scu_notifier_add(&msic_scu_notifier);
return 0;
}
arch_initcall(msic_init);
/*
* msic_generic_platform_data - sets generic platform data for the block
* @info: pointer to the SFI device table entry for this block
* @block: MSIC block
*
* Function sets IRQ number from the SFI table entry for given device to
* the MSIC platform data.
*/
void *msic_generic_platform_data(void *info, enum intel_msic_block block)
{
struct sfi_device_table_entry *entry = info;
BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
msic_pdata.irq[block] = entry->irq;
return NULL;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* platform_msic.h: MSIC platform data header file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#ifndef _PLATFORM_MSIC_H_
#define _PLATFORM_MSIC_H_
extern struct intel_msic_platform_data msic_pdata;
void *msic_generic_platform_data(void *info, enum intel_msic_block block);
#endif
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_audio.c: MSIC audio platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/platform_device.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void *msic_audio_platform_data(void *info)
{
struct platform_device *pdev;
pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
if (IS_ERR(pdev)) {
pr_err("failed to create audio platform device\n");
return NULL;
}
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
}
static const struct devs_id msic_audio_dev_id __initconst = {
.name = "msic_audio",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_audio_platform_data,
};
sfi_device(msic_audio_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_battery.c: MSIC battery platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void __init *msic_battery_platform_data(void *info)
{
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
}
static const struct devs_id msic_battery_dev_id __initconst = {
.name = "msic_battery",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_battery_platform_data,
};
sfi_device(msic_battery_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_gpio.c: MSIC GPIO platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/sfi.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void __init *msic_gpio_platform_data(void *info)
{
static struct intel_msic_gpio_pdata msic_gpio_pdata;
int gpio = get_gpio_by_name("msic_gpio_base");
if (gpio < 0)
return NULL;
msic_gpio_pdata.gpio_base = gpio;
msic_pdata.gpio = &msic_gpio_pdata;
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
}
static const struct devs_id msic_gpio_dev_id __initconst = {
.name = "msic_gpio",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_gpio_platform_data,
};
sfi_device(msic_gpio_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_ocd.c: MSIC OCD platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/sfi.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void __init *msic_ocd_platform_data(void *info)
{
static struct intel_msic_ocd_pdata msic_ocd_pdata;
int gpio;
gpio = get_gpio_by_name("ocd_gpio");
if (gpio < 0)
return NULL;
msic_ocd_pdata.gpio = gpio;
msic_pdata.ocd = &msic_ocd_pdata;
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
}
static const struct devs_id msic_ocd_dev_id __initconst = {
.name = "msic_ocd",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_ocd_platform_data,
};
sfi_device(msic_ocd_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_power_btn.c: MSIC power btn platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/scatterlist.h>
#include <linux/sfi.h>
#include <linux/init.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void __init *msic_power_btn_platform_data(void *info)
{
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
}
static const struct devs_id msic_power_btn_dev_id __initconst = {
.name = "msic_power_btn",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_power_btn_platform_data,
};
sfi_device(msic_power_btn_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_msic_thermal.c: msic_thermal platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/input.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/mfd/intel_msic.h>
#include <asm/intel-mid.h>
#include "platform_msic.h"
static void __init *msic_thermal_platform_data(void *info)
{
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
}
static const struct devs_id msic_thermal_dev_id __initconst = {
.name = "msic_thermal",
.type = SFI_DEV_TYPE_IPC,
.delay = 1,
.msic = 1,
.get_platform_data = &msic_thermal_platform_data,
};
sfi_device(msic_thermal_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* PCAL9555a platform data initialization file
*
* Copyright (C) 2016, Intel Corporation
*
* Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Dan O'Donovan <dan@emutex.com>
*/
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
#include <linux/sfi.h>
#include <asm/intel-mid.h>
#define PCAL9555A_NUM 4
static struct pca953x_platform_data pcal9555a_pdata[PCAL9555A_NUM];
static int nr;
static void __init *pcal9555a_platform_data(void *info)
{
struct i2c_board_info *i2c_info = info;
char *type = i2c_info->type;
struct pca953x_platform_data *pcal9555a;
char base_pin_name[SFI_NAME_LEN + 1];
char intr_pin_name[SFI_NAME_LEN + 1];
int gpio_base, intr;
snprintf(base_pin_name, sizeof(base_pin_name), "%s_base", type);
snprintf(intr_pin_name, sizeof(intr_pin_name), "%s_int", type);
gpio_base = get_gpio_by_name(base_pin_name);
intr = get_gpio_by_name(intr_pin_name);
/* Check if the SFI record valid */
if (gpio_base == -1)
return NULL;
if (nr >= PCAL9555A_NUM) {
pr_err("%s: Too many instances, only %d supported\n", __func__,
PCAL9555A_NUM);
return NULL;
}
pcal9555a = &pcal9555a_pdata[nr++];
pcal9555a->gpio_base = gpio_base;
if (intr >= 0) {
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
pcal9555a->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
} else {
i2c_info->irq = -1;
pcal9555a->irq_base = -1;
}
strcpy(type, "pcal9555a");
return pcal9555a;
}
static const struct devs_id pcal9555a_1_dev_id __initconst = {
.name = "pcal9555a-1",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &pcal9555a_platform_data,
};
static const struct devs_id pcal9555a_2_dev_id __initconst = {
.name = "pcal9555a-2",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &pcal9555a_platform_data,
};
static const struct devs_id pcal9555a_3_dev_id __initconst = {
.name = "pcal9555a-3",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &pcal9555a_platform_data,
};
static const struct devs_id pcal9555a_4_dev_id __initconst = {
.name = "pcal9555a-4",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &pcal9555a_platform_data,
};
sfi_device(pcal9555a_1_dev_id);
sfi_device(pcal9555a_2_dev_id);
sfi_device(pcal9555a_3_dev_id);
sfi_device(pcal9555a_4_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_tc35876x.c: tc35876x platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/gpio/machine.h>
#include <asm/intel-mid.h>
static struct gpiod_lookup_table tc35876x_gpio_table = {
.dev_id = "i2c_disp_brig",
.table = {
GPIO_LOOKUP("0000:00:0c.0", -1, "bridge-reset", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "bl-en", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "vadd", GPIO_ACTIVE_HIGH),
{ },
},
};
/*tc35876x DSI_LVDS bridge chip and panel platform data*/
static void *tc35876x_platform_data(void *data)
{
struct gpiod_lookup_table *table = &tc35876x_gpio_table;
struct gpiod_lookup *lookup = table->table;
lookup[0].chip_hwnum = get_gpio_by_name("LCMB_RXEN");
lookup[1].chip_hwnum = get_gpio_by_name("6S6P_BL_EN");
lookup[2].chip_hwnum = get_gpio_by_name("EN_VREG_LCD_V3P3");
gpiod_add_lookup_table(table);
return NULL;
}
static const struct devs_id tc35876x_dev_id __initconst = {
.name = "i2c_disp_brig",
.type = SFI_DEV_TYPE_I2C,
.get_platform_data = &tc35876x_platform_data,
};
sfi_device(tc35876x_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* platform_tca6416.c: tca6416 platform data initialization file
*
* (C) Copyright 2013 Intel Corporation
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
#include <linux/platform_data/pca953x.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <asm/intel-mid.h>
#define TCA6416_NAME "tca6416"
#define TCA6416_BASE "tca6416_base"
#define TCA6416_INTR "tca6416_int"
static void *tca6416_platform_data(void *info)
{
static struct pca953x_platform_data tca6416;
struct i2c_board_info *i2c_info = info;
int gpio_base, intr;
char base_pin_name[SFI_NAME_LEN + 1];
char intr_pin_name[SFI_NAME_LEN + 1];
strcpy(i2c_info->type, TCA6416_NAME);
strcpy(base_pin_name, TCA6416_BASE);
strcpy(intr_pin_name, TCA6416_INTR);
gpio_base = get_gpio_by_name(base_pin_name);
intr = get_gpio_by_name(intr_pin_name);
if (gpio_base < 0)
return NULL;
tca6416.gpio_base = gpio_base;
if (intr >= 0) {
i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
} else {
i2c_info->irq = -1;
tca6416.irq_base = -1;
}
return &tca6416;
}
static const struct devs_id tca6416_dev_id __initconst = {
.name = "tca6416",
.type = SFI_DEV_TYPE_I2C,
.delay = 1,
.get_platform_data = &tca6416_platform_data,
};
sfi_device(tca6416_dev_id);
// SPDX-License-Identifier: GPL-2.0-only
/*
* intel-mid.c: Intel MID platform setup code
* Intel MID platform setup code
*
* (C) Copyright 2008, 2012 Intel Corporation
* (C) Copyright 2008, 2012, 2021 Intel Corporation
* Author: Jacob Pan (jacob.jun.pan@intel.com)
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/
......@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/regulator/machine.h>
#include <linux/scatterlist.h>
#include <linux/sfi.h>
#include <linux/irq.h>
#include <linux/export.h>
#include <linux/notifier.h>
......@@ -25,38 +24,13 @@
#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>
#include <asm/io.h>
#include <asm/i8259.h>
#include <asm/intel_scu_ipc.h>
#include <asm/apb_timer.h>
#include <asm/reboot.h>
/*
* the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
* cmdline option x86_intel_mid_timer can be used to override the configuration
* 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
*/
enum intel_mid_timer_options intel_mid_timer_options;
enum intel_mid_cpu_type __intel_mid_cpu_chip;
EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
#define IPCMSG_COLD_RESET 0xF1
static void intel_mid_power_off(void)
{
......@@ -64,69 +38,32 @@ static void intel_mid_power_off(void)
intel_mid_pwr_power_off();
/* Only for Tangier, the rest will ignore this command */
intel_scu_ipc_simple_command(IPCMSG_COLD_OFF, 1);
intel_scu_ipc_dev_simple_command(NULL, IPCMSG_COLD_OFF, 1);
};
static void intel_mid_reboot(void)
{
intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0);
}
static void __init intel_mid_setup_bp_timer(void)
{
apbt_time_init();
setup_boot_APIC_clock();
intel_scu_ipc_dev_simple_command(NULL, IPCMSG_COLD_RESET, 0);
}
static void __init intel_mid_time_init(void)
{
sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
switch (intel_mid_timer_options) {
case INTEL_MID_TIMER_APBT_ONLY:
break;
case INTEL_MID_TIMER_LAPIC_APBT:
/* Use apbt and local apic */
x86_init.timers.setup_percpu_clockev = intel_mid_setup_bp_timer;
x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
return;
default:
if (!boot_cpu_has(X86_FEATURE_ARAT))
break;
/* Lapic only, no apbt */
x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
return;
}
x86_init.timers.setup_percpu_clockev = apbt_time_init;
/* Lapic only, no apbt */
x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
}
static void intel_mid_arch_setup(void)
{
if (boot_cpu_data.x86 != 6) {
pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
boot_cpu_data.x86, boot_cpu_data.x86_model);
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
goto out;
}
switch (boot_cpu_data.x86_model) {
case 0x35:
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_CLOVERVIEW;
break;
case 0x3C:
case 0x4A:
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_TANGIER;
x86_platform.legacy.rtc = 1;
break;
case 0x27:
default:
__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
break;
}
out:
/*
* Intel MID platforms are using explicitly defined regulators.
*
......@@ -159,14 +96,11 @@ void __init x86_intel_mid_early_setup(void)
x86_init.timers.timer_init = intel_mid_time_init;
x86_init.timers.setup_percpu_clockev = x86_init_noop;
x86_init.timers.wallclock_init = intel_mid_rtc_init;
x86_init.irqs.pre_vector_init = x86_init_noop;
x86_init.oem.arch_setup = intel_mid_arch_setup;
x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
x86_platform.get_nmi_reason = intel_mid_get_nmi_reason;
x86_init.pci.arch_init = intel_mid_pci_init;
......@@ -188,25 +122,3 @@ void __init x86_intel_mid_early_setup(void)
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
set_bit(MP_BUS_ISA, mp_bus_not_pci);
}
/*
* 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.
*/
static inline int __init setup_x86_intel_mid_timer(char *arg)
{
if (!arg)
return -EINVAL;
if (strcmp("apbt_only", arg) == 0)
intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY;
else if (strcmp("lapic_and_apbt", arg) == 0)
intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT;
else {
pr_warn("X86 INTEL_MID timer option %s not recognised use x86_intel_mid_timer=apbt_only or lapic_and_apbt\n",
arg);
return -EINVAL;
}
return 0;
}
__setup("x86_intel_mid_timer=", setup_x86_intel_mid_timer);
// SPDX-License-Identifier: GPL-2.0-only
/*
* intel_mid_vrtc.c: Driver for virtual RTC device on Intel MID platform
*
* (C) Copyright 2009 Intel Corporation
*
* Note:
* VRTC is emulated by system controller firmware, the real HW
* RTC is located in the PMIC device. SCU FW shadows PMIC RTC
* in a memory mapped IO space that is visible to the host IA
* processor.
*
* This driver is based on RTC CMOS driver.
*/
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>
#include <asm/time.h>
#include <asm/fixmap.h>
static unsigned char __iomem *vrtc_virt_base;
unsigned char vrtc_cmos_read(unsigned char reg)
{
unsigned char retval;
/* vRTC's registers range from 0x0 to 0xD */
if (reg > 0xd || !vrtc_virt_base)
return 0xff;
lock_cmos_prefix(reg);
retval = __raw_readb(vrtc_virt_base + (reg << 2));
lock_cmos_suffix(reg);
return retval;
}
EXPORT_SYMBOL_GPL(vrtc_cmos_read);
void vrtc_cmos_write(unsigned char val, unsigned char reg)
{
if (reg > 0xd || !vrtc_virt_base)
return;
lock_cmos_prefix(reg);
__raw_writeb(val, vrtc_virt_base + (reg << 2));
lock_cmos_suffix(reg);
}
EXPORT_SYMBOL_GPL(vrtc_cmos_write);
void vrtc_get_time(struct timespec64 *now)
{
u8 sec, min, hour, mday, mon;
unsigned long flags;
u32 year;
spin_lock_irqsave(&rtc_lock, flags);
while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
cpu_relax();
sec = vrtc_cmos_read(RTC_SECONDS);
min = vrtc_cmos_read(RTC_MINUTES);
hour = vrtc_cmos_read(RTC_HOURS);
mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
mon = vrtc_cmos_read(RTC_MONTH);
year = vrtc_cmos_read(RTC_YEAR);
spin_unlock_irqrestore(&rtc_lock, flags);
/* vRTC YEAR reg contains the offset to 1972 */
year += 1972;
pr_info("vRTC: sec: %d min: %d hour: %d day: %d "
"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
now->tv_sec = mktime64(year, mon, mday, hour, min, sec);
now->tv_nsec = 0;
}
int vrtc_set_mmss(const struct timespec64 *now)
{
unsigned long flags;
struct rtc_time tm;
int year;
int retval = 0;
rtc_time64_to_tm(now->tv_sec, &tm);
if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
/*
* tm.year is the number of years since 1900, and the
* vrtc need the years since 1972.
*/
year = tm.tm_year - 72;
spin_lock_irqsave(&rtc_lock, flags);
vrtc_cmos_write(year, RTC_YEAR);
vrtc_cmos_write(tm.tm_mon, RTC_MONTH);
vrtc_cmos_write(tm.tm_mday, RTC_DAY_OF_MONTH);
vrtc_cmos_write(tm.tm_hour, RTC_HOURS);
vrtc_cmos_write(tm.tm_min, RTC_MINUTES);
vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
spin_unlock_irqrestore(&rtc_lock, flags);
} else {
pr_err("%s: Invalid vRTC value: write of %llx to vRTC failed\n",
__func__, (s64)now->tv_sec);
retval = -EINVAL;
}
return retval;
}
void __init intel_mid_rtc_init(void)
{
unsigned long vrtc_paddr;
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
vrtc_paddr = sfi_mrtc_array[0].phys_addr;
if (!sfi_mrtc_num || !vrtc_paddr)
return;
vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
vrtc_paddr);
x86_platform.get_wallclock = vrtc_get_time;
x86_platform.set_wallclock = vrtc_set_mmss;
}
/*
* The Moorestown platform has a memory mapped virtual RTC device that emulates
* the programming interface of the RTC.
*/
static struct resource vrtc_resources[] = {
[0] = {
.flags = IORESOURCE_MEM,
},
[1] = {
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device vrtc_device = {
.name = "rtc_mrst",
.id = -1,
.resource = vrtc_resources,
.num_resources = ARRAY_SIZE(vrtc_resources),
};
/* Register the RTC device if appropriate */
static int __init intel_mid_device_create(void)
{
/* No Moorestown, no device */
if (!intel_mid_identify_cpu())
return -ENODEV;
/* No timer, no device */
if (!sfi_mrtc_num)
return -ENODEV;
/* iomem resource */
vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr;
vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr +
MRST_VRTC_MAP_SZ;
/* irq resource */
vrtc_resources[1].start = sfi_mrtc_array[0].irq;
vrtc_resources[1].end = sfi_mrtc_array[0].irq;
return platform_device_register(&vrtc_device);
}
device_initcall(intel_mid_device_create);
This diff is collapsed.
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_SFI) += sfi.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* sfi.c - x86 architecture SFI support.
*
* Copyright (c) 2009, Intel Corporation.
*/
#define KMSG_COMPONENT "SFI"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/io.h>
#include <asm/irqdomain.h>
#include <asm/io_apic.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
#include <asm/apic.h>
#ifdef CONFIG_X86_LOCAL_APIC
static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
/* All CPUs enumerated by SFI must be present and enabled */
static void __init mp_sfi_register_lapic(u8 id)
{
if (MAX_LOCAL_APIC - id <= 0) {
pr_warn("Processor #%d invalid (max %d)\n", id, MAX_LOCAL_APIC);
return;
}
pr_info("registering lapic[%d]\n", id);
generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR)));
}
static int __init sfi_parse_cpus(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_cpu_table_entry *pentry;
int i;
int cpu_num;
sb = (struct sfi_table_simple *)table;
cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry);
pentry = (struct sfi_cpu_table_entry *)sb->pentry;
for (i = 0; i < cpu_num; i++) {
mp_sfi_register_lapic(pentry->apic_id);
pentry++;
}
smp_found_config = 1;
return 0;
}
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_apic_table_entry *pentry;
int i, num;
struct ioapic_domain_cfg cfg = {
.type = IOAPIC_DOMAIN_STRICT,
.ops = &mp_ioapic_irqdomain_ops,
};
sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
pentry = (struct sfi_apic_table_entry *)sb->pentry;
for (i = 0; i < num; i++) {
mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
pentry++;
}
WARN(pic_mode, KERN_WARNING
"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n");
pic_mode = 0;
return 0;
}
#endif /* CONFIG_X86_IO_APIC */
/*
* sfi_platform_init(): register lapics & io-apics
*/
int __init sfi_platform_init(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
register_lapic_address(sfi_lapic_addr);
sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
#endif
#ifdef CONFIG_X86_IO_APIC
sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic);
#endif
return 0;
}
......@@ -27,7 +27,7 @@ obj-y += idle/
obj-y += char/ipmi/
obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_SFI) += sfi/
# PnP must come after ACPI since it will eventually need to check if acpi
# was used and do nothing if so
obj-$(CONFIG_PNP) += pnp/
......
......@@ -62,16 +62,6 @@ config X86_ACPI_CPUFREQ_CPB
By enabling this option the acpi_cpufreq driver provides the old
entry in addition to the new boost ones, for compatibility reasons.
config X86_SFI_CPUFREQ
tristate "SFI Performance-States driver"
depends on X86_INTEL_MID && SFI
help
This adds a CPUFreq driver for some Silvermont based Intel Atom
architectures like Z34xx and Z35xx which enumerate processor
performance states through SFI.
If in doubt, say N.
config ELAN_CPUFREQ
tristate "AMD Elan SC400 and SC410"
depends on MELAN
......
......@@ -43,7 +43,6 @@ obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o
obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o
obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o
##################################################################################
# ARM SoC drivers
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* SFI Performance States Driver
*
* Author: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
* Author: Srinidhi Kasagar <srinidhi.kasagar@intel.com>
*/
#include <linux/cpufreq.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sfi.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <asm/msr.h>
static struct cpufreq_frequency_table *freq_table;
static struct sfi_freq_table_entry *sfi_cpufreq_array;
static int num_freq_table_entries;
static int sfi_parse_freq(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_freq_table_entry *pentry;
int totallen;
sb = (struct sfi_table_simple *)table;
num_freq_table_entries = SFI_GET_NUM_ENTRIES(sb,
struct sfi_freq_table_entry);
if (num_freq_table_entries <= 1) {
pr_err("No p-states discovered\n");
return -ENODEV;
}
pentry = (struct sfi_freq_table_entry *)sb->pentry;
totallen = num_freq_table_entries * sizeof(*pentry);
sfi_cpufreq_array = kmemdup(pentry, totallen, GFP_KERNEL);
if (!sfi_cpufreq_array)
return -ENOMEM;
return 0;
}
static int sfi_cpufreq_target(struct cpufreq_policy *policy, unsigned int index)
{
unsigned int next_perf_state = 0; /* Index into perf table */
u32 lo, hi;
next_perf_state = policy->freq_table[index].driver_data;
rdmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, &lo, &hi);
lo = (lo & ~INTEL_PERF_CTL_MASK) |
((u32) sfi_cpufreq_array[next_perf_state].ctrl_val &
INTEL_PERF_CTL_MASK);
wrmsr_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, lo, hi);
return 0;
}
static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
policy->cpuinfo.transition_latency = 100000; /* 100us */
policy->freq_table = freq_table;
return 0;
}
static struct cpufreq_driver sfi_cpufreq_driver = {
.flags = CPUFREQ_CONST_LOOPS,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = sfi_cpufreq_target,
.init = sfi_cpufreq_cpu_init,
.name = "sfi-cpufreq",
.attr = cpufreq_generic_attr,
};
static int __init sfi_cpufreq_init(void)
{
int ret, i;
/* parse the freq table from SFI */
ret = sfi_table_parse(SFI_SIG_FREQ, NULL, NULL, sfi_parse_freq);
if (ret)
return ret;
freq_table = kcalloc(num_freq_table_entries + 1, sizeof(*freq_table),
GFP_KERNEL);
if (!freq_table) {
ret = -ENOMEM;
goto err_free_array;
}
for (i = 0; i < num_freq_table_entries; i++) {
freq_table[i].driver_data = i;
freq_table[i].frequency = sfi_cpufreq_array[i].freq_mhz * 1000;
}
freq_table[i].frequency = CPUFREQ_TABLE_END;
ret = cpufreq_register_driver(&sfi_cpufreq_driver);
if (ret)
goto err_free_tbl;
return ret;
err_free_tbl:
kfree(freq_table);
err_free_array:
kfree(sfi_cpufreq_array);
return ret;
}
late_initcall(sfi_cpufreq_init);
static void __exit sfi_cpufreq_exit(void)
{
cpufreq_unregister_driver(&sfi_cpufreq_driver);
kfree(freq_table);
kfree(sfi_cpufreq_array);
}
module_exit(sfi_cpufreq_exit);
MODULE_AUTHOR("Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>");
MODULE_DESCRIPTION("SFI Performance-States Driver");
MODULE_LICENSE("GPL");
......@@ -659,15 +659,6 @@ config MFD_INTEL_LPSS_PCI
I2C, SPI and HS-UART starting from Intel Sunrisepoint (Intel Skylake
PCH) in PCI mode.
config MFD_INTEL_MSIC
bool "Intel MSIC"
depends on INTEL_SCU
select MFD_CORE
help
Select this option to enable access to Intel MSIC (Avatele
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
config MFD_INTEL_PMC_BXT
tristate "Intel PMC Driver for Broxton"
depends on X86
......
......@@ -214,7 +214,6 @@ obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o
obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o
obj-$(CONFIG_MFD_INTEL_PMT) += intel_pmt.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
......
This diff is collapsed.
......@@ -17,7 +17,6 @@
static int intel_scu_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void (*setup_fn)(void) = (void (*)(void))id->driver_data;
struct intel_scu_ipc_data scu_data = {};
struct intel_scu_ipc_dev *scu;
int ret;
......@@ -30,27 +29,14 @@ static int intel_scu_pci_probe(struct pci_dev *pdev,
scu_data.irq = pdev->irq;
scu = intel_scu_ipc_register(&pdev->dev, &scu_data);
if (IS_ERR(scu))
return PTR_ERR(scu);
if (setup_fn)
setup_fn();
return 0;
}
static void intel_mid_scu_setup(void)
{
intel_scu_devices_create();
return PTR_ERR_OR_ZERO(scu);
}
static const struct pci_device_id pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x080e),
.driver_data = (kernel_ulong_t)intel_mid_scu_setup },
{ PCI_VDEVICE(INTEL, 0x08ea),
.driver_data = (kernel_ulong_t)intel_mid_scu_setup },
{ PCI_VDEVICE(INTEL, 0x080e) },
{ PCI_VDEVICE(INTEL, 0x08ea) },
{ PCI_VDEVICE(INTEL, 0x0a94) },
{ PCI_VDEVICE(INTEL, 0x11a0),
.driver_data = (kernel_ulong_t)intel_mid_scu_setup },
{ PCI_VDEVICE(INTEL, 0x11a0) },
{ PCI_VDEVICE(INTEL, 0x1a94) },
{ PCI_VDEVICE(INTEL, 0x5a94) },
{}
......
# SPDX-License-Identifier: GPL-2.0-only
#
# SFI Configuration
#
menuconfig SFI
bool "SFI (Simple Firmware Interface) Support"
help
The Simple Firmware Interface (SFI) provides a lightweight method
for platform firmware to pass information to the operating system
via static tables in memory. Kernel SFI support is required to
boot on SFI-only platforms. Currently, all SFI-only platforms are
based on the 2nd generation Intel Atom processor platform,
code-named Moorestown.
For more information, see http://simplefirmware.org
Say 'Y' here to enable the kernel to boot on SFI-only platforms.
# SPDX-License-Identifier: GPL-2.0-only
obj-y += sfi_acpi.o
obj-y += sfi_core.o
/* sfi_acpi.c Simple Firmware Interface - ACPI extensions */
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright(c) 2009 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
BSD LICENSE
Copyright(c) 2009 Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define KMSG_COMPONENT "SFI"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/sfi_acpi.h>
#include "sfi_core.h"
/*
* SFI can access ACPI-defined tables via an optional ACPI XSDT.
*
* This allows re-use, and avoids re-definition, of standard tables.
* For example, the "MCFG" table is defined by PCI, reserved by ACPI,
* and is expected to be present many SFI-only systems.
*/
static struct acpi_table_xsdt *xsdt_va __read_mostly;
#define XSDT_GET_NUM_ENTRIES(ptable, entry_type) \
((ptable->header.length - sizeof(struct acpi_table_header)) / \
(sizeof(entry_type)))
static inline struct sfi_table_header *acpi_to_sfi_th(
struct acpi_table_header *th)
{
return (struct sfi_table_header *)th;
}
static inline struct acpi_table_header *sfi_to_acpi_th(
struct sfi_table_header *th)
{
return (struct acpi_table_header *)th;
}
/*
* sfi_acpi_parse_xsdt()
*
* Parse the ACPI XSDT for later access by sfi_acpi_table_parse().
*/
static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *th)
{
struct sfi_table_key key = SFI_ANY_KEY;
int tbl_cnt, i;
void *ret;
xsdt_va = (struct acpi_table_xsdt *)th;
tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64);
for (i = 0; i < tbl_cnt; i++) {
ret = sfi_check_table(xsdt_va->table_offset_entry[i], &key);
if (IS_ERR(ret)) {
disable_sfi();
return -1;
}
}
return 0;
}
int __init sfi_acpi_init(void)
{
struct sfi_table_key xsdt_key = { .sig = SFI_SIG_XSDT };
sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, sfi_acpi_parse_xsdt);
/* Only call the get_table to keep the table mapped */
xsdt_va = (struct acpi_table_xsdt *)sfi_get_table(&xsdt_key);
return 0;
}
static struct acpi_table_header *sfi_acpi_get_table(struct sfi_table_key *key)
{
u32 tbl_cnt, i;
void *ret;
tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64);
for (i = 0; i < tbl_cnt; i++) {
ret = sfi_check_table(xsdt_va->table_offset_entry[i], key);
if (!IS_ERR(ret) && ret)
return sfi_to_acpi_th(ret);
}
return NULL;
}
static void sfi_acpi_put_table(struct acpi_table_header *table)
{
sfi_put_table(acpi_to_sfi_th(table));
}
/*
* sfi_acpi_table_parse()
*
* Find specified table in XSDT, run handler on it and return its return value
*/
int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id,
int(*handler)(struct acpi_table_header *))
{
struct acpi_table_header *table = NULL;
struct sfi_table_key key;
int ret = 0;
if (sfi_disabled)
return -1;
key.sig = signature;
key.oem_id = oem_id;
key.oem_table_id = oem_table_id;
table = sfi_acpi_get_table(&key);
if (!table)
return -EINVAL;
ret = handler(table);
sfi_acpi_put_table(table);
return ret;
}
static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t offset, size_t count)
{
struct sfi_table_attr *tbl_attr =
container_of(bin_attr, struct sfi_table_attr, attr);
struct acpi_table_header *th = NULL;
struct sfi_table_key key;
ssize_t cnt;
key.sig = tbl_attr->name;
key.oem_id = NULL;
key.oem_table_id = NULL;
th = sfi_acpi_get_table(&key);
if (!th)
return 0;
cnt = memory_read_from_buffer(buf, count, &offset,
th, th->length);
sfi_acpi_put_table(th);
return cnt;
}
void __init sfi_acpi_sysfs_init(void)
{
u32 tbl_cnt, i;
struct sfi_table_attr *tbl_attr;
tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64);
for (i = 0; i < tbl_cnt; i++) {
tbl_attr =
sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]);
tbl_attr->attr.read = sfi_acpi_table_show;
}
return;
}
This diff is collapsed.
/* sfi_core.h Simple Firmware Interface, internal header */
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright(c) 2009 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
BSD LICENSE
Copyright(c) 2009 Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/sysfs.h>
struct sfi_table_key{
char *sig;
char *oem_id;
char *oem_table_id;
};
/* sysfs interface */
struct sfi_table_attr {
struct bin_attribute attr;
char name[8];
};
#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL }
extern int __init sfi_acpi_init(void);
extern struct sfi_table_header *sfi_check_table(u64 paddr,
struct sfi_table_key *key);
struct sfi_table_header *sfi_get_table(struct sfi_table_key *key);
extern void sfi_put_table(struct sfi_table_header *table);
extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa);
extern void __init sfi_acpi_sysfs_init(void);
......@@ -22,7 +22,6 @@
#include <asm/processor.h>
#include <linux/i2c.h>
#include <linux/sfi.h>
#include <media/v4l2-subdev.h>
#include "atomisp.h"
......
This diff is collapsed.
/* sfi.h Simple Firmware Interface */
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright(c) 2009 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
BSD LICENSE
Copyright(c) 2009 Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_SFI_H
#define _LINUX_SFI_H
#include <linux/init.h>
#include <linux/types.h>
/* Table signatures reserved by the SFI specification */
#define SFI_SIG_SYST "SYST"
#define SFI_SIG_FREQ "FREQ"
#define SFI_SIG_IDLE "IDLE"
#define SFI_SIG_CPUS "CPUS"
#define SFI_SIG_MTMR "MTMR"
#define SFI_SIG_MRTC "MRTC"
#define SFI_SIG_MMAP "MMAP"
#define SFI_SIG_APIC "APIC"
#define SFI_SIG_XSDT "XSDT"
#define SFI_SIG_WAKE "WAKE"
#define SFI_SIG_DEVS "DEVS"
#define SFI_SIG_GPIO "GPIO"
#define SFI_SIGNATURE_SIZE 4
#define SFI_OEM_ID_SIZE 6
#define SFI_OEM_TABLE_ID_SIZE 8
#define SFI_NAME_LEN 16
#define SFI_SYST_SEARCH_BEGIN 0x000E0000
#define SFI_SYST_SEARCH_END 0x000FFFFF
#define SFI_GET_NUM_ENTRIES(ptable, entry_type) \
((ptable->header.len - sizeof(struct sfi_table_header)) / \
(sizeof(entry_type)))
/*
* Table structures must be byte-packed to match the SFI specification,
* as they are provided by the BIOS.
*/
struct sfi_table_header {
char sig[SFI_SIGNATURE_SIZE];
u32 len;
u8 rev;
u8 csum;
char oem_id[SFI_OEM_ID_SIZE];
char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
} __packed;
struct sfi_table_simple {
struct sfi_table_header header;
u64 pentry[1];
} __packed;
/* Comply with UEFI spec 2.1 */
struct sfi_mem_entry {
u32 type;
u64 phys_start;
u64 virt_start;
u64 pages;
u64 attrib;
} __packed;
struct sfi_cpu_table_entry {
u32 apic_id;
} __packed;
struct sfi_cstate_table_entry {
u32 hint; /* MWAIT hint */
u32 latency; /* latency in ms */
} __packed;
struct sfi_apic_table_entry {
u64 phys_addr; /* phy base addr for APIC reg */
} __packed;
struct sfi_freq_table_entry {
u32 freq_mhz; /* in MHZ */
u32 latency; /* transition latency in ms */
u32 ctrl_val; /* value to write to PERF_CTL */
} __packed;
struct sfi_wake_table_entry {
u64 phys_addr; /* pointer to where the wake vector locates */
} __packed;
struct sfi_timer_table_entry {
u64 phys_addr; /* phy base addr for the timer */
u32 freq_hz; /* in HZ */
u32 irq;
} __packed;
struct sfi_rtc_table_entry {
u64 phys_addr; /* phy base addr for the RTC */
u32 irq;
} __packed;
struct sfi_device_table_entry {
u8 type; /* bus type, I2C, SPI or ...*/
#define SFI_DEV_TYPE_SPI 0
#define SFI_DEV_TYPE_I2C 1
#define SFI_DEV_TYPE_UART 2
#define SFI_DEV_TYPE_HSI 3
#define SFI_DEV_TYPE_IPC 4
#define SFI_DEV_TYPE_SD 5
u8 host_num; /* attached to host 0, 1...*/
u16 addr;
u8 irq;
u32 max_freq;
char name[SFI_NAME_LEN];
} __packed;
struct sfi_gpio_table_entry {
char controller_name[SFI_NAME_LEN];
u16 pin_no;
char pin_name[SFI_NAME_LEN];
} __packed;
typedef int (*sfi_table_handler) (struct sfi_table_header *table);
#ifdef CONFIG_SFI
extern void __init sfi_init(void);
extern int __init sfi_platform_init(void);
extern void __init sfi_init_late(void);
extern int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id,
sfi_table_handler handler);
extern int sfi_disabled;
static inline void disable_sfi(void)
{
sfi_disabled = 1;
}
#else /* !CONFIG_SFI */
static inline void sfi_init(void)
{
}
static inline void sfi_init_late(void)
{
}
#define sfi_disabled 0
static inline int sfi_table_parse(char *signature, char *oem_id,
char *oem_table_id,
sfi_table_handler handler)
{
return -1;
}
#endif /* !CONFIG_SFI */
#endif /*_LINUX_SFI_H*/
/* sfi.h Simple Firmware Interface */
/*
This file is provided under a dual BSD/GPLv2 license. When using or
redistributing this file, you may do so under either license.
GPL LICENSE SUMMARY
Copyright(c) 2009 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution
in the file called LICENSE.GPL.
BSD LICENSE
Copyright(c) 2009 Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_SFI_ACPI_H
#define _LINUX_SFI_ACPI_H
#include <linux/acpi.h>
#include <linux/sfi.h>
#ifdef CONFIG_SFI
extern int sfi_acpi_table_parse(char *signature, char *oem_id,
char *oem_table_id,
int (*handler)(struct acpi_table_header *));
static inline int __init acpi_sfi_table_parse(char *signature,
int (*handler)(struct acpi_table_header *))
{
if (!acpi_table_parse(signature, handler))
return 0;
return sfi_acpi_table_parse(signature, NULL, NULL, handler);
}
#else /* !CONFIG_SFI */
static inline int sfi_acpi_table_parse(char *signature, char *oem_id,
char *oem_table_id,
int (*handler)(struct acpi_table_header *))
{
return -1;
}
static inline int __init acpi_sfi_table_parse(char *signature,
int (*handler)(struct acpi_table_header *))
{
return acpi_table_parse(signature, handler);
}
#endif /* !CONFIG_SFI */
#endif /*_LINUX_SFI_ACPI_H*/
......@@ -74,7 +74,6 @@
#include <linux/kgdb.h>
#include <linux/ftrace.h>
#include <linux/async.h>
#include <linux/sfi.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/perf_event.h>
......@@ -1054,7 +1053,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
acpi_subsystem_init();
arch_post_acpi_subsys_init();
sfi_init_late();
kcsan_init();
/* Do the rest non-__init'ed, we're now alive */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment