forked from mirrors/linux
		
	sfi: Remove framework for deprecated firmware
SFI-based platforms are gone. So does this framework. This removes mention of SFI through the drivers and other code as well. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									73f70d6c20
								
							
						
					
					
						commit
						4590d98f5a
					
				
					 42 changed files with 14 additions and 2695 deletions
				
			
		|  | @ -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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -16234,13 +16234,6 @@ S:	Maintained | |||
| F:	Documentation/fb/sm712fb.rst | ||||
| F:	drivers/video/fbdev/sm712* | ||||
| 
 | ||||
| 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 | ||||
|  |  | |||
|  | @ -444,7 +444,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 | ||||
|  | @ -603,7 +603,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 | ||||
|  | @ -2457,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 | ||||
|  | @ -2645,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 | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ | |||
| #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> | ||||
| 
 | ||||
|  | @ -22,39 +21,6 @@ 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); | ||||
| 
 | ||||
| /*
 | ||||
|  * 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; | ||||
| 	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 | ||||
|  | @ -99,7 +65,4 @@ static inline void intel_scu_devices_destroy(void) { } | |||
| /* FSB 83MHz */ | ||||
| #define BSEL_SOC_FUSE_111		0x7 | ||||
| 
 | ||||
| /* The offset for the mapping of global gpio pin to irq */ | ||||
| #define INTEL_MID_IRQ_OFFSET		0x100 | ||||
| 
 | ||||
| #endif /* _ASM_X86_INTEL_MID_H */ | ||||
|  |  | |||
|  | @ -2,73 +2,17 @@ | |||
| #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 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| /* Don't call these in new code - they will be removed eventually */ | ||||
| 
 | ||||
| /* 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 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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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(); | ||||
| 
 | ||||
| 	/*
 | ||||
|  |  | |||
|  | @ -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); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -11,6 +11,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 pwr.o | ||||
| 
 | ||||
| # SFI specific code
 | ||||
| ifdef CONFIG_X86_INTEL_MID | ||||
| obj-$(CONFIG_SFI) += sfi.o device_libs/ | ||||
| endif | ||||
|  |  | |||
|  | @ -1,23 +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 | ||||
| # 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_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,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,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); | ||||
|  | @ -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> | ||||
|  |  | |||
|  | @ -1,419 +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/io.h> | ||||
| #include <asm/i8259.h> | ||||
| #include <asm/intel_scu_ipc.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 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; | ||||
| 
 | ||||
| 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) | ||||
| 
 | ||||
| /*
 | ||||
|  * 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; | ||||
| 
 | ||||
| 	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/ | ||||
|  |  | |||
|  | @ -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); | ||||
|  | @ -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 a new issue
	
	 Andy Shevchenko
						Andy Shevchenko