Simple Firmware Interface (SFI) support removal for v5.12-rc1
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). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmA2ZukSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxKcAP/RAkbRVFndhQIZYTCu74O64v86FjTBcS 3vvcKevVkBJiPJL1l10Yo3UMEYAbJIRZY00jkUjX7pq4eurELu6LwdMtJlHwh0p5 ZP5QeSdq1xN+9UGwBGXlnka2ypmD8fjbQyxHKErYgvmOl4ltFm40PyUC9GCVFLnW /1o83t/dcmTtaOGPYWTW3HuCsbYqANG/x8PYAFeAk5dBxoSaNV69gAEuCYr1JC5N Nie4x2m2I5v9egJFhy6rmRrpHPBvocCho+FipJFagSKWHPCI2rBSKESVOj23zWt2 eIWhK5T/ZR3OqQb9tZN6uAPJmBAerc3l7ZHZ1oFBP68MjUJJJhduQ+hNxljOyLLw CVx0UhuancIWZdyJon5f7E9S9STZLIZ/3usx3K+7AZK+PSmH8d/UEIeXfkC0FcAr eO3gwalB9KuhhXbVvihW79RkfkV5pTaMvVS7l1BffN4WE1dB9PKtJ8/MKFbGaTUF 4Rev6BdAEDqJrw6OIARvNcI6TAEhbKe5yIghzhQWn+fZ7oEm6f6fvFObBzD0KvQP 4RwYJhXU0gtK5yo/Ib1sUqjVQn8Jgqb7Xq46WZsP07Yc6O2Ws/86qCpX1GSCv5FU 1CZEJLGLGTbjDYOyMaUDfO/tI5kXG11e0Ss7Q+snWH4Iyhg0aNEYChKjOAFIxIxg JJYOH8O5p2IP =jlPz -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c4fbde84fe
@ -1,15 +0,0 @@
|
||||
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
|
||||
|
@ -1,40 +0,0 @@
|
||||
/* 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 */
|
||||
|
@ -1,15 +1,13 @@
|
||||
/* 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 */
|
||||
|
@ -1,10 +0,0 @@
|
||||
/* 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
|
||||
|
@ -1,91 +0,0 @@
|
||||
/* 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
|
||||
|
@ -1,347 +0,0 @@
|
||||
// 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/
|
||||
|
@ -1,7 +1,2 @@
|
||||
# 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
|
||||
|
@ -1,32 +0,0 @@
|
||||
# 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
|
@ -1,101 +0,0 @@
|
||||
// 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);
|
@ -1,16 +0,0 @@
|
||||
// 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);
|
@ -1,101 +0,0 @@
|
||||
// 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);
|
@ -1,39 +0,0 @@
|
||||
// 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);
|
@ -1,81 +0,0 @@
|
||||
// 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);
|
@ -1,37 +0,0 @@
|
||||
// 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);
|
@ -1,77 +0,0 @@
|
||||
// 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);
|
@ -1,32 +0,0 @@
|
||||
// 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);
|
@ -1,39 +0,0 @@
|
||||
// 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);
|
@ -1,78 +0,0 @@
|
||||
// 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);
|
@ -1,44 +0,0 @@
|
||||
// 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);
|
@ -1,43 +0,0 @@
|
||||
// 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);
|
@ -1,50 +0,0 @@
|
||||
// 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);
|
@ -1,83 +0,0 @@
|
||||
// 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;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/* 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
|
@ -1,42 +0,0 @@
|
||||
// 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);
|
@ -1,32 +0,0 @@
|
||||
// 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);
|
@ -1,43 +0,0 @@
|
||||
// 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);
|
@ -1,44 +0,0 @@
|
||||
// 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);
|
@ -1,31 +0,0 @@
|
||||
// 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);
|
@ -1,32 +0,0 @@
|
||||
// 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);
|
@ -1,95 +0,0 @@
|
||||
// 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);
|
@ -1,42 +0,0 @@
|
||||
// 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);
|
@ -1,53 +0,0 @@
|
||||
// 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);
|
@ -1,8 +1,8 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -1,173 +0,0 @@
|
||||
// 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);
|
@ -1,543 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* intel_mid_sfi.c: Intel MID SFI initialization code
|
||||
*
|
||||
* (C) Copyright 2013 Intel Corporation
|
||||
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/sfi.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/mmc/core.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mpspec_def.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#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>
|
||||
|
||||
#define SFI_SIG_OEM0 "OEM0"
|
||||
#define MAX_IPCDEVS 24
|
||||
#define MAX_SCU_SPI 24
|
||||
#define MAX_SCU_I2C 24
|
||||
|
||||
static struct platform_device *ipc_devs[MAX_IPCDEVS];
|
||||
static struct spi_board_info *spi_devs[MAX_SCU_SPI];
|
||||
static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
|
||||
static struct sfi_gpio_table_entry *gpio_table;
|
||||
static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
|
||||
static int ipc_next_dev;
|
||||
static int spi_next_dev;
|
||||
static int i2c_next_dev;
|
||||
static int i2c_bus[MAX_SCU_I2C];
|
||||
static int gpio_num_entry;
|
||||
static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
|
||||
int sfi_mrtc_num;
|
||||
int sfi_mtimer_num;
|
||||
|
||||
struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
|
||||
EXPORT_SYMBOL_GPL(sfi_mrtc_array);
|
||||
|
||||
struct blocking_notifier_head intel_scu_notifier =
|
||||
BLOCKING_NOTIFIER_INIT(intel_scu_notifier);
|
||||
EXPORT_SYMBOL_GPL(intel_scu_notifier);
|
||||
|
||||
#define intel_mid_sfi_get_pdata(dev, priv) \
|
||||
((dev)->get_platform_data ? (dev)->get_platform_data(priv) : NULL)
|
||||
|
||||
/* parse all the mtimer info to a static mtimer array */
|
||||
int __init sfi_parse_mtmr(struct sfi_table_header *table)
|
||||
{
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_timer_table_entry *pentry;
|
||||
struct mpc_intsrc mp_irq;
|
||||
int totallen;
|
||||
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
if (!sfi_mtimer_num) {
|
||||
sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
|
||||
struct sfi_timer_table_entry);
|
||||
pentry = (struct sfi_timer_table_entry *) sb->pentry;
|
||||
totallen = sfi_mtimer_num * sizeof(*pentry);
|
||||
memcpy(sfi_mtimer_array, pentry, totallen);
|
||||
}
|
||||
|
||||
pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
|
||||
pentry = sfi_mtimer_array;
|
||||
for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
|
||||
pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
|
||||
totallen, (u32)pentry->phys_addr,
|
||||
pentry->freq_hz, pentry->irq);
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = MP_IRQTRIG_EDGE | MP_IRQPOL_ACTIVE_HIGH;
|
||||
mp_irq.srcbus = MP_BUS_ISA;
|
||||
mp_irq.srcbusirq = pentry->irq; /* IRQ */
|
||||
mp_irq.dstapic = MP_APIC_ALL;
|
||||
mp_irq.dstirq = pentry->irq;
|
||||
mp_save_irq(&mp_irq);
|
||||
mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
|
||||
{
|
||||
int i;
|
||||
if (hint < sfi_mtimer_num) {
|
||||
if (!sfi_mtimer_usage[hint]) {
|
||||
pr_debug("hint taken for timer %d irq %d\n",
|
||||
hint, sfi_mtimer_array[hint].irq);
|
||||
sfi_mtimer_usage[hint] = 1;
|
||||
return &sfi_mtimer_array[hint];
|
||||
}
|
||||
}
|
||||
/* take the first timer available */
|
||||
for (i = 0; i < sfi_mtimer_num;) {
|
||||
if (!sfi_mtimer_usage[i]) {
|
||||
sfi_mtimer_usage[i] = 1;
|
||||
return &sfi_mtimer_array[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sfi_mtimer_num;) {
|
||||
if (mtmr->irq == sfi_mtimer_array[i].irq) {
|
||||
sfi_mtimer_usage[i] = 0;
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse all the mrtc info to a global mrtc array */
|
||||
int __init sfi_parse_mrtc(struct sfi_table_header *table)
|
||||
{
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_rtc_table_entry *pentry;
|
||||
struct mpc_intsrc mp_irq;
|
||||
|
||||
int totallen;
|
||||
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
if (!sfi_mrtc_num) {
|
||||
sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
|
||||
struct sfi_rtc_table_entry);
|
||||
pentry = (struct sfi_rtc_table_entry *)sb->pentry;
|
||||
totallen = sfi_mrtc_num * sizeof(*pentry);
|
||||
memcpy(sfi_mrtc_array, pentry, totallen);
|
||||
}
|
||||
|
||||
pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
|
||||
pentry = sfi_mrtc_array;
|
||||
for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
|
||||
pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
|
||||
totallen, (u32)pentry->phys_addr, pentry->irq);
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = MP_IRQTRIG_LEVEL | MP_IRQPOL_ACTIVE_LOW;
|
||||
mp_irq.srcbus = MP_BUS_ISA;
|
||||
mp_irq.srcbusirq = pentry->irq; /* IRQ */
|
||||
mp_irq.dstapic = MP_APIC_ALL;
|
||||
mp_irq.dstirq = pentry->irq;
|
||||
mp_save_irq(&mp_irq);
|
||||
mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parsing GPIO table first, since the DEVS table will need this table
|
||||
* to map the pin name to the actual pin.
|
||||
*/
|
||||
static int __init sfi_parse_gpio(struct sfi_table_header *table)
|
||||
{
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_gpio_table_entry *pentry;
|
||||
int num, i;
|
||||
|
||||
if (gpio_table)
|
||||
return 0;
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
|
||||
pentry = (struct sfi_gpio_table_entry *)sb->pentry;
|
||||
|
||||
gpio_table = kmemdup(pentry, num * sizeof(*pentry), GFP_KERNEL);
|
||||
if (!gpio_table)
|
||||
return -1;
|
||||
gpio_num_entry = num;
|
||||
|
||||
pr_debug("GPIO pin info:\n");
|
||||
for (i = 0; i < num; i++, pentry++)
|
||||
pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
|
||||
" pin = %d\n", i,
|
||||
pentry->controller_name,
|
||||
pentry->pin_name,
|
||||
pentry->pin_no);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_gpio_by_name(const char *name)
|
||||
{
|
||||
struct sfi_gpio_table_entry *pentry = gpio_table;
|
||||
int i;
|
||||
|
||||
if (!pentry)
|
||||
return -1;
|
||||
for (i = 0; i < gpio_num_entry; i++, pentry++) {
|
||||
if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
|
||||
return pentry->pin_no;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void __init intel_scu_ipc_device_register(struct platform_device *pdev)
|
||||
{
|
||||
if (ipc_next_dev == MAX_IPCDEVS)
|
||||
pr_err("too many SCU IPC devices");
|
||||
else
|
||||
ipc_devs[ipc_next_dev++] = pdev;
|
||||
}
|
||||
|
||||
static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
|
||||
{
|
||||
struct spi_board_info *new_dev;
|
||||
|
||||
if (spi_next_dev == MAX_SCU_SPI) {
|
||||
pr_err("too many SCU SPI devices");
|
||||
return;
|
||||
}
|
||||
|
||||
new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
|
||||
if (!new_dev) {
|
||||
pr_err("failed to alloc mem for delayed spi dev %s\n",
|
||||
sdev->modalias);
|
||||
return;
|
||||
}
|
||||
*new_dev = *sdev;
|
||||
|
||||
spi_devs[spi_next_dev++] = new_dev;
|
||||
}
|
||||
|
||||
static void __init intel_scu_i2c_device_register(int bus,
|
||||
struct i2c_board_info *idev)
|
||||
{
|
||||
struct i2c_board_info *new_dev;
|
||||
|
||||
if (i2c_next_dev == MAX_SCU_I2C) {
|
||||
pr_err("too many SCU I2C devices");
|
||||
return;
|
||||
}
|
||||
|
||||
new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
|
||||
if (!new_dev) {
|
||||
pr_err("failed to alloc mem for delayed i2c dev %s\n",
|
||||
idev->type);
|
||||
return;
|
||||
}
|
||||
*new_dev = *idev;
|
||||
|
||||
i2c_bus[i2c_next_dev] = bus;
|
||||
i2c_devs[i2c_next_dev++] = new_dev;
|
||||
}
|
||||
|
||||
/* Called by IPC driver */
|
||||
void intel_scu_devices_create(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ipc_next_dev; i++)
|
||||
platform_device_add(ipc_devs[i]);
|
||||
|
||||
for (i = 0; i < spi_next_dev; i++)
|
||||
spi_register_board_info(spi_devs[i], 1);
|
||||
|
||||
for (i = 0; i < i2c_next_dev; i++) {
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *client;
|
||||
|
||||
adapter = i2c_get_adapter(i2c_bus[i]);
|
||||
if (adapter) {
|
||||
client = i2c_new_client_device(adapter, i2c_devs[i]);
|
||||
if (IS_ERR(client))
|
||||
pr_err("can't create i2c device %s\n",
|
||||
i2c_devs[i]->type);
|
||||
} else
|
||||
i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
|
||||
}
|
||||
intel_scu_notifier_post(SCU_AVAILABLE, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_scu_devices_create);
|
||||
|
||||
/* Called by IPC driver */
|
||||
void intel_scu_devices_destroy(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
intel_scu_notifier_post(SCU_DOWN, NULL);
|
||||
|
||||
for (i = 0; i < ipc_next_dev; i++)
|
||||
platform_device_del(ipc_devs[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
|
||||
|
||||
static void __init install_irq_resource(struct platform_device *pdev, int irq)
|
||||
{
|
||||
/* Single threaded */
|
||||
static struct resource res __initdata = {
|
||||
.name = "IRQ",
|
||||
.flags = IORESOURCE_IRQ,
|
||||
};
|
||||
res.start = irq;
|
||||
platform_device_add_resources(pdev, &res, 1);
|
||||
}
|
||||
|
||||
static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry,
|
||||
struct devs_id *dev)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
void *pdata = NULL;
|
||||
|
||||
pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
|
||||
pentry->name, pentry->irq);
|
||||
|
||||
/*
|
||||
* We need to call platform init of IPC devices to fill misc_pdata
|
||||
* structure. It will be used in msic_init for initialization.
|
||||
*/
|
||||
pdata = intel_mid_sfi_get_pdata(dev, pentry);
|
||||
if (IS_ERR(pdata))
|
||||
return;
|
||||
|
||||
/*
|
||||
* On Medfield the platform device creation is handled by the MSIC
|
||||
* MFD driver so we don't need to do it here.
|
||||
*/
|
||||
if (dev->msic && intel_mid_has_msic())
|
||||
return;
|
||||
|
||||
pdev = platform_device_alloc(pentry->name, 0);
|
||||
if (pdev == NULL) {
|
||||
pr_err("out of memory for SFI platform device '%s'.\n",
|
||||
pentry->name);
|
||||
return;
|
||||
}
|
||||
install_irq_resource(pdev, pentry->irq);
|
||||
|
||||
pdev->dev.platform_data = pdata;
|
||||
if (dev->delay)
|
||||
intel_scu_ipc_device_register(pdev);
|
||||
else
|
||||
platform_device_add(pdev);
|
||||
}
|
||||
|
||||
static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry,
|
||||
struct devs_id *dev)
|
||||
{
|
||||
struct spi_board_info spi_info;
|
||||
void *pdata = NULL;
|
||||
|
||||
memset(&spi_info, 0, sizeof(spi_info));
|
||||
strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
|
||||
spi_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
|
||||
spi_info.bus_num = pentry->host_num;
|
||||
spi_info.chip_select = pentry->addr;
|
||||
spi_info.max_speed_hz = pentry->max_freq;
|
||||
pr_debug("SPI bus=%d, name=%16.16s, irq=0x%2x, max_freq=%d, cs=%d\n",
|
||||
spi_info.bus_num,
|
||||
spi_info.modalias,
|
||||
spi_info.irq,
|
||||
spi_info.max_speed_hz,
|
||||
spi_info.chip_select);
|
||||
|
||||
pdata = intel_mid_sfi_get_pdata(dev, &spi_info);
|
||||
if (IS_ERR(pdata))
|
||||
return;
|
||||
|
||||
spi_info.platform_data = pdata;
|
||||
if (dev->delay)
|
||||
intel_scu_spi_device_register(&spi_info);
|
||||
else
|
||||
spi_register_board_info(&spi_info, 1);
|
||||
}
|
||||
|
||||
static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry,
|
||||
struct devs_id *dev)
|
||||
{
|
||||
struct i2c_board_info i2c_info;
|
||||
void *pdata = NULL;
|
||||
|
||||
memset(&i2c_info, 0, sizeof(i2c_info));
|
||||
strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
|
||||
i2c_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
|
||||
i2c_info.addr = pentry->addr;
|
||||
pr_debug("I2C bus = %d, name = %16.16s, irq = 0x%2x, addr = 0x%x\n",
|
||||
pentry->host_num,
|
||||
i2c_info.type,
|
||||
i2c_info.irq,
|
||||
i2c_info.addr);
|
||||
pdata = intel_mid_sfi_get_pdata(dev, &i2c_info);
|
||||
i2c_info.platform_data = pdata;
|
||||
if (IS_ERR(pdata))
|
||||
return;
|
||||
|
||||
if (dev->delay)
|
||||
intel_scu_i2c_device_register(pentry->host_num, &i2c_info);
|
||||
else
|
||||
i2c_register_board_info(pentry->host_num, &i2c_info, 1);
|
||||
}
|
||||
|
||||
static void __init sfi_handle_sd_dev(struct sfi_device_table_entry *pentry,
|
||||
struct devs_id *dev)
|
||||
{
|
||||
struct mid_sd_board_info sd_info;
|
||||
void *pdata;
|
||||
|
||||
memset(&sd_info, 0, sizeof(sd_info));
|
||||
strncpy(sd_info.name, pentry->name, SFI_NAME_LEN);
|
||||
sd_info.bus_num = pentry->host_num;
|
||||
sd_info.max_clk = pentry->max_freq;
|
||||
sd_info.addr = pentry->addr;
|
||||
pr_debug("SD bus = %d, name = %16.16s, max_clk = %d, addr = 0x%x\n",
|
||||
sd_info.bus_num,
|
||||
sd_info.name,
|
||||
sd_info.max_clk,
|
||||
sd_info.addr);
|
||||
pdata = intel_mid_sfi_get_pdata(dev, &sd_info);
|
||||
if (IS_ERR(pdata))
|
||||
return;
|
||||
|
||||
/* Nothing we can do with this for now */
|
||||
sd_info.platform_data = pdata;
|
||||
|
||||
pr_debug("Successfully registered %16.16s", sd_info.name);
|
||||
}
|
||||
|
||||
extern struct devs_id *const __x86_intel_mid_dev_start[],
|
||||
*const __x86_intel_mid_dev_end[];
|
||||
|
||||
static struct devs_id __init *get_device_id(u8 type, char *name)
|
||||
{
|
||||
struct devs_id *const *dev_table;
|
||||
|
||||
for (dev_table = __x86_intel_mid_dev_start;
|
||||
dev_table < __x86_intel_mid_dev_end; dev_table++) {
|
||||
struct devs_id *dev = *dev_table;
|
||||
if (dev->type == type &&
|
||||
!strncmp(dev->name, name, SFI_NAME_LEN)) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __init sfi_parse_devs(struct sfi_table_header *table)
|
||||
{
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_device_table_entry *pentry;
|
||||
struct devs_id *dev = NULL;
|
||||
int num, i, ret;
|
||||
int polarity;
|
||||
struct irq_alloc_info info;
|
||||
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
|
||||
pentry = (struct sfi_device_table_entry *)sb->pentry;
|
||||
|
||||
for (i = 0; i < num; i++, pentry++) {
|
||||
int irq = pentry->irq;
|
||||
|
||||
if (irq != (u8)0xff) { /* native RTE case */
|
||||
/* these SPI2 devices are not exposed to system as PCI
|
||||
* devices, but they have separate RTE entry in IOAPIC
|
||||
* so we have to enable them one by one here
|
||||
*/
|
||||
if (intel_mid_identify_cpu() ==
|
||||
INTEL_MID_CPU_CHIP_TANGIER) {
|
||||
if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
|
||||
/* active low */
|
||||
polarity = 1;
|
||||
else if (!strncmp(pentry->name,
|
||||
"synaptics_3202", 14))
|
||||
/* active low */
|
||||
polarity = 1;
|
||||
else if (irq == 41)
|
||||
/* fast_int_1 */
|
||||
polarity = 1;
|
||||
else
|
||||
/* active high */
|
||||
polarity = 0;
|
||||
} else {
|
||||
/* PNW and CLV go with active low */
|
||||
polarity = 1;
|
||||
}
|
||||
|
||||
ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity);
|
||||
ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC, &info);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
|
||||
dev = get_device_id(pentry->type, pentry->name);
|
||||
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
switch (pentry->type) {
|
||||
case SFI_DEV_TYPE_IPC:
|
||||
sfi_handle_ipc_dev(pentry, dev);
|
||||
break;
|
||||
case SFI_DEV_TYPE_SPI:
|
||||
sfi_handle_spi_dev(pentry, dev);
|
||||
break;
|
||||
case SFI_DEV_TYPE_I2C:
|
||||
sfi_handle_i2c_dev(pentry, dev);
|
||||
break;
|
||||
case SFI_DEV_TYPE_SD:
|
||||
sfi_handle_sd_dev(pentry, dev);
|
||||
break;
|
||||
case SFI_DEV_TYPE_UART:
|
||||
case SFI_DEV_TYPE_HSI:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init intel_mid_platform_init(void)
|
||||
{
|
||||
sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
|
||||
sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(intel_mid_platform_init);
|
@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_SFI) += sfi.o
|
@ -1,100 +0,0 @@
|
||||
// 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
|
||||
|
@ -1,127 +0,0 @@
|
||||
// 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
|
||||
|
@ -1,425 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for Intel MSIC
|
||||
*
|
||||
* Copyright (C) 2011, Intel Corporation
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/intel_msic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/intel_scu_ipc.h>
|
||||
|
||||
#define MSIC_VENDOR(id) ((id >> 6) & 3)
|
||||
#define MSIC_VERSION(id) (id & 0x3f)
|
||||
#define MSIC_MAJOR(id) ('A' + ((id >> 3) & 7))
|
||||
#define MSIC_MINOR(id) (id & 7)
|
||||
|
||||
/*
|
||||
* MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
|
||||
* Since IRQ block starts from address 0x002 we need to subtract that from
|
||||
* the actual IRQ status register address.
|
||||
*/
|
||||
#define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
|
||||
#define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
|
||||
|
||||
/*
|
||||
* The SCU hardware has limitation of 16 bytes per read/write buffer on
|
||||
* Medfield.
|
||||
*/
|
||||
#define SCU_IPC_RWBUF_LIMIT 16
|
||||
|
||||
/**
|
||||
* struct intel_msic - an MSIC MFD instance
|
||||
* @pdev: pointer to the platform device
|
||||
* @vendor: vendor ID
|
||||
* @version: chip version
|
||||
* @irq_base: base address of the mapped MSIC SRAM interrupt tree
|
||||
*/
|
||||
struct intel_msic {
|
||||
struct platform_device *pdev;
|
||||
unsigned vendor;
|
||||
unsigned version;
|
||||
void __iomem *irq_base;
|
||||
};
|
||||
|
||||
static const struct resource msic_touch_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_adc_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_battery_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_gpio_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_audio_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(0, "IRQ"),
|
||||
/*
|
||||
* We will pass IRQ_BASE to the driver now but this can be removed
|
||||
* when/if the driver starts to use intel_msic_irq_read().
|
||||
*/
|
||||
DEFINE_RES_MEM_NAMED(MSIC_IRQ_STATUS_ACCDET, 1, "IRQ_BASE"),
|
||||
};
|
||||
|
||||
static const struct resource msic_hdmi_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_thermal_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_power_btn_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
static const struct resource msic_ocd_resources[] = {
|
||||
DEFINE_RES_IRQ(0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Devices that are part of the MSIC and are available via firmware
|
||||
* populated SFI DEVS table.
|
||||
*/
|
||||
static struct mfd_cell msic_devs[] = {
|
||||
[INTEL_MSIC_BLOCK_TOUCH] = {
|
||||
.name = "msic_touch",
|
||||
.num_resources = ARRAY_SIZE(msic_touch_resources),
|
||||
.resources = msic_touch_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_ADC] = {
|
||||
.name = "msic_adc",
|
||||
.num_resources = ARRAY_SIZE(msic_adc_resources),
|
||||
.resources = msic_adc_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_BATTERY] = {
|
||||
.name = "msic_battery",
|
||||
.num_resources = ARRAY_SIZE(msic_battery_resources),
|
||||
.resources = msic_battery_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_GPIO] = {
|
||||
.name = "msic_gpio",
|
||||
.num_resources = ARRAY_SIZE(msic_gpio_resources),
|
||||
.resources = msic_gpio_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_AUDIO] = {
|
||||
.name = "msic_audio",
|
||||
.num_resources = ARRAY_SIZE(msic_audio_resources),
|
||||
.resources = msic_audio_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_HDMI] = {
|
||||
.name = "msic_hdmi",
|
||||
.num_resources = ARRAY_SIZE(msic_hdmi_resources),
|
||||
.resources = msic_hdmi_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_THERMAL] = {
|
||||
.name = "msic_thermal",
|
||||
.num_resources = ARRAY_SIZE(msic_thermal_resources),
|
||||
.resources = msic_thermal_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_POWER_BTN] = {
|
||||
.name = "msic_power_btn",
|
||||
.num_resources = ARRAY_SIZE(msic_power_btn_resources),
|
||||
.resources = msic_power_btn_resources,
|
||||
},
|
||||
[INTEL_MSIC_BLOCK_OCD] = {
|
||||
.name = "msic_ocd",
|
||||
.num_resources = ARRAY_SIZE(msic_ocd_resources),
|
||||
.resources = msic_ocd_resources,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Other MSIC related devices which are not directly available via SFI DEVS
|
||||
* table. These can be pseudo devices, regulators etc. which are needed for
|
||||
* different purposes.
|
||||
*
|
||||
* These devices appear only after the MSIC driver itself is initialized so
|
||||
* we can guarantee that the SCU IPC interface is ready.
|
||||
*/
|
||||
static const struct mfd_cell msic_other_devs[] = {
|
||||
/* Audio codec in the MSIC */
|
||||
{
|
||||
.id = -1,
|
||||
.name = "sn95031",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_msic_reg_read - read a single MSIC register
|
||||
* @reg: register to read
|
||||
* @val: register value is placed here
|
||||
*
|
||||
* Read a single register from MSIC. Returns %0 on success and negative
|
||||
* errno in case of failure.
|
||||
*
|
||||
* Function may sleep.
|
||||
*/
|
||||
int intel_msic_reg_read(unsigned short reg, u8 *val)
|
||||
{
|
||||
return intel_scu_ipc_ioread8(reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_reg_read);
|
||||
|
||||
/**
|
||||
* intel_msic_reg_write - write a single MSIC register
|
||||
* @reg: register to write
|
||||
* @val: value to write to that register
|
||||
*
|
||||
* Write a single MSIC register. Returns 0 on success and negative
|
||||
* errno in case of failure.
|
||||
*
|
||||
* Function may sleep.
|
||||
*/
|
||||
int intel_msic_reg_write(unsigned short reg, u8 val)
|
||||
{
|
||||
return intel_scu_ipc_iowrite8(reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_reg_write);
|
||||
|
||||
/**
|
||||
* intel_msic_reg_update - update a single MSIC register
|
||||
* @reg: register to update
|
||||
* @val: value to write to the register
|
||||
* @mask: specifies which of the bits are updated (%0 = don't update,
|
||||
* %1 = update)
|
||||
*
|
||||
* Perform an update to a register @reg. @mask is used to specify which
|
||||
* bits are updated. Returns %0 in case of success and negative errno in
|
||||
* case of failure.
|
||||
*
|
||||
* Function may sleep.
|
||||
*/
|
||||
int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
|
||||
{
|
||||
return intel_scu_ipc_update_register(reg, val, mask);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_reg_update);
|
||||
|
||||
/**
|
||||
* intel_msic_bulk_read - read an array of registers
|
||||
* @reg: array of register addresses to read
|
||||
* @buf: array where the read values are placed
|
||||
* @count: number of registers to read
|
||||
*
|
||||
* Function reads @count registers from the MSIC using addresses passed in
|
||||
* @reg. Read values are placed in @buf. Reads are performed atomically
|
||||
* wrt. MSIC.
|
||||
*
|
||||
* Returns %0 in case of success and negative errno in case of failure.
|
||||
*
|
||||
* Function may sleep.
|
||||
*/
|
||||
int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
|
||||
{
|
||||
if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
|
||||
return -EINVAL;
|
||||
|
||||
return intel_scu_ipc_readv(reg, buf, count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
|
||||
|
||||
/**
|
||||
* intel_msic_bulk_write - write an array of values to the MSIC registers
|
||||
* @reg: array of registers to write
|
||||
* @buf: values to write to each register
|
||||
* @count: number of registers to write
|
||||
*
|
||||
* Function writes @count registers in @buf to MSIC. Writes are performed
|
||||
* atomically wrt MSIC. Returns %0 in case of success and negative errno in
|
||||
* case of failure.
|
||||
*
|
||||
* Function may sleep.
|
||||
*/
|
||||
int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
|
||||
{
|
||||
if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
|
||||
return -EINVAL;
|
||||
|
||||
return intel_scu_ipc_writev(reg, buf, count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
|
||||
|
||||
/**
|
||||
* intel_msic_irq_read - read a register from an MSIC interrupt tree
|
||||
* @msic: MSIC instance
|
||||
* @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
|
||||
* %INTEL_MSIC_RESETIRQ2)
|
||||
* @val: value of the register is placed here
|
||||
*
|
||||
* This function can be used by an MSIC subdevice interrupt handler to read
|
||||
* a register value from the MSIC interrupt tree. In this way subdevice
|
||||
* drivers don't have to map in the interrupt tree themselves but can just
|
||||
* call this function instead.
|
||||
*
|
||||
* Function doesn't sleep and is callable from interrupt context.
|
||||
*
|
||||
* Returns %-EINVAL if @reg is outside of the allowed register region.
|
||||
*/
|
||||
int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
|
||||
{
|
||||
if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
|
||||
return -EINVAL;
|
||||
|
||||
*val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_msic_irq_read);
|
||||
|
||||
static int intel_msic_init_devices(struct intel_msic *msic)
|
||||
{
|
||||
struct platform_device *pdev = msic->pdev;
|
||||
struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int ret, i;
|
||||
|
||||
if (pdata->gpio) {
|
||||
struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
|
||||
|
||||
cell->platform_data = pdata->gpio;
|
||||
cell->pdata_size = sizeof(*pdata->gpio);
|
||||
}
|
||||
|
||||
if (pdata->ocd) {
|
||||
unsigned gpio = pdata->ocd->gpio;
|
||||
|
||||
ret = devm_gpio_request_one(&pdev->dev, gpio,
|
||||
GPIOF_IN, "ocd_gpio");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register OCD GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_to_irq(gpio);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update the IRQ number for the OCD */
|
||||
pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
|
||||
if (!pdata->irq[i])
|
||||
continue;
|
||||
|
||||
ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
|
||||
pdata->irq[i], NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
|
||||
ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intel_msic_remove_devices(struct intel_msic *msic)
|
||||
{
|
||||
struct platform_device *pdev = msic->pdev;
|
||||
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
}
|
||||
|
||||
static int intel_msic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct intel_msic *msic;
|
||||
struct resource *res;
|
||||
u8 id0, id1;
|
||||
int ret;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* First validate that we have an MSIC in place */
|
||||
ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
|
||||
dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
msic = devm_kzalloc(&pdev->dev, sizeof(*msic), GFP_KERNEL);
|
||||
if (!msic)
|
||||
return -ENOMEM;
|
||||
|
||||
msic->vendor = MSIC_VENDOR(id0);
|
||||
msic->version = MSIC_VERSION(id0);
|
||||
msic->pdev = pdev;
|
||||
|
||||
/*
|
||||
* Map in the MSIC interrupt tree area in SRAM. This is exposed to
|
||||
* the clients via intel_msic_irq_read().
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
msic->irq_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(msic->irq_base))
|
||||
return PTR_ERR(msic->irq_base);
|
||||
|
||||
platform_set_drvdata(pdev, msic);
|
||||
|
||||
ret = intel_msic_init_devices(msic);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
|
||||
MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
|
||||
msic->vendor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_msic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct intel_msic *msic = platform_get_drvdata(pdev);
|
||||
|
||||
intel_msic_remove_devices(msic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver intel_msic_driver = {
|
||||
.probe = intel_msic_probe,
|
||||
.remove = intel_msic_remove,
|
||||
.driver = {
|
||||
.name = "intel_msic",
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(intel_msic_driver);
|
@ -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) },
|
||||
{}
|
||||
|
@ -1,18 +0,0 @@
|
||||
# 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.
|
@ -1,4 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-y += sfi_acpi.o
|
||||
obj-y += sfi_core.o
|
||||
|
@ -1,214 +0,0 @@
|
||||
/* 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;
|
||||
}
|
@ -1,522 +0,0 @@
|
||||
/* sfi_core.c Simple Firmware Interface - core internals */
|
||||
|
||||
/*
|
||||
|
||||
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/memblock.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sfi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "sfi_core.h"
|
||||
|
||||
#define ON_SAME_PAGE(addr1, addr2) \
|
||||
(((unsigned long)(addr1) & PAGE_MASK) == \
|
||||
((unsigned long)(addr2) & PAGE_MASK))
|
||||
#define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \
|
||||
ON_SAME_PAGE(page, table + size))
|
||||
|
||||
int sfi_disabled __read_mostly;
|
||||
EXPORT_SYMBOL(sfi_disabled);
|
||||
|
||||
static u64 syst_pa __read_mostly;
|
||||
static struct sfi_table_simple *syst_va __read_mostly;
|
||||
|
||||
/*
|
||||
* FW creates and saves the SFI tables in memory. When these tables get
|
||||
* used, they may need to be mapped to virtual address space, and the mapping
|
||||
* can happen before or after the memremap() is ready, so a flag is needed
|
||||
* to indicating this
|
||||
*/
|
||||
static u32 sfi_use_memremap __read_mostly;
|
||||
|
||||
/*
|
||||
* sfi_un/map_memory calls early_memremap/memunmap which is a __init function
|
||||
* and introduces section mismatch. So use __ref to make it calm.
|
||||
*/
|
||||
static void __iomem * __ref sfi_map_memory(u64 phys, u32 size)
|
||||
{
|
||||
if (!phys || !size)
|
||||
return NULL;
|
||||
|
||||
if (sfi_use_memremap)
|
||||
return memremap(phys, size, MEMREMAP_WB);
|
||||
else
|
||||
return early_memremap(phys, size);
|
||||
}
|
||||
|
||||
static void __ref sfi_unmap_memory(void __iomem *virt, u32 size)
|
||||
{
|
||||
if (!virt || !size)
|
||||
return;
|
||||
|
||||
if (sfi_use_memremap)
|
||||
memunmap(virt);
|
||||
else
|
||||
early_memunmap(virt, size);
|
||||
}
|
||||
|
||||
static void sfi_print_table_header(unsigned long long pa,
|
||||
struct sfi_table_header *header)
|
||||
{
|
||||
pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n",
|
||||
header->sig, pa,
|
||||
header->len, header->rev, header->oem_id,
|
||||
header->oem_table_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfi_verify_table()
|
||||
* Sanity check table lengh, calculate checksum
|
||||
*/
|
||||
static int sfi_verify_table(struct sfi_table_header *table)
|
||||
{
|
||||
|
||||
u8 checksum = 0;
|
||||
u8 *puchar = (u8 *)table;
|
||||
u32 length = table->len;
|
||||
|
||||
/* Sanity check table length against arbitrary 1MB limit */
|
||||
if (length > 0x100000) {
|
||||
pr_err("Invalid table length 0x%x\n", length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (length--)
|
||||
checksum += *puchar++;
|
||||
|
||||
if (checksum) {
|
||||
pr_err("Checksum %2.2X should be %2.2X\n",
|
||||
table->csum, table->csum - checksum);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfi_map_table()
|
||||
*
|
||||
* Return address of mapped table
|
||||
* Check for common case that we can re-use mapping to SYST,
|
||||
* which requires syst_pa, syst_va to be initialized.
|
||||
*/
|
||||
static struct sfi_table_header *sfi_map_table(u64 pa)
|
||||
{
|
||||
struct sfi_table_header *th;
|
||||
u32 length;
|
||||
|
||||
if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header)))
|
||||
th = sfi_map_memory(pa, sizeof(struct sfi_table_header));
|
||||
else
|
||||
th = (void *)syst_va + (pa - syst_pa);
|
||||
|
||||
/* If table fits on same page as its header, we are done */
|
||||
if (TABLE_ON_PAGE(th, th, th->len))
|
||||
return th;
|
||||
|
||||
/* Entire table does not fit on same page as SYST */
|
||||
length = th->len;
|
||||
if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header)))
|
||||
sfi_unmap_memory(th, sizeof(struct sfi_table_header));
|
||||
|
||||
return sfi_map_memory(pa, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfi_unmap_table()
|
||||
*
|
||||
* Undoes effect of sfi_map_table() by unmapping table
|
||||
* if it did not completely fit on same page as SYST.
|
||||
*/
|
||||
static void sfi_unmap_table(struct sfi_table_header *th)
|
||||
{
|
||||
if (!TABLE_ON_PAGE(syst_va, th, th->len))
|
||||
sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ?
|
||||
sizeof(*th) : th->len);
|
||||
}
|
||||
|
||||
static int sfi_table_check_key(struct sfi_table_header *th,
|
||||
struct sfi_table_key *key)
|
||||
{
|
||||
|
||||
if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE)
|
||||
|| (key->oem_id && strncmp(th->oem_id,
|
||||
key->oem_id, SFI_OEM_ID_SIZE))
|
||||
|| (key->oem_table_id && strncmp(th->oem_table_id,
|
||||
key->oem_table_id, SFI_OEM_TABLE_ID_SIZE)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will be used in 2 cases:
|
||||
* 1. used to enumerate and verify the tables addressed by SYST/XSDT,
|
||||
* thus no signature will be given (in kernel boot phase)
|
||||
* 2. used to parse one specific table, signature must exist, and
|
||||
* the mapped virt address will be returned, and the virt space
|
||||
* will be released by call sfi_put_table() later
|
||||
*
|
||||
* This two cases are from two different functions with two different
|
||||
* sections and causes section mismatch warning. So use __ref to tell
|
||||
* modpost not to make any noise.
|
||||
*
|
||||
* Return value:
|
||||
* NULL: when can't find a table matching the key
|
||||
* ERR_PTR(error): error value
|
||||
* virt table address: when a matched table is found
|
||||
*/
|
||||
struct sfi_table_header *
|
||||
__ref sfi_check_table(u64 pa, struct sfi_table_key *key)
|
||||
{
|
||||
struct sfi_table_header *th;
|
||||
void *ret = NULL;
|
||||
|
||||
th = sfi_map_table(pa);
|
||||
if (!th)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (!key->sig) {
|
||||
sfi_print_table_header(pa, th);
|
||||
if (sfi_verify_table(th))
|
||||
ret = ERR_PTR(-EINVAL);
|
||||
} else {
|
||||
if (!sfi_table_check_key(th, key))
|
||||
return th; /* Success */
|
||||
}
|
||||
|
||||
sfi_unmap_table(th);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfi_get_table()
|
||||
*
|
||||
* Search SYST for the specified table with the signature in
|
||||
* the key, and return the mapped table
|
||||
*/
|
||||
struct sfi_table_header *sfi_get_table(struct sfi_table_key *key)
|
||||
{
|
||||
struct sfi_table_header *th;
|
||||
u32 tbl_cnt, i;
|
||||
|
||||
tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
|
||||
for (i = 0; i < tbl_cnt; i++) {
|
||||
th = sfi_check_table(syst_va->pentry[i], key);
|
||||
if (!IS_ERR(th) && th)
|
||||
return th;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sfi_put_table(struct sfi_table_header *th)
|
||||
{
|
||||
sfi_unmap_table(th);
|
||||
}
|
||||
|
||||
/* Find table with signature, run handler on it */
|
||||
int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id,
|
||||
sfi_table_handler handler)
|
||||
{
|
||||
struct sfi_table_header *table = NULL;
|
||||
struct sfi_table_key key;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (sfi_disabled || !handler || !signature)
|
||||
goto exit;
|
||||
|
||||
key.sig = signature;
|
||||
key.oem_id = oem_id;
|
||||
key.oem_table_id = oem_table_id;
|
||||
|
||||
table = sfi_get_table(&key);
|
||||
if (!table)
|
||||
goto exit;
|
||||
|
||||
ret = handler(table);
|
||||
sfi_put_table(table);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfi_table_parse);
|
||||
|
||||
/*
|
||||
* sfi_parse_syst()
|
||||
* Checksum all the tables in SYST and print their headers
|
||||
*
|
||||
* success: set syst_va, return 0
|
||||
*/
|
||||
static int __init sfi_parse_syst(void)
|
||||
{
|
||||
struct sfi_table_key key = SFI_ANY_KEY;
|
||||
int tbl_cnt, i;
|
||||
void *ret;
|
||||
|
||||
syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple));
|
||||
if (!syst_va)
|
||||
return -ENOMEM;
|
||||
|
||||
tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
|
||||
for (i = 0; i < tbl_cnt; i++) {
|
||||
ret = sfi_check_table(syst_va->pentry[i], &key);
|
||||
if (IS_ERR(ret))
|
||||
return PTR_ERR(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The OS finds the System Table by searching 16-byte boundaries between
|
||||
* physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region
|
||||
* starting at the low address and shall stop searching when the 1st valid SFI
|
||||
* System Table is found.
|
||||
*
|
||||
* success: set syst_pa, return 0
|
||||
* fail: return -1
|
||||
*/
|
||||
static __init int sfi_find_syst(void)
|
||||
{
|
||||
unsigned long offset, len;
|
||||
void *start;
|
||||
|
||||
len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN;
|
||||
start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len);
|
||||
if (!start)
|
||||
return -1;
|
||||
|
||||
for (offset = 0; offset < len; offset += 16) {
|
||||
struct sfi_table_header *syst_hdr;
|
||||
|
||||
syst_hdr = start + offset;
|
||||
if (strncmp(syst_hdr->sig, SFI_SIG_SYST,
|
||||
SFI_SIGNATURE_SIZE))
|
||||
continue;
|
||||
|
||||
if (syst_hdr->len > PAGE_SIZE)
|
||||
continue;
|
||||
|
||||
sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset,
|
||||
syst_hdr);
|
||||
|
||||
if (sfi_verify_table(syst_hdr))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Enforce SFI spec mandate that SYST reside within a page.
|
||||
*/
|
||||
if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) {
|
||||
pr_info("SYST 0x%llx + 0x%x crosses page\n",
|
||||
syst_pa, syst_hdr->len);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
syst_pa = SFI_SYST_SEARCH_BEGIN + offset;
|
||||
sfi_unmap_memory(start, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfi_unmap_memory(start, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct kobject *sfi_kobj;
|
||||
static struct kobject *tables_kobj;
|
||||
|
||||
static ssize_t sfi_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 sfi_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;
|
||||
|
||||
if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) {
|
||||
th = sfi_get_table(&key);
|
||||
if (!th)
|
||||
return 0;
|
||||
|
||||
cnt = memory_read_from_buffer(buf, count, &offset,
|
||||
th, th->len);
|
||||
sfi_put_table(th);
|
||||
} else
|
||||
cnt = memory_read_from_buffer(buf, count, &offset,
|
||||
syst_va, syst_va->header.len);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa)
|
||||
{
|
||||
struct sfi_table_attr *tbl_attr;
|
||||
struct sfi_table_header *th;
|
||||
int ret;
|
||||
|
||||
tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL);
|
||||
if (!tbl_attr)
|
||||
return NULL;
|
||||
|
||||
th = sfi_map_table(pa);
|
||||
if (!th || !th->sig[0]) {
|
||||
kfree(tbl_attr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sysfs_attr_init(&tbl_attr->attr.attr);
|
||||
memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE);
|
||||
|
||||
tbl_attr->attr.size = 0;
|
||||
tbl_attr->attr.read = sfi_table_show;
|
||||
tbl_attr->attr.attr.name = tbl_attr->name;
|
||||
tbl_attr->attr.attr.mode = 0400;
|
||||
|
||||
ret = sysfs_create_bin_file(tables_kobj,
|
||||
&tbl_attr->attr);
|
||||
if (ret) {
|
||||
kfree(tbl_attr);
|
||||
tbl_attr = NULL;
|
||||
}
|
||||
|
||||
sfi_unmap_table(th);
|
||||
return tbl_attr;
|
||||
}
|
||||
|
||||
static int __init sfi_sysfs_init(void)
|
||||
{
|
||||
int tbl_cnt, i;
|
||||
|
||||
if (sfi_disabled)
|
||||
return 0;
|
||||
|
||||
sfi_kobj = kobject_create_and_add("sfi", firmware_kobj);
|
||||
if (!sfi_kobj)
|
||||
return 0;
|
||||
|
||||
tables_kobj = kobject_create_and_add("tables", sfi_kobj);
|
||||
if (!tables_kobj) {
|
||||
kobject_put(sfi_kobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfi_sysfs_install_table(syst_pa);
|
||||
|
||||
tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
|
||||
|
||||
for (i = 0; i < tbl_cnt; i++)
|
||||
sfi_sysfs_install_table(syst_va->pentry[i]);
|
||||
|
||||
sfi_acpi_sysfs_init();
|
||||
kobject_uevent(sfi_kobj, KOBJ_ADD);
|
||||
kobject_uevent(tables_kobj, KOBJ_ADD);
|
||||
pr_info("SFI sysfs interfaces init success\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init sfi_init(void)
|
||||
{
|
||||
if (!acpi_disabled)
|
||||
disable_sfi();
|
||||
|
||||
if (sfi_disabled)
|
||||
return;
|
||||
|
||||
pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n");
|
||||
|
||||
if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init())
|
||||
disable_sfi();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void __init sfi_init_late(void)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (sfi_disabled)
|
||||
return;
|
||||
|
||||
length = syst_va->header.len;
|
||||
sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple));
|
||||
|
||||
/* Use memremap now after it is ready */
|
||||
sfi_use_memremap = 1;
|
||||
syst_va = sfi_map_memory(syst_pa, length);
|
||||
|
||||
sfi_acpi_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* The reason we put it here because we need wait till the /sys/firmware
|
||||
* is setup, then our interface can be registered in /sys/firmware/sfi
|
||||
*/
|
||||
core_initcall(sfi_sysfs_init);
|
@ -1,81 +0,0 @@
|
||||
/* 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"
|
||||
|
||||
|
@ -1,453 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Core interface for Intel MSIC
|
||||
*
|
||||
* Copyright (C) 2011, Intel Corporation
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_INTEL_MSIC_H__
|
||||
#define __LINUX_MFD_INTEL_MSIC_H__
|
||||
|
||||
/* ID */
|
||||
#define INTEL_MSIC_ID0 0x000 /* RO */
|
||||
#define INTEL_MSIC_ID1 0x001 /* RO */
|
||||
|
||||
/* IRQ */
|
||||
#define INTEL_MSIC_IRQLVL1 0x002
|
||||
#define INTEL_MSIC_ADC1INT 0x003
|
||||
#define INTEL_MSIC_CCINT 0x004
|
||||
#define INTEL_MSIC_PWRSRCINT 0x005
|
||||
#define INTEL_MSIC_PWRSRCINT1 0x006
|
||||
#define INTEL_MSIC_CHRINT 0x007
|
||||
#define INTEL_MSIC_CHRINT1 0x008
|
||||
#define INTEL_MSIC_RTCIRQ 0x009
|
||||
#define INTEL_MSIC_GPIO0LVIRQ 0x00a
|
||||
#define INTEL_MSIC_GPIO1LVIRQ 0x00b
|
||||
#define INTEL_MSIC_GPIOHVIRQ 0x00c
|
||||
#define INTEL_MSIC_VRINT 0x00d
|
||||
#define INTEL_MSIC_OCAUDIO 0x00e
|
||||
#define INTEL_MSIC_ACCDET 0x00f
|
||||
#define INTEL_MSIC_RESETIRQ1 0x010
|
||||
#define INTEL_MSIC_RESETIRQ2 0x011
|
||||
#define INTEL_MSIC_MADC1INT 0x012
|
||||
#define INTEL_MSIC_MCCINT 0x013
|
||||
#define INTEL_MSIC_MPWRSRCINT 0x014
|
||||
#define INTEL_MSIC_MPWRSRCINT1 0x015
|
||||
#define INTEL_MSIC_MCHRINT 0x016
|
||||
#define INTEL_MSIC_MCHRINT1 0x017
|
||||
#define INTEL_MSIC_RTCIRQMASK 0x018
|
||||
#define INTEL_MSIC_GPIO0LVIRQMASK 0x019
|
||||
#define INTEL_MSIC_GPIO1LVIRQMASK 0x01a
|
||||
#define INTEL_MSIC_GPIOHVIRQMASK 0x01b
|
||||
#define INTEL_MSIC_VRINTMASK 0x01c
|
||||
#define INTEL_MSIC_OCAUDIOMASK 0x01d
|
||||
#define INTEL_MSIC_ACCDETMASK 0x01e
|
||||
#define INTEL_MSIC_RESETIRQ1MASK 0x01f
|
||||
#define INTEL_MSIC_RESETIRQ2MASK 0x020
|
||||
#define INTEL_MSIC_IRQLVL1MSK 0x021
|
||||
#define INTEL_MSIC_PBCONFIG 0x03e
|
||||
#define INTEL_MSIC_PBSTATUS 0x03f /* RO */
|
||||
|
||||
/* GPIO */
|
||||
#define INTEL_MSIC_GPIO0LV7CTLO 0x040
|
||||
#define INTEL_MSIC_GPIO0LV6CTLO 0x041
|
||||
#define INTEL_MSIC_GPIO0LV5CTLO 0x042
|
||||
#define INTEL_MSIC_GPIO0LV4CTLO 0x043
|
||||
#define INTEL_MSIC_GPIO0LV3CTLO 0x044
|
||||
#define INTEL_MSIC_GPIO0LV2CTLO 0x045
|
||||
#define INTEL_MSIC_GPIO0LV1CTLO 0x046
|
||||
#define INTEL_MSIC_GPIO0LV0CTLO 0x047
|
||||
#define INTEL_MSIC_GPIO1LV7CTLOS 0x048
|
||||
#define INTEL_MSIC_GPIO1LV6CTLO 0x049
|
||||
#define INTEL_MSIC_GPIO1LV5CTLO 0x04a
|
||||
#define INTEL_MSIC_GPIO1LV4CTLO 0x04b
|
||||
#define INTEL_MSIC_GPIO1LV3CTLO 0x04c
|
||||
#define INTEL_MSIC_GPIO1LV2CTLO 0x04d
|
||||
#define INTEL_MSIC_GPIO1LV1CTLO 0x04e
|
||||
#define INTEL_MSIC_GPIO1LV0CTLO 0x04f
|
||||
#define INTEL_MSIC_GPIO0LV7CTLI 0x050
|
||||
#define INTEL_MSIC_GPIO0LV6CTLI 0x051
|
||||
#define INTEL_MSIC_GPIO0LV5CTLI 0x052
|
||||
#define INTEL_MSIC_GPIO0LV4CTLI 0x053
|
||||
#define INTEL_MSIC_GPIO0LV3CTLI 0x054
|
||||
#define INTEL_MSIC_GPIO0LV2CTLI 0x055
|
||||
#define INTEL_MSIC_GPIO0LV1CTLI 0x056
|
||||
#define INTEL_MSIC_GPIO0LV0CTLI 0x057
|
||||
#define INTEL_MSIC_GPIO1LV7CTLIS 0x058
|
||||
#define INTEL_MSIC_GPIO1LV6CTLI 0x059
|
||||
#define INTEL_MSIC_GPIO1LV5CTLI 0x05a
|
||||
#define INTEL_MSIC_GPIO1LV4CTLI 0x05b
|
||||
#define INTEL_MSIC_GPIO1LV3CTLI 0x05c
|
||||
#define INTEL_MSIC_GPIO1LV2CTLI 0x05d
|
||||
#define INTEL_MSIC_GPIO1LV1CTLI 0x05e
|
||||
#define INTEL_MSIC_GPIO1LV0CTLI 0x05f
|
||||
#define INTEL_MSIC_PWM0CLKDIV1 0x061
|
||||
#define INTEL_MSIC_PWM0CLKDIV0 0x062
|
||||
#define INTEL_MSIC_PWM1CLKDIV1 0x063
|
||||
#define INTEL_MSIC_PWM1CLKDIV0 0x064
|
||||
#define INTEL_MSIC_PWM2CLKDIV1 0x065
|
||||
#define INTEL_MSIC_PWM2CLKDIV0 0x066
|
||||
#define INTEL_MSIC_PWM0DUTYCYCLE 0x067
|
||||
#define INTEL_MSIC_PWM1DUTYCYCLE 0x068
|
||||
#define INTEL_MSIC_PWM2DUTYCYCLE 0x069
|
||||
#define INTEL_MSIC_GPIO0HV3CTLO 0x06d
|
||||
#define INTEL_MSIC_GPIO0HV2CTLO 0x06e
|
||||
#define INTEL_MSIC_GPIO0HV1CTLO 0x06f
|
||||
#define INTEL_MSIC_GPIO0HV0CTLO 0x070
|
||||
#define INTEL_MSIC_GPIO1HV3CTLO 0x071
|
||||
#define INTEL_MSIC_GPIO1HV2CTLO 0x072
|
||||
#define INTEL_MSIC_GPIO1HV1CTLO 0x073
|
||||
#define INTEL_MSIC_GPIO1HV0CTLO 0x074
|
||||
#define INTEL_MSIC_GPIO0HV3CTLI 0x075
|
||||
#define INTEL_MSIC_GPIO0HV2CTLI 0x076
|
||||
#define INTEL_MSIC_GPIO0HV1CTLI 0x077
|
||||
#define INTEL_MSIC_GPIO0HV0CTLI 0x078
|
||||
#define INTEL_MSIC_GPIO1HV3CTLI 0x079
|
||||
#define INTEL_MSIC_GPIO1HV2CTLI 0x07a
|
||||
#define INTEL_MSIC_GPIO1HV1CTLI 0x07b
|
||||
#define INTEL_MSIC_GPIO1HV0CTLI 0x07c
|
||||
|
||||
/* SVID */
|
||||
#define INTEL_MSIC_SVIDCTRL0 0x080
|
||||
#define INTEL_MSIC_SVIDCTRL1 0x081
|
||||
#define INTEL_MSIC_SVIDCTRL2 0x082
|
||||
#define INTEL_MSIC_SVIDTXLASTPKT3 0x083 /* RO */
|
||||
#define INTEL_MSIC_SVIDTXLASTPKT2 0x084 /* RO */
|
||||
#define INTEL_MSIC_SVIDTXLASTPKT1 0x085 /* RO */
|
||||
#define INTEL_MSIC_SVIDTXLASTPKT0 0x086 /* RO */
|
||||
#define INTEL_MSIC_SVIDPKTOUTBYTE3 0x087
|
||||
#define INTEL_MSIC_SVIDPKTOUTBYTE2 0x088
|
||||
#define INTEL_MSIC_SVIDPKTOUTBYTE1 0x089
|
||||
#define INTEL_MSIC_SVIDPKTOUTBYTE0 0x08a
|
||||
#define INTEL_MSIC_SVIDRXVPDEBUG1 0x08b
|
||||
#define INTEL_MSIC_SVIDRXVPDEBUG0 0x08c
|
||||
#define INTEL_MSIC_SVIDRXLASTPKT3 0x08d /* RO */
|
||||
#define INTEL_MSIC_SVIDRXLASTPKT2 0x08e /* RO */
|
||||
#define INTEL_MSIC_SVIDRXLASTPKT1 0x08f /* RO */
|
||||
#define INTEL_MSIC_SVIDRXLASTPKT0 0x090 /* RO */
|
||||
#define INTEL_MSIC_SVIDRXCHKSTATUS3 0x091 /* RO */
|
||||
#define INTEL_MSIC_SVIDRXCHKSTATUS2 0x092 /* RO */
|
||||
#define INTEL_MSIC_SVIDRXCHKSTATUS1 0x093 /* RO */
|
||||
#define INTEL_MSIC_SVIDRXCHKSTATUS0 0x094 /* RO */
|
||||
|
||||
/* VREG */
|
||||
#define INTEL_MSIC_VCCLATCH 0x0c0
|
||||
#define INTEL_MSIC_VNNLATCH 0x0c1
|
||||
#define INTEL_MSIC_VCCCNT 0x0c2
|
||||
#define INTEL_MSIC_SMPSRAMP 0x0c3
|
||||
#define INTEL_MSIC_VNNCNT 0x0c4
|
||||
#define INTEL_MSIC_VNNAONCNT 0x0c5
|
||||
#define INTEL_MSIC_VCC122AONCNT 0x0c6
|
||||
#define INTEL_MSIC_V180AONCNT 0x0c7
|
||||
#define INTEL_MSIC_V500CNT 0x0c8
|
||||
#define INTEL_MSIC_VIHFCNT 0x0c9
|
||||
#define INTEL_MSIC_LDORAMP1 0x0ca
|
||||
#define INTEL_MSIC_LDORAMP2 0x0cb
|
||||
#define INTEL_MSIC_VCC108AONCNT 0x0cc
|
||||
#define INTEL_MSIC_VCC108ASCNT 0x0cd
|
||||
#define INTEL_MSIC_VCC108CNT 0x0ce
|
||||
#define INTEL_MSIC_VCCA100ASCNT 0x0cf
|
||||
#define INTEL_MSIC_VCCA100CNT 0x0d0
|
||||
#define INTEL_MSIC_VCC180AONCNT 0x0d1
|
||||
#define INTEL_MSIC_VCC180CNT 0x0d2
|
||||
#define INTEL_MSIC_VCC330CNT 0x0d3
|
||||
#define INTEL_MSIC_VUSB330CNT 0x0d4
|
||||
#define INTEL_MSIC_VCCSDIOCNT 0x0d5
|
||||
#define INTEL_MSIC_VPROG1CNT 0x0d6
|
||||
#define INTEL_MSIC_VPROG2CNT 0x0d7
|
||||
#define INTEL_MSIC_VEMMCSCNT 0x0d8
|
||||
#define INTEL_MSIC_VEMMC1CNT 0x0d9
|
||||
#define INTEL_MSIC_VEMMC2CNT 0x0da
|
||||
#define INTEL_MSIC_VAUDACNT 0x0db
|
||||
#define INTEL_MSIC_VHSPCNT 0x0dc
|
||||
#define INTEL_MSIC_VHSNCNT 0x0dd
|
||||
#define INTEL_MSIC_VHDMICNT 0x0de
|
||||
#define INTEL_MSIC_VOTGCNT 0x0df
|
||||
#define INTEL_MSIC_V1P35CNT 0x0e0
|
||||
#define INTEL_MSIC_V330AONCNT 0x0e1
|
||||
|
||||
/* RESET */
|
||||
#define INTEL_MSIC_CHIPCNTRL 0x100 /* WO */
|
||||
#define INTEL_MSIC_ERCONFIG 0x101
|
||||
|
||||
/* BURST */
|
||||
#define INTEL_MSIC_BATCURRENTLIMIT12 0x102
|
||||
#define INTEL_MSIC_BATTIMELIMIT12 0x103
|
||||
#define INTEL_MSIC_BATTIMELIMIT3 0x104
|
||||
#define INTEL_MSIC_BATTIMEDB 0x105
|
||||
#define INTEL_MSIC_BRSTCONFIGOUTPUTS 0x106
|
||||
#define INTEL_MSIC_BRSTCONFIGACTIONS 0x107
|
||||
#define INTEL_MSIC_BURSTCONTROLSTATUS 0x108
|
||||
|
||||
/* RTC */
|
||||
#define INTEL_MSIC_RTCB1 0x140 /* RO */
|
||||
#define INTEL_MSIC_RTCB2 0x141 /* RO */
|
||||
#define INTEL_MSIC_RTCB3 0x142 /* RO */
|
||||
#define INTEL_MSIC_RTCB4 0x143 /* RO */
|
||||
#define INTEL_MSIC_RTCOB1 0x144
|
||||
#define INTEL_MSIC_RTCOB2 0x145
|
||||
#define INTEL_MSIC_RTCOB3 0x146
|
||||
#define INTEL_MSIC_RTCOB4 0x147
|
||||
#define INTEL_MSIC_RTCAB1 0x148
|
||||
#define INTEL_MSIC_RTCAB2 0x149
|
||||
#define INTEL_MSIC_RTCAB3 0x14a
|
||||
#define INTEL_MSIC_RTCAB4 0x14b
|
||||
#define INTEL_MSIC_RTCWAB1 0x14c
|
||||
#define INTEL_MSIC_RTCWAB2 0x14d
|
||||
#define INTEL_MSIC_RTCWAB3 0x14e
|
||||
#define INTEL_MSIC_RTCWAB4 0x14f
|
||||
#define INTEL_MSIC_RTCSC1 0x150
|
||||
#define INTEL_MSIC_RTCSC2 0x151
|
||||
#define INTEL_MSIC_RTCSC3 0x152
|
||||
#define INTEL_MSIC_RTCSC4 0x153
|
||||
#define INTEL_MSIC_RTCSTATUS 0x154 /* RO */
|
||||
#define INTEL_MSIC_RTCCONFIG1 0x155
|
||||
#define INTEL_MSIC_RTCCONFIG2 0x156
|
||||
|
||||
/* CHARGER */
|
||||
#define INTEL_MSIC_BDTIMER 0x180
|
||||
#define INTEL_MSIC_BATTRMV 0x181
|
||||
#define INTEL_MSIC_VBUSDET 0x182
|
||||
#define INTEL_MSIC_VBUSDET1 0x183
|
||||
#define INTEL_MSIC_ADPHVDET 0x184
|
||||
#define INTEL_MSIC_ADPLVDET 0x185
|
||||
#define INTEL_MSIC_ADPDETDBDM 0x186
|
||||
#define INTEL_MSIC_LOWBATTDET 0x187
|
||||
#define INTEL_MSIC_CHRCTRL 0x188
|
||||
#define INTEL_MSIC_CHRCVOLTAGE 0x189
|
||||
#define INTEL_MSIC_CHRCCURRENT 0x18a
|
||||
#define INTEL_MSIC_SPCHARGER 0x18b
|
||||
#define INTEL_MSIC_CHRTTIME 0x18c
|
||||
#define INTEL_MSIC_CHRCTRL1 0x18d
|
||||
#define INTEL_MSIC_PWRSRCLMT 0x18e
|
||||
#define INTEL_MSIC_CHRSTWDT 0x18f
|
||||
#define INTEL_MSIC_WDTWRITE 0x190 /* WO */
|
||||
#define INTEL_MSIC_CHRSAFELMT 0x191
|
||||
#define INTEL_MSIC_SPWRSRCINT 0x192 /* RO */
|
||||
#define INTEL_MSIC_SPWRSRCINT1 0x193 /* RO */
|
||||
#define INTEL_MSIC_CHRLEDPWM 0x194
|
||||
#define INTEL_MSIC_CHRLEDCTRL 0x195
|
||||
|
||||
/* ADC */
|
||||
#define INTEL_MSIC_ADC1CNTL1 0x1c0
|
||||
#define INTEL_MSIC_ADC1CNTL2 0x1c1
|
||||
#define INTEL_MSIC_ADC1CNTL3 0x1c2
|
||||
#define INTEL_MSIC_ADC1OFFSETH 0x1c3 /* RO */
|
||||
#define INTEL_MSIC_ADC1OFFSETL 0x1c4 /* RO */
|
||||
#define INTEL_MSIC_ADC1ADDR0 0x1c5
|
||||
#define INTEL_MSIC_ADC1ADDR1 0x1c6
|
||||
#define INTEL_MSIC_ADC1ADDR2 0x1c7
|
||||
#define INTEL_MSIC_ADC1ADDR3 0x1c8
|
||||
#define INTEL_MSIC_ADC1ADDR4 0x1c9
|
||||
#define INTEL_MSIC_ADC1ADDR5 0x1ca
|
||||
#define INTEL_MSIC_ADC1ADDR6 0x1cb
|
||||
#define INTEL_MSIC_ADC1ADDR7 0x1cc
|
||||
#define INTEL_MSIC_ADC1ADDR8 0x1cd
|
||||
#define INTEL_MSIC_ADC1ADDR9 0x1ce
|
||||
#define INTEL_MSIC_ADC1ADDR10 0x1cf
|
||||
#define INTEL_MSIC_ADC1ADDR11 0x1d0
|
||||
#define INTEL_MSIC_ADC1ADDR12 0x1d1
|
||||
#define INTEL_MSIC_ADC1ADDR13 0x1d2
|
||||
#define INTEL_MSIC_ADC1ADDR14 0x1d3
|
||||
#define INTEL_MSIC_ADC1SNS0H 0x1d4 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS0L 0x1d5 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS1H 0x1d6 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS1L 0x1d7 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS2H 0x1d8 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS2L 0x1d9 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS3H 0x1da /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS3L 0x1db /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS4H 0x1dc /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS4L 0x1dd /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS5H 0x1de /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS5L 0x1df /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS6H 0x1e0 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS6L 0x1e1 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS7H 0x1e2 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS7L 0x1e3 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS8H 0x1e4 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS8L 0x1e5 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS9H 0x1e6 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS9L 0x1e7 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS10H 0x1e8 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS10L 0x1e9 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS11H 0x1ea /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS11L 0x1eb /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS12H 0x1ec /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS12L 0x1ed /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS13H 0x1ee /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS13L 0x1ef /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS14H 0x1f0 /* RO */
|
||||
#define INTEL_MSIC_ADC1SNS14L 0x1f1 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV0H 0x1f2 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV0L 0x1f3 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV1H 0x1f4 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV1L 0x1f5 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV2H 0x1f6 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV2L 0x1f7 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV3H 0x1f8 /* RO */
|
||||
#define INTEL_MSIC_ADC1BV3L 0x1f9 /* RO */
|
||||
#define INTEL_MSIC_ADC1BI0H 0x1fa /* RO */
|
||||
#define INTEL_MSIC_ADC1BI0L 0x1fb /* RO */
|
||||
#define INTEL_MSIC_ADC1BI1H 0x1fc /* RO */
|
||||
#define INTEL_MSIC_ADC1BI1L 0x1fd /* RO */
|
||||
#define INTEL_MSIC_ADC1BI2H 0x1fe /* RO */
|
||||
#define INTEL_MSIC_ADC1BI2L 0x1ff /* RO */
|
||||
#define INTEL_MSIC_ADC1BI3H 0x200 /* RO */
|
||||
#define INTEL_MSIC_ADC1BI3L 0x201 /* RO */
|
||||
#define INTEL_MSIC_CCCNTL 0x202
|
||||
#define INTEL_MSIC_CCOFFSETH 0x203 /* RO */
|
||||
#define INTEL_MSIC_CCOFFSETL 0x204 /* RO */
|
||||
#define INTEL_MSIC_CCADCHA 0x205 /* RO */
|
||||
#define INTEL_MSIC_CCADCLA 0x206 /* RO */
|
||||
|
||||
/* AUDIO */
|
||||
#define INTEL_MSIC_AUDPLLCTRL 0x240
|
||||
#define INTEL_MSIC_DMICBUF0123 0x241
|
||||
#define INTEL_MSIC_DMICBUF45 0x242
|
||||
#define INTEL_MSIC_DMICGPO 0x244
|
||||
#define INTEL_MSIC_DMICMUX 0x245
|
||||
#define INTEL_MSIC_DMICCLK 0x246
|
||||
#define INTEL_MSIC_MICBIAS 0x247
|
||||
#define INTEL_MSIC_ADCCONFIG 0x248
|
||||
#define INTEL_MSIC_MICAMP1 0x249
|
||||
#define INTEL_MSIC_MICAMP2 0x24a
|
||||
#define INTEL_MSIC_NOISEMUX 0x24b
|
||||
#define INTEL_MSIC_AUDIOMUX12 0x24c
|
||||
#define INTEL_MSIC_AUDIOMUX34 0x24d
|
||||
#define INTEL_MSIC_AUDIOSINC 0x24e
|
||||
#define INTEL_MSIC_AUDIOTXEN 0x24f
|
||||
#define INTEL_MSIC_HSEPRXCTRL 0x250
|
||||
#define INTEL_MSIC_IHFRXCTRL 0x251
|
||||
#define INTEL_MSIC_VOICETXVOL 0x252
|
||||
#define INTEL_MSIC_SIDETONEVOL 0x253
|
||||
#define INTEL_MSIC_MUSICSHARVOL 0x254
|
||||
#define INTEL_MSIC_VOICETXCTRL 0x255
|
||||
#define INTEL_MSIC_HSMIXER 0x256
|
||||
#define INTEL_MSIC_DACCONFIG 0x257
|
||||
#define INTEL_MSIC_SOFTMUTE 0x258
|
||||
#define INTEL_MSIC_HSLVOLCTRL 0x259
|
||||
#define INTEL_MSIC_HSRVOLCTRL 0x25a
|
||||
#define INTEL_MSIC_IHFLVOLCTRL 0x25b
|
||||
#define INTEL_MSIC_IHFRVOLCTRL 0x25c
|
||||
#define INTEL_MSIC_DRIVEREN 0x25d
|
||||
#define INTEL_MSIC_LINEOUTCTRL 0x25e
|
||||
#define INTEL_MSIC_VIB1CTRL1 0x25f
|
||||
#define INTEL_MSIC_VIB1CTRL2 0x260
|
||||
#define INTEL_MSIC_VIB1CTRL3 0x261
|
||||
#define INTEL_MSIC_VIB1SPIPCM_1 0x262
|
||||
#define INTEL_MSIC_VIB1SPIPCM_2 0x263
|
||||
#define INTEL_MSIC_VIB1CTRL5 0x264
|
||||
#define INTEL_MSIC_VIB2CTRL1 0x265
|
||||
#define INTEL_MSIC_VIB2CTRL2 0x266
|
||||
#define INTEL_MSIC_VIB2CTRL3 0x267
|
||||
#define INTEL_MSIC_VIB2SPIPCM_1 0x268
|
||||
#define INTEL_MSIC_VIB2SPIPCM_2 0x269
|
||||
#define INTEL_MSIC_VIB2CTRL5 0x26a
|
||||
#define INTEL_MSIC_BTNCTRL1 0x26b
|
||||
#define INTEL_MSIC_BTNCTRL2 0x26c
|
||||
#define INTEL_MSIC_PCM1TXSLOT01 0x26d
|
||||
#define INTEL_MSIC_PCM1TXSLOT23 0x26e
|
||||
#define INTEL_MSIC_PCM1TXSLOT45 0x26f
|
||||
#define INTEL_MSIC_PCM1RXSLOT0123 0x270
|
||||
#define INTEL_MSIC_PCM1RXSLOT045 0x271
|
||||
#define INTEL_MSIC_PCM2TXSLOT01 0x272
|
||||
#define INTEL_MSIC_PCM2TXSLOT23 0x273
|
||||
#define INTEL_MSIC_PCM2TXSLOT45 0x274
|
||||
#define INTEL_MSIC_PCM2RXSLOT01 0x275
|
||||
#define INTEL_MSIC_PCM2RXSLOT23 0x276
|
||||
#define INTEL_MSIC_PCM2RXSLOT45 0x277
|
||||
#define INTEL_MSIC_PCM1CTRL1 0x278
|
||||
#define INTEL_MSIC_PCM1CTRL2 0x279
|
||||
#define INTEL_MSIC_PCM1CTRL3 0x27a
|
||||
#define INTEL_MSIC_PCM2CTRL1 0x27b
|
||||
#define INTEL_MSIC_PCM2CTRL2 0x27c
|
||||
|
||||
/* HDMI */
|
||||
#define INTEL_MSIC_HDMIPUEN 0x280
|
||||
#define INTEL_MSIC_HDMISTATUS 0x281 /* RO */
|
||||
|
||||
/* Physical address of the start of the MSIC interrupt tree in SRAM */
|
||||
#define INTEL_MSIC_IRQ_PHYS_BASE 0xffff7fc0
|
||||
|
||||
/**
|
||||
* struct intel_msic_gpio_pdata - platform data for the MSIC GPIO driver
|
||||
* @gpio_base: base number for the GPIOs
|
||||
*/
|
||||
struct intel_msic_gpio_pdata {
|
||||
unsigned gpio_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct intel_msic_ocd_pdata - platform data for the MSIC OCD driver
|
||||
* @gpio: GPIO number used for OCD interrupts
|
||||
*
|
||||
* The MSIC MFD driver converts @gpio into an IRQ number and passes it to
|
||||
* the OCD driver as %IORESOURCE_IRQ.
|
||||
*/
|
||||
struct intel_msic_ocd_pdata {
|
||||
unsigned gpio;
|
||||
};
|
||||
|
||||
/* MSIC embedded blocks (subdevices) */
|
||||
enum intel_msic_block {
|
||||
INTEL_MSIC_BLOCK_TOUCH,
|
||||
INTEL_MSIC_BLOCK_ADC,
|
||||
INTEL_MSIC_BLOCK_BATTERY,
|
||||
INTEL_MSIC_BLOCK_GPIO,
|
||||
INTEL_MSIC_BLOCK_AUDIO,
|
||||
INTEL_MSIC_BLOCK_HDMI,
|
||||
INTEL_MSIC_BLOCK_THERMAL,
|
||||
INTEL_MSIC_BLOCK_POWER_BTN,
|
||||
INTEL_MSIC_BLOCK_OCD,
|
||||
|
||||
INTEL_MSIC_BLOCK_LAST,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct intel_msic_platform_data - platform data for the MSIC driver
|
||||
* @irq: array of interrupt numbers, one per device. If @irq is set to %0
|
||||
* for a given block, the corresponding platform device is not
|
||||
* created. For devices which don't have an interrupt, use %0xff
|
||||
* (this is same as in SFI spec).
|
||||
* @gpio: platform data for the MSIC GPIO driver
|
||||
* @ocd: platform data for the MSIC OCD driver
|
||||
*
|
||||
* Once the MSIC driver is initialized, the register interface is ready to
|
||||
* use. All the platform devices for subdevices are created after the
|
||||
* register interface is ready so that we can guarantee its availability to
|
||||
* the subdevice drivers.
|
||||
*
|
||||
* Interrupt numbers are passed to the subdevices via %IORESOURCE_IRQ
|
||||
* resources of the created platform device.
|
||||
*/
|
||||
struct intel_msic_platform_data {
|
||||
int irq[INTEL_MSIC_BLOCK_LAST];
|
||||
struct intel_msic_gpio_pdata *gpio;
|
||||
struct intel_msic_ocd_pdata *ocd;
|
||||
};
|
||||
|
||||
struct intel_msic;
|
||||
|
||||
extern int intel_msic_reg_read(unsigned short reg, u8 *val);
|
||||
extern int intel_msic_reg_write(unsigned short reg, u8 val);
|
||||
extern int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask);
|
||||
extern int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count);
|
||||
extern int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count);
|
||||
|
||||
/*
|
||||
* pdev_to_intel_msic - gets an MSIC instance from the platform device
|
||||
* @pdev: platform device pointer
|
||||
*
|
||||
* The client drivers need to have pointer to the MSIC instance if they
|
||||
* want to call intel_msic_irq_read(). This macro can be used for
|
||||
* convenience to get the MSIC pointer from @pdev where needed. This is
|
||||
* _only_ valid for devices which are managed by the MSIC.
|
||||
*/
|
||||
#define pdev_to_intel_msic(pdev) (dev_get_drvdata(pdev->dev.parent))
|
||||
|
||||
extern int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg,
|
||||
u8 *val);
|
||||
|
||||
#endif /* __LINUX_MFD_INTEL_MSIC_H__ */
|
@ -1,210 +0,0 @@
|
||||
/* 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*/
|
@ -1,93 +0,0 @@
|
||||
/* 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user