diff options
Diffstat (limited to 'arch/x86/platform')
| -rw-r--r-- | arch/x86/platform/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi-bgrt.c | 7 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 59 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 22 | ||||
| -rw-r--r-- | arch/x86/platform/goldfish/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/platform/goldfish/goldfish.c | 51 | ||||
| -rw-r--r-- | arch/x86/platform/mrst/mrst.c | 2 | ||||
| -rw-r--r-- | arch/x86/platform/olpc/olpc-xo1-pm.c | 8 | ||||
| -rw-r--r-- | arch/x86/platform/olpc/olpc-xo1-sci.c | 18 | ||||
| -rw-r--r-- | arch/x86/platform/scx200/scx200_32.c | 6 | ||||
| -rw-r--r-- | arch/x86/platform/sfi/sfi.c | 2 | ||||
| -rw-r--r-- | arch/x86/platform/ts5500/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/platform/ts5500/ts5500.c | 339 | ||||
| -rw-r--r-- | arch/x86/platform/uv/tlb_uv.c | 14 | ||||
| -rw-r--r-- | arch/x86/platform/uv/uv_time.c | 13 | 
15 files changed, 484 insertions, 61 deletions
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 8d874396cb2..01e0231a113 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile @@ -2,10 +2,12 @@  obj-y	+= ce4100/  obj-y	+= efi/  obj-y	+= geode/ +obj-y	+= goldfish/  obj-y	+= iris/  obj-y	+= mrst/  obj-y	+= olpc/  obj-y	+= scx200/  obj-y	+= sfi/ +obj-y	+= ts5500/  obj-y	+= visws/  obj-y	+= uv/ diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c index d9c1b95af17..7145ec63c52 100644 --- a/arch/x86/platform/efi/efi-bgrt.c +++ b/arch/x86/platform/efi/efi-bgrt.c @@ -11,20 +11,21 @@   * published by the Free Software Foundation.   */  #include <linux/kernel.h> +#include <linux/init.h>  #include <linux/acpi.h>  #include <linux/efi.h>  #include <linux/efi-bgrt.h>  struct acpi_table_bgrt *bgrt_tab; -void *bgrt_image; -size_t bgrt_image_size; +void *__initdata bgrt_image; +size_t __initdata bgrt_image_size;  struct bmp_header {  	u16 id;  	u32 size;  } __packed; -void efi_bgrt_init(void) +void __init efi_bgrt_init(void)  {  	acpi_status status;  	void __iomem *image; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ad4439145f8..928bf837040 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -51,9 +51,6 @@  #define EFI_DEBUG	1 -int efi_enabled; -EXPORT_SYMBOL(efi_enabled); -  struct efi __read_mostly efi = {  	.mps        = EFI_INVALID_TABLE_ADDR,  	.acpi       = EFI_INVALID_TABLE_ADDR, @@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi);  struct efi_memory_map memmap; -bool efi_64bit; -  static struct efi efi_phys __initdata;  static efi_system_table_t efi_systab __initdata;  static inline bool efi_is_native(void)  { -	return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +	return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); +} + +unsigned long x86_efi_facility; + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ +	return test_bit(facility, &x86_efi_facility) != 0;  } +EXPORT_SYMBOL(efi_enabled);  static int __init setup_noefi(char *arg)  { -	efi_enabled = 0; +	clear_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);  	return 0;  }  early_param("noefi", setup_noefi); @@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void)  void __init efi_unmap_memmap(void)  { +	clear_bit(EFI_MEMMAP, &x86_efi_facility);  	if (memmap.map) {  		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);  		memmap.map = NULL; @@ -460,7 +467,7 @@ void __init efi_free_boot_services(void)  static int __init efi_systab_init(void *phys)  { -	if (efi_64bit) { +	if (efi_enabled(EFI_64BIT)) {  		efi_system_table_64_t *systab64;  		u64 tmp = 0; @@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)  	void *config_tables, *tablep;  	int i, sz; -	if (efi_64bit) +	if (efi_enabled(EFI_64BIT))  		sz = sizeof(efi_config_table_64_t);  	else  		sz = sizeof(efi_config_table_32_t); @@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)  		efi_guid_t guid;  		unsigned long table; -		if (efi_64bit) { +		if (efi_enabled(EFI_64BIT)) {  			u64 table64;  			guid = ((efi_config_table_64_t *)tablep)->guid;  			table64 = ((efi_config_table_64_t *)tablep)->table; @@ -684,7 +691,6 @@ void __init efi_init(void)  	if (boot_params.efi_info.efi_systab_hi ||  	    boot_params.efi_info.efi_memmap_hi) {  		pr_info("Table located above 4GB, disabling EFI.\n"); -		efi_enabled = 0;  		return;  	}  	efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; @@ -694,10 +700,10 @@ void __init efi_init(void)  			  ((__u64)boot_params.efi_info.efi_systab_hi<<32));  #endif -	if (efi_systab_init(efi_phys.systab)) { -		efi_enabled = 0; +	if (efi_systab_init(efi_phys.systab))  		return; -	} + +	set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);  	/*  	 * Show what we know for posterity @@ -715,10 +721,10 @@ void __init efi_init(void)  		efi.systab->hdr.revision >> 16,  		efi.systab->hdr.revision & 0xffff, vendor); -	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { -		efi_enabled = 0; +	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))  		return; -	} + +	set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);  	/*  	 * Note: We currently don't support runtime services on an EFI @@ -727,15 +733,17 @@ void __init efi_init(void)  	if (!efi_is_native())  		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); -	else if (efi_runtime_init()) { -		efi_enabled = 0; -		return; +	else { +		if (efi_runtime_init()) +			return; +		set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);  	} -	if (efi_memmap_init()) { -		efi_enabled = 0; +	if (efi_memmap_init())  		return; -	} + +	set_bit(EFI_MEMMAP, &x86_efi_facility); +  #ifdef CONFIG_X86_32  	if (efi_is_native()) {  		x86_platform.get_wallclock = efi_get_time; @@ -941,7 +949,7 @@ void __init efi_enter_virtual_mode(void)  	 *  	 * Call EFI services through wrapper functions.  	 */ -	efi.runtime_version = efi_systab.fw_revision; +	efi.runtime_version = efi_systab.hdr.revision;  	efi.get_time = virt_efi_get_time;  	efi.set_time = virt_efi_set_time;  	efi.get_wakeup_time = virt_efi_get_wakeup_time; @@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr)  	efi_memory_desc_t *md;  	void *p; +	if (!efi_enabled(EFI_MEMMAP)) +		return 0; +  	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {  		md = p;  		if ((md->phys_addr <= phys_addr) && diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 95fd505dfeb..2b200386061 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -38,7 +38,7 @@  #include <asm/cacheflush.h>  #include <asm/fixmap.h> -static pgd_t save_pgd __initdata; +static pgd_t *save_pgd __initdata;  static unsigned long efi_flags __initdata;  static void __init early_code_mapping_set_exec(int executable) @@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable)  void __init efi_call_phys_prelog(void)  {  	unsigned long vaddress; +	int pgd; +	int n_pgds;  	early_code_mapping_set_exec(1);  	local_irq_save(efi_flags); -	vaddress = (unsigned long)__va(0x0UL); -	save_pgd = *pgd_offset_k(0x0UL); -	set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); + +	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); +	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); + +	for (pgd = 0; pgd < n_pgds; pgd++) { +		save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); +		vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); +		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); +	}  	__flush_tlb_all();  } @@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void)  	/*  	 * After the lock is released, the original page table is restored.  	 */ -	set_pgd(pgd_offset_k(0x0UL), save_pgd); +	int pgd; +	int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); +	for (pgd = 0; pgd < n_pgds; pgd++) +		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); +	kfree(save_pgd);  	__flush_tlb_all();  	local_irq_restore(efi_flags);  	early_code_mapping_set_exec(0); diff --git a/arch/x86/platform/goldfish/Makefile b/arch/x86/platform/goldfish/Makefile new file mode 100644 index 00000000000..f030b532fdf --- /dev/null +++ b/arch/x86/platform/goldfish/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_GOLDFISH)	+= goldfish.o diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c new file mode 100644 index 00000000000..1693107a518 --- /dev/null +++ b/arch/x86/platform/goldfish/goldfish.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (C) 2011 Intel, Inc. + * Copyright (C) 2013 Intel, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/platform_device.h> + +/* + * Where in virtual device memory the IO devices (timers, system controllers + * and so on) + */ + +#define GOLDFISH_PDEV_BUS_BASE	(0xff001000) +#define GOLDFISH_PDEV_BUS_END	(0xff7fffff) +#define GOLDFISH_PDEV_BUS_IRQ	(4) + +#define GOLDFISH_TTY_BASE	(0x2000) + +static struct resource goldfish_pdev_bus_resources[] = { +	{ +		.start  = GOLDFISH_PDEV_BUS_BASE, +		.end    = GOLDFISH_PDEV_BUS_END, +		.flags  = IORESOURCE_MEM, +	}, +	{ +		.start	= GOLDFISH_PDEV_BUS_IRQ, +		.end	= GOLDFISH_PDEV_BUS_IRQ, +		.flags	= IORESOURCE_IRQ, +	} +}; + +static int __init goldfish_init(void) +{ +	platform_device_register_simple("goldfish_pdev_bus", -1, +						goldfish_pdev_bus_resources, 2); +	return 0; +} +device_initcall(goldfish_init); diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index fd41a9262d6..e31bcd8f2ee 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -782,7 +782,7 @@ BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);  EXPORT_SYMBOL_GPL(intel_scu_notifier);  /* Called by IPC driver */ -void __devinit intel_scu_devices_create(void) +void intel_scu_devices_create(void)  {  	int i; diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index d75582d1aa5..ff0174dda81 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -121,7 +121,7 @@ static const struct platform_suspend_ops xo1_suspend_ops = {  	.enter = xo1_power_state_enter,  }; -static int __devinit xo1_pm_probe(struct platform_device *pdev) +static int xo1_pm_probe(struct platform_device *pdev)  {  	struct resource *res;  	int err; @@ -154,7 +154,7 @@ static int __devinit xo1_pm_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit xo1_pm_remove(struct platform_device *pdev) +static int xo1_pm_remove(struct platform_device *pdev)  {  	mfd_cell_disable(pdev); @@ -173,7 +173,7 @@ static struct platform_driver cs5535_pms_driver = {  		.owner = THIS_MODULE,  	},  	.probe = xo1_pm_probe, -	.remove = __devexit_p(xo1_pm_remove), +	.remove = xo1_pm_remove,  };  static struct platform_driver cs5535_acpi_driver = { @@ -182,7 +182,7 @@ static struct platform_driver cs5535_acpi_driver = {  		.owner = THIS_MODULE,  	},  	.probe = xo1_pm_probe, -	.remove = __devexit_p(xo1_pm_remove), +	.remove = xo1_pm_remove,  };  static int __init xo1_pm_init(void) diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 63d4aa40956..74704be7b1f 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -309,7 +309,7 @@ static int xo1_sci_resume(struct platform_device *pdev)  	return 0;  } -static int __devinit setup_sci_interrupt(struct platform_device *pdev) +static int setup_sci_interrupt(struct platform_device *pdev)  {  	u32 lo, hi;  	u32 sts; @@ -351,7 +351,7 @@ static int __devinit setup_sci_interrupt(struct platform_device *pdev)  	return r;  } -static int __devinit setup_ec_sci(void) +static int setup_ec_sci(void)  {  	int r; @@ -395,7 +395,7 @@ static void free_ec_sci(void)  	gpio_free(OLPC_GPIO_ECSCI);  } -static int __devinit setup_lid_events(void) +static int setup_lid_events(void)  {  	int r; @@ -432,7 +432,7 @@ static void free_lid_events(void)  	gpio_free(OLPC_GPIO_LID);  } -static int __devinit setup_power_button(struct platform_device *pdev) +static int setup_power_button(struct platform_device *pdev)  {  	int r; @@ -463,7 +463,7 @@ static void free_power_button(void)  	input_free_device(power_button_idev);  } -static int __devinit setup_ebook_switch(struct platform_device *pdev) +static int setup_ebook_switch(struct platform_device *pdev)  {  	int r; @@ -494,7 +494,7 @@ static void free_ebook_switch(void)  	input_free_device(ebook_switch_idev);  } -static int __devinit setup_lid_switch(struct platform_device *pdev) +static int setup_lid_switch(struct platform_device *pdev)  {  	int r; @@ -538,7 +538,7 @@ static void free_lid_switch(void)  	input_free_device(lid_switch_idev);  } -static int __devinit xo1_sci_probe(struct platform_device *pdev) +static int xo1_sci_probe(struct platform_device *pdev)  {  	struct resource *res;  	int r; @@ -613,7 +613,7 @@ err_ebook:  	return r;  } -static int __devexit xo1_sci_remove(struct platform_device *pdev) +static int xo1_sci_remove(struct platform_device *pdev)  {  	mfd_cell_disable(pdev);  	free_irq(sci_irq, pdev); @@ -632,7 +632,7 @@ static struct platform_driver xo1_sci_driver = {  		.name = "olpc-xo1-sci-acpi",  	},  	.probe = xo1_sci_probe, -	.remove = __devexit_p(xo1_sci_remove), +	.remove = xo1_sci_remove,  	.suspend = xo1_sci_suspend,  	.resume = xo1_sci_resume,  }; diff --git a/arch/x86/platform/scx200/scx200_32.c b/arch/x86/platform/scx200/scx200_32.c index 7a9ad30d6c9..3dc9aee41d9 100644 --- a/arch/x86/platform/scx200/scx200_32.c +++ b/arch/x86/platform/scx200/scx200_32.c @@ -35,7 +35,7 @@ static struct pci_device_id scx200_tbl[] = {  };  MODULE_DEVICE_TABLE(pci,scx200_tbl); -static int __devinit scx200_probe(struct pci_dev *, const struct pci_device_id *); +static int scx200_probe(struct pci_dev *, const struct pci_device_id *);  static struct pci_driver scx200_pci_driver = {  	.name = "scx200", @@ -45,7 +45,7 @@ static struct pci_driver scx200_pci_driver = {  static DEFINE_MUTEX(scx200_gpio_config_lock); -static void __devinit scx200_init_shadow(void) +static void scx200_init_shadow(void)  {  	int bank; @@ -54,7 +54,7 @@ static void __devinit scx200_init_shadow(void)  		scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);  } -static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	unsigned base; diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c index 7785b72ecc3..bcd1a703e3e 100644 --- a/arch/x86/platform/sfi/sfi.c +++ b/arch/x86/platform/sfi/sfi.c @@ -35,7 +35,7 @@  static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;  /* All CPUs enumerated by SFI must be present and enabled */ -static void __cpuinit mp_sfi_register_lapic(u8 id) +static void __init mp_sfi_register_lapic(u8 id)  {  	if (MAX_LOCAL_APIC - id <= 0) {  		pr_warning("Processor #%d invalid (max %d)\n", diff --git a/arch/x86/platform/ts5500/Makefile b/arch/x86/platform/ts5500/Makefile new file mode 100644 index 00000000000..c54e348c96a --- /dev/null +++ b/arch/x86/platform/ts5500/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TS5500)	+= ts5500.o diff --git a/arch/x86/platform/ts5500/ts5500.c b/arch/x86/platform/ts5500/ts5500.c new file mode 100644 index 00000000000..39febb214e8 --- /dev/null +++ b/arch/x86/platform/ts5500/ts5500.c @@ -0,0 +1,339 @@ +/* + * Technologic Systems TS-5500 Single Board Computer support + * + * Copyright (C) 2013 Savoir-faire Linux Inc. + *	Vivien Didelot <vivien.didelot@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * + * This driver registers the Technologic Systems TS-5500 Single Board Computer + * (SBC) and its devices, and exposes information to userspace such as jumpers' + * state or available options. For further information about sysfs entries, see + * Documentation/ABI/testing/sysfs-platform-ts5500. + * + * This code actually supports the TS-5500 platform, but it may be extended to + * support similar Technologic Systems x86-based platforms, such as the TS-5600. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/platform_data/gpio-ts5500.h> +#include <linux/platform_data/max197.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +/* Product code register */ +#define TS5500_PRODUCT_CODE_ADDR	0x74 +#define TS5500_PRODUCT_CODE		0x60	/* TS-5500 product code */ + +/* SRAM/RS-485/ADC options, and RS-485 RTS/Automatic RS-485 flags register */ +#define TS5500_SRAM_RS485_ADC_ADDR	0x75 +#define TS5500_SRAM			BIT(0)	/* SRAM option */ +#define TS5500_RS485			BIT(1)	/* RS-485 option */ +#define TS5500_ADC			BIT(2)	/* A/D converter option */ +#define TS5500_RS485_RTS		BIT(6)	/* RTS for RS-485 */ +#define TS5500_RS485_AUTO		BIT(7)	/* Automatic RS-485 */ + +/* External Reset/Industrial Temperature Range options register */ +#define TS5500_ERESET_ITR_ADDR		0x76 +#define TS5500_ERESET			BIT(0)	/* External Reset option */ +#define TS5500_ITR			BIT(1)	/* Indust. Temp. Range option */ + +/* LED/Jumpers register */ +#define TS5500_LED_JP_ADDR		0x77 +#define TS5500_LED			BIT(0)	/* LED flag */ +#define TS5500_JP1			BIT(1)	/* Automatic CMOS */ +#define TS5500_JP2			BIT(2)	/* Enable Serial Console */ +#define TS5500_JP3			BIT(3)	/* Write Enable Drive A */ +#define TS5500_JP4			BIT(4)	/* Fast Console (115K baud) */ +#define TS5500_JP5			BIT(5)	/* User Jumper */ +#define TS5500_JP6			BIT(6)	/* Console on COM1 (req. JP2) */ +#define TS5500_JP7			BIT(7)	/* Undocumented (Unused) */ + +/* A/D Converter registers */ +#define TS5500_ADC_CONV_BUSY_ADDR	0x195	/* Conversion state register */ +#define TS5500_ADC_CONV_BUSY		BIT(0) +#define TS5500_ADC_CONV_INIT_LSB_ADDR	0x196	/* Start conv. / LSB register */ +#define TS5500_ADC_CONV_MSB_ADDR	0x197	/* MSB register */ +#define TS5500_ADC_CONV_DELAY		12	/* usec */ + +/** + * struct ts5500_sbc - TS-5500 board description + * @id:		Board product ID. + * @sram:	Flag for SRAM option. + * @rs485:	Flag for RS-485 option. + * @adc:	Flag for Analog/Digital converter option. + * @ereset:	Flag for External Reset option. + * @itr:	Flag for Industrial Temperature Range option. + * @jumpers:	Bitfield for jumpers' state. + */ +struct ts5500_sbc { +	int	id; +	bool	sram; +	bool	rs485; +	bool	adc; +	bool	ereset; +	bool	itr; +	u8	jumpers; +}; + +/* Board signatures in BIOS shadow RAM */ +static const struct { +	const char * const string; +	const ssize_t offset; +} ts5500_signatures[] __initdata = { +	{ "TS-5x00 AMD Elan", 0xb14 }, +}; + +static int __init ts5500_check_signature(void) +{ +	void __iomem *bios; +	int i, ret = -ENODEV; + +	bios = ioremap(0xf0000, 0x10000); +	if (!bios) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(ts5500_signatures); i++) { +		if (check_signature(bios + ts5500_signatures[i].offset, +				    ts5500_signatures[i].string, +				    strlen(ts5500_signatures[i].string))) { +			ret = 0; +			break; +		} +	} + +	iounmap(bios); +	return ret; +} + +static int __init ts5500_detect_config(struct ts5500_sbc *sbc) +{ +	u8 tmp; +	int ret = 0; + +	if (!request_region(TS5500_PRODUCT_CODE_ADDR, 4, "ts5500")) +		return -EBUSY; + +	tmp = inb(TS5500_PRODUCT_CODE_ADDR); +	if (tmp != TS5500_PRODUCT_CODE) { +		pr_err("This platform is not a TS-5500 (found ID 0x%x)\n", tmp); +		ret = -ENODEV; +		goto cleanup; +	} +	sbc->id = tmp; + +	tmp = inb(TS5500_SRAM_RS485_ADC_ADDR); +	sbc->sram = tmp & TS5500_SRAM; +	sbc->rs485 = tmp & TS5500_RS485; +	sbc->adc = tmp & TS5500_ADC; + +	tmp = inb(TS5500_ERESET_ITR_ADDR); +	sbc->ereset = tmp & TS5500_ERESET; +	sbc->itr = tmp & TS5500_ITR; + +	tmp = inb(TS5500_LED_JP_ADDR); +	sbc->jumpers = tmp & ~TS5500_LED; + +cleanup: +	release_region(TS5500_PRODUCT_CODE_ADDR, 4); +	return ret; +} + +static ssize_t ts5500_show_id(struct device *dev, +			      struct device_attribute *attr, char *buf) +{ +	struct ts5500_sbc *sbc = dev_get_drvdata(dev); + +	return sprintf(buf, "0x%.2x\n", sbc->id); +} + +static ssize_t ts5500_show_jumpers(struct device *dev, +				   struct device_attribute *attr, +				   char *buf) +{ +	struct ts5500_sbc *sbc = dev_get_drvdata(dev); + +	return sprintf(buf, "0x%.2x\n", sbc->jumpers >> 1); +} + +#define TS5500_SHOW(field)					\ +	static ssize_t ts5500_show_##field(struct device *dev,	\ +			struct device_attribute *attr,		\ +			char *buf)				\ +	{							\ +		struct ts5500_sbc *sbc = dev_get_drvdata(dev);	\ +		return sprintf(buf, "%d\n", sbc->field);	\ +	} + +TS5500_SHOW(sram) +TS5500_SHOW(rs485) +TS5500_SHOW(adc) +TS5500_SHOW(ereset) +TS5500_SHOW(itr) + +static DEVICE_ATTR(id, S_IRUGO, ts5500_show_id, NULL); +static DEVICE_ATTR(jumpers, S_IRUGO, ts5500_show_jumpers, NULL); +static DEVICE_ATTR(sram, S_IRUGO, ts5500_show_sram, NULL); +static DEVICE_ATTR(rs485, S_IRUGO, ts5500_show_rs485, NULL); +static DEVICE_ATTR(adc, S_IRUGO, ts5500_show_adc, NULL); +static DEVICE_ATTR(ereset, S_IRUGO, ts5500_show_ereset, NULL); +static DEVICE_ATTR(itr, S_IRUGO, ts5500_show_itr, NULL); + +static struct attribute *ts5500_attributes[] = { +	&dev_attr_id.attr, +	&dev_attr_jumpers.attr, +	&dev_attr_sram.attr, +	&dev_attr_rs485.attr, +	&dev_attr_adc.attr, +	&dev_attr_ereset.attr, +	&dev_attr_itr.attr, +	NULL +}; + +static const struct attribute_group ts5500_attr_group = { +	.attrs = ts5500_attributes, +}; + +static struct resource ts5500_dio1_resource[] = { +	DEFINE_RES_IRQ_NAMED(7, "DIO1 interrupt"), +}; + +static struct platform_device ts5500_dio1_pdev = { +	.name = "ts5500-dio1", +	.id = -1, +	.resource = ts5500_dio1_resource, +	.num_resources = 1, +}; + +static struct resource ts5500_dio2_resource[] = { +	DEFINE_RES_IRQ_NAMED(6, "DIO2 interrupt"), +}; + +static struct platform_device ts5500_dio2_pdev = { +	.name = "ts5500-dio2", +	.id = -1, +	.resource = ts5500_dio2_resource, +	.num_resources = 1, +}; + +static void ts5500_led_set(struct led_classdev *led_cdev, +			   enum led_brightness brightness) +{ +	outb(!!brightness, TS5500_LED_JP_ADDR); +} + +static enum led_brightness ts5500_led_get(struct led_classdev *led_cdev) +{ +	return (inb(TS5500_LED_JP_ADDR) & TS5500_LED) ? LED_FULL : LED_OFF; +} + +static struct led_classdev ts5500_led_cdev = { +	.name = "ts5500:green:", +	.brightness_set = ts5500_led_set, +	.brightness_get = ts5500_led_get, +}; + +static int ts5500_adc_convert(u8 ctrl) +{ +	u8 lsb, msb; + +	/* Start conversion (ensure the 3 MSB are set to 0) */ +	outb(ctrl & 0x1f, TS5500_ADC_CONV_INIT_LSB_ADDR); + +	/* +	 * The platform has CPLD logic driving the A/D converter. +	 * The conversion must complete within 11 microseconds, +	 * otherwise we have to re-initiate a conversion. +	 */ +	udelay(TS5500_ADC_CONV_DELAY); +	if (inb(TS5500_ADC_CONV_BUSY_ADDR) & TS5500_ADC_CONV_BUSY) +		return -EBUSY; + +	/* Read the raw data */ +	lsb = inb(TS5500_ADC_CONV_INIT_LSB_ADDR); +	msb = inb(TS5500_ADC_CONV_MSB_ADDR); + +	return (msb << 8) | lsb; +} + +static struct max197_platform_data ts5500_adc_pdata = { +	.convert = ts5500_adc_convert, +}; + +static struct platform_device ts5500_adc_pdev = { +	.name = "max197", +	.id = -1, +	.dev = { +		.platform_data = &ts5500_adc_pdata, +	}, +}; + +static int __init ts5500_init(void) +{ +	struct platform_device *pdev; +	struct ts5500_sbc *sbc; +	int err; + +	/* +	 * There is no DMI available or PCI bridge subvendor info, +	 * only the BIOS provides a 16-bit identification call. +	 * It is safer to find a signature in the BIOS shadow RAM. +	 */ +	err = ts5500_check_signature(); +	if (err) +		return err; + +	pdev = platform_device_register_simple("ts5500", -1, NULL, 0); +	if (IS_ERR(pdev)) +		return PTR_ERR(pdev); + +	sbc = devm_kzalloc(&pdev->dev, sizeof(struct ts5500_sbc), GFP_KERNEL); +	if (!sbc) { +		err = -ENOMEM; +		goto error; +	} + +	err = ts5500_detect_config(sbc); +	if (err) +		goto error; + +	platform_set_drvdata(pdev, sbc); + +	err = sysfs_create_group(&pdev->dev.kobj, &ts5500_attr_group); +	if (err) +		goto error; + +	ts5500_dio1_pdev.dev.parent = &pdev->dev; +	if (platform_device_register(&ts5500_dio1_pdev)) +		dev_warn(&pdev->dev, "DIO1 block registration failed\n"); +	ts5500_dio2_pdev.dev.parent = &pdev->dev; +	if (platform_device_register(&ts5500_dio2_pdev)) +		dev_warn(&pdev->dev, "DIO2 block registration failed\n"); + +	if (led_classdev_register(&pdev->dev, &ts5500_led_cdev)) +		dev_warn(&pdev->dev, "LED registration failed\n"); + +	if (sbc->adc) { +		ts5500_adc_pdev.dev.parent = &pdev->dev; +		if (platform_device_register(&ts5500_adc_pdev)) +			dev_warn(&pdev->dev, "ADC registration failed\n"); +	} + +	return 0; +error: +	platform_device_unregister(pdev); +	return err; +} +device_initcall(ts5500_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>"); +MODULE_DESCRIPTION("Technologic Systems TS-5500 platform driver"); diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index b8b3a37c80c..0f92173a12b 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,   * globally purge translation cache of a virtual address or all TLB's   * @cpumask: mask of all cpu's in which the address is to be removed   * @mm: mm_struct containing virtual address range - * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) + * @start: start virtual address to be removed from TLB + * @end: end virtual address to be remove from TLB   * @cpu: the current cpu   *   * This is the entry point for initiating any UV global TLB shootdown. @@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,   */  const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,  				struct mm_struct *mm, unsigned long start, -				unsigned end, unsigned int cpu) +				unsigned long end, unsigned int cpu)  {  	int locals = 0;  	int remotes = 0; @@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,  	record_send_statistics(stat, locals, hubs, remotes, bau_desc); -	bau_desc->payload.address = start; +	if (!end || (end - start) <= PAGE_SIZE) +		bau_desc->payload.address = start; +	else +		bau_desc->payload.address = TLB_FLUSH_ALL;  	bau_desc->payload.sending_cpu = cpu;  	/*  	 * uv_flush_send_and_wait returns 0 if all cpu's were messaged, @@ -1463,7 +1467,7 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,  	}  	if (input_arg == 0) { -		elements = sizeof(stat_description)/sizeof(*stat_description); +		elements = ARRAY_SIZE(stat_description);  		printk(KERN_DEBUG "# cpu:      cpu number\n");  		printk(KERN_DEBUG "Sender statistics:\n");  		for (i = 0; i < elements; i++) @@ -1504,7 +1508,7 @@ static int parse_tunables_write(struct bau_control *bcp, char *instr,  	char *q;  	int cnt = 0;  	int val; -	int e = sizeof(tunables) / sizeof(*tunables); +	int e = ARRAY_SIZE(tunables);  	p = instr + strspn(instr, WHITESPACE);  	q = p; diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c index 5032e0d19b8..98718f604eb 100644 --- a/arch/x86/platform/uv/uv_time.c +++ b/arch/x86/platform/uv/uv_time.c @@ -15,7 +15,7 @@   *  along with this program; if not, write to the Free Software   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   * - *  Copyright (c) 2009 Silicon Graphics, Inc.  All Rights Reserved. + *  Copyright (c) 2009-2013 Silicon Graphics, Inc.  All Rights Reserved.   *  Copyright (c) Dimitri Sivanich   */  #include <linux/clockchips.h> @@ -102,9 +102,10 @@ static int uv_intr_pending(int pnode)  	if (is_uv1_hub())  		return uv_read_global_mmr64(pnode, UVH_EVENT_OCCURRED0) &  			UV1H_EVENT_OCCURRED0_RTC1_MASK; -	else -		return uv_read_global_mmr64(pnode, UV2H_EVENT_OCCURRED2) & -			UV2H_EVENT_OCCURRED2_RTC_1_MASK; +	else if (is_uvx_hub()) +		return uv_read_global_mmr64(pnode, UVXH_EVENT_OCCURRED2) & +			UVXH_EVENT_OCCURRED2_RTC_1_MASK; +	return 0;  }  /* Setup interrupt and return non-zero if early expiration occurred. */ @@ -122,8 +123,8 @@ static int uv_setup_intr(int cpu, u64 expires)  		uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED0_ALIAS,  				UV1H_EVENT_OCCURRED0_RTC1_MASK);  	else -		uv_write_global_mmr64(pnode, UV2H_EVENT_OCCURRED2_ALIAS, -				UV2H_EVENT_OCCURRED2_RTC_1_MASK); +		uv_write_global_mmr64(pnode, UVXH_EVENT_OCCURRED2_ALIAS, +				UVXH_EVENT_OCCURRED2_RTC_1_MASK);  	val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |  		((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);  |