diff options
34 files changed, 442 insertions, 2226 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6c29256a71a6..901952355969 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -422,27 +422,6 @@ if X86_WANT_INTEL_MID | |||
422 | config X86_INTEL_MID | 422 | config X86_INTEL_MID |
423 | bool | 423 | bool |
424 | 424 | ||
425 | config X86_MRST | ||
426 | bool "Moorestown MID platform" | ||
427 | depends on PCI | ||
428 | depends on PCI_GOANY | ||
429 | depends on X86_IO_APIC | ||
430 | select X86_INTEL_MID | ||
431 | select SFI | ||
432 | select DW_APB_TIMER | ||
433 | select APB_TIMER | ||
434 | select I2C | ||
435 | select SPI | ||
436 | select INTEL_SCU_IPC | ||
437 | select X86_PLATFORM_DEVICES | ||
438 | ---help--- | ||
439 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin | ||
440 | Internet Device(MID) platform. Moorestown consists of two chips: | ||
441 | Lincroft (CPU core, graphics, and memory controller) and Langwell IOH. | ||
442 | Unlike standard x86 PCs, Moorestown does not have many legacy devices | ||
443 | nor standard legacy replacement devices/features. e.g. Moorestown does | ||
444 | not contain i8259, i8254, HPET, legacy BIOS, most of the io ports. | ||
445 | |||
446 | config X86_MDFLD | 425 | config X86_MDFLD |
447 | bool "Medfield MID platform" | 426 | bool "Medfield MID platform" |
448 | depends on PCI | 427 | depends on PCI |
@@ -456,6 +435,7 @@ config X86_MDFLD | |||
456 | select SPI | 435 | select SPI |
457 | select INTEL_SCU_IPC | 436 | select INTEL_SCU_IPC |
458 | select X86_PLATFORM_DEVICES | 437 | select X86_PLATFORM_DEVICES |
438 | select MFD_INTEL_MSIC | ||
459 | ---help--- | 439 | ---help--- |
460 | Medfield is Intel's Low Power Intel Architecture (LPIA) based Moblin | 440 | Medfield is Intel's Low Power Intel Architecture (LPIA) based Moblin |
461 | Internet Device(MID) platform. | 441 | Internet Device(MID) platform. |
@@ -2139,6 +2119,12 @@ config ALIX | |||
2139 | 2119 | ||
2140 | Note: You have to set alix.force=1 for boards with Award BIOS. | 2120 | Note: You have to set alix.force=1 for boards with Award BIOS. |
2141 | 2121 | ||
2122 | config NET5501 | ||
2123 | bool "Soekris Engineering net5501 System Support (LEDS, GPIO, etc)" | ||
2124 | select GPIOLIB | ||
2125 | ---help--- | ||
2126 | This option enables system support for the Soekris Engineering net5501. | ||
2127 | |||
2142 | endif # X86_32 | 2128 | endif # X86_32 |
2143 | 2129 | ||
2144 | config AMD_NB | 2130 | config AMD_NB |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3ab9bdd87e79..a9371c91718c 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -288,6 +288,7 @@ struct apic { | |||
288 | 288 | ||
289 | int (*probe)(void); | 289 | int (*probe)(void); |
290 | int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); | 290 | int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); |
291 | int (*apic_id_valid)(int apicid); | ||
291 | int (*apic_id_registered)(void); | 292 | int (*apic_id_registered)(void); |
292 | 293 | ||
293 | u32 irq_delivery_mode; | 294 | u32 irq_delivery_mode; |
@@ -532,6 +533,11 @@ static inline unsigned int read_apic_id(void) | |||
532 | return apic->get_apic_id(reg); | 533 | return apic->get_apic_id(reg); |
533 | } | 534 | } |
534 | 535 | ||
536 | static inline int default_apic_id_valid(int apicid) | ||
537 | { | ||
538 | return x2apic_mode || (apicid < 255); | ||
539 | } | ||
540 | |||
535 | extern void default_setup_apic_routing(void); | 541 | extern void default_setup_apic_routing(void); |
536 | 542 | ||
537 | extern struct apic apic_noop; | 543 | extern struct apic apic_noop; |
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index 0a0a95460434..fc18bf3ce7c8 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h | |||
@@ -26,8 +26,8 @@ extern struct sfi_rtc_table_entry sfi_mrtc_array[]; | |||
26 | * identified via MSRs. | 26 | * identified via MSRs. |
27 | */ | 27 | */ |
28 | enum mrst_cpu_type { | 28 | enum mrst_cpu_type { |
29 | MRST_CPU_CHIP_LINCROFT = 1, | 29 | /* 1 was Moorestown */ |
30 | MRST_CPU_CHIP_PENWELL, | 30 | MRST_CPU_CHIP_PENWELL = 2, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | extern enum mrst_cpu_type __mrst_cpu_chip; | 33 | extern enum mrst_cpu_type __mrst_cpu_chip; |
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 8c3cdded6f2b..359b6899a36c 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
@@ -180,6 +180,7 @@ static struct apic apic_flat = { | |||
180 | .name = "flat", | 180 | .name = "flat", |
181 | .probe = flat_probe, | 181 | .probe = flat_probe, |
182 | .acpi_madt_oem_check = flat_acpi_madt_oem_check, | 182 | .acpi_madt_oem_check = flat_acpi_madt_oem_check, |
183 | .apic_id_valid = default_apic_id_valid, | ||
183 | .apic_id_registered = flat_apic_id_registered, | 184 | .apic_id_registered = flat_apic_id_registered, |
184 | 185 | ||
185 | .irq_delivery_mode = dest_LowestPrio, | 186 | .irq_delivery_mode = dest_LowestPrio, |
@@ -337,6 +338,7 @@ static struct apic apic_physflat = { | |||
337 | .name = "physical flat", | 338 | .name = "physical flat", |
338 | .probe = physflat_probe, | 339 | .probe = physflat_probe, |
339 | .acpi_madt_oem_check = physflat_acpi_madt_oem_check, | 340 | .acpi_madt_oem_check = physflat_acpi_madt_oem_check, |
341 | .apic_id_valid = default_apic_id_valid, | ||
340 | .apic_id_registered = flat_apic_id_registered, | 342 | .apic_id_registered = flat_apic_id_registered, |
341 | 343 | ||
342 | .irq_delivery_mode = dest_Fixed, | 344 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 775b82bc655c..634ae6cdd5c9 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c | |||
@@ -124,6 +124,7 @@ struct apic apic_noop = { | |||
124 | .probe = noop_probe, | 124 | .probe = noop_probe, |
125 | .acpi_madt_oem_check = NULL, | 125 | .acpi_madt_oem_check = NULL, |
126 | 126 | ||
127 | .apic_id_valid = default_apic_id_valid, | ||
127 | .apic_id_registered = noop_apic_id_registered, | 128 | .apic_id_registered = noop_apic_id_registered, |
128 | 129 | ||
129 | .irq_delivery_mode = dest_LowestPrio, | 130 | .irq_delivery_mode = dest_LowestPrio, |
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 09d3d8c1cd99..d9ea5f331ac5 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c | |||
@@ -56,6 +56,12 @@ static unsigned int read_xapic_id(void) | |||
56 | return get_apic_id(apic_read(APIC_ID)); | 56 | return get_apic_id(apic_read(APIC_ID)); |
57 | } | 57 | } |
58 | 58 | ||
59 | static int numachip_apic_id_valid(int apicid) | ||
60 | { | ||
61 | /* Trust what bootloader passes in MADT */ | ||
62 | return 1; | ||
63 | } | ||
64 | |||
59 | static int numachip_apic_id_registered(void) | 65 | static int numachip_apic_id_registered(void) |
60 | { | 66 | { |
61 | return physid_isset(read_xapic_id(), phys_cpu_present_map); | 67 | return physid_isset(read_xapic_id(), phys_cpu_present_map); |
@@ -223,10 +229,11 @@ static int __init numachip_system_init(void) | |||
223 | } | 229 | } |
224 | early_initcall(numachip_system_init); | 230 | early_initcall(numachip_system_init); |
225 | 231 | ||
226 | static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 232 | static int __cpuinit numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
227 | { | 233 | { |
228 | if (!strncmp(oem_id, "NUMASC", 6)) { | 234 | if (!strncmp(oem_id, "NUMASC", 6)) { |
229 | numachip_system = 1; | 235 | numachip_system = 1; |
236 | setup_force_cpu_cap(X86_FEATURE_X2APIC); | ||
230 | return 1; | 237 | return 1; |
231 | } | 238 | } |
232 | 239 | ||
@@ -238,6 +245,7 @@ static struct apic apic_numachip __refconst = { | |||
238 | .name = "NumaConnect system", | 245 | .name = "NumaConnect system", |
239 | .probe = numachip_probe, | 246 | .probe = numachip_probe, |
240 | .acpi_madt_oem_check = numachip_acpi_madt_oem_check, | 247 | .acpi_madt_oem_check = numachip_acpi_madt_oem_check, |
248 | .apic_id_valid = numachip_apic_id_valid, | ||
241 | .apic_id_registered = numachip_apic_id_registered, | 249 | .apic_id_registered = numachip_apic_id_registered, |
242 | 250 | ||
243 | .irq_delivery_mode = dest_Fixed, | 251 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 521bead01137..0cdec7065aff 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c | |||
@@ -198,6 +198,7 @@ static struct apic apic_bigsmp = { | |||
198 | .name = "bigsmp", | 198 | .name = "bigsmp", |
199 | .probe = probe_bigsmp, | 199 | .probe = probe_bigsmp, |
200 | .acpi_madt_oem_check = NULL, | 200 | .acpi_madt_oem_check = NULL, |
201 | .apic_id_valid = default_apic_id_valid, | ||
201 | .apic_id_registered = bigsmp_apic_id_registered, | 202 | .apic_id_registered = bigsmp_apic_id_registered, |
202 | 203 | ||
203 | .irq_delivery_mode = dest_Fixed, | 204 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 5d513bc47b6b..e42d1d3b9134 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c | |||
@@ -625,6 +625,7 @@ static struct apic __refdata apic_es7000_cluster = { | |||
625 | .name = "es7000", | 625 | .name = "es7000", |
626 | .probe = probe_es7000, | 626 | .probe = probe_es7000, |
627 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check_cluster, | 627 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check_cluster, |
628 | .apic_id_valid = default_apic_id_valid, | ||
628 | .apic_id_registered = es7000_apic_id_registered, | 629 | .apic_id_registered = es7000_apic_id_registered, |
629 | 630 | ||
630 | .irq_delivery_mode = dest_LowestPrio, | 631 | .irq_delivery_mode = dest_LowestPrio, |
@@ -690,6 +691,7 @@ static struct apic __refdata apic_es7000 = { | |||
690 | .name = "es7000", | 691 | .name = "es7000", |
691 | .probe = probe_es7000, | 692 | .probe = probe_es7000, |
692 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check, | 693 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check, |
694 | .apic_id_valid = default_apic_id_valid, | ||
693 | .apic_id_registered = es7000_apic_id_registered, | 695 | .apic_id_registered = es7000_apic_id_registered, |
694 | 696 | ||
695 | .irq_delivery_mode = dest_Fixed, | 697 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index c4a61ca1349a..00d2422ca7c9 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c | |||
@@ -478,6 +478,7 @@ static struct apic __refdata apic_numaq = { | |||
478 | .name = "NUMAQ", | 478 | .name = "NUMAQ", |
479 | .probe = probe_numaq, | 479 | .probe = probe_numaq, |
480 | .acpi_madt_oem_check = NULL, | 480 | .acpi_madt_oem_check = NULL, |
481 | .apic_id_valid = default_apic_id_valid, | ||
481 | .apic_id_registered = numaq_apic_id_registered, | 482 | .apic_id_registered = numaq_apic_id_registered, |
482 | 483 | ||
483 | .irq_delivery_mode = dest_LowestPrio, | 484 | .irq_delivery_mode = dest_LowestPrio, |
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 0787bb3412f4..ff2c1b9aac4d 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
@@ -92,6 +92,7 @@ static struct apic apic_default = { | |||
92 | .name = "default", | 92 | .name = "default", |
93 | .probe = probe_default, | 93 | .probe = probe_default, |
94 | .acpi_madt_oem_check = NULL, | 94 | .acpi_madt_oem_check = NULL, |
95 | .apic_id_valid = default_apic_id_valid, | ||
95 | .apic_id_registered = default_apic_id_registered, | 96 | .apic_id_registered = default_apic_id_registered, |
96 | 97 | ||
97 | .irq_delivery_mode = dest_LowestPrio, | 98 | .irq_delivery_mode = dest_LowestPrio, |
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 19114423c58c..fea000b27f07 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c | |||
@@ -496,6 +496,7 @@ static struct apic apic_summit = { | |||
496 | .name = "summit", | 496 | .name = "summit", |
497 | .probe = probe_summit, | 497 | .probe = probe_summit, |
498 | .acpi_madt_oem_check = summit_acpi_madt_oem_check, | 498 | .acpi_madt_oem_check = summit_acpi_madt_oem_check, |
499 | .apic_id_valid = default_apic_id_valid, | ||
499 | .apic_id_registered = summit_apic_id_registered, | 500 | .apic_id_registered = summit_apic_id_registered, |
500 | 501 | ||
501 | .irq_delivery_mode = dest_LowestPrio, | 502 | .irq_delivery_mode = dest_LowestPrio, |
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 500795875827..9193713060a9 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -213,6 +213,7 @@ static struct apic apic_x2apic_cluster = { | |||
213 | .name = "cluster x2apic", | 213 | .name = "cluster x2apic", |
214 | .probe = x2apic_cluster_probe, | 214 | .probe = x2apic_cluster_probe, |
215 | .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, | 215 | .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, |
216 | .apic_id_valid = default_apic_id_valid, | ||
216 | .apic_id_registered = x2apic_apic_id_registered, | 217 | .apic_id_registered = x2apic_apic_id_registered, |
217 | 218 | ||
218 | .irq_delivery_mode = dest_LowestPrio, | 219 | .irq_delivery_mode = dest_LowestPrio, |
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index f5373dfde21e..bcd1db6eaca9 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c | |||
@@ -119,6 +119,7 @@ static struct apic apic_x2apic_phys = { | |||
119 | .name = "physical x2apic", | 119 | .name = "physical x2apic", |
120 | .probe = x2apic_phys_probe, | 120 | .probe = x2apic_phys_probe, |
121 | .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, | 121 | .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, |
122 | .apic_id_valid = default_apic_id_valid, | ||
122 | .apic_id_registered = x2apic_apic_id_registered, | 123 | .apic_id_registered = x2apic_apic_id_registered, |
123 | 124 | ||
124 | .irq_delivery_mode = dest_Fixed, | 125 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 79b05b88aa19..fc4771425852 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -351,6 +351,7 @@ static struct apic __refdata apic_x2apic_uv_x = { | |||
351 | .name = "UV large system", | 351 | .name = "UV large system", |
352 | .probe = uv_probe, | 352 | .probe = uv_probe, |
353 | .acpi_madt_oem_check = uv_acpi_madt_oem_check, | 353 | .acpi_madt_oem_check = uv_acpi_madt_oem_check, |
354 | .apic_id_valid = default_apic_id_valid, | ||
354 | .apic_id_registered = uv_apic_id_registered, | 355 | .apic_id_registered = uv_apic_id_registered, |
355 | 356 | ||
356 | .irq_delivery_mode = dest_Fixed, | 357 | .irq_delivery_mode = dest_Fixed, |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index dccebbe758ca..e578a79a3093 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -833,7 +833,7 @@ int __cpuinit native_cpu_up(unsigned int cpu) | |||
833 | 833 | ||
834 | if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid || | 834 | if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid || |
835 | !physid_isset(apicid, phys_cpu_present_map) || | 835 | !physid_isset(apicid, phys_cpu_present_map) || |
836 | (!x2apic_mode && apicid >= 255)) { | 836 | !apic->apic_id_valid(apicid)) { |
837 | printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu); | 837 | printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu); |
838 | return -EINVAL; | 838 | return -EINVAL; |
839 | } | 839 | } |
diff --git a/arch/x86/platform/geode/Makefile b/arch/x86/platform/geode/Makefile index 07c9cd05021a..246b788847ff 100644 --- a/arch/x86/platform/geode/Makefile +++ b/arch/x86/platform/geode/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-$(CONFIG_ALIX) += alix.o | 1 | obj-$(CONFIG_ALIX) += alix.o |
2 | obj-$(CONFIG_NET5501) += net5501.o | ||
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c index dc5f1d32aced..90e23e7679a5 100644 --- a/arch/x86/platform/geode/alix.c +++ b/arch/x86/platform/geode/alix.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> | 7 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> |
8 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> | 8 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> |
9 | * and Philip Prindeville <philipp@redfish-solutions.com> | ||
9 | * | 10 | * |
10 | * TODO: There are large similarities with leds-net5501.c | 11 | * TODO: There are large similarities with leds-net5501.c |
11 | * by Alessandro Zummo <a.zummo@towertech.it> | 12 | * by Alessandro Zummo <a.zummo@towertech.it> |
@@ -24,14 +25,47 @@ | |||
24 | #include <linux/leds.h> | 25 | #include <linux/leds.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/input.h> | ||
29 | #include <linux/gpio_keys.h> | ||
30 | #include <linux/dmi.h> | ||
27 | 31 | ||
28 | #include <asm/geode.h> | 32 | #include <asm/geode.h> |
29 | 33 | ||
34 | #define BIOS_SIGNATURE_TINYBIOS 0xf0000 | ||
35 | #define BIOS_SIGNATURE_COREBOOT 0x500 | ||
36 | #define BIOS_REGION_SIZE 0x10000 | ||
37 | |||
30 | static bool force = 0; | 38 | static bool force = 0; |
31 | module_param(force, bool, 0444); | 39 | module_param(force, bool, 0444); |
32 | /* FIXME: Award bios is not automatically detected as Alix platform */ | 40 | /* FIXME: Award bios is not automatically detected as Alix platform */ |
33 | MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); | 41 | MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); |
34 | 42 | ||
43 | static struct gpio_keys_button alix_gpio_buttons[] = { | ||
44 | { | ||
45 | .code = KEY_RESTART, | ||
46 | .gpio = 24, | ||
47 | .active_low = 1, | ||
48 | .desc = "Reset button", | ||
49 | .type = EV_KEY, | ||
50 | .wakeup = 0, | ||
51 | .debounce_interval = 100, | ||
52 | .can_disable = 0, | ||
53 | } | ||
54 | }; | ||
55 | static struct gpio_keys_platform_data alix_buttons_data = { | ||
56 | .buttons = alix_gpio_buttons, | ||
57 | .nbuttons = ARRAY_SIZE(alix_gpio_buttons), | ||
58 | .poll_interval = 20, | ||
59 | }; | ||
60 | |||
61 | static struct platform_device alix_buttons_dev = { | ||
62 | .name = "gpio-keys-polled", | ||
63 | .id = 1, | ||
64 | .dev = { | ||
65 | .platform_data = &alix_buttons_data, | ||
66 | } | ||
67 | }; | ||
68 | |||
35 | static struct gpio_led alix_leds[] = { | 69 | static struct gpio_led alix_leds[] = { |
36 | { | 70 | { |
37 | .name = "alix:1", | 71 | .name = "alix:1", |
@@ -64,17 +98,22 @@ static struct platform_device alix_leds_dev = { | |||
64 | .dev.platform_data = &alix_leds_data, | 98 | .dev.platform_data = &alix_leds_data, |
65 | }; | 99 | }; |
66 | 100 | ||
101 | static struct __initdata platform_device *alix_devs[] = { | ||
102 | &alix_buttons_dev, | ||
103 | &alix_leds_dev, | ||
104 | }; | ||
105 | |||
67 | static void __init register_alix(void) | 106 | static void __init register_alix(void) |
68 | { | 107 | { |
69 | /* Setup LED control through leds-gpio driver */ | 108 | /* Setup LED control through leds-gpio driver */ |
70 | platform_device_register(&alix_leds_dev); | 109 | platform_add_devices(alix_devs, ARRAY_SIZE(alix_devs)); |
71 | } | 110 | } |
72 | 111 | ||
73 | static int __init alix_present(unsigned long bios_phys, | 112 | static bool __init alix_present(unsigned long bios_phys, |
74 | const char *alix_sig, | 113 | const char *alix_sig, |
75 | size_t alix_sig_len) | 114 | size_t alix_sig_len) |
76 | { | 115 | { |
77 | const size_t bios_len = 0x00010000; | 116 | const size_t bios_len = BIOS_REGION_SIZE; |
78 | const char *bios_virt; | 117 | const char *bios_virt; |
79 | const char *scan_end; | 118 | const char *scan_end; |
80 | const char *p; | 119 | const char *p; |
@@ -84,7 +123,7 @@ static int __init alix_present(unsigned long bios_phys, | |||
84 | printk(KERN_NOTICE "%s: forced to skip BIOS test, " | 123 | printk(KERN_NOTICE "%s: forced to skip BIOS test, " |
85 | "assume system is ALIX.2/ALIX.3\n", | 124 | "assume system is ALIX.2/ALIX.3\n", |
86 | KBUILD_MODNAME); | 125 | KBUILD_MODNAME); |
87 | return 1; | 126 | return true; |
88 | } | 127 | } |
89 | 128 | ||
90 | bios_virt = phys_to_virt(bios_phys); | 129 | bios_virt = phys_to_virt(bios_phys); |
@@ -109,15 +148,33 @@ static int __init alix_present(unsigned long bios_phys, | |||
109 | *a = '\0'; | 148 | *a = '\0'; |
110 | 149 | ||
111 | tail = p + alix_sig_len; | 150 | tail = p + alix_sig_len; |
112 | if ((tail[0] == '2' || tail[0] == '3')) { | 151 | if ((tail[0] == '2' || tail[0] == '3' || tail[0] == '6')) { |
113 | printk(KERN_INFO | 152 | printk(KERN_INFO |
114 | "%s: system is recognized as \"%s\"\n", | 153 | "%s: system is recognized as \"%s\"\n", |
115 | KBUILD_MODNAME, name); | 154 | KBUILD_MODNAME, name); |
116 | return 1; | 155 | return true; |
117 | } | 156 | } |
118 | } | 157 | } |
119 | 158 | ||
120 | return 0; | 159 | return false; |
160 | } | ||
161 | |||
162 | static bool __init alix_present_dmi(void) | ||
163 | { | ||
164 | const char *vendor, *product; | ||
165 | |||
166 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | ||
167 | if (!vendor || strcmp(vendor, "PC Engines")) | ||
168 | return false; | ||
169 | |||
170 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
171 | if (!product || (strcmp(product, "ALIX.2D") && strcmp(product, "ALIX.6"))) | ||
172 | return false; | ||
173 | |||
174 | printk(KERN_INFO "%s: system is recognized as \"%s %s\"\n", | ||
175 | KBUILD_MODNAME, vendor, product); | ||
176 | |||
177 | return true; | ||
121 | } | 178 | } |
122 | 179 | ||
123 | static int __init alix_init(void) | 180 | static int __init alix_init(void) |
@@ -128,8 +185,9 @@ static int __init alix_init(void) | |||
128 | if (!is_geode()) | 185 | if (!is_geode()) |
129 | return 0; | 186 | return 0; |
130 | 187 | ||
131 | if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) || | 188 | if (alix_present(BIOS_SIGNATURE_TINYBIOS, tinybios_sig, sizeof(tinybios_sig) - 1) || |
132 | alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1)) | 189 | alix_present(BIOS_SIGNATURE_COREBOOT, coreboot_sig, sizeof(coreboot_sig) - 1) || |
190 | alix_present_dmi()) | ||
133 | register_alix(); | 191 | register_alix(); |
134 | 192 | ||
135 | return 0; | 193 | return 0; |
diff --git a/arch/x86/platform/geode/net5501.c b/arch/x86/platform/geode/net5501.c new file mode 100644 index 000000000000..66d377e334f7 --- /dev/null +++ b/arch/x86/platform/geode/net5501.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * System Specific setup for Soekris net5501 | ||
3 | * At the moment this means setup of GPIO control of LEDs and buttons | ||
4 | * on net5501 boards. | ||
5 | * | ||
6 | * | ||
7 | * Copyright (C) 2008-2009 Tower Technologies | ||
8 | * Written by Alessandro Zummo <a.zummo@towertech.it> | ||
9 | * | ||
10 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> | ||
11 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> | ||
12 | * and Philip Prindeville <philipp@redfish-solutions.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 | ||
16 | * as published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/leds.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/gpio_keys.h> | ||
29 | |||
30 | #include <asm/geode.h> | ||
31 | |||
32 | #define BIOS_REGION_BASE 0xffff0000 | ||
33 | #define BIOS_REGION_SIZE 0x00010000 | ||
34 | |||
35 | static struct gpio_keys_button net5501_gpio_buttons[] = { | ||
36 | { | ||
37 | .code = KEY_RESTART, | ||
38 | .gpio = 24, | ||
39 | .active_low = 1, | ||
40 | .desc = "Reset button", | ||
41 | .type = EV_KEY, | ||
42 | .wakeup = 0, | ||
43 | .debounce_interval = 100, | ||
44 | .can_disable = 0, | ||
45 | } | ||
46 | }; | ||
47 | static struct gpio_keys_platform_data net5501_buttons_data = { | ||
48 | .buttons = net5501_gpio_buttons, | ||
49 | .nbuttons = ARRAY_SIZE(net5501_gpio_buttons), | ||
50 | .poll_interval = 20, | ||
51 | }; | ||
52 | |||
53 | static struct platform_device net5501_buttons_dev = { | ||
54 | .name = "gpio-keys-polled", | ||
55 | .id = 1, | ||
56 | .dev = { | ||
57 | .platform_data = &net5501_buttons_data, | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | static struct gpio_led net5501_leds[] = { | ||
62 | { | ||
63 | .name = "net5501:1", | ||
64 | .gpio = 6, | ||
65 | .default_trigger = "default-on", | ||
66 | .active_low = 1, | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static struct gpio_led_platform_data net5501_leds_data = { | ||
71 | .num_leds = ARRAY_SIZE(net5501_leds), | ||
72 | .leds = net5501_leds, | ||
73 | }; | ||
74 | |||
75 | static struct platform_device net5501_leds_dev = { | ||
76 | .name = "leds-gpio", | ||
77 | .id = -1, | ||
78 | .dev.platform_data = &net5501_leds_data, | ||
79 | }; | ||
80 | |||
81 | static struct __initdata platform_device *net5501_devs[] = { | ||
82 | &net5501_buttons_dev, | ||
83 | &net5501_leds_dev, | ||
84 | }; | ||
85 | |||
86 | static void __init register_net5501(void) | ||
87 | { | ||
88 | /* Setup LED control through leds-gpio driver */ | ||
89 | platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs)); | ||
90 | } | ||
91 | |||
92 | struct net5501_board { | ||
93 | u16 offset; | ||
94 | u16 len; | ||
95 | char *sig; | ||
96 | }; | ||
97 | |||
98 | static struct net5501_board __initdata boards[] = { | ||
99 | { 0xb7b, 7, "net5501" }, /* net5501 v1.33/1.33c */ | ||
100 | { 0xb1f, 7, "net5501" }, /* net5501 v1.32i */ | ||
101 | }; | ||
102 | |||
103 | static bool __init net5501_present(void) | ||
104 | { | ||
105 | int i; | ||
106 | unsigned char *rombase, *bios; | ||
107 | bool found = false; | ||
108 | |||
109 | rombase = ioremap(BIOS_REGION_BASE, BIOS_REGION_SIZE - 1); | ||
110 | if (!rombase) { | ||
111 | printk(KERN_ERR "%s: failed to get rombase\n", KBUILD_MODNAME); | ||
112 | return found; | ||
113 | } | ||
114 | |||
115 | bios = rombase + 0x20; /* null terminated */ | ||
116 | |||
117 | if (memcmp(bios, "comBIOS", 7)) | ||
118 | goto unmap; | ||
119 | |||
120 | for (i = 0; i < ARRAY_SIZE(boards); i++) { | ||
121 | unsigned char *model = rombase + boards[i].offset; | ||
122 | |||
123 | if (!memcmp(model, boards[i].sig, boards[i].len)) { | ||
124 | printk(KERN_INFO "%s: system is recognized as \"%s\"\n", | ||
125 | KBUILD_MODNAME, model); | ||
126 | |||
127 | found = true; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | unmap: | ||
133 | iounmap(rombase); | ||
134 | return found; | ||
135 | } | ||
136 | |||
137 | static int __init net5501_init(void) | ||
138 | { | ||
139 | if (!is_geode()) | ||
140 | return 0; | ||
141 | |||
142 | if (!net5501_present()) | ||
143 | return 0; | ||
144 | |||
145 | register_net5501(); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | module_init(net5501_init); | ||
151 | |||
152 | MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>"); | ||
153 | MODULE_DESCRIPTION("Soekris net5501 System Setup"); | ||
154 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile index 7baed5135e0f..af1da7e623f9 100644 --- a/arch/x86/platform/mrst/Makefile +++ b/arch/x86/platform/mrst/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | obj-$(CONFIG_X86_INTEL_MID) += mrst.o | 1 | obj-$(CONFIG_X86_INTEL_MID) += mrst.o |
2 | obj-$(CONFIG_X86_INTEL_MID) += vrtc.o | 2 | obj-$(CONFIG_X86_INTEL_MID) += vrtc.o |
3 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_mrst.o | 3 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_mrst.o |
4 | obj-$(CONFIG_X86_MRST) += pmu.o | ||
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 475e2cd0f3c3..721e65285dce 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
@@ -78,16 +78,11 @@ int sfi_mrtc_num; | |||
78 | 78 | ||
79 | static void mrst_power_off(void) | 79 | static void mrst_power_off(void) |
80 | { | 80 | { |
81 | if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) | ||
82 | intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1); | ||
83 | } | 81 | } |
84 | 82 | ||
85 | static void mrst_reboot(void) | 83 | static void mrst_reboot(void) |
86 | { | 84 | { |
87 | if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) | 85 | intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); |
88 | intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); | ||
89 | else | ||
90 | intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); | ||
91 | } | 86 | } |
92 | 87 | ||
93 | /* parse all the mtimer info to a static mtimer array */ | 88 | /* parse all the mtimer info to a static mtimer array */ |
@@ -200,34 +195,28 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table) | |||
200 | 195 | ||
201 | static unsigned long __init mrst_calibrate_tsc(void) | 196 | static unsigned long __init mrst_calibrate_tsc(void) |
202 | { | 197 | { |
203 | unsigned long flags, fast_calibrate; | 198 | unsigned long fast_calibrate; |
204 | if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { | 199 | u32 lo, hi, ratio, fsb; |
205 | u32 lo, hi, ratio, fsb; | 200 | |
206 | 201 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | |
207 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | 202 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); |
208 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | 203 | ratio = (hi >> 8) & 0x1f; |
209 | ratio = (hi >> 8) & 0x1f; | 204 | pr_debug("ratio is %d\n", ratio); |
210 | pr_debug("ratio is %d\n", ratio); | 205 | if (!ratio) { |
211 | if (!ratio) { | 206 | pr_err("read a zero ratio, should be incorrect!\n"); |
212 | pr_err("read a zero ratio, should be incorrect!\n"); | 207 | pr_err("force tsc ratio to 16 ...\n"); |
213 | pr_err("force tsc ratio to 16 ...\n"); | 208 | ratio = 16; |
214 | ratio = 16; | ||
215 | } | ||
216 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
217 | if ((lo & 0x7) == 0x7) | ||
218 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
219 | else | ||
220 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
221 | fast_calibrate = ratio * fsb; | ||
222 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
223 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
224 | /* mark tsc clocksource as reliable */ | ||
225 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
226 | } else { | ||
227 | local_irq_save(flags); | ||
228 | fast_calibrate = apbt_quick_calibrate(); | ||
229 | local_irq_restore(flags); | ||
230 | } | 209 | } |
210 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
211 | if ((lo & 0x7) == 0x7) | ||
212 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
213 | else | ||
214 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
215 | fast_calibrate = ratio * fsb; | ||
216 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
217 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
218 | /* mark tsc clocksource as reliable */ | ||
219 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
231 | 220 | ||
232 | if (fast_calibrate) | 221 | if (fast_calibrate) |
233 | return fast_calibrate; | 222 | return fast_calibrate; |
@@ -261,16 +250,11 @@ static void __cpuinit mrst_arch_setup(void) | |||
261 | { | 250 | { |
262 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | 251 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) |
263 | __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; | 252 | __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; |
264 | else if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x26) | ||
265 | __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT; | ||
266 | else { | 253 | else { |
267 | pr_err("Unknown Moorestown CPU (%d:%d), default to Lincroft\n", | 254 | pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n", |
268 | boot_cpu_data.x86, boot_cpu_data.x86_model); | 255 | boot_cpu_data.x86, boot_cpu_data.x86_model); |
269 | __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT; | 256 | __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; |
270 | } | 257 | } |
271 | pr_debug("Moorestown CPU %s identified\n", | ||
272 | (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ? | ||
273 | "Lincroft" : "Penwell"); | ||
274 | } | 258 | } |
275 | 259 | ||
276 | /* MID systems don't have i8042 controller */ | 260 | /* MID systems don't have i8042 controller */ |
@@ -686,6 +670,11 @@ static void *msic_ocd_platform_data(void *info) | |||
686 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD); | 670 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD); |
687 | } | 671 | } |
688 | 672 | ||
673 | static void *msic_thermal_platform_data(void *info) | ||
674 | { | ||
675 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL); | ||
676 | } | ||
677 | |||
689 | static const struct devs_id __initconst device_ids[] = { | 678 | static const struct devs_id __initconst device_ids[] = { |
690 | {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data}, | 679 | {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data}, |
691 | {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, | 680 | {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, |
@@ -705,6 +694,7 @@ static const struct devs_id __initconst device_ids[] = { | |||
705 | {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data}, | 694 | {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data}, |
706 | {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data}, | 695 | {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data}, |
707 | {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data}, | 696 | {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data}, |
697 | {"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data}, | ||
708 | 698 | ||
709 | {}, | 699 | {}, |
710 | }; | 700 | }; |
diff --git a/arch/x86/platform/mrst/pmu.c b/arch/x86/platform/mrst/pmu.c deleted file mode 100644 index c0ac06da57ac..000000000000 --- a/arch/x86/platform/mrst/pmu.c +++ /dev/null | |||
@@ -1,817 +0,0 @@ | |||
1 | /* | ||
2 | * mrst/pmu.c - driver for MRST Power Management Unit | ||
3 | * | ||
4 | * Copyright (c) 2011, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/cpuidle.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/sfi.h> | ||
28 | #include <asm/intel_scu_ipc.h> | ||
29 | #include "pmu.h" | ||
30 | |||
31 | #define IPCMSG_FW_REVISION 0xF4 | ||
32 | |||
33 | struct mrst_device { | ||
34 | u16 pci_dev_num; /* DEBUG only */ | ||
35 | u16 lss; | ||
36 | u16 latest_request; | ||
37 | unsigned int pci_state_counts[PCI_D3cold + 1]; /* DEBUG only */ | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * comlete list of MRST PCI devices | ||
42 | */ | ||
43 | static struct mrst_device mrst_devs[] = { | ||
44 | /* 0 */ { 0x0800, LSS_SPI0 }, /* Moorestown SPI Ctrl 0 */ | ||
45 | /* 1 */ { 0x0801, LSS_SPI1 }, /* Moorestown SPI Ctrl 1 */ | ||
46 | /* 2 */ { 0x0802, LSS_I2C0 }, /* Moorestown I2C 0 */ | ||
47 | /* 3 */ { 0x0803, LSS_I2C1 }, /* Moorestown I2C 1 */ | ||
48 | /* 4 */ { 0x0804, LSS_I2C2 }, /* Moorestown I2C 2 */ | ||
49 | /* 5 */ { 0x0805, LSS_KBD }, /* Moorestown Keyboard Ctrl */ | ||
50 | /* 6 */ { 0x0806, LSS_USB_HC }, /* Moorestown USB Ctrl */ | ||
51 | /* 7 */ { 0x0807, LSS_SD_HC0 }, /* Moorestown SD Host Ctrl 0 */ | ||
52 | /* 8 */ { 0x0808, LSS_SD_HC1 }, /* Moorestown SD Host Ctrl 1 */ | ||
53 | /* 9 */ { 0x0809, LSS_NAND }, /* Moorestown NAND Ctrl */ | ||
54 | /* 10 */ { 0x080a, LSS_AUDIO }, /* Moorestown Audio Ctrl */ | ||
55 | /* 11 */ { 0x080b, LSS_IMAGING }, /* Moorestown ISP */ | ||
56 | /* 12 */ { 0x080c, LSS_SECURITY }, /* Moorestown Security Controller */ | ||
57 | /* 13 */ { 0x080d, LSS_DISPLAY }, /* Moorestown External Displays */ | ||
58 | /* 14 */ { 0x080e, 0 }, /* Moorestown SCU IPC */ | ||
59 | /* 15 */ { 0x080f, LSS_GPIO }, /* Moorestown GPIO Controller */ | ||
60 | /* 16 */ { 0x0810, 0 }, /* Moorestown Power Management Unit */ | ||
61 | /* 17 */ { 0x0811, LSS_USB_OTG }, /* Moorestown OTG Ctrl */ | ||
62 | /* 18 */ { 0x0812, LSS_SPI2 }, /* Moorestown SPI Ctrl 2 */ | ||
63 | /* 19 */ { 0x0813, 0 }, /* Moorestown SC DMA */ | ||
64 | /* 20 */ { 0x0814, LSS_AUDIO_LPE }, /* Moorestown LPE DMA */ | ||
65 | /* 21 */ { 0x0815, LSS_AUDIO_SSP }, /* Moorestown SSP0 */ | ||
66 | |||
67 | /* 22 */ { 0x084F, LSS_SD_HC2 }, /* Moorestown SD Host Ctrl 2 */ | ||
68 | |||
69 | /* 23 */ { 0x4102, 0 }, /* Lincroft */ | ||
70 | /* 24 */ { 0x4110, 0 }, /* Lincroft */ | ||
71 | }; | ||
72 | |||
73 | /* n.b. We ignore PCI-id 0x815 in LSS9 b/c Linux has no driver for it */ | ||
74 | static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0}; | ||
75 | static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803, | ||
76 | 0x0804, 0x0805, 0x080f, 0}; | ||
77 | |||
78 | /* handle concurrent SMP invokations of pmu_pci_set_power_state() */ | ||
79 | static spinlock_t mrst_pmu_power_state_lock; | ||
80 | |||
81 | static unsigned int wake_counters[MRST_NUM_LSS]; /* DEBUG only */ | ||
82 | static unsigned int pmu_irq_stats[INT_INVALID + 1]; /* DEBUG only */ | ||
83 | |||
84 | static int graphics_is_off; | ||
85 | static int lss_s0i3_enabled; | ||
86 | static bool mrst_pmu_s0i3_enable; | ||
87 | |||
88 | /* debug counters */ | ||
89 | static u32 pmu_wait_ready_calls; | ||
90 | static u32 pmu_wait_ready_udelays; | ||
91 | static u32 pmu_wait_ready_udelays_max; | ||
92 | static u32 pmu_wait_done_calls; | ||
93 | static u32 pmu_wait_done_udelays; | ||
94 | static u32 pmu_wait_done_udelays_max; | ||
95 | static u32 pmu_set_power_state_entry; | ||
96 | static u32 pmu_set_power_state_send_cmd; | ||
97 | |||
98 | static struct mrst_device *pci_id_2_mrst_dev(u16 pci_dev_num) | ||
99 | { | ||
100 | int index = 0; | ||
101 | |||
102 | if ((pci_dev_num >= 0x0800) && (pci_dev_num <= 0x815)) | ||
103 | index = pci_dev_num - 0x800; | ||
104 | else if (pci_dev_num == 0x084F) | ||
105 | index = 22; | ||
106 | else if (pci_dev_num == 0x4102) | ||
107 | index = 23; | ||
108 | else if (pci_dev_num == 0x4110) | ||
109 | index = 24; | ||
110 | |||
111 | if (pci_dev_num != mrst_devs[index].pci_dev_num) { | ||
112 | WARN_ONCE(1, FW_BUG "Unknown PCI device 0x%04X\n", pci_dev_num); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | return &mrst_devs[index]; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * mrst_pmu_validate_cstates | ||
121 | * @dev: cpuidle_device | ||
122 | * | ||
123 | * Certain states are not appropriate for governor to pick in some cases. | ||
124 | * This function will be called as cpuidle_device's prepare callback and | ||
125 | * thus tells governor to ignore such states when selecting the next state | ||
126 | * to enter. | ||
127 | */ | ||
128 | |||
129 | #define IDLE_STATE4_IS_C6 4 | ||
130 | #define IDLE_STATE5_IS_S0I3 5 | ||
131 | |||
132 | int mrst_pmu_invalid_cstates(void) | ||
133 | { | ||
134 | int cpu = smp_processor_id(); | ||
135 | |||
136 | /* | ||
137 | * Demote to C4 if the PMU is busy. | ||
138 | * Since LSS changes leave the busy bit clear... | ||
139 | * busy means either the PMU is waiting for an ACK-C6 that | ||
140 | * isn't coming due to an MWAIT that returned immediately; | ||
141 | * or we returned from S0i3 successfully, and the PMU | ||
142 | * is not done sending us interrupts. | ||
143 | */ | ||
144 | if (pmu_read_busy_status()) | ||
145 | return 1 << IDLE_STATE4_IS_C6 | 1 << IDLE_STATE5_IS_S0I3; | ||
146 | |||
147 | /* | ||
148 | * Disallow S0i3 if: PMU is not initialized, or CPU1 is active, | ||
149 | * or if device LSS is insufficient, or the GPU is active, | ||
150 | * or if it has been explicitly disabled. | ||
151 | */ | ||
152 | if (!pmu_reg || !cpumask_equal(cpu_online_mask, cpumask_of(cpu)) || | ||
153 | !lss_s0i3_enabled || !graphics_is_off || !mrst_pmu_s0i3_enable) | ||
154 | return 1 << IDLE_STATE5_IS_S0I3; | ||
155 | else | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * pmu_update_wake_counters(): read PM_WKS, update wake_counters[] | ||
161 | * DEBUG only. | ||
162 | */ | ||
163 | static void pmu_update_wake_counters(void) | ||
164 | { | ||
165 | int lss; | ||
166 | u32 wake_status; | ||
167 | |||
168 | wake_status = pmu_read_wks(); | ||
169 | |||
170 | for (lss = 0; lss < MRST_NUM_LSS; ++lss) { | ||
171 | if (wake_status & (1 << lss)) | ||
172 | wake_counters[lss]++; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | int mrst_pmu_s0i3_entry(void) | ||
177 | { | ||
178 | int status; | ||
179 | |||
180 | /* Clear any possible error conditions */ | ||
181 | pmu_write_ics(0x300); | ||
182 | |||
183 | /* set wake control to current D-states */ | ||
184 | pmu_write_wssc(S0I3_SSS_TARGET); | ||
185 | |||
186 | status = mrst_s0i3_entry(PM_S0I3_COMMAND, &pmu_reg->pm_cmd); | ||
187 | pmu_update_wake_counters(); | ||
188 | return status; | ||
189 | } | ||
190 | |||
191 | /* poll for maximum of 5ms for busy bit to clear */ | ||
192 | static int pmu_wait_ready(void) | ||
193 | { | ||
194 | int udelays; | ||
195 | |||
196 | pmu_wait_ready_calls++; | ||
197 | |||
198 | for (udelays = 0; udelays < 500; ++udelays) { | ||
199 | if (udelays > pmu_wait_ready_udelays_max) | ||
200 | pmu_wait_ready_udelays_max = udelays; | ||
201 | |||
202 | if (pmu_read_busy_status() == 0) | ||
203 | return 0; | ||
204 | |||
205 | udelay(10); | ||
206 | pmu_wait_ready_udelays++; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * if this fires, observe | ||
211 | * /sys/kernel/debug/mrst_pmu_wait_ready_calls | ||
212 | * /sys/kernel/debug/mrst_pmu_wait_ready_udelays | ||
213 | */ | ||
214 | WARN_ONCE(1, "SCU not ready for 5ms"); | ||
215 | return -EBUSY; | ||
216 | } | ||
217 | /* poll for maximum of 50ms us for busy bit to clear */ | ||
218 | static int pmu_wait_done(void) | ||
219 | { | ||
220 | int udelays; | ||
221 | |||
222 | pmu_wait_done_calls++; | ||
223 | |||
224 | for (udelays = 0; udelays < 500; ++udelays) { | ||
225 | if (udelays > pmu_wait_done_udelays_max) | ||
226 | pmu_wait_done_udelays_max = udelays; | ||
227 | |||
228 | if (pmu_read_busy_status() == 0) | ||
229 | return 0; | ||
230 | |||
231 | udelay(100); | ||
232 | pmu_wait_done_udelays++; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * if this fires, observe | ||
237 | * /sys/kernel/debug/mrst_pmu_wait_done_calls | ||
238 | * /sys/kernel/debug/mrst_pmu_wait_done_udelays | ||
239 | */ | ||
240 | WARN_ONCE(1, "SCU not done for 50ms"); | ||
241 | return -EBUSY; | ||
242 | } | ||
243 | |||
244 | u32 mrst_pmu_msi_is_disabled(void) | ||
245 | { | ||
246 | return pmu_msi_is_disabled(); | ||
247 | } | ||
248 | |||
249 | void mrst_pmu_enable_msi(void) | ||
250 | { | ||
251 | pmu_msi_enable(); | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * pmu_irq - pmu driver interrupt handler | ||
256 | * Context: interrupt context | ||
257 | */ | ||
258 | static irqreturn_t pmu_irq(int irq, void *dummy) | ||
259 | { | ||
260 | union pmu_pm_ics pmu_ics; | ||
261 | |||
262 | pmu_ics.value = pmu_read_ics(); | ||
263 | |||
264 | if (!pmu_ics.bits.pending) | ||
265 | return IRQ_NONE; | ||
266 | |||
267 | switch (pmu_ics.bits.cause) { | ||
268 | case INT_SPURIOUS: | ||
269 | case INT_CMD_DONE: | ||
270 | case INT_CMD_ERR: | ||
271 | case INT_WAKE_RX: | ||
272 | case INT_SS_ERROR: | ||
273 | case INT_S0IX_MISS: | ||
274 | case INT_NO_ACKC6: | ||
275 | pmu_irq_stats[pmu_ics.bits.cause]++; | ||
276 | break; | ||
277 | default: | ||
278 | pmu_irq_stats[INT_INVALID]++; | ||
279 | } | ||
280 | |||
281 | pmu_write_ics(pmu_ics.value); /* Clear pending interrupt */ | ||
282 | |||
283 | return IRQ_HANDLED; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Translate PCI power management to MRST LSS D-states | ||
288 | */ | ||
289 | static int pci_2_mrst_state(int lss, pci_power_t pci_state) | ||
290 | { | ||
291 | switch (pci_state) { | ||
292 | case PCI_D0: | ||
293 | if (SSMSK(D0i1, lss) & D0I1_ACG_SSS_TARGET) | ||
294 | return D0i1; | ||
295 | else | ||
296 | return D0; | ||
297 | case PCI_D1: | ||
298 | return D0i1; | ||
299 | case PCI_D2: | ||
300 | return D0i2; | ||
301 | case PCI_D3hot: | ||
302 | case PCI_D3cold: | ||
303 | return D0i3; | ||
304 | default: | ||
305 | WARN(1, "pci_state %d\n", pci_state); | ||
306 | return 0; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static int pmu_issue_command(u32 pm_ssc) | ||
311 | { | ||
312 | union pmu_pm_set_cfg_cmd_t command; | ||
313 | |||
314 | if (pmu_read_busy_status()) { | ||
315 | pr_debug("pmu is busy, Operation not permitted\n"); | ||
316 | return -1; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * enable interrupts in PMU so that interrupts are | ||
321 | * propagated when ioc bit for a particular set | ||
322 | * command is set | ||
323 | */ | ||
324 | |||
325 | pmu_irq_enable(); | ||
326 | |||
327 | /* Configure the sub systems for pmu2 */ | ||
328 | |||
329 | pmu_write_ssc(pm_ssc); | ||
330 | |||
331 | /* | ||
332 | * Send the set config command for pmu its configured | ||
333 | * for mode CM_IMMEDIATE & hence with No Trigger | ||
334 | */ | ||
335 | |||
336 | command.pmu2_params.d_param.cfg_mode = CM_IMMEDIATE; | ||
337 | command.pmu2_params.d_param.cfg_delay = 0; | ||
338 | command.pmu2_params.d_param.rsvd = 0; | ||
339 | |||
340 | /* construct the command to send SET_CFG to particular PMU */ | ||
341 | command.pmu2_params.d_param.cmd = SET_CFG_CMD; | ||
342 | command.pmu2_params.d_param.ioc = 0; | ||
343 | command.pmu2_params.d_param.mode_id = 0; | ||
344 | command.pmu2_params.d_param.sys_state = SYS_STATE_S0I0; | ||
345 | |||
346 | /* write the value of PM_CMD into particular PMU */ | ||
347 | pr_debug("pmu command being written %x\n", | ||
348 | command.pmu_pm_set_cfg_cmd_value); | ||
349 | |||
350 | pmu_write_cmd(command.pmu_pm_set_cfg_cmd_value); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static u16 pmu_min_lss_pci_req(u16 *ids, u16 pci_state) | ||
356 | { | ||
357 | u16 existing_request; | ||
358 | int i; | ||
359 | |||
360 | for (i = 0; ids[i]; ++i) { | ||
361 | struct mrst_device *mrst_dev; | ||
362 | |||
363 | mrst_dev = pci_id_2_mrst_dev(ids[i]); | ||
364 | if (unlikely(!mrst_dev)) | ||
365 | continue; | ||
366 | |||
367 | existing_request = mrst_dev->latest_request; | ||
368 | if (existing_request < pci_state) | ||
369 | pci_state = existing_request; | ||
370 | } | ||
371 | return pci_state; | ||
372 | } | ||
373 | |||
374 | /** | ||
375 | * pmu_pci_set_power_state - Callback function is used by all the PCI devices | ||
376 | * for a platform specific device power on/shutdown. | ||
377 | */ | ||
378 | |||
379 | int pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t pci_state) | ||
380 | { | ||
381 | u32 old_sss, new_sss; | ||
382 | int status = 0; | ||
383 | struct mrst_device *mrst_dev; | ||
384 | |||
385 | pmu_set_power_state_entry++; | ||
386 | |||
387 | BUG_ON(pdev->vendor != PCI_VENDOR_ID_INTEL); | ||
388 | BUG_ON(pci_state < PCI_D0 || pci_state > PCI_D3cold); | ||
389 | |||
390 | mrst_dev = pci_id_2_mrst_dev(pdev->device); | ||
391 | if (unlikely(!mrst_dev)) | ||
392 | return -ENODEV; | ||
393 | |||
394 | mrst_dev->pci_state_counts[pci_state]++; /* count invocations */ | ||
395 | |||
396 | /* PMU driver calls self as part of PCI initialization, ignore */ | ||
397 | if (pdev->device == PCI_DEV_ID_MRST_PMU) | ||
398 | return 0; | ||
399 | |||
400 | BUG_ON(!pmu_reg); /* SW bug if called before initialized */ | ||
401 | |||
402 | spin_lock(&mrst_pmu_power_state_lock); | ||
403 | |||
404 | if (pdev->d3_delay) { | ||
405 | dev_dbg(&pdev->dev, "d3_delay %d, should be 0\n", | ||
406 | pdev->d3_delay); | ||
407 | pdev->d3_delay = 0; | ||
408 | } | ||
409 | /* | ||
410 | * If Lincroft graphics, simply remember state | ||
411 | */ | ||
412 | if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY | ||
413 | && !((pdev->class & PCI_SUB_CLASS_MASK) >> 8)) { | ||
414 | if (pci_state == PCI_D0) | ||
415 | graphics_is_off = 0; | ||
416 | else | ||
417 | graphics_is_off = 1; | ||
418 | goto ret; | ||
419 | } | ||
420 | |||
421 | if (!mrst_dev->lss) | ||
422 | goto ret; /* device with no LSS */ | ||
423 | |||
424 | if (mrst_dev->latest_request == pci_state) | ||
425 | goto ret; /* no change */ | ||
426 | |||
427 | mrst_dev->latest_request = pci_state; /* record latest request */ | ||
428 | |||
429 | /* | ||
430 | * LSS9 and LSS10 contain multiple PCI devices. | ||
431 | * Use the lowest numbered (highest power) state in the LSS | ||
432 | */ | ||
433 | if (mrst_dev->lss == 9) | ||
434 | pci_state = pmu_min_lss_pci_req(mrst_lss9_pci_ids, pci_state); | ||
435 | else if (mrst_dev->lss == 10) | ||
436 | pci_state = pmu_min_lss_pci_req(mrst_lss10_pci_ids, pci_state); | ||
437 | |||
438 | status = pmu_wait_ready(); | ||
439 | if (status) | ||
440 | goto ret; | ||
441 | |||
442 | old_sss = pmu_read_sss(); | ||
443 | new_sss = old_sss & ~SSMSK(3, mrst_dev->lss); | ||
444 | new_sss |= SSMSK(pci_2_mrst_state(mrst_dev->lss, pci_state), | ||
445 | mrst_dev->lss); | ||
446 | |||
447 | if (new_sss == old_sss) | ||
448 | goto ret; /* nothing to do */ | ||
449 | |||
450 | pmu_set_power_state_send_cmd++; | ||
451 | |||
452 | status = pmu_issue_command(new_sss); | ||
453 | |||
454 | if (unlikely(status != 0)) { | ||
455 | dev_err(&pdev->dev, "Failed to Issue a PM command\n"); | ||
456 | goto ret; | ||
457 | } | ||
458 | |||
459 | if (pmu_wait_done()) | ||
460 | goto ret; | ||
461 | |||
462 | lss_s0i3_enabled = | ||
463 | ((pmu_read_sss() & S0I3_SSS_TARGET) == S0I3_SSS_TARGET); | ||
464 | ret: | ||
465 | spin_unlock(&mrst_pmu_power_state_lock); | ||
466 | return status; | ||
467 | } | ||
468 | |||
469 | #ifdef CONFIG_DEBUG_FS | ||
470 | static char *d0ix_names[] = {"D0", "D0i1", "D0i2", "D0i3"}; | ||
471 | |||
472 | static inline const char *d0ix_name(int state) | ||
473 | { | ||
474 | return d0ix_names[(int) state]; | ||
475 | } | ||
476 | |||
477 | static int debug_mrst_pmu_show(struct seq_file *s, void *unused) | ||
478 | { | ||
479 | struct pci_dev *pdev = NULL; | ||
480 | u32 cur_pmsss; | ||
481 | int lss; | ||
482 | |||
483 | seq_printf(s, "0x%08X D0I1_ACG_SSS_TARGET\n", D0I1_ACG_SSS_TARGET); | ||
484 | |||
485 | cur_pmsss = pmu_read_sss(); | ||
486 | |||
487 | seq_printf(s, "0x%08X S0I3_SSS_TARGET\n", S0I3_SSS_TARGET); | ||
488 | |||
489 | seq_printf(s, "0x%08X Current SSS ", cur_pmsss); | ||
490 | seq_printf(s, lss_s0i3_enabled ? "\n" : "[BLOCKS s0i3]\n"); | ||
491 | |||
492 | if (cpumask_equal(cpu_online_mask, cpumask_of(0))) | ||
493 | seq_printf(s, "cpu0 is only cpu online\n"); | ||
494 | else | ||
495 | seq_printf(s, "cpu0 is NOT only cpu online [BLOCKS S0i3]\n"); | ||
496 | |||
497 | seq_printf(s, "GFX: %s\n", graphics_is_off ? "" : "[BLOCKS s0i3]"); | ||
498 | |||
499 | |||
500 | for_each_pci_dev(pdev) { | ||
501 | int pos; | ||
502 | u16 pmcsr; | ||
503 | struct mrst_device *mrst_dev; | ||
504 | int i; | ||
505 | |||
506 | mrst_dev = pci_id_2_mrst_dev(pdev->device); | ||
507 | |||
508 | seq_printf(s, "%s %04x/%04X %-16.16s ", | ||
509 | dev_name(&pdev->dev), | ||
510 | pdev->vendor, pdev->device, | ||
511 | dev_driver_string(&pdev->dev)); | ||
512 | |||
513 | if (unlikely (!mrst_dev)) { | ||
514 | seq_printf(s, " UNKNOWN\n"); | ||
515 | continue; | ||
516 | } | ||
517 | |||
518 | if (mrst_dev->lss) | ||
519 | seq_printf(s, "LSS %2d %-4s ", mrst_dev->lss, | ||
520 | d0ix_name(((cur_pmsss >> | ||
521 | (mrst_dev->lss * 2)) & 0x3))); | ||
522 | else | ||
523 | seq_printf(s, " "); | ||
524 | |||
525 | /* PCI PM config space setting */ | ||
526 | pos = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
527 | if (pos != 0) { | ||
528 | pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); | ||
529 | seq_printf(s, "PCI-%-4s", | ||
530 | pci_power_name(pmcsr & PCI_PM_CTRL_STATE_MASK)); | ||
531 | } else { | ||
532 | seq_printf(s, " "); | ||
533 | } | ||
534 | |||
535 | seq_printf(s, " %s ", pci_power_name(mrst_dev->latest_request)); | ||
536 | for (i = 0; i <= PCI_D3cold; ++i) | ||
537 | seq_printf(s, "%d ", mrst_dev->pci_state_counts[i]); | ||
538 | |||
539 | if (mrst_dev->lss) { | ||
540 | unsigned int lssmask; | ||
541 | |||
542 | lssmask = SSMSK(D0i3, mrst_dev->lss); | ||
543 | |||
544 | if ((lssmask & S0I3_SSS_TARGET) && | ||
545 | ((lssmask & cur_pmsss) != | ||
546 | (lssmask & S0I3_SSS_TARGET))) | ||
547 | seq_printf(s , "[BLOCKS s0i3]"); | ||
548 | } | ||
549 | |||
550 | seq_printf(s, "\n"); | ||
551 | } | ||
552 | seq_printf(s, "Wake Counters:\n"); | ||
553 | for (lss = 0; lss < MRST_NUM_LSS; ++lss) | ||
554 | seq_printf(s, "LSS%d %d\n", lss, wake_counters[lss]); | ||
555 | |||
556 | seq_printf(s, "Interrupt Counters:\n"); | ||
557 | seq_printf(s, | ||
558 | "INT_SPURIOUS \t%8u\n" "INT_CMD_DONE \t%8u\n" | ||
559 | "INT_CMD_ERR \t%8u\n" "INT_WAKE_RX \t%8u\n" | ||
560 | "INT_SS_ERROR \t%8u\n" "INT_S0IX_MISS\t%8u\n" | ||
561 | "INT_NO_ACKC6 \t%8u\n" "INT_INVALID \t%8u\n", | ||
562 | pmu_irq_stats[INT_SPURIOUS], pmu_irq_stats[INT_CMD_DONE], | ||
563 | pmu_irq_stats[INT_CMD_ERR], pmu_irq_stats[INT_WAKE_RX], | ||
564 | pmu_irq_stats[INT_SS_ERROR], pmu_irq_stats[INT_S0IX_MISS], | ||
565 | pmu_irq_stats[INT_NO_ACKC6], pmu_irq_stats[INT_INVALID]); | ||
566 | |||
567 | seq_printf(s, "mrst_pmu_wait_ready_calls %8d\n", | ||
568 | pmu_wait_ready_calls); | ||
569 | seq_printf(s, "mrst_pmu_wait_ready_udelays %8d\n", | ||
570 | pmu_wait_ready_udelays); | ||
571 | seq_printf(s, "mrst_pmu_wait_ready_udelays_max %8d\n", | ||
572 | pmu_wait_ready_udelays_max); | ||
573 | seq_printf(s, "mrst_pmu_wait_done_calls %8d\n", | ||
574 | pmu_wait_done_calls); | ||
575 | seq_printf(s, "mrst_pmu_wait_done_udelays %8d\n", | ||
576 | pmu_wait_done_udelays); | ||
577 | seq_printf(s, "mrst_pmu_wait_done_udelays_max %8d\n", | ||
578 | pmu_wait_done_udelays_max); | ||
579 | seq_printf(s, "mrst_pmu_set_power_state_entry %8d\n", | ||
580 | pmu_set_power_state_entry); | ||
581 | seq_printf(s, "mrst_pmu_set_power_state_send_cmd %8d\n", | ||
582 | pmu_set_power_state_send_cmd); | ||
583 | seq_printf(s, "SCU busy: %d\n", pmu_read_busy_status()); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int debug_mrst_pmu_open(struct inode *inode, struct file *file) | ||
589 | { | ||
590 | return single_open(file, debug_mrst_pmu_show, NULL); | ||
591 | } | ||
592 | |||
593 | static const struct file_operations devices_state_operations = { | ||
594 | .open = debug_mrst_pmu_open, | ||
595 | .read = seq_read, | ||
596 | .llseek = seq_lseek, | ||
597 | .release = single_release, | ||
598 | }; | ||
599 | #endif /* DEBUG_FS */ | ||
600 | |||
601 | /* | ||
602 | * Validate SCU PCI shim PCI vendor capability byte | ||
603 | * against LSS hard-coded in mrst_devs[] above. | ||
604 | * DEBUG only. | ||
605 | */ | ||
606 | static void pmu_scu_firmware_debug(void) | ||
607 | { | ||
608 | struct pci_dev *pdev = NULL; | ||
609 | |||
610 | for_each_pci_dev(pdev) { | ||
611 | struct mrst_device *mrst_dev; | ||
612 | u8 pci_config_lss; | ||
613 | int pos; | ||
614 | |||
615 | mrst_dev = pci_id_2_mrst_dev(pdev->device); | ||
616 | if (unlikely(!mrst_dev)) { | ||
617 | printk(KERN_ERR FW_BUG "pmu: Unknown " | ||
618 | "PCI device 0x%04X\n", pdev->device); | ||
619 | continue; | ||
620 | } | ||
621 | |||
622 | if (mrst_dev->lss == 0) | ||
623 | continue; /* no LSS in our table */ | ||
624 | |||
625 | pos = pci_find_capability(pdev, PCI_CAP_ID_VNDR); | ||
626 | if (!pos != 0) { | ||
627 | printk(KERN_ERR FW_BUG "pmu: 0x%04X " | ||
628 | "missing PCI Vendor Capability\n", | ||
629 | pdev->device); | ||
630 | continue; | ||
631 | } | ||
632 | pci_read_config_byte(pdev, pos + 4, &pci_config_lss); | ||
633 | if (!(pci_config_lss & PCI_VENDOR_CAP_LOG_SS_MASK)) { | ||
634 | printk(KERN_ERR FW_BUG "pmu: 0x%04X " | ||
635 | "invalid PCI Vendor Capability 0x%x " | ||
636 | " expected LSS 0x%X\n", | ||
637 | pdev->device, pci_config_lss, mrst_dev->lss); | ||
638 | continue; | ||
639 | } | ||
640 | pci_config_lss &= PCI_VENDOR_CAP_LOG_ID_MASK; | ||
641 | |||
642 | if (mrst_dev->lss == pci_config_lss) | ||
643 | continue; | ||
644 | |||
645 | printk(KERN_ERR FW_BUG "pmu: 0x%04X LSS = %d, expected %d\n", | ||
646 | pdev->device, pci_config_lss, mrst_dev->lss); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * pmu_probe | ||
652 | */ | ||
653 | static int __devinit pmu_probe(struct pci_dev *pdev, | ||
654 | const struct pci_device_id *pci_id) | ||
655 | { | ||
656 | int ret; | ||
657 | struct mrst_pmu_reg *pmu; | ||
658 | |||
659 | /* Init the device */ | ||
660 | ret = pci_enable_device(pdev); | ||
661 | if (ret) { | ||
662 | dev_err(&pdev->dev, "Unable to Enable PCI device\n"); | ||
663 | return ret; | ||
664 | } | ||
665 | |||
666 | ret = pci_request_regions(pdev, MRST_PMU_DRV_NAME); | ||
667 | if (ret < 0) { | ||
668 | dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); | ||
669 | goto out_err1; | ||
670 | } | ||
671 | |||
672 | /* Map the memory of PMU reg base */ | ||
673 | pmu = pci_iomap(pdev, 0, 0); | ||
674 | if (!pmu) { | ||
675 | dev_err(&pdev->dev, "Unable to map the PMU address space\n"); | ||
676 | ret = -ENOMEM; | ||
677 | goto out_err2; | ||
678 | } | ||
679 | |||
680 | #ifdef CONFIG_DEBUG_FS | ||
681 | /* /sys/kernel/debug/mrst_pmu */ | ||
682 | (void) debugfs_create_file("mrst_pmu", S_IFREG | S_IRUGO, | ||
683 | NULL, NULL, &devices_state_operations); | ||
684 | #endif | ||
685 | pmu_reg = pmu; /* success */ | ||
686 | |||
687 | if (request_irq(pdev->irq, pmu_irq, 0, MRST_PMU_DRV_NAME, NULL)) { | ||
688 | dev_err(&pdev->dev, "Registering isr has failed\n"); | ||
689 | ret = -1; | ||
690 | goto out_err3; | ||
691 | } | ||
692 | |||
693 | pmu_scu_firmware_debug(); | ||
694 | |||
695 | pmu_write_wkc(S0I3_WAKE_SOURCES); /* Enable S0i3 wakeup sources */ | ||
696 | |||
697 | pmu_wait_ready(); | ||
698 | |||
699 | pmu_write_ssc(D0I1_ACG_SSS_TARGET); /* Enable Auto-Clock_Gating */ | ||
700 | pmu_write_cmd(0x201); | ||
701 | |||
702 | spin_lock_init(&mrst_pmu_power_state_lock); | ||
703 | |||
704 | /* Enable the hardware interrupt */ | ||
705 | pmu_irq_enable(); | ||
706 | return 0; | ||
707 | |||
708 | out_err3: | ||
709 | free_irq(pdev->irq, NULL); | ||
710 | pci_iounmap(pdev, pmu_reg); | ||
711 | pmu_reg = NULL; | ||
712 | out_err2: | ||
713 | pci_release_region(pdev, 0); | ||
714 | out_err1: | ||
715 | pci_disable_device(pdev); | ||
716 | return ret; | ||
717 | } | ||
718 | |||
719 | static void __devexit pmu_remove(struct pci_dev *pdev) | ||
720 | { | ||
721 | dev_err(&pdev->dev, "Mid PM pmu_remove called\n"); | ||
722 | |||
723 | /* Freeing up the irq */ | ||
724 | free_irq(pdev->irq, NULL); | ||
725 | |||
726 | pci_iounmap(pdev, pmu_reg); | ||
727 | pmu_reg = NULL; | ||
728 | |||
729 | /* disable the current PCI device */ | ||
730 | pci_release_region(pdev, 0); | ||
731 | pci_disable_device(pdev); | ||
732 | } | ||
733 | |||
734 | static DEFINE_PCI_DEVICE_TABLE(pmu_pci_ids) = { | ||
735 | { PCI_VDEVICE(INTEL, PCI_DEV_ID_MRST_PMU), 0 }, | ||
736 | { } | ||
737 | }; | ||
738 | |||
739 | MODULE_DEVICE_TABLE(pci, pmu_pci_ids); | ||
740 | |||
741 | static struct pci_driver driver = { | ||
742 | .name = MRST_PMU_DRV_NAME, | ||
743 | .id_table = pmu_pci_ids, | ||
744 | .probe = pmu_probe, | ||
745 | .remove = __devexit_p(pmu_remove), | ||
746 | }; | ||
747 | |||
748 | /** | ||
749 | * pmu_pci_register - register the PMU driver as PCI device | ||
750 | */ | ||
751 | static int __init pmu_pci_register(void) | ||
752 | { | ||
753 | return pci_register_driver(&driver); | ||
754 | } | ||
755 | |||
756 | /* Register and probe via fs_initcall() to preceed device_initcall() */ | ||
757 | fs_initcall(pmu_pci_register); | ||
758 | |||
759 | static void __exit mid_pci_cleanup(void) | ||
760 | { | ||
761 | pci_unregister_driver(&driver); | ||
762 | } | ||
763 | |||
764 | static int ia_major; | ||
765 | static int ia_minor; | ||
766 | |||
767 | static int pmu_sfi_parse_oem(struct sfi_table_header *table) | ||
768 | { | ||
769 | struct sfi_table_simple *sb; | ||
770 | |||
771 | sb = (struct sfi_table_simple *)table; | ||
772 | ia_major = (sb->pentry[1] >> 0) & 0xFFFF; | ||
773 | ia_minor = (sb->pentry[1] >> 16) & 0xFFFF; | ||
774 | printk(KERN_INFO "mrst_pmu: IA FW version v%x.%x\n", | ||
775 | ia_major, ia_minor); | ||
776 | |||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | static int __init scu_fw_check(void) | ||
781 | { | ||
782 | int ret; | ||
783 | u32 fw_version; | ||
784 | |||
785 | if (!pmu_reg) | ||
786 | return 0; /* this driver didn't probe-out */ | ||
787 | |||
788 | sfi_table_parse("OEMB", NULL, NULL, pmu_sfi_parse_oem); | ||
789 | |||
790 | if (ia_major < 0x6005 || ia_minor < 0x1525) { | ||
791 | WARN(1, "mrst_pmu: IA FW version too old\n"); | ||
792 | return -1; | ||
793 | } | ||
794 | |||
795 | ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0, | ||
796 | &fw_version, 1); | ||
797 | |||
798 | if (ret) { | ||
799 | WARN(1, "mrst_pmu: IPC FW version? %d\n", ret); | ||
800 | } else { | ||
801 | int scu_major = (fw_version >> 8) & 0xFF; | ||
802 | int scu_minor = (fw_version >> 0) & 0xFF; | ||
803 | |||
804 | printk(KERN_INFO "mrst_pmu: firmware v%x\n", fw_version); | ||
805 | |||
806 | if ((scu_major >= 0xC0) && (scu_minor >= 0x49)) { | ||
807 | printk(KERN_INFO "mrst_pmu: enabling S0i3\n"); | ||
808 | mrst_pmu_s0i3_enable = true; | ||
809 | } else { | ||
810 | WARN(1, "mrst_pmu: S0i3 disabled, old firmware %X.%X", | ||
811 | scu_major, scu_minor); | ||
812 | } | ||
813 | } | ||
814 | return 0; | ||
815 | } | ||
816 | late_initcall(scu_fw_check); | ||
817 | module_exit(mid_pci_cleanup); | ||
diff --git a/arch/x86/platform/mrst/pmu.h b/arch/x86/platform/mrst/pmu.h deleted file mode 100644 index bfbfe64b167b..000000000000 --- a/arch/x86/platform/mrst/pmu.h +++ /dev/null | |||
@@ -1,234 +0,0 @@ | |||
1 | /* | ||
2 | * mrst/pmu.h - private definitions for MRST Power Management Unit mrst/pmu.c | ||
3 | * | ||
4 | * Copyright (c) 2011, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _MRST_PMU_H_ | ||
21 | #define _MRST_PMU_H_ | ||
22 | |||
23 | #define PCI_DEV_ID_MRST_PMU 0x0810 | ||
24 | #define MRST_PMU_DRV_NAME "mrst_pmu" | ||
25 | #define PCI_SUB_CLASS_MASK 0xFF00 | ||
26 | |||
27 | #define PCI_VENDOR_CAP_LOG_ID_MASK 0x7F | ||
28 | #define PCI_VENDOR_CAP_LOG_SS_MASK 0x80 | ||
29 | |||
30 | #define SUB_SYS_ALL_D0I1 0x01155555 | ||
31 | #define S0I3_WAKE_SOURCES 0x00001FFF | ||
32 | |||
33 | #define PM_S0I3_COMMAND \ | ||
34 | ((0 << 31) | /* Reserved */ \ | ||
35 | (0 << 30) | /* Core must be idle */ \ | ||
36 | (0xc2 << 22) | /* ACK C6 trigger */ \ | ||
37 | (3 << 19) | /* Trigger on DMI message */ \ | ||
38 | (3 << 16) | /* Enter S0i3 */ \ | ||
39 | (0 << 13) | /* Numeric mode ID (sw) */ \ | ||
40 | (3 << 9) | /* Trigger mode */ \ | ||
41 | (0 << 8) | /* Do not interrupt */ \ | ||
42 | (1 << 0)) /* Set configuration */ | ||
43 | |||
44 | #define LSS_DMI 0 | ||
45 | #define LSS_SD_HC0 1 | ||
46 | #define LSS_SD_HC1 2 | ||
47 | #define LSS_NAND 3 | ||
48 | #define LSS_IMAGING 4 | ||
49 | #define LSS_SECURITY 5 | ||
50 | #define LSS_DISPLAY 6 | ||
51 | #define LSS_USB_HC 7 | ||
52 | #define LSS_USB_OTG 8 | ||
53 | #define LSS_AUDIO 9 | ||
54 | #define LSS_AUDIO_LPE 9 | ||
55 | #define LSS_AUDIO_SSP 9 | ||
56 | #define LSS_I2C0 10 | ||
57 | #define LSS_I2C1 10 | ||
58 | #define LSS_I2C2 10 | ||
59 | #define LSS_KBD 10 | ||
60 | #define LSS_SPI0 10 | ||
61 | #define LSS_SPI1 10 | ||
62 | #define LSS_SPI2 10 | ||
63 | #define LSS_GPIO 10 | ||
64 | #define LSS_SRAM 11 /* used by SCU, do not touch */ | ||
65 | #define LSS_SD_HC2 12 | ||
66 | /* LSS hardware bits 15,14,13 are hardwired to 0, thus unusable */ | ||
67 | #define MRST_NUM_LSS 13 | ||
68 | |||
69 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||
70 | |||
71 | #define SSMSK(mask, lss) ((mask) << ((lss) * 2)) | ||
72 | #define D0 0 | ||
73 | #define D0i1 1 | ||
74 | #define D0i2 2 | ||
75 | #define D0i3 3 | ||
76 | |||
77 | #define S0I3_SSS_TARGET ( \ | ||
78 | SSMSK(D0i1, LSS_DMI) | \ | ||
79 | SSMSK(D0i3, LSS_SD_HC0) | \ | ||
80 | SSMSK(D0i3, LSS_SD_HC1) | \ | ||
81 | SSMSK(D0i3, LSS_NAND) | \ | ||
82 | SSMSK(D0i3, LSS_SD_HC2) | \ | ||
83 | SSMSK(D0i3, LSS_IMAGING) | \ | ||
84 | SSMSK(D0i3, LSS_SECURITY) | \ | ||
85 | SSMSK(D0i3, LSS_DISPLAY) | \ | ||
86 | SSMSK(D0i3, LSS_USB_HC) | \ | ||
87 | SSMSK(D0i3, LSS_USB_OTG) | \ | ||
88 | SSMSK(D0i3, LSS_AUDIO) | \ | ||
89 | SSMSK(D0i1, LSS_I2C0)) | ||
90 | |||
91 | /* | ||
92 | * D0i1 on Langwell is Autonomous Clock Gating (ACG). | ||
93 | * Enable ACG on every LSS except camera and audio | ||
94 | */ | ||
95 | #define D0I1_ACG_SSS_TARGET \ | ||
96 | (SUB_SYS_ALL_D0I1 & ~SSMSK(D0i1, LSS_IMAGING) & ~SSMSK(D0i1, LSS_AUDIO)) | ||
97 | |||
98 | enum cm_mode { | ||
99 | CM_NOP, /* ignore the config mode value */ | ||
100 | CM_IMMEDIATE, | ||
101 | CM_DELAY, | ||
102 | CM_TRIGGER, | ||
103 | CM_INVALID | ||
104 | }; | ||
105 | |||
106 | enum sys_state { | ||
107 | SYS_STATE_S0I0, | ||
108 | SYS_STATE_S0I1, | ||
109 | SYS_STATE_S0I2, | ||
110 | SYS_STATE_S0I3, | ||
111 | SYS_STATE_S3, | ||
112 | SYS_STATE_S5 | ||
113 | }; | ||
114 | |||
115 | #define SET_CFG_CMD 1 | ||
116 | |||
117 | enum int_status { | ||
118 | INT_SPURIOUS = 0, | ||
119 | INT_CMD_DONE = 1, | ||
120 | INT_CMD_ERR = 2, | ||
121 | INT_WAKE_RX = 3, | ||
122 | INT_SS_ERROR = 4, | ||
123 | INT_S0IX_MISS = 5, | ||
124 | INT_NO_ACKC6 = 6, | ||
125 | INT_INVALID = 7, | ||
126 | }; | ||
127 | |||
128 | /* PMU register interface */ | ||
129 | static struct mrst_pmu_reg { | ||
130 | u32 pm_sts; /* 0x00 */ | ||
131 | u32 pm_cmd; /* 0x04 */ | ||
132 | u32 pm_ics; /* 0x08 */ | ||
133 | u32 _resv1; /* 0x0C */ | ||
134 | u32 pm_wkc[2]; /* 0x10 */ | ||
135 | u32 pm_wks[2]; /* 0x18 */ | ||
136 | u32 pm_ssc[4]; /* 0x20 */ | ||
137 | u32 pm_sss[4]; /* 0x30 */ | ||
138 | u32 pm_wssc[4]; /* 0x40 */ | ||
139 | u32 pm_c3c4; /* 0x50 */ | ||
140 | u32 pm_c5c6; /* 0x54 */ | ||
141 | u32 pm_msi_disable; /* 0x58 */ | ||
142 | } *pmu_reg; | ||
143 | |||
144 | static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); } | ||
145 | static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); } | ||
146 | static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); } | ||
147 | static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); } | ||
148 | |||
149 | static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); } | ||
150 | static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); } | ||
151 | static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); } | ||
152 | static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); } | ||
153 | static inline void pmu_write_wssc(u32 arg) | ||
154 | { writel(arg, &pmu_reg->pm_wssc[0]); } | ||
155 | |||
156 | static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); } | ||
157 | static inline u32 pmu_msi_is_disabled(void) | ||
158 | { return readl(&pmu_reg->pm_msi_disable); } | ||
159 | |||
160 | union pmu_pm_ics { | ||
161 | struct { | ||
162 | u32 cause:8; | ||
163 | u32 enable:1; | ||
164 | u32 pending:1; | ||
165 | u32 reserved:22; | ||
166 | } bits; | ||
167 | u32 value; | ||
168 | }; | ||
169 | |||
170 | static inline void pmu_irq_enable(void) | ||
171 | { | ||
172 | union pmu_pm_ics pmu_ics; | ||
173 | |||
174 | pmu_ics.value = pmu_read_ics(); | ||
175 | pmu_ics.bits.enable = 1; | ||
176 | pmu_write_ics(pmu_ics.value); | ||
177 | } | ||
178 | |||
179 | union pmu_pm_status { | ||
180 | struct { | ||
181 | u32 pmu_rev:8; | ||
182 | u32 pmu_busy:1; | ||
183 | u32 mode_id:4; | ||
184 | u32 Reserved:19; | ||
185 | } pmu_status_parts; | ||
186 | u32 pmu_status_value; | ||
187 | }; | ||
188 | |||
189 | static inline int pmu_read_busy_status(void) | ||
190 | { | ||
191 | union pmu_pm_status result; | ||
192 | |||
193 | result.pmu_status_value = pmu_read_sts(); | ||
194 | |||
195 | return result.pmu_status_parts.pmu_busy; | ||
196 | } | ||
197 | |||
198 | /* pmu set config parameters */ | ||
199 | struct cfg_delay_param_t { | ||
200 | u32 cmd:8; | ||
201 | u32 ioc:1; | ||
202 | u32 cfg_mode:4; | ||
203 | u32 mode_id:3; | ||
204 | u32 sys_state:3; | ||
205 | u32 cfg_delay:8; | ||
206 | u32 rsvd:5; | ||
207 | }; | ||
208 | |||
209 | struct cfg_trig_param_t { | ||
210 | u32 cmd:8; | ||
211 | u32 ioc:1; | ||
212 | u32 cfg_mode:4; | ||
213 | u32 mode_id:3; | ||
214 | u32 sys_state:3; | ||
215 | u32 cfg_trig_type:3; | ||
216 | u32 cfg_trig_val:8; | ||
217 | u32 cmbi:1; | ||
218 | u32 rsvd1:1; | ||
219 | }; | ||
220 | |||
221 | union pmu_pm_set_cfg_cmd_t { | ||
222 | union { | ||
223 | struct cfg_delay_param_t d_param; | ||
224 | struct cfg_trig_param_t t_param; | ||
225 | } pmu2_params; | ||
226 | u32 pmu_pm_set_cfg_cmd_value; | ||
227 | }; | ||
228 | |||
229 | #ifdef FUTURE_PATCH | ||
230 | extern int mrst_s0i3_entry(u32 regval, u32 *regaddr); | ||
231 | #else | ||
232 | static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; } | ||
233 | #endif | ||
234 | #endif | ||
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 2b235b77d9ab..23e5b9d7977b 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c | |||
@@ -23,7 +23,66 @@ | |||
23 | #define XO15_SCI_CLASS DRV_NAME | 23 | #define XO15_SCI_CLASS DRV_NAME |
24 | #define XO15_SCI_DEVICE_NAME "OLPC XO-1.5 SCI" | 24 | #define XO15_SCI_DEVICE_NAME "OLPC XO-1.5 SCI" |
25 | 25 | ||
26 | static unsigned long xo15_sci_gpe; | 26 | static unsigned long xo15_sci_gpe; |
27 | static bool lid_wake_on_close; | ||
28 | |||
29 | /* | ||
30 | * The normal ACPI LID wakeup behavior is wake-on-open, but not | ||
31 | * wake-on-close. This is implemented as standard by the XO-1.5 DSDT. | ||
32 | * | ||
33 | * We provide here a sysfs attribute that will additionally enable | ||
34 | * wake-on-close behavior. This is useful (e.g.) when we oportunistically | ||
35 | * suspend with the display running; if the lid is then closed, we want to | ||
36 | * wake up to turn the display off. | ||
37 | * | ||
38 | * This is controlled through a custom method in the XO-1.5 DSDT. | ||
39 | */ | ||
40 | static int set_lid_wake_behavior(bool wake_on_close) | ||
41 | { | ||
42 | struct acpi_object_list arg_list; | ||
43 | union acpi_object arg; | ||
44 | acpi_status status; | ||
45 | |||
46 | arg_list.count = 1; | ||
47 | arg_list.pointer = &arg; | ||
48 | arg.type = ACPI_TYPE_INTEGER; | ||
49 | arg.integer.value = wake_on_close; | ||
50 | |||
51 | status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL); | ||
52 | if (ACPI_FAILURE(status)) { | ||
53 | pr_warning(PFX "failed to set lid behavior\n"); | ||
54 | return 1; | ||
55 | } | ||
56 | |||
57 | lid_wake_on_close = wake_on_close; | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static ssize_t | ||
63 | lid_wake_on_close_show(struct kobject *s, struct kobj_attribute *attr, char *buf) | ||
64 | { | ||
65 | return sprintf(buf, "%u\n", lid_wake_on_close); | ||
66 | } | ||
67 | |||
68 | static ssize_t lid_wake_on_close_store(struct kobject *s, | ||
69 | struct kobj_attribute *attr, | ||
70 | const char *buf, size_t n) | ||
71 | { | ||
72 | unsigned int val; | ||
73 | |||
74 | if (sscanf(buf, "%u", &val) != 1) | ||
75 | return -EINVAL; | ||
76 | |||
77 | set_lid_wake_behavior(!!val); | ||
78 | |||
79 | return n; | ||
80 | } | ||
81 | |||
82 | static struct kobj_attribute lid_wake_on_close_attr = | ||
83 | __ATTR(lid_wake_on_close, 0644, | ||
84 | lid_wake_on_close_show, | ||
85 | lid_wake_on_close_store); | ||
27 | 86 | ||
28 | static void battery_status_changed(void) | 87 | static void battery_status_changed(void) |
29 | { | 88 | { |
@@ -91,6 +150,7 @@ static int xo15_sci_add(struct acpi_device *device) | |||
91 | { | 150 | { |
92 | unsigned long long tmp; | 151 | unsigned long long tmp; |
93 | acpi_status status; | 152 | acpi_status status; |
153 | int r; | ||
94 | 154 | ||
95 | if (!device) | 155 | if (!device) |
96 | return -EINVAL; | 156 | return -EINVAL; |
@@ -112,6 +172,10 @@ static int xo15_sci_add(struct acpi_device *device) | |||
112 | 172 | ||
113 | dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe); | 173 | dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe); |
114 | 174 | ||
175 | r = sysfs_create_file(&device->dev.kobj, &lid_wake_on_close_attr.attr); | ||
176 | if (r) | ||
177 | goto err_sysfs; | ||
178 | |||
115 | /* Flush queue, and enable all SCI events */ | 179 | /* Flush queue, and enable all SCI events */ |
116 | process_sci_queue(); | 180 | process_sci_queue(); |
117 | olpc_ec_mask_write(EC_SCI_SRC_ALL); | 181 | olpc_ec_mask_write(EC_SCI_SRC_ALL); |
@@ -123,6 +187,11 @@ static int xo15_sci_add(struct acpi_device *device) | |||
123 | device_init_wakeup(&device->dev, true); | 187 | device_init_wakeup(&device->dev, true); |
124 | 188 | ||
125 | return 0; | 189 | return 0; |
190 | |||
191 | err_sysfs: | ||
192 | acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler); | ||
193 | cancel_work_sync(&sci_work); | ||
194 | return r; | ||
126 | } | 195 | } |
127 | 196 | ||
128 | static int xo15_sci_remove(struct acpi_device *device, int type) | 197 | static int xo15_sci_remove(struct acpi_device *device, int type) |
@@ -130,6 +199,7 @@ static int xo15_sci_remove(struct acpi_device *device, int type) | |||
130 | acpi_disable_gpe(NULL, xo15_sci_gpe); | 199 | acpi_disable_gpe(NULL, xo15_sci_gpe); |
131 | acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler); | 200 | acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler); |
132 | cancel_work_sync(&sci_work); | 201 | cancel_work_sync(&sci_work); |
202 | sysfs_remove_file(&device->dev.kobj, &lid_wake_on_close_attr.attr); | ||
133 | return 0; | 203 | return 0; |
134 | } | 204 | } |
135 | 205 | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9ca28fced2b9..8c7a75d53101 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -89,16 +89,6 @@ config LEDS_NET48XX | |||
89 | This option enables support for the Soekris net4801 and net4826 error | 89 | This option enables support for the Soekris net4801 and net4826 error |
90 | LED. | 90 | LED. |
91 | 91 | ||
92 | config LEDS_NET5501 | ||
93 | tristate "LED Support for Soekris net5501 series Error LED" | ||
94 | depends on LEDS_TRIGGERS | ||
95 | depends on X86 && GPIO_CS5535 | ||
96 | select LEDS_TRIGGER_DEFAULT_ON | ||
97 | default n | ||
98 | help | ||
99 | Add support for the Soekris net5501 board (detection, error led | ||
100 | and GPIO). | ||
101 | |||
102 | config LEDS_FSG | 92 | config LEDS_FSG |
103 | tristate "LED Support for the Freecom FSG-3" | 93 | tristate "LED Support for the Freecom FSG-3" |
104 | depends on LEDS_CLASS | 94 | depends on LEDS_CLASS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 1fc6875a8b20..6bcf4f695515 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -14,7 +14,6 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o | |||
14 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o | 14 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o |
15 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o | 15 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o |
16 | obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o | 16 | obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o |
17 | obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o | ||
18 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o | 17 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o |
19 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o | 18 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o |
20 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | 19 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o |
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c deleted file mode 100644 index 0555d4709a7c..000000000000 --- a/drivers/leds/leds-net5501.c +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /* | ||
2 | * Soekris board support code | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Tower Technologies | ||
5 | * Written by Alessandro Zummo <a.zummo@towertech.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/leds.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <asm/geode.h> | ||
22 | |||
23 | static const struct gpio_led net5501_leds[] = { | ||
24 | { | ||
25 | .name = "error", | ||
26 | .gpio = 6, | ||
27 | .default_trigger = "default-on", | ||
28 | }, | ||
29 | }; | ||
30 | |||
31 | static struct gpio_led_platform_data net5501_leds_data = { | ||
32 | .num_leds = ARRAY_SIZE(net5501_leds), | ||
33 | .leds = net5501_leds, | ||
34 | }; | ||
35 | |||
36 | static struct platform_device net5501_leds_dev = { | ||
37 | .name = "leds-gpio", | ||
38 | .id = -1, | ||
39 | .dev.platform_data = &net5501_leds_data, | ||
40 | }; | ||
41 | |||
42 | static void __init init_net5501(void) | ||
43 | { | ||
44 | platform_device_register(&net5501_leds_dev); | ||
45 | } | ||
46 | |||
47 | struct soekris_board { | ||
48 | u16 offset; | ||
49 | char *sig; | ||
50 | u8 len; | ||
51 | void (*init)(void); | ||
52 | }; | ||
53 | |||
54 | static struct soekris_board __initdata boards[] = { | ||
55 | { 0xb7b, "net5501", 7, init_net5501 }, /* net5501 v1.33/1.33c */ | ||
56 | { 0xb1f, "net5501", 7, init_net5501 }, /* net5501 v1.32i */ | ||
57 | }; | ||
58 | |||
59 | static int __init soekris_init(void) | ||
60 | { | ||
61 | int i; | ||
62 | unsigned char *rombase, *bios; | ||
63 | |||
64 | if (!is_geode()) | ||
65 | return 0; | ||
66 | |||
67 | rombase = ioremap(0xffff0000, 0xffff); | ||
68 | if (!rombase) { | ||
69 | printk(KERN_INFO "Soekris net5501 LED driver failed to get rombase"); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | bios = rombase + 0x20; /* null terminated */ | ||
74 | |||
75 | if (strncmp(bios, "comBIOS", 7)) | ||
76 | goto unmap; | ||
77 | |||
78 | for (i = 0; i < ARRAY_SIZE(boards); i++) { | ||
79 | unsigned char *model = rombase + boards[i].offset; | ||
80 | |||
81 | if (strncmp(model, boards[i].sig, boards[i].len) == 0) { | ||
82 | printk(KERN_INFO "Soekris %s: %s\n", model, bios); | ||
83 | |||
84 | if (boards[i].init) | ||
85 | boards[i].init(); | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | unmap: | ||
91 | iounmap(rombase); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | arch_initcall(soekris_init); | ||
96 | |||
97 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 15dbd8cc445f..2dc02c972ce9 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -696,33 +696,11 @@ config INTEL_MID_POWER_BUTTON | |||
696 | 696 | ||
697 | config INTEL_MFLD_THERMAL | 697 | config INTEL_MFLD_THERMAL |
698 | tristate "Thermal driver for Intel Medfield platform" | 698 | tristate "Thermal driver for Intel Medfield platform" |
699 | depends on INTEL_SCU_IPC && THERMAL | 699 | depends on MFD_INTEL_MSIC && THERMAL |
700 | help | 700 | help |
701 | Say Y here to enable thermal driver support for the Intel Medfield | 701 | Say Y here to enable thermal driver support for the Intel Medfield |
702 | platform. | 702 | platform. |
703 | 703 | ||
704 | config RAR_REGISTER | ||
705 | bool "Restricted Access Region Register Driver" | ||
706 | depends on PCI && X86_MRST | ||
707 | default n | ||
708 | ---help--- | ||
709 | This driver allows other kernel drivers access to the | ||
710 | contents of the restricted access region control registers. | ||
711 | |||
712 | The restricted access region control registers | ||
713 | (rar_registers) are used to pass address and | ||
714 | locking information on restricted access regions | ||
715 | to other drivers that use restricted access regions. | ||
716 | |||
717 | The restricted access regions are regions of memory | ||
718 | on the Intel MID Platform that are not accessible to | ||
719 | the x86 processor, but are accessible to dedicated | ||
720 | processors on board peripheral devices. | ||
721 | |||
722 | The purpose of the restricted access regions is to | ||
723 | protect sensitive data from compromise by unauthorized | ||
724 | programs running on the x86 processor. | ||
725 | |||
726 | config INTEL_IPS | 704 | config INTEL_IPS |
727 | tristate "Intel Intelligent Power Sharing" | 705 | tristate "Intel Intelligent Power Sharing" |
728 | depends on ACPI | 706 | depends on ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index d328f21e9fdd..bb947657d490 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
@@ -36,7 +36,6 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o | |||
36 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o | 36 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o |
37 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o | 37 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o |
38 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o | 38 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o |
39 | obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o | ||
40 | obj-$(CONFIG_INTEL_IPS) += intel_ips.o | 39 | obj-$(CONFIG_INTEL_IPS) += intel_ips.o |
41 | obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o | 40 | obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o |
42 | obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o | 41 | obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o |
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c index f1ae5078b7ec..0903a883e9f4 100644 --- a/drivers/platform/x86/intel_mid_powerbtn.c +++ b/drivers/platform/x86/intel_mid_powerbtn.c | |||
@@ -23,21 +23,27 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | 26 | #include <linux/mfd/intel_msic.h> | |
27 | #include <asm/intel_scu_ipc.h> | ||
28 | 27 | ||
29 | #define DRIVER_NAME "msic_power_btn" | 28 | #define DRIVER_NAME "msic_power_btn" |
30 | 29 | ||
31 | #define MSIC_PB_STATUS 0x3f | ||
32 | #define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */ | 30 | #define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */ |
33 | 31 | ||
32 | /* | ||
33 | * MSIC document ti_datasheet defines the 1st bit reg 0x21 is used to mask | ||
34 | * power button interrupt | ||
35 | */ | ||
36 | #define MSIC_PWRBTNM (1 << 0) | ||
37 | |||
34 | static irqreturn_t mfld_pb_isr(int irq, void *dev_id) | 38 | static irqreturn_t mfld_pb_isr(int irq, void *dev_id) |
35 | { | 39 | { |
36 | struct input_dev *input = dev_id; | 40 | struct input_dev *input = dev_id; |
37 | int ret; | 41 | int ret; |
38 | u8 pbstat; | 42 | u8 pbstat; |
39 | 43 | ||
40 | ret = intel_scu_ipc_ioread8(MSIC_PB_STATUS, &pbstat); | 44 | ret = intel_msic_reg_read(INTEL_MSIC_PBSTATUS, &pbstat); |
45 | dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat); | ||
46 | |||
41 | if (ret < 0) { | 47 | if (ret < 0) { |
42 | dev_err(input->dev.parent, "Read error %d while reading" | 48 | dev_err(input->dev.parent, "Read error %d while reading" |
43 | " MSIC_PB_STATUS\n", ret); | 49 | " MSIC_PB_STATUS\n", ret); |
@@ -88,6 +94,24 @@ static int __devinit mfld_pb_probe(struct platform_device *pdev) | |||
88 | } | 94 | } |
89 | 95 | ||
90 | platform_set_drvdata(pdev, input); | 96 | platform_set_drvdata(pdev, input); |
97 | |||
98 | /* | ||
99 | * SCU firmware might send power button interrupts to IA core before | ||
100 | * kernel boots and doesn't get EOI from IA core. The first bit of | ||
101 | * MSIC reg 0x21 is kept masked, and SCU firmware doesn't send new | ||
102 | * power interrupt to Android kernel. Unmask the bit when probing | ||
103 | * power button in kernel. | ||
104 | * There is a very narrow race between irq handler and power button | ||
105 | * initialization. The race happens rarely. So we needn't worry | ||
106 | * about it. | ||
107 | */ | ||
108 | error = intel_msic_reg_update(INTEL_MSIC_IRQLVL1MSK, 0, MSIC_PWRBTNM); | ||
109 | if (error) { | ||
110 | dev_err(&pdev->dev, "Unable to clear power button interrupt, " | ||
111 | "error: %d\n", error); | ||
112 | goto err_free_irq; | ||
113 | } | ||
114 | |||
91 | return 0; | 115 | return 0; |
92 | 116 | ||
93 | err_free_irq: | 117 | err_free_irq: |
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index ccd7b1f83519..2ee9766737ea 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c | |||
@@ -33,18 +33,15 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/pm.h> | 34 | #include <linux/pm.h> |
35 | #include <linux/thermal.h> | 35 | #include <linux/thermal.h> |
36 | 36 | #include <linux/mfd/intel_msic.h> | |
37 | #include <asm/intel_scu_ipc.h> | ||
38 | 37 | ||
39 | /* Number of thermal sensors */ | 38 | /* Number of thermal sensors */ |
40 | #define MSIC_THERMAL_SENSORS 4 | 39 | #define MSIC_THERMAL_SENSORS 4 |
41 | 40 | ||
42 | /* ADC1 - thermal registers */ | 41 | /* ADC1 - thermal registers */ |
43 | #define MSIC_THERM_ADC1CNTL1 0x1C0 | ||
44 | #define MSIC_ADC_ENBL 0x10 | 42 | #define MSIC_ADC_ENBL 0x10 |
45 | #define MSIC_ADC_START 0x08 | 43 | #define MSIC_ADC_START 0x08 |
46 | 44 | ||
47 | #define MSIC_THERM_ADC1CNTL3 0x1C2 | ||
48 | #define MSIC_ADCTHERM_ENBL 0x04 | 45 | #define MSIC_ADCTHERM_ENBL 0x04 |
49 | #define MSIC_ADCRRDATA_ENBL 0x05 | 46 | #define MSIC_ADCRRDATA_ENBL 0x05 |
50 | #define MSIC_CHANL_MASK_VAL 0x0F | 47 | #define MSIC_CHANL_MASK_VAL 0x0F |
@@ -75,8 +72,8 @@ | |||
75 | #define ADC_VAL60C 315 | 72 | #define ADC_VAL60C 315 |
76 | 73 | ||
77 | /* ADC base addresses */ | 74 | /* ADC base addresses */ |
78 | #define ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */ | 75 | #define ADC_CHNL_START_ADDR INTEL_MSIC_ADC1ADDR0 /* increments by 1 */ |
79 | #define ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */ | 76 | #define ADC_DATA_START_ADDR INTEL_MSIC_ADC1SNS0H /* increments by 2 */ |
80 | 77 | ||
81 | /* MSIC die attributes */ | 78 | /* MSIC die attributes */ |
82 | #define MSIC_DIE_ADC_MIN 488 | 79 | #define MSIC_DIE_ADC_MIN 488 |
@@ -189,17 +186,17 @@ static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp) | |||
189 | addr = td_info->chnl_addr; | 186 | addr = td_info->chnl_addr; |
190 | 187 | ||
191 | /* Enable the msic for conversion before reading */ | 188 | /* Enable the msic for conversion before reading */ |
192 | ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCRRDATA_ENBL); | 189 | ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCRRDATA_ENBL); |
193 | if (ret) | 190 | if (ret) |
194 | return ret; | 191 | return ret; |
195 | 192 | ||
196 | /* Re-toggle the RRDATARD bit (temporary workaround) */ | 193 | /* Re-toggle the RRDATARD bit (temporary workaround) */ |
197 | ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCTHERM_ENBL); | 194 | ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, MSIC_ADCTHERM_ENBL); |
198 | if (ret) | 195 | if (ret) |
199 | return ret; | 196 | return ret; |
200 | 197 | ||
201 | /* Read the higher bits of data */ | 198 | /* Read the higher bits of data */ |
202 | ret = intel_scu_ipc_ioread8(addr, &data); | 199 | ret = intel_msic_reg_read(addr, &data); |
203 | if (ret) | 200 | if (ret) |
204 | return ret; | 201 | return ret; |
205 | 202 | ||
@@ -207,7 +204,7 @@ static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp) | |||
207 | adc_val = (data << 2); | 204 | adc_val = (data << 2); |
208 | addr++; | 205 | addr++; |
209 | 206 | ||
210 | ret = intel_scu_ipc_ioread8(addr, &data);/* Read lower bits */ | 207 | ret = intel_msic_reg_read(addr, &data);/* Read lower bits */ |
211 | if (ret) | 208 | if (ret) |
212 | return ret; | 209 | return ret; |
213 | 210 | ||
@@ -235,7 +232,7 @@ static int configure_adc(int val) | |||
235 | int ret; | 232 | int ret; |
236 | uint8_t data; | 233 | uint8_t data; |
237 | 234 | ||
238 | ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data); | 235 | ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data); |
239 | if (ret) | 236 | if (ret) |
240 | return ret; | 237 | return ret; |
241 | 238 | ||
@@ -246,7 +243,7 @@ static int configure_adc(int val) | |||
246 | /* Just stop the ADC */ | 243 | /* Just stop the ADC */ |
247 | data &= (~MSIC_ADC_START); | 244 | data &= (~MSIC_ADC_START); |
248 | } | 245 | } |
249 | return intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1, data); | 246 | return intel_msic_reg_write(INTEL_MSIC_ADC1CNTL1, data); |
250 | } | 247 | } |
251 | 248 | ||
252 | /** | 249 | /** |
@@ -262,21 +259,21 @@ static int set_up_therm_channel(u16 base_addr) | |||
262 | int ret; | 259 | int ret; |
263 | 260 | ||
264 | /* Enable all the sensor channels */ | 261 | /* Enable all the sensor channels */ |
265 | ret = intel_scu_ipc_iowrite8(base_addr, SKIN_SENSOR0_CODE); | 262 | ret = intel_msic_reg_write(base_addr, SKIN_SENSOR0_CODE); |
266 | if (ret) | 263 | if (ret) |
267 | return ret; | 264 | return ret; |
268 | 265 | ||
269 | ret = intel_scu_ipc_iowrite8(base_addr + 1, SKIN_SENSOR1_CODE); | 266 | ret = intel_msic_reg_write(base_addr + 1, SKIN_SENSOR1_CODE); |
270 | if (ret) | 267 | if (ret) |
271 | return ret; | 268 | return ret; |
272 | 269 | ||
273 | ret = intel_scu_ipc_iowrite8(base_addr + 2, SYS_SENSOR_CODE); | 270 | ret = intel_msic_reg_write(base_addr + 2, SYS_SENSOR_CODE); |
274 | if (ret) | 271 | if (ret) |
275 | return ret; | 272 | return ret; |
276 | 273 | ||
277 | /* Since this is the last channel, set the stop bit | 274 | /* Since this is the last channel, set the stop bit |
278 | * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */ | 275 | * to 1 by ORing the DIE_SENSOR_CODE with 0x10 */ |
279 | ret = intel_scu_ipc_iowrite8(base_addr + 3, | 276 | ret = intel_msic_reg_write(base_addr + 3, |
280 | (MSIC_DIE_SENSOR_CODE | 0x10)); | 277 | (MSIC_DIE_SENSOR_CODE | 0x10)); |
281 | if (ret) | 278 | if (ret) |
282 | return ret; | 279 | return ret; |
@@ -295,11 +292,11 @@ static int reset_stopbit(uint16_t addr) | |||
295 | { | 292 | { |
296 | int ret; | 293 | int ret; |
297 | uint8_t data; | 294 | uint8_t data; |
298 | ret = intel_scu_ipc_ioread8(addr, &data); | 295 | ret = intel_msic_reg_read(addr, &data); |
299 | if (ret) | 296 | if (ret) |
300 | return ret; | 297 | return ret; |
301 | /* Set the stop bit to zero */ | 298 | /* Set the stop bit to zero */ |
302 | return intel_scu_ipc_iowrite8(addr, (data & 0xEF)); | 299 | return intel_msic_reg_write(addr, (data & 0xEF)); |
303 | } | 300 | } |
304 | 301 | ||
305 | /** | 302 | /** |
@@ -322,7 +319,7 @@ static int find_free_channel(void) | |||
322 | uint8_t data; | 319 | uint8_t data; |
323 | 320 | ||
324 | /* check whether ADC is enabled */ | 321 | /* check whether ADC is enabled */ |
325 | ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data); | 322 | ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL1, &data); |
326 | if (ret) | 323 | if (ret) |
327 | return ret; | 324 | return ret; |
328 | 325 | ||
@@ -331,7 +328,7 @@ static int find_free_channel(void) | |||
331 | 328 | ||
332 | /* ADC is already enabled; Looking for an empty channel */ | 329 | /* ADC is already enabled; Looking for an empty channel */ |
333 | for (i = 0; i < ADC_CHANLS_MAX; i++) { | 330 | for (i = 0; i < ADC_CHANLS_MAX; i++) { |
334 | ret = intel_scu_ipc_ioread8(ADC_CHNL_START_ADDR + i, &data); | 331 | ret = intel_msic_reg_read(ADC_CHNL_START_ADDR + i, &data); |
335 | if (ret) | 332 | if (ret) |
336 | return ret; | 333 | return ret; |
337 | 334 | ||
@@ -359,12 +356,14 @@ static int mid_initialize_adc(struct device *dev) | |||
359 | * Ensure that adctherm is disabled before we | 356 | * Ensure that adctherm is disabled before we |
360 | * initialize the ADC | 357 | * initialize the ADC |
361 | */ | 358 | */ |
362 | ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL3, &data); | 359 | ret = intel_msic_reg_read(INTEL_MSIC_ADC1CNTL3, &data); |
363 | if (ret) | 360 | if (ret) |
364 | return ret; | 361 | return ret; |
365 | 362 | ||
366 | if (data & MSIC_ADCTHERM_MASK) | 363 | data &= ~MSIC_ADCTHERM_MASK; |
367 | dev_warn(dev, "ADCTHERM already set"); | 364 | ret = intel_msic_reg_write(INTEL_MSIC_ADC1CNTL3, data); |
365 | if (ret) | ||
366 | return ret; | ||
368 | 367 | ||
369 | /* Index of the first channel in which the stop bit is set */ | 368 | /* Index of the first channel in which the stop bit is set */ |
370 | channel_index = find_free_channel(); | 369 | channel_index = find_free_channel(); |
@@ -546,7 +545,7 @@ static int mid_thermal_remove(struct platform_device *pdev) | |||
546 | return configure_adc(0); | 545 | return configure_adc(0); |
547 | } | 546 | } |
548 | 547 | ||
549 | #define DRIVER_NAME "msic_sensor" | 548 | #define DRIVER_NAME "msic_thermal" |
550 | 549 | ||
551 | static const struct platform_device_id therm_id_table[] = { | 550 | static const struct platform_device_id therm_id_table[] = { |
552 | { DRIVER_NAME, 1 }, | 551 | { DRIVER_NAME, 1 }, |
diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c deleted file mode 100644 index c8a6aed45277..000000000000 --- a/drivers/platform/x86/intel_rar_register.c +++ /dev/null | |||
@@ -1,669 +0,0 @@ | |||
1 | /* | ||
2 | * rar_register.c - An Intel Restricted Access Region register driver | ||
3 | * | ||
4 | * Copyright(c) 2009 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
19 | * 02111-1307, USA. | ||
20 | * | ||
21 | * ------------------------------------------------------------------- | ||
22 | * 20091204 Mark Allyn <mark.a.allyn@intel.com> | ||
23 | * Ossama Othman <ossama.othman@intel.com> | ||
24 | * Cleanup per feedback from Alan Cox and Arjan Van De Ven | ||
25 | * | ||
26 | * 20090806 Ossama Othman <ossama.othman@intel.com> | ||
27 | * Return zero high address if upper 22 bits is zero. | ||
28 | * Cleaned up checkpatch errors. | ||
29 | * Clarified that driver is dealing with bus addresses. | ||
30 | * | ||
31 | * 20090702 Ossama Othman <ossama.othman@intel.com> | ||
32 | * Removed unnecessary include directives | ||
33 | * Cleaned up spinlocks. | ||
34 | * Cleaned up logging. | ||
35 | * Improved invalid parameter checks. | ||
36 | * Fixed and simplified RAR address retrieval and RAR locking | ||
37 | * code. | ||
38 | * | ||
39 | * 20090626 Mark Allyn <mark.a.allyn@intel.com> | ||
40 | * Initial publish | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/pci.h> | ||
45 | #include <linux/spinlock.h> | ||
46 | #include <linux/device.h> | ||
47 | #include <linux/kernel.h> | ||
48 | #include <linux/rar_register.h> | ||
49 | |||
50 | /* === Lincroft Message Bus Interface === */ | ||
51 | #define LNC_MCR_OFFSET 0xD0 /* Message Control Register */ | ||
52 | #define LNC_MDR_OFFSET 0xD4 /* Message Data Register */ | ||
53 | |||
54 | /* Message Opcodes */ | ||
55 | #define LNC_MESSAGE_READ_OPCODE 0xD0 | ||
56 | #define LNC_MESSAGE_WRITE_OPCODE 0xE0 | ||
57 | |||
58 | /* Message Write Byte Enables */ | ||
59 | #define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF | ||
60 | |||
61 | /* B-unit Port */ | ||
62 | #define LNC_BUNIT_PORT 0x3 | ||
63 | |||
64 | /* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */ | ||
65 | #define LNC_BRAR0L 0x10 | ||
66 | #define LNC_BRAR0H 0x11 | ||
67 | #define LNC_BRAR1L 0x12 | ||
68 | #define LNC_BRAR1H 0x13 | ||
69 | /* Reserved for SeP */ | ||
70 | #define LNC_BRAR2L 0x14 | ||
71 | #define LNC_BRAR2H 0x15 | ||
72 | |||
73 | /* Moorestown supports three restricted access regions. */ | ||
74 | #define MRST_NUM_RAR 3 | ||
75 | |||
76 | /* RAR Bus Address Range */ | ||
77 | struct rar_addr { | ||
78 | dma_addr_t low; | ||
79 | dma_addr_t high; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * We create one of these for each RAR | ||
84 | */ | ||
85 | struct client { | ||
86 | int (*callback)(unsigned long data); | ||
87 | unsigned long driver_priv; | ||
88 | bool busy; | ||
89 | }; | ||
90 | |||
91 | static DEFINE_MUTEX(rar_mutex); | ||
92 | static DEFINE_MUTEX(lnc_reg_mutex); | ||
93 | |||
94 | /* | ||
95 | * One per RAR device (currently only one device) | ||
96 | */ | ||
97 | struct rar_device { | ||
98 | struct rar_addr rar_addr[MRST_NUM_RAR]; | ||
99 | struct pci_dev *rar_dev; | ||
100 | bool registered; | ||
101 | bool allocated; | ||
102 | struct client client[MRST_NUM_RAR]; | ||
103 | }; | ||
104 | |||
105 | /* Current platforms have only one rar_device for 3 rar regions */ | ||
106 | static struct rar_device my_rar_device; | ||
107 | |||
108 | /* | ||
109 | * Abstract out multiple device support. Current platforms only | ||
110 | * have a single RAR device. | ||
111 | */ | ||
112 | |||
113 | /** | ||
114 | * alloc_rar_device - return a new RAR structure | ||
115 | * | ||
116 | * Return a new (but not yet ready) RAR device object | ||
117 | */ | ||
118 | static struct rar_device *alloc_rar_device(void) | ||
119 | { | ||
120 | if (my_rar_device.allocated) | ||
121 | return NULL; | ||
122 | my_rar_device.allocated = 1; | ||
123 | return &my_rar_device; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * free_rar_device - free a RAR object | ||
128 | * @rar: the RAR device being freed | ||
129 | * | ||
130 | * Release a RAR object and any attached resources | ||
131 | */ | ||
132 | static void free_rar_device(struct rar_device *rar) | ||
133 | { | ||
134 | pci_dev_put(rar->rar_dev); | ||
135 | rar->allocated = 0; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * _rar_to_device - return the device handling this RAR | ||
140 | * @rar: RAR number | ||
141 | * @off: returned offset | ||
142 | * | ||
143 | * Internal helper for looking up RAR devices. This and alloc are the | ||
144 | * two functions that need touching to go to multiple RAR devices. | ||
145 | */ | ||
146 | static struct rar_device *_rar_to_device(int rar, int *off) | ||
147 | { | ||
148 | if (rar >= 0 && rar < MRST_NUM_RAR) { | ||
149 | *off = rar; | ||
150 | return &my_rar_device; | ||
151 | } | ||
152 | return NULL; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * rar_to_device - return the device handling this RAR | ||
157 | * @rar: RAR number | ||
158 | * @off: returned offset | ||
159 | * | ||
160 | * Return the device this RAR maps to if one is present, otherwise | ||
161 | * returns NULL. Reports the offset relative to the base of this | ||
162 | * RAR device in off. | ||
163 | */ | ||
164 | static struct rar_device *rar_to_device(int rar, int *off) | ||
165 | { | ||
166 | struct rar_device *rar_dev = _rar_to_device(rar, off); | ||
167 | if (rar_dev == NULL || !rar_dev->registered) | ||
168 | return NULL; | ||
169 | return rar_dev; | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * rar_to_client - return the client handling this RAR | ||
174 | * @rar: RAR number | ||
175 | * | ||
176 | * Return the client this RAR maps to if a mapping is known, otherwise | ||
177 | * returns NULL. | ||
178 | */ | ||
179 | static struct client *rar_to_client(int rar) | ||
180 | { | ||
181 | int idx; | ||
182 | struct rar_device *r = _rar_to_device(rar, &idx); | ||
183 | if (r != NULL) | ||
184 | return &r->client[idx]; | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * rar_read_addr - retrieve a RAR mapping | ||
190 | * @pdev: PCI device for the RAR | ||
191 | * @offset: offset for message | ||
192 | * @addr: returned address | ||
193 | * | ||
194 | * Reads the address of a given RAR register. Returns 0 on success | ||
195 | * or an error code on failure. | ||
196 | */ | ||
197 | static int rar_read_addr(struct pci_dev *pdev, int offset, dma_addr_t *addr) | ||
198 | { | ||
199 | /* | ||
200 | * ======== The Lincroft Message Bus Interface ======== | ||
201 | * Lincroft registers may be obtained via PCI from | ||
202 | * the host bridge using the Lincroft Message Bus | ||
203 | * Interface. That message bus interface is generally | ||
204 | * comprised of two registers: a control register (MCR, 0xDO) | ||
205 | * and a data register (MDR, 0xD4). | ||
206 | * | ||
207 | * The MCR (message control register) format is the following: | ||
208 | * 1. [31:24]: Opcode | ||
209 | * 2. [23:16]: Port | ||
210 | * 3. [15:8]: Register Offset | ||
211 | * 4. [7:4]: Byte Enables (use 0xF to set all of these bits | ||
212 | * to 1) | ||
213 | * 5. [3:0]: reserved | ||
214 | * | ||
215 | * Read (0xD0) and write (0xE0) opcodes are written to the | ||
216 | * control register when reading and writing to Lincroft | ||
217 | * registers, respectively. | ||
218 | * | ||
219 | * We're interested in registers found in the Lincroft | ||
220 | * B-unit. The B-unit port is 0x3. | ||
221 | * | ||
222 | * The six B-unit RAR register offsets we use are listed | ||
223 | * earlier in this file. | ||
224 | * | ||
225 | * Lastly writing to the MCR register requires the "Byte | ||
226 | * enables" bits to be set to 1. This may be achieved by | ||
227 | * writing 0xF at bit 4. | ||
228 | * | ||
229 | * The MDR (message data register) format is the following: | ||
230 | * 1. [31:0]: Read/Write Data | ||
231 | * | ||
232 | * Data being read from this register is only available after | ||
233 | * writing the appropriate control message to the MCR | ||
234 | * register. | ||
235 | * | ||
236 | * Data being written to this register must be written before | ||
237 | * writing the appropriate control message to the MCR | ||
238 | * register. | ||
239 | */ | ||
240 | |||
241 | int result; | ||
242 | u32 addr32; | ||
243 | |||
244 | /* Construct control message */ | ||
245 | u32 const message = | ||
246 | (LNC_MESSAGE_READ_OPCODE << 24) | ||
247 | | (LNC_BUNIT_PORT << 16) | ||
248 | | (offset << 8) | ||
249 | | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); | ||
250 | |||
251 | dev_dbg(&pdev->dev, "Offset for 'get' LNC MSG is %x\n", offset); | ||
252 | |||
253 | /* | ||
254 | * We synchronize access to the Lincroft MCR and MDR registers | ||
255 | * until BOTH the command is issued through the MCR register | ||
256 | * and the corresponding data is read from the MDR register. | ||
257 | * Otherwise a race condition would exist between accesses to | ||
258 | * both registers. | ||
259 | */ | ||
260 | |||
261 | mutex_lock(&lnc_reg_mutex); | ||
262 | |||
263 | /* Send the control message */ | ||
264 | result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); | ||
265 | if (!result) { | ||
266 | /* Read back the address as a 32bit value */ | ||
267 | result = pci_read_config_dword(pdev, LNC_MDR_OFFSET, &addr32); | ||
268 | *addr = (dma_addr_t)addr32; | ||
269 | } | ||
270 | mutex_unlock(&lnc_reg_mutex); | ||
271 | return result; | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * rar_set_addr - Set a RAR mapping | ||
276 | * @pdev: PCI device for the RAR | ||
277 | * @offset: offset for message | ||
278 | * @addr: address to set | ||
279 | * | ||
280 | * Sets the address of a given RAR register. Returns 0 on success | ||
281 | * or an error code on failure. | ||
282 | */ | ||
283 | static int rar_set_addr(struct pci_dev *pdev, | ||
284 | int offset, | ||
285 | dma_addr_t addr) | ||
286 | { | ||
287 | /* | ||
288 | * Data being written to this register must be written before | ||
289 | * writing the appropriate control message to the MCR | ||
290 | * register. | ||
291 | * See rar_get_addrs() for a description of the | ||
292 | * message bus interface being used here. | ||
293 | */ | ||
294 | |||
295 | int result; | ||
296 | |||
297 | /* Construct control message */ | ||
298 | u32 const message = (LNC_MESSAGE_WRITE_OPCODE << 24) | ||
299 | | (LNC_BUNIT_PORT << 16) | ||
300 | | (offset << 8) | ||
301 | | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); | ||
302 | |||
303 | /* | ||
304 | * We synchronize access to the Lincroft MCR and MDR registers | ||
305 | * until BOTH the command is issued through the MCR register | ||
306 | * and the corresponding data is read from the MDR register. | ||
307 | * Otherwise a race condition would exist between accesses to | ||
308 | * both registers. | ||
309 | */ | ||
310 | |||
311 | mutex_lock(&lnc_reg_mutex); | ||
312 | |||
313 | /* Send the control message */ | ||
314 | result = pci_write_config_dword(pdev, LNC_MDR_OFFSET, addr); | ||
315 | if (!result) | ||
316 | /* And address */ | ||
317 | result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); | ||
318 | |||
319 | mutex_unlock(&lnc_reg_mutex); | ||
320 | return result; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * rar_init_params - Initialize RAR parameters | ||
325 | * @rar: RAR device to initialise | ||
326 | * | ||
327 | * Initialize RAR parameters, such as bus addresses, etc. Returns 0 | ||
328 | * on success, or an error code on failure. | ||
329 | */ | ||
330 | static int init_rar_params(struct rar_device *rar) | ||
331 | { | ||
332 | struct pci_dev *pdev = rar->rar_dev; | ||
333 | unsigned int i; | ||
334 | int result = 0; | ||
335 | int offset = 0x10; /* RAR 0 to 2 in order low/high/low/high/... */ | ||
336 | |||
337 | /* Retrieve RAR start and end bus addresses. | ||
338 | * Access the RAR registers through the Lincroft Message Bus | ||
339 | * Interface on PCI device: 00:00.0 Host bridge. | ||
340 | */ | ||
341 | |||
342 | for (i = 0; i < MRST_NUM_RAR; ++i) { | ||
343 | struct rar_addr *addr = &rar->rar_addr[i]; | ||
344 | |||
345 | result = rar_read_addr(pdev, offset++, &addr->low); | ||
346 | if (result != 0) | ||
347 | return result; | ||
348 | |||
349 | result = rar_read_addr(pdev, offset++, &addr->high); | ||
350 | if (result != 0) | ||
351 | return result; | ||
352 | |||
353 | |||
354 | /* | ||
355 | * Only the upper 22 bits of the RAR addresses are | ||
356 | * stored in their corresponding RAR registers so we | ||
357 | * must set the lower 10 bits accordingly. | ||
358 | |||
359 | * The low address has its lower 10 bits cleared, and | ||
360 | * the high address has all its lower 10 bits set, | ||
361 | * e.g.: | ||
362 | * low = 0x2ffffc00 | ||
363 | */ | ||
364 | |||
365 | addr->low &= (dma_addr_t)0xfffffc00u; | ||
366 | |||
367 | /* | ||
368 | * Set bits 9:0 on uppser address if bits 31:10 are non | ||
369 | * zero; otherwize clear all bits | ||
370 | */ | ||
371 | |||
372 | if ((addr->high & 0xfffffc00u) == 0) | ||
373 | addr->high = 0; | ||
374 | else | ||
375 | addr->high |= 0x3ffu; | ||
376 | } | ||
377 | /* Done accessing the device. */ | ||
378 | |||
379 | if (result == 0) { | ||
380 | for (i = 0; i != MRST_NUM_RAR; ++i) { | ||
381 | /* | ||
382 | * "BRAR" refers to the RAR registers in the | ||
383 | * Lincroft B-unit. | ||
384 | */ | ||
385 | dev_info(&pdev->dev, "BRAR[%u] bus address range = " | ||
386 | "[%lx, %lx]\n", i, | ||
387 | (unsigned long)rar->rar_addr[i].low, | ||
388 | (unsigned long)rar->rar_addr[i].high); | ||
389 | } | ||
390 | } | ||
391 | return result; | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * rar_get_address - get the bus address in a RAR | ||
396 | * @start: return value of start address of block | ||
397 | * @end: return value of end address of block | ||
398 | * | ||
399 | * The rar_get_address function is used by other device drivers | ||
400 | * to obtain RAR address information on a RAR. It takes three | ||
401 | * parameters: | ||
402 | * | ||
403 | * The function returns a 0 upon success or an error if there is no RAR | ||
404 | * facility on this system. | ||
405 | */ | ||
406 | int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end) | ||
407 | { | ||
408 | int idx; | ||
409 | struct rar_device *rar = rar_to_device(rar_index, &idx); | ||
410 | |||
411 | if (rar == NULL) { | ||
412 | WARN_ON(1); | ||
413 | return -ENODEV; | ||
414 | } | ||
415 | |||
416 | *start = rar->rar_addr[idx].low; | ||
417 | *end = rar->rar_addr[idx].high; | ||
418 | return 0; | ||
419 | } | ||
420 | EXPORT_SYMBOL(rar_get_address); | ||
421 | |||
422 | /** | ||
423 | * rar_lock - lock a RAR register | ||
424 | * @rar_index: RAR to lock (0-2) | ||
425 | * | ||
426 | * The rar_lock function is ued by other device drivers to lock an RAR. | ||
427 | * once a RAR is locked, it stays locked until the next system reboot. | ||
428 | * | ||
429 | * The function returns a 0 upon success or an error if there is no RAR | ||
430 | * facility on this system, or the locking fails | ||
431 | */ | ||
432 | int rar_lock(int rar_index) | ||
433 | { | ||
434 | struct rar_device *rar; | ||
435 | int result; | ||
436 | int idx; | ||
437 | dma_addr_t low, high; | ||
438 | |||
439 | rar = rar_to_device(rar_index, &idx); | ||
440 | |||
441 | if (rar == NULL) { | ||
442 | WARN_ON(1); | ||
443 | return -EINVAL; | ||
444 | } | ||
445 | |||
446 | low = rar->rar_addr[idx].low & 0xfffffc00u; | ||
447 | high = rar->rar_addr[idx].high & 0xfffffc00u; | ||
448 | |||
449 | /* | ||
450 | * Only allow I/O from the graphics and Langwell; | ||
451 | * not from the x86 processor | ||
452 | */ | ||
453 | |||
454 | if (rar_index == RAR_TYPE_VIDEO) { | ||
455 | low |= 0x00000009; | ||
456 | high |= 0x00000015; | ||
457 | } else if (rar_index == RAR_TYPE_AUDIO) { | ||
458 | /* Only allow I/O from Langwell; nothing from x86 */ | ||
459 | low |= 0x00000008; | ||
460 | high |= 0x00000018; | ||
461 | } else | ||
462 | /* Read-only from all agents */ | ||
463 | high |= 0x00000018; | ||
464 | |||
465 | /* | ||
466 | * Now program the register using the Lincroft message | ||
467 | * bus interface. | ||
468 | */ | ||
469 | result = rar_set_addr(rar->rar_dev, | ||
470 | 2 * idx, low); | ||
471 | |||
472 | if (result == 0) | ||
473 | result = rar_set_addr(rar->rar_dev, | ||
474 | 2 * idx + 1, high); | ||
475 | |||
476 | return result; | ||
477 | } | ||
478 | EXPORT_SYMBOL(rar_lock); | ||
479 | |||
480 | /** | ||
481 | * register_rar - register a RAR handler | ||
482 | * @num: RAR we wish to register for | ||
483 | * @callback: function to call when RAR support is available | ||
484 | * @data: data to pass to this function | ||
485 | * | ||
486 | * The register_rar function is to used by other device drivers | ||
487 | * to ensure that this driver is ready. As we cannot be sure of | ||
488 | * the compile/execute order of drivers in the kernel, it is | ||
489 | * best to give this driver a callback function to call when | ||
490 | * it is ready to give out addresses. The callback function | ||
491 | * would have those steps that continue the initialization of | ||
492 | * a driver that do require a valid RAR address. One of those | ||
493 | * steps would be to call rar_get_address() | ||
494 | * | ||
495 | * This function return 0 on success or an error code on failure. | ||
496 | */ | ||
497 | int register_rar(int num, int (*callback)(unsigned long data), | ||
498 | unsigned long data) | ||
499 | { | ||
500 | /* For now we hardcode a single RAR device */ | ||
501 | struct rar_device *rar; | ||
502 | struct client *c; | ||
503 | int idx; | ||
504 | int retval = 0; | ||
505 | |||
506 | mutex_lock(&rar_mutex); | ||
507 | |||
508 | /* Do we have a client mapping for this RAR number ? */ | ||
509 | c = rar_to_client(num); | ||
510 | if (c == NULL) { | ||
511 | retval = -ERANGE; | ||
512 | goto done; | ||
513 | } | ||
514 | /* Is it claimed ? */ | ||
515 | if (c->busy) { | ||
516 | retval = -EBUSY; | ||
517 | goto done; | ||
518 | } | ||
519 | c->busy = 1; | ||
520 | |||
521 | /* See if we have a handler for this RAR yet, if we do then fire it */ | ||
522 | rar = rar_to_device(num, &idx); | ||
523 | |||
524 | if (rar) { | ||
525 | /* | ||
526 | * if the driver already registered, then we can simply | ||
527 | * call the callback right now | ||
528 | */ | ||
529 | (*callback)(data); | ||
530 | goto done; | ||
531 | } | ||
532 | |||
533 | /* Arrange to be called back when the hardware is found */ | ||
534 | c->callback = callback; | ||
535 | c->driver_priv = data; | ||
536 | done: | ||
537 | mutex_unlock(&rar_mutex); | ||
538 | return retval; | ||
539 | } | ||
540 | EXPORT_SYMBOL(register_rar); | ||
541 | |||
542 | /** | ||
543 | * unregister_rar - release a RAR allocation | ||
544 | * @num: RAR number | ||
545 | * | ||
546 | * Releases a RAR allocation, or pending allocation. If a callback is | ||
547 | * pending then this function will either complete before the unregister | ||
548 | * returns or not at all. | ||
549 | */ | ||
550 | |||
551 | void unregister_rar(int num) | ||
552 | { | ||
553 | struct client *c; | ||
554 | |||
555 | mutex_lock(&rar_mutex); | ||
556 | c = rar_to_client(num); | ||
557 | if (c == NULL || !c->busy) | ||
558 | WARN_ON(1); | ||
559 | else | ||
560 | c->busy = 0; | ||
561 | mutex_unlock(&rar_mutex); | ||
562 | } | ||
563 | EXPORT_SYMBOL(unregister_rar); | ||
564 | |||
565 | /** | ||
566 | * rar_callback - Process callbacks | ||
567 | * @rar: new RAR device | ||
568 | * | ||
569 | * Process the callbacks for a newly found RAR device. | ||
570 | */ | ||
571 | |||
572 | static void rar_callback(struct rar_device *rar) | ||
573 | { | ||
574 | struct client *c = &rar->client[0]; | ||
575 | int i; | ||
576 | |||
577 | mutex_lock(&rar_mutex); | ||
578 | |||
579 | rar->registered = 1; /* Ensure no more callbacks queue */ | ||
580 | |||
581 | for (i = 0; i < MRST_NUM_RAR; i++) { | ||
582 | if (c->callback && c->busy) { | ||
583 | c->callback(c->driver_priv); | ||
584 | c->callback = NULL; | ||
585 | } | ||
586 | c++; | ||
587 | } | ||
588 | mutex_unlock(&rar_mutex); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * rar_probe - PCI probe callback | ||
593 | * @dev: PCI device | ||
594 | * @id: matching entry in the match table | ||
595 | * | ||
596 | * A RAR device has been discovered. Initialise it and if successful | ||
597 | * process any pending callbacks that can now be completed. | ||
598 | */ | ||
599 | static int rar_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
600 | { | ||
601 | int error; | ||
602 | struct rar_device *rar; | ||
603 | |||
604 | dev_dbg(&dev->dev, "PCI probe starting\n"); | ||
605 | |||
606 | rar = alloc_rar_device(); | ||
607 | if (rar == NULL) | ||
608 | return -EBUSY; | ||
609 | |||
610 | /* Enable the device */ | ||
611 | error = pci_enable_device(dev); | ||
612 | if (error) { | ||
613 | dev_err(&dev->dev, | ||
614 | "Error enabling RAR register PCI device\n"); | ||
615 | goto end_function; | ||
616 | } | ||
617 | |||
618 | /* Fill in the rar_device structure */ | ||
619 | rar->rar_dev = pci_dev_get(dev); | ||
620 | pci_set_drvdata(dev, rar); | ||
621 | |||
622 | /* | ||
623 | * Initialize the RAR parameters, which have to be retrieved | ||
624 | * via the message bus interface. | ||
625 | */ | ||
626 | error = init_rar_params(rar); | ||
627 | if (error) { | ||
628 | pci_disable_device(dev); | ||
629 | dev_err(&dev->dev, "Error retrieving RAR addresses\n"); | ||
630 | goto end_function; | ||
631 | } | ||
632 | /* now call anyone who has registered (using callbacks) */ | ||
633 | rar_callback(rar); | ||
634 | return 0; | ||
635 | end_function: | ||
636 | free_rar_device(rar); | ||
637 | return error; | ||
638 | } | ||
639 | |||
640 | static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = { | ||
641 | { PCI_VDEVICE(INTEL, 0x4110) }, | ||
642 | { 0 } | ||
643 | }; | ||
644 | |||
645 | MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl); | ||
646 | |||
647 | /* field for registering driver to PCI device */ | ||
648 | static struct pci_driver rar_pci_driver = { | ||
649 | .name = "rar_register_driver", | ||
650 | .id_table = rar_pci_id_tbl, | ||
651 | .probe = rar_probe, | ||
652 | /* Cannot be unplugged - no remove */ | ||
653 | }; | ||
654 | |||
655 | static int __init rar_init_handler(void) | ||
656 | { | ||
657 | return pci_register_driver(&rar_pci_driver); | ||
658 | } | ||
659 | |||
660 | static void __exit rar_exit_handler(void) | ||
661 | { | ||
662 | pci_unregister_driver(&rar_pci_driver); | ||
663 | } | ||
664 | |||
665 | module_init(rar_init_handler); | ||
666 | module_exit(rar_exit_handler); | ||
667 | |||
668 | MODULE_LICENSE("GPL"); | ||
669 | MODULE_DESCRIPTION("Intel Restricted Access Region Register Driver"); | ||
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index f00d0d1e0653..9215ed72bece 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c | |||
@@ -159,7 +159,7 @@ static inline int busy_loop(void) /* Wait till scu status is busy */ | |||
159 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ | 159 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ |
160 | static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | 160 | static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) |
161 | { | 161 | { |
162 | int i, nc, bytes, d; | 162 | int nc; |
163 | u32 offset = 0; | 163 | u32 offset = 0; |
164 | int err; | 164 | int err; |
165 | u8 cbuf[IPC_WWBUF_SIZE] = { }; | 165 | u8 cbuf[IPC_WWBUF_SIZE] = { }; |
@@ -174,55 +174,34 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | |||
174 | return -ENODEV; | 174 | return -ENODEV; |
175 | } | 175 | } |
176 | 176 | ||
177 | if (platform != MRST_CPU_CHIP_PENWELL) { | 177 | for (nc = 0; nc < count; nc++, offset += 2) { |
178 | bytes = 0; | 178 | cbuf[offset] = addr[nc]; |
179 | d = 0; | 179 | cbuf[offset + 1] = addr[nc] >> 8; |
180 | for (i = 0; i < count; i++) { | 180 | } |
181 | cbuf[bytes++] = addr[i]; | ||
182 | cbuf[bytes++] = addr[i] >> 8; | ||
183 | if (id != IPC_CMD_PCNTRL_R) | ||
184 | cbuf[bytes++] = data[d++]; | ||
185 | if (id == IPC_CMD_PCNTRL_M) | ||
186 | cbuf[bytes++] = data[d++]; | ||
187 | } | ||
188 | for (i = 0; i < bytes; i += 4) | ||
189 | ipc_data_writel(wbuf[i/4], i); | ||
190 | ipc_command(bytes << 16 | id << 12 | 0 << 8 | op); | ||
191 | } else { | ||
192 | for (nc = 0; nc < count; nc++, offset += 2) { | ||
193 | cbuf[offset] = addr[nc]; | ||
194 | cbuf[offset + 1] = addr[nc] >> 8; | ||
195 | } | ||
196 | 181 | ||
197 | if (id == IPC_CMD_PCNTRL_R) { | 182 | if (id == IPC_CMD_PCNTRL_R) { |
198 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) | 183 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) |
199 | ipc_data_writel(wbuf[nc], offset); | 184 | ipc_data_writel(wbuf[nc], offset); |
200 | ipc_command((count*2) << 16 | id << 12 | 0 << 8 | op); | 185 | ipc_command((count*2) << 16 | id << 12 | 0 << 8 | op); |
201 | } else if (id == IPC_CMD_PCNTRL_W) { | 186 | } else if (id == IPC_CMD_PCNTRL_W) { |
202 | for (nc = 0; nc < count; nc++, offset += 1) | 187 | for (nc = 0; nc < count; nc++, offset += 1) |
203 | cbuf[offset] = data[nc]; | 188 | cbuf[offset] = data[nc]; |
204 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) | 189 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) |
205 | ipc_data_writel(wbuf[nc], offset); | 190 | ipc_data_writel(wbuf[nc], offset); |
206 | ipc_command((count*3) << 16 | id << 12 | 0 << 8 | op); | 191 | ipc_command((count*3) << 16 | id << 12 | 0 << 8 | op); |
207 | } else if (id == IPC_CMD_PCNTRL_M) { | 192 | } else if (id == IPC_CMD_PCNTRL_M) { |
208 | cbuf[offset] = data[0]; | 193 | cbuf[offset] = data[0]; |
209 | cbuf[offset + 1] = data[1]; | 194 | cbuf[offset + 1] = data[1]; |
210 | ipc_data_writel(wbuf[0], 0); /* Write wbuff */ | 195 | ipc_data_writel(wbuf[0], 0); /* Write wbuff */ |
211 | ipc_command(4 << 16 | id << 12 | 0 << 8 | op); | 196 | ipc_command(4 << 16 | id << 12 | 0 << 8 | op); |
212 | } | ||
213 | } | 197 | } |
214 | 198 | ||
215 | err = busy_loop(); | 199 | err = busy_loop(); |
216 | if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ | 200 | if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ |
217 | /* Workaround: values are read as 0 without memcpy_fromio */ | 201 | /* Workaround: values are read as 0 without memcpy_fromio */ |
218 | memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); | 202 | memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); |
219 | if (platform != MRST_CPU_CHIP_PENWELL) { | 203 | for (nc = 0; nc < count; nc++) |
220 | for (nc = 0, offset = 2; nc < count; nc++, offset += 3) | 204 | data[nc] = ipc_data_readb(nc); |
221 | data[nc] = ipc_data_readb(offset); | ||
222 | } else { | ||
223 | for (nc = 0; nc < count; nc++) | ||
224 | data[nc] = ipc_data_readb(nc); | ||
225 | } | ||
226 | } | 205 | } |
227 | mutex_unlock(&ipclock); | 206 | mutex_unlock(&ipclock); |
228 | return err; | 207 | return err; |
@@ -503,148 +482,6 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data) | |||
503 | } | 482 | } |
504 | EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl); | 483 | EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl); |
505 | 484 | ||
506 | #define IPC_FW_LOAD_ADDR 0xFFFC0000 /* Storage location for FW image */ | ||
507 | #define IPC_FW_UPDATE_MBOX_ADDR 0xFFFFDFF4 /* Mailbox between ipc and scu */ | ||
508 | #define IPC_MAX_FW_SIZE 262144 /* 256K storage size for loading the FW image */ | ||
509 | #define IPC_FW_MIP_HEADER_SIZE 2048 /* Firmware MIP header size */ | ||
510 | /* IPC inform SCU to get ready for update process */ | ||
511 | #define IPC_CMD_FW_UPDATE_READY 0x10FE | ||
512 | /* IPC inform SCU to go for update process */ | ||
513 | #define IPC_CMD_FW_UPDATE_GO 0x20FE | ||
514 | /* Status code for fw update */ | ||
515 | #define IPC_FW_UPDATE_SUCCESS 0x444f4e45 /* Status code 'DONE' */ | ||
516 | #define IPC_FW_UPDATE_BADN 0x4241444E /* Status code 'BADN' */ | ||
517 | #define IPC_FW_TXHIGH 0x54784849 /* Status code 'IPC_FW_TXHIGH' */ | ||
518 | #define IPC_FW_TXLOW 0x54784c4f /* Status code 'IPC_FW_TXLOW' */ | ||
519 | |||
520 | struct fw_update_mailbox { | ||
521 | u32 status; | ||
522 | u32 scu_flag; | ||
523 | u32 driver_flag; | ||
524 | }; | ||
525 | |||
526 | |||
527 | /** | ||
528 | * intel_scu_ipc_fw_update - Firmware update utility | ||
529 | * @buffer: firmware buffer | ||
530 | * @length: size of firmware buffer | ||
531 | * | ||
532 | * This function provides an interface to load the firmware into | ||
533 | * the SCU. Returns 0 on success or -1 on failure | ||
534 | */ | ||
535 | int intel_scu_ipc_fw_update(u8 *buffer, u32 length) | ||
536 | { | ||
537 | void __iomem *fw_update_base; | ||
538 | struct fw_update_mailbox __iomem *mailbox = NULL; | ||
539 | int retry_cnt = 0; | ||
540 | u32 status; | ||
541 | |||
542 | mutex_lock(&ipclock); | ||
543 | fw_update_base = ioremap_nocache(IPC_FW_LOAD_ADDR, (128*1024)); | ||
544 | if (fw_update_base == NULL) { | ||
545 | mutex_unlock(&ipclock); | ||
546 | return -ENOMEM; | ||
547 | } | ||
548 | mailbox = ioremap_nocache(IPC_FW_UPDATE_MBOX_ADDR, | ||
549 | sizeof(struct fw_update_mailbox)); | ||
550 | if (mailbox == NULL) { | ||
551 | iounmap(fw_update_base); | ||
552 | mutex_unlock(&ipclock); | ||
553 | return -ENOMEM; | ||
554 | } | ||
555 | |||
556 | ipc_command(IPC_CMD_FW_UPDATE_READY); | ||
557 | |||
558 | /* Intitialize mailbox */ | ||
559 | writel(0, &mailbox->status); | ||
560 | writel(0, &mailbox->scu_flag); | ||
561 | writel(0, &mailbox->driver_flag); | ||
562 | |||
563 | /* Driver copies the 2KB MIP header to SRAM at 0xFFFC0000*/ | ||
564 | memcpy_toio(fw_update_base, buffer, 0x800); | ||
565 | |||
566 | /* Driver sends "FW Update" IPC command (CMD_ID 0xFE; MSG_ID 0x02). | ||
567 | * Upon receiving this command, SCU will write the 2K MIP header | ||
568 | * from 0xFFFC0000 into NAND. | ||
569 | * SCU will write a status code into the Mailbox, and then set scu_flag. | ||
570 | */ | ||
571 | |||
572 | ipc_command(IPC_CMD_FW_UPDATE_GO); | ||
573 | |||
574 | /*Driver stalls until scu_flag is set */ | ||
575 | while (readl(&mailbox->scu_flag) != 1) { | ||
576 | rmb(); | ||
577 | mdelay(1); | ||
578 | } | ||
579 | |||
580 | /* Driver checks Mailbox status. | ||
581 | * If the status is 'BADN', then abort (bad NAND). | ||
582 | * If the status is 'IPC_FW_TXLOW', then continue. | ||
583 | */ | ||
584 | while (readl(&mailbox->status) != IPC_FW_TXLOW) { | ||
585 | rmb(); | ||
586 | mdelay(10); | ||
587 | } | ||
588 | mdelay(10); | ||
589 | |||
590 | update_retry: | ||
591 | if (retry_cnt > 5) | ||
592 | goto update_end; | ||
593 | |||
594 | if (readl(&mailbox->status) != IPC_FW_TXLOW) | ||
595 | goto update_end; | ||
596 | buffer = buffer + 0x800; | ||
597 | memcpy_toio(fw_update_base, buffer, 0x20000); | ||
598 | writel(1, &mailbox->driver_flag); | ||
599 | while (readl(&mailbox->scu_flag) == 1) { | ||
600 | rmb(); | ||
601 | mdelay(1); | ||
602 | } | ||
603 | |||
604 | /* check for 'BADN' */ | ||
605 | if (readl(&mailbox->status) == IPC_FW_UPDATE_BADN) | ||
606 | goto update_end; | ||
607 | |||
608 | while (readl(&mailbox->status) != IPC_FW_TXHIGH) { | ||
609 | rmb(); | ||
610 | mdelay(10); | ||
611 | } | ||
612 | mdelay(10); | ||
613 | |||
614 | if (readl(&mailbox->status) != IPC_FW_TXHIGH) | ||
615 | goto update_end; | ||
616 | |||
617 | buffer = buffer + 0x20000; | ||
618 | memcpy_toio(fw_update_base, buffer, 0x20000); | ||
619 | writel(0, &mailbox->driver_flag); | ||
620 | |||
621 | while (mailbox->scu_flag == 0) { | ||
622 | rmb(); | ||
623 | mdelay(1); | ||
624 | } | ||
625 | |||
626 | /* check for 'BADN' */ | ||
627 | if (readl(&mailbox->status) == IPC_FW_UPDATE_BADN) | ||
628 | goto update_end; | ||
629 | |||
630 | if (readl(&mailbox->status) == IPC_FW_TXLOW) { | ||
631 | ++retry_cnt; | ||
632 | goto update_retry; | ||
633 | } | ||
634 | |||
635 | update_end: | ||
636 | status = readl(&mailbox->status); | ||
637 | |||
638 | iounmap(fw_update_base); | ||
639 | iounmap(mailbox); | ||
640 | mutex_unlock(&ipclock); | ||
641 | |||
642 | if (status == IPC_FW_UPDATE_SUCCESS) | ||
643 | return 0; | ||
644 | return -EIO; | ||
645 | } | ||
646 | EXPORT_SYMBOL(intel_scu_ipc_fw_update); | ||
647 | |||
648 | /* | 485 | /* |
649 | * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1 | 486 | * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1 |
650 | * When ioc bit is set to 1, caller api must wait for interrupt handler called | 487 | * When ioc bit is set to 1, caller api must wait for interrupt handler called |
@@ -727,7 +564,6 @@ static void ipc_remove(struct pci_dev *pdev) | |||
727 | } | 564 | } |
728 | 565 | ||
729 | static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { | 566 | static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { |
730 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, | ||
731 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, | 567 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, |
732 | { 0,} | 568 | { 0,} |
733 | }; | 569 | }; |
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c index 2d0f9136ea9a..02bc5a6343c3 100644 --- a/drivers/platform/x86/intel_scu_ipcutil.c +++ b/drivers/platform/x86/intel_scu_ipcutil.c | |||
@@ -26,13 +26,10 @@ | |||
26 | 26 | ||
27 | static int major; | 27 | static int major; |
28 | 28 | ||
29 | #define MAX_FW_SIZE 264192 | ||
30 | |||
31 | /* ioctl commnds */ | 29 | /* ioctl commnds */ |
32 | #define INTE_SCU_IPC_REGISTER_READ 0 | 30 | #define INTE_SCU_IPC_REGISTER_READ 0 |
33 | #define INTE_SCU_IPC_REGISTER_WRITE 1 | 31 | #define INTE_SCU_IPC_REGISTER_WRITE 1 |
34 | #define INTE_SCU_IPC_REGISTER_UPDATE 2 | 32 | #define INTE_SCU_IPC_REGISTER_UPDATE 2 |
35 | #define INTE_SCU_IPC_FW_UPDATE 0xA2 | ||
36 | 33 | ||
37 | struct scu_ipc_data { | 34 | struct scu_ipc_data { |
38 | u32 count; /* No. of registers */ | 35 | u32 count; /* No. of registers */ |
@@ -88,27 +85,14 @@ static long scu_ipc_ioctl(struct file *fp, unsigned int cmd, | |||
88 | if (!capable(CAP_SYS_RAWIO)) | 85 | if (!capable(CAP_SYS_RAWIO)) |
89 | return -EPERM; | 86 | return -EPERM; |
90 | 87 | ||
91 | if (cmd == INTE_SCU_IPC_FW_UPDATE) { | 88 | if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data))) |
92 | u8 *fwbuf = kmalloc(MAX_FW_SIZE, GFP_KERNEL); | 89 | return -EFAULT; |
93 | if (fwbuf == NULL) | 90 | ret = scu_reg_access(cmd, &data); |
94 | return -ENOMEM; | 91 | if (ret < 0) |
95 | if (copy_from_user(fwbuf, (u8 *)arg, MAX_FW_SIZE)) { | 92 | return ret; |
96 | kfree(fwbuf); | 93 | if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data))) |
97 | return -EFAULT; | 94 | return -EFAULT; |
98 | } | 95 | return 0; |
99 | ret = intel_scu_ipc_fw_update(fwbuf, MAX_FW_SIZE); | ||
100 | kfree(fwbuf); | ||
101 | return ret; | ||
102 | } else { | ||
103 | if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data))) | ||
104 | return -EFAULT; | ||
105 | ret = scu_reg_access(cmd, &data); | ||
106 | if (ret < 0) | ||
107 | return ret; | ||
108 | if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data))) | ||
109 | return -EFAULT; | ||
110 | return 0; | ||
111 | } | ||
112 | } | 96 | } |
113 | 97 | ||
114 | static const struct file_operations scu_ipc_fops = { | 98 | static const struct file_operations scu_ipc_fops = { |
diff --git a/include/linux/rar_register.h b/include/linux/rar_register.h deleted file mode 100644 index 5c6118189363..000000000000 --- a/include/linux/rar_register.h +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of version 2 of the GNU General | ||
6 | * Public License as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be | ||
9 | * useful, but WITHOUT ANY WARRANTY; without even the implied | ||
10 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
11 | * PURPOSE. See the GNU General Public License for more details. | ||
12 | * You should have received a copy of the GNU General Public | ||
13 | * License along with this program; if not, write to the Free | ||
14 | * Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
15 | * Boston, MA 02111-1307, USA. | ||
16 | * The full GNU General Public License is included in this | ||
17 | * distribution in the file called COPYING. | ||
18 | */ | ||
19 | |||
20 | |||
21 | #ifndef _RAR_REGISTER_H | ||
22 | #define _RAR_REGISTER_H | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | |||
26 | /* following are used both in drivers as well as user space apps */ | ||
27 | |||
28 | #define RAR_TYPE_VIDEO 0 | ||
29 | #define RAR_TYPE_AUDIO 1 | ||
30 | #define RAR_TYPE_IMAGE 2 | ||
31 | #define RAR_TYPE_DATA 3 | ||
32 | |||
33 | #ifdef __KERNEL__ | ||
34 | |||
35 | struct rar_device; | ||
36 | |||
37 | #if defined(CONFIG_RAR_REGISTER) | ||
38 | int register_rar(int num, | ||
39 | int (*callback)(unsigned long data), unsigned long data); | ||
40 | void unregister_rar(int num); | ||
41 | int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end); | ||
42 | int rar_lock(int rar_index); | ||
43 | #else | ||
44 | extern void unregister_rar(int num) { } | ||
45 | extern int rar_lock(int rar_index) { return -EIO; } | ||
46 | |||
47 | extern inline int register_rar(int num, | ||
48 | int (*callback)(unsigned long data), unsigned long data) | ||
49 | { | ||
50 | return -ENODEV; | ||
51 | } | ||
52 | |||
53 | extern int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end) | ||
54 | { | ||
55 | return -ENODEV; | ||
56 | } | ||
57 | #endif /* RAR_REGISTER */ | ||
58 | |||
59 | #endif /* __KERNEL__ */ | ||
60 | #endif /* _RAR_REGISTER_H */ | ||