aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-28 12:46:22 -0500
committerTejun Heo <tj@kernel.org>2011-11-28 12:46:22 -0500
commitd4bbf7e7759afc172e2bfbc5c416324590049cdd (patch)
tree7eab5ee5481cd3dcf1162329fec827177640018a /arch/x86/platform
parenta150439c4a97db379f0ed6faa46fbbb6e7bf3cb2 (diff)
parent401d0069cb344f401bc9d264c31db55876ff78c0 (diff)
Merge branch 'master' into x86/memblock
Conflicts & resolutions: * arch/x86/xen/setup.c dc91c728fd "xen: allow extra memory to be in multiple regions" 24aa07882b "memblock, x86: Replace memblock_x86_reserve/free..." conflicted on xen_add_extra_mem() updates. The resolution is trivial as the latter just want to replace memblock_x86_reserve_range() with memblock_reserve(). * drivers/pci/intel-iommu.c 166e9278a3f "x86/ia64: intel-iommu: move to drivers/iommu/" 5dfe8660a3d "bootmem: Replace work_with_active_regions() with..." conflicted as the former moved the file under drivers/iommu/. Resolved by applying the chnages from the latter on the moved file. * mm/Kconfig 6661672053a "memblock: add NO_BOOTMEM config symbol" c378ddd53f9 "memblock, x86: Make ARCH_DISCARD_MEMBLOCK a config option" conflicted trivially. Both added config options. Just letting both add their own options resolves the conflict. * mm/memblock.c d1f0ece6cdc "mm/memblock.c: small function definition fixes" ed7b56a799c "memblock: Remove memblock_memory_can_coalesce()" confliected. The former updates function removed by the latter. Resolution is trivial. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'arch/x86/platform')
-rw-r--r--arch/x86/platform/Makefile1
-rw-r--r--arch/x86/platform/ce4100/ce4100.c2
-rw-r--r--arch/x86/platform/efi/efi.c91
-rw-r--r--arch/x86/platform/efi/efi_32.c1
-rw-r--r--arch/x86/platform/geode/Makefile1
-rw-r--r--arch/x86/platform/geode/alix.c142
-rw-r--r--arch/x86/platform/mrst/Makefile1
-rw-r--r--arch/x86/platform/mrst/mrst.c242
-rw-r--r--arch/x86/platform/mrst/pmu.c817
-rw-r--r--arch/x86/platform/mrst/pmu.h234
-rw-r--r--arch/x86/platform/mrst/vrtc.c14
-rw-r--r--arch/x86/platform/olpc/Makefile5
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-pm.c216
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-rtc.c81
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-sci.c614
-rw-r--r--arch/x86/platform/olpc/olpc-xo1.c146
-rw-r--r--arch/x86/platform/olpc/olpc-xo15-sci.c168
-rw-r--r--arch/x86/platform/olpc/olpc.c99
-rw-r--r--arch/x86/platform/olpc/olpc_dt.c103
-rw-r--r--arch/x86/platform/olpc/xo1-wakeup.S124
-rw-r--r--arch/x86/platform/uv/bios_uv.c1
-rw-r--r--arch/x86/platform/uv/tlb_uv.c86
22 files changed, 2970 insertions, 219 deletions
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 021eee91c056..8d874396cb29 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -1,6 +1,7 @@
1# Platform specific code goes here 1# Platform specific code goes here
2obj-y += ce4100/ 2obj-y += ce4100/
3obj-y += efi/ 3obj-y += efi/
4obj-y += geode/
4obj-y += iris/ 5obj-y += iris/
5obj-y += mrst/ 6obj-y += mrst/
6obj-y += olpc/ 7obj-y += olpc/
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 28071bb31db7..4c61b52191eb 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -109,7 +109,7 @@ static __init void sdv_serial_fixup(void)
109} 109}
110 110
111#else 111#else
112static inline void sdv_serial_fixup(void); 112static inline void sdv_serial_fixup(void) {};
113#endif 113#endif
114 114
115static void __init sdv_arch_setup(void) 115static void __init sdv_arch_setup(void)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 3b4e86bda3cb..4a01967f02e7 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -29,6 +29,7 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/efi.h> 31#include <linux/efi.h>
32#include <linux/export.h>
32#include <linux/bootmem.h> 33#include <linux/bootmem.h>
33#include <linux/memblock.h> 34#include <linux/memblock.h>
34#include <linux/spinlock.h> 35#include <linux/spinlock.h>
@@ -51,7 +52,17 @@
51int efi_enabled; 52int efi_enabled;
52EXPORT_SYMBOL(efi_enabled); 53EXPORT_SYMBOL(efi_enabled);
53 54
54struct efi efi; 55struct efi __read_mostly efi = {
56 .mps = EFI_INVALID_TABLE_ADDR,
57 .acpi = EFI_INVALID_TABLE_ADDR,
58 .acpi20 = EFI_INVALID_TABLE_ADDR,
59 .smbios = EFI_INVALID_TABLE_ADDR,
60 .sal_systab = EFI_INVALID_TABLE_ADDR,
61 .boot_info = EFI_INVALID_TABLE_ADDR,
62 .hcdp = EFI_INVALID_TABLE_ADDR,
63 .uga = EFI_INVALID_TABLE_ADDR,
64 .uv_systab = EFI_INVALID_TABLE_ADDR,
65};
55EXPORT_SYMBOL(efi); 66EXPORT_SYMBOL(efi);
56 67
57struct efi_memory_map memmap; 68struct efi_memory_map memmap;
@@ -79,26 +90,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
79 90
80static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) 91static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
81{ 92{
82 return efi_call_virt2(get_time, tm, tc); 93 unsigned long flags;
94 efi_status_t status;
95
96 spin_lock_irqsave(&rtc_lock, flags);
97 status = efi_call_virt2(get_time, tm, tc);
98 spin_unlock_irqrestore(&rtc_lock, flags);
99 return status;
83} 100}
84 101
85static efi_status_t virt_efi_set_time(efi_time_t *tm) 102static efi_status_t virt_efi_set_time(efi_time_t *tm)
86{ 103{
87 return efi_call_virt1(set_time, tm); 104 unsigned long flags;
105 efi_status_t status;
106
107 spin_lock_irqsave(&rtc_lock, flags);
108 status = efi_call_virt1(set_time, tm);
109 spin_unlock_irqrestore(&rtc_lock, flags);
110 return status;
88} 111}
89 112
90static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, 113static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
91 efi_bool_t *pending, 114 efi_bool_t *pending,
92 efi_time_t *tm) 115 efi_time_t *tm)
93{ 116{
94 return efi_call_virt3(get_wakeup_time, 117 unsigned long flags;
95 enabled, pending, tm); 118 efi_status_t status;
119
120 spin_lock_irqsave(&rtc_lock, flags);
121 status = efi_call_virt3(get_wakeup_time,
122 enabled, pending, tm);
123 spin_unlock_irqrestore(&rtc_lock, flags);
124 return status;
96} 125}
97 126
98static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) 127static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
99{ 128{
100 return efi_call_virt2(set_wakeup_time, 129 unsigned long flags;
101 enabled, tm); 130 efi_status_t status;
131
132 spin_lock_irqsave(&rtc_lock, flags);
133 status = efi_call_virt2(set_wakeup_time,
134 enabled, tm);
135 spin_unlock_irqrestore(&rtc_lock, flags);
136 return status;
102} 137}
103 138
104static efi_status_t virt_efi_get_variable(efi_char16_t *name, 139static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -122,7 +157,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
122 157
123static efi_status_t virt_efi_set_variable(efi_char16_t *name, 158static efi_status_t virt_efi_set_variable(efi_char16_t *name,
124 efi_guid_t *vendor, 159 efi_guid_t *vendor,
125 unsigned long attr, 160 u32 attr,
126 unsigned long data_size, 161 unsigned long data_size,
127 void *data) 162 void *data)
128{ 163{
@@ -131,6 +166,18 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
131 data_size, data); 166 data_size, data);
132} 167}
133 168
169static efi_status_t virt_efi_query_variable_info(u32 attr,
170 u64 *storage_space,
171 u64 *remaining_space,
172 u64 *max_variable_size)
173{
174 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
175 return EFI_UNSUPPORTED;
176
177 return efi_call_virt4(query_variable_info, attr, storage_space,
178 remaining_space, max_variable_size);
179}
180
134static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) 181static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
135{ 182{
136 return efi_call_virt1(get_next_high_mono_count, count); 183 return efi_call_virt1(get_next_high_mono_count, count);
@@ -145,6 +192,28 @@ static void virt_efi_reset_system(int reset_type,
145 data_size, data); 192 data_size, data);
146} 193}
147 194
195static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
196 unsigned long count,
197 unsigned long sg_list)
198{
199 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
200 return EFI_UNSUPPORTED;
201
202 return efi_call_virt3(update_capsule, capsules, count, sg_list);
203}
204
205static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
206 unsigned long count,
207 u64 *max_size,
208 int *reset_type)
209{
210 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
211 return EFI_UNSUPPORTED;
212
213 return efi_call_virt4(query_capsule_caps, capsules, count, max_size,
214 reset_type);
215}
216
148static efi_status_t __init phys_efi_set_virtual_address_map( 217static efi_status_t __init phys_efi_set_virtual_address_map(
149 unsigned long memory_map_size, 218 unsigned long memory_map_size,
150 unsigned long descriptor_size, 219 unsigned long descriptor_size,
@@ -164,11 +233,14 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
164static efi_status_t __init phys_efi_get_time(efi_time_t *tm, 233static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
165 efi_time_cap_t *tc) 234 efi_time_cap_t *tc)
166{ 235{
236 unsigned long flags;
167 efi_status_t status; 237 efi_status_t status;
168 238
239 spin_lock_irqsave(&rtc_lock, flags);
169 efi_call_phys_prelog(); 240 efi_call_phys_prelog();
170 status = efi_call_phys2(efi_phys.get_time, tm, tc); 241 status = efi_call_phys2(efi_phys.get_time, tm, tc);
171 efi_call_phys_epilog(); 242 efi_call_phys_epilog();
243 spin_unlock_irqrestore(&rtc_lock, flags);
172 return status; 244 return status;
173} 245}
174 246
@@ -666,6 +738,9 @@ void __init efi_enter_virtual_mode(void)
666 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; 738 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
667 efi.reset_system = virt_efi_reset_system; 739 efi.reset_system = virt_efi_reset_system;
668 efi.set_virtual_address_map = NULL; 740 efi.set_virtual_address_map = NULL;
741 efi.query_variable_info = virt_efi_query_variable_info;
742 efi.update_capsule = virt_efi_update_capsule;
743 efi.query_capsule_caps = virt_efi_query_capsule_caps;
669 if (__supported_pte_mask & _PAGE_NX) 744 if (__supported_pte_mask & _PAGE_NX)
670 runtime_code_page_mkexec(); 745 runtime_code_page_mkexec();
671 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); 746 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index 5cab48ee61a4..e36bf714cb77 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -25,6 +25,7 @@
25#include <linux/efi.h> 25#include <linux/efi.h>
26 26
27#include <asm/io.h> 27#include <asm/io.h>
28#include <asm/desc.h>
28#include <asm/page.h> 29#include <asm/page.h>
29#include <asm/pgtable.h> 30#include <asm/pgtable.h>
30#include <asm/tlbflush.h> 31#include <asm/tlbflush.h>
diff --git a/arch/x86/platform/geode/Makefile b/arch/x86/platform/geode/Makefile
new file mode 100644
index 000000000000..07c9cd05021a
--- /dev/null
+++ b/arch/x86/platform/geode/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_ALIX) += alix.o
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c
new file mode 100644
index 000000000000..ca1973699d3d
--- /dev/null
+++ b/arch/x86/platform/geode/alix.c
@@ -0,0 +1,142 @@
1/*
2 * System Specific setup for PCEngines ALIX.
3 * At the moment this means setup of GPIO control of LEDs
4 * on Alix.2/3/6 boards.
5 *
6 *
7 * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
8 * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
9 *
10 * TODO: There are large similarities with leds-net5501.c
11 * by Alessandro Zummo <a.zummo@towertech.it>
12 * In the future leds-net5501.c should be migrated over to platform
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
28#include <asm/geode.h>
29
30static int force = 0;
31module_param(force, bool, 0444);
32/* FIXME: Award bios is not automatically detected as Alix platform */
33MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform");
34
35static struct gpio_led alix_leds[] = {
36 {
37 .name = "alix:1",
38 .gpio = 6,
39 .default_trigger = "default-on",
40 .active_low = 1,
41 },
42 {
43 .name = "alix:2",
44 .gpio = 25,
45 .default_trigger = "default-off",
46 .active_low = 1,
47 },
48 {
49 .name = "alix:3",
50 .gpio = 27,
51 .default_trigger = "default-off",
52 .active_low = 1,
53 },
54};
55
56static struct gpio_led_platform_data alix_leds_data = {
57 .num_leds = ARRAY_SIZE(alix_leds),
58 .leds = alix_leds,
59};
60
61static struct platform_device alix_leds_dev = {
62 .name = "leds-gpio",
63 .id = -1,
64 .dev.platform_data = &alix_leds_data,
65};
66
67static void __init register_alix(void)
68{
69 /* Setup LED control through leds-gpio driver */
70 platform_device_register(&alix_leds_dev);
71}
72
73static int __init alix_present(unsigned long bios_phys,
74 const char *alix_sig,
75 size_t alix_sig_len)
76{
77 const size_t bios_len = 0x00010000;
78 const char *bios_virt;
79 const char *scan_end;
80 const char *p;
81 char name[64];
82
83 if (force) {
84 printk(KERN_NOTICE "%s: forced to skip BIOS test, "
85 "assume system is ALIX.2/ALIX.3\n",
86 KBUILD_MODNAME);
87 return 1;
88 }
89
90 bios_virt = phys_to_virt(bios_phys);
91 scan_end = bios_virt + bios_len - (alix_sig_len + 2);
92 for (p = bios_virt; p < scan_end; p++) {
93 const char *tail;
94 char *a;
95
96 if (memcmp(p, alix_sig, alix_sig_len) != 0)
97 continue;
98
99 memcpy(name, p, sizeof(name));
100
101 /* remove the first \0 character from string */
102 a = strchr(name, '\0');
103 if (a)
104 *a = ' ';
105
106 /* cut the string at a newline */
107 a = strchr(name, '\r');
108 if (a)
109 *a = '\0';
110
111 tail = p + alix_sig_len;
112 if ((tail[0] == '2' || tail[0] == '3')) {
113 printk(KERN_INFO
114 "%s: system is recognized as \"%s\"\n",
115 KBUILD_MODNAME, name);
116 return 1;
117 }
118 }
119
120 return 0;
121}
122
123static int __init alix_init(void)
124{
125 const char tinybios_sig[] = "PC Engines ALIX.";
126 const char coreboot_sig[] = "PC Engines\0ALIX.";
127
128 if (!is_geode())
129 return 0;
130
131 if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
132 alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
133 register_alix();
134
135 return 0;
136}
137
138module_init(alix_init);
139
140MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
141MODULE_DESCRIPTION("PCEngines ALIX System Setup");
142MODULE_LICENSE("GPL");
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
index f61ccdd49341..1ea38775a6d3 100644
--- a/arch/x86/platform/mrst/Makefile
+++ b/arch/x86/platform/mrst/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_X86_MRST) += mrst.o 1obj-$(CONFIG_X86_MRST) += mrst.o
2obj-$(CONFIG_X86_MRST) += vrtc.o 2obj-$(CONFIG_X86_MRST) += vrtc.o
3obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o 3obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
4obj-$(CONFIG_X86_MRST) += pmu.o
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index 7000e74b3087..b1489a06a49d 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -14,6 +14,8 @@
14 14
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/interrupt.h>
18#include <linux/scatterlist.h>
17#include <linux/sfi.h> 19#include <linux/sfi.h>
18#include <linux/intel_pmic_gpio.h> 20#include <linux/intel_pmic_gpio.h>
19#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
@@ -24,6 +26,8 @@
24#include <linux/platform_device.h> 26#include <linux/platform_device.h>
25#include <linux/irq.h> 27#include <linux/irq.h>
26#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/notifier.h>
30#include <linux/mfd/intel_msic.h>
27 31
28#include <asm/setup.h> 32#include <asm/setup.h>
29#include <asm/mpspec_def.h> 33#include <asm/mpspec_def.h>
@@ -183,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
183static unsigned long __init mrst_calibrate_tsc(void) 187static unsigned long __init mrst_calibrate_tsc(void)
184{ 188{
185 unsigned long flags, fast_calibrate; 189 unsigned long flags, fast_calibrate;
186 190 if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
187 local_irq_save(flags); 191 u32 lo, hi, ratio, fsb;
188 fast_calibrate = apbt_quick_calibrate(); 192
189 local_irq_restore(flags); 193 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
190 194 pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
195 ratio = (hi >> 8) & 0x1f;
196 pr_debug("ratio is %d\n", ratio);
197 if (!ratio) {
198 pr_err("read a zero ratio, should be incorrect!\n");
199 pr_err("force tsc ratio to 16 ...\n");
200 ratio = 16;
201 }
202 rdmsr(MSR_FSB_FREQ, lo, hi);
203 if ((lo & 0x7) == 0x7)
204 fsb = PENWELL_FSB_FREQ_83SKU;
205 else
206 fsb = PENWELL_FSB_FREQ_100SKU;
207 fast_calibrate = ratio * fsb;
208 pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
209 lapic_timer_frequency = fsb * 1000 / HZ;
210 /* mark tsc clocksource as reliable */
211 set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
212 } else {
213 local_irq_save(flags);
214 fast_calibrate = apbt_quick_calibrate();
215 local_irq_restore(flags);
216 }
217
191 if (fast_calibrate) 218 if (fast_calibrate)
192 return fast_calibrate; 219 return fast_calibrate;
193 220
@@ -250,6 +277,17 @@ static void mrst_reboot(void)
250} 277}
251 278
252/* 279/*
280 * Moorestown does not have external NMI source nor port 0x61 to report
281 * NMI status. The possible NMI sources are from pmu as a result of NMI
282 * watchdog or lock debug. Reading io port 0x61 results in 0xff which
283 * misled NMI handler.
284 */
285static unsigned char mrst_get_nmi_reason(void)
286{
287 return 0;
288}
289
290/*
253 * Moorestown specific x86_init function overrides and early setup 291 * Moorestown specific x86_init function overrides and early setup
254 * calls. 292 * calls.
255 */ 293 */
@@ -270,6 +308,8 @@ void __init x86_mrst_early_setup(void)
270 x86_platform.calibrate_tsc = mrst_calibrate_tsc; 308 x86_platform.calibrate_tsc = mrst_calibrate_tsc;
271 x86_platform.i8042_detect = mrst_i8042_detect; 309 x86_platform.i8042_detect = mrst_i8042_detect;
272 x86_init.timers.wallclock_init = mrst_rtc_init; 310 x86_init.timers.wallclock_init = mrst_rtc_init;
311 x86_platform.get_nmi_reason = mrst_get_nmi_reason;
312
273 x86_init.pci.init = pci_mrst_init; 313 x86_init.pci.init = pci_mrst_init;
274 x86_init.pci.fixup_irqs = x86_init_noop; 314 x86_init.pci.fixup_irqs = x86_init_noop;
275 315
@@ -392,6 +432,7 @@ static void __init *max3111_platform_data(void *info)
392 struct spi_board_info *spi_info = info; 432 struct spi_board_info *spi_info = info;
393 int intr = get_gpio_by_name("max3111_int"); 433 int intr = get_gpio_by_name("max3111_int");
394 434
435 spi_info->mode = SPI_MODE_0;
395 if (intr == -1) 436 if (intr == -1)
396 return NULL; 437 return NULL;
397 spi_info->irq = intr + MRST_IRQ_OFFSET; 438 spi_info->irq = intr + MRST_IRQ_OFFSET;
@@ -480,7 +521,130 @@ static void __init *no_platform_data(void *info)
480 return NULL; 521 return NULL;
481} 522}
482 523
524static struct resource msic_resources[] = {
525 {
526 .start = INTEL_MSIC_IRQ_PHYS_BASE,
527 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
528 .flags = IORESOURCE_MEM,
529 },
530};
531
532static struct intel_msic_platform_data msic_pdata;
533
534static struct platform_device msic_device = {
535 .name = "intel_msic",
536 .id = -1,
537 .dev = {
538 .platform_data = &msic_pdata,
539 },
540 .num_resources = ARRAY_SIZE(msic_resources),
541 .resource = msic_resources,
542};
543
544static inline bool mrst_has_msic(void)
545{
546 return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
547}
548
549static int msic_scu_status_change(struct notifier_block *nb,
550 unsigned long code, void *data)
551{
552 if (code == SCU_DOWN) {
553 platform_device_unregister(&msic_device);
554 return 0;
555 }
556
557 return platform_device_register(&msic_device);
558}
559
560static int __init msic_init(void)
561{
562 static struct notifier_block msic_scu_notifier = {
563 .notifier_call = msic_scu_status_change,
564 };
565
566 /*
567 * We need to be sure that the SCU IPC is ready before MSIC device
568 * can be registered.
569 */
570 if (mrst_has_msic())
571 intel_scu_notifier_add(&msic_scu_notifier);
572
573 return 0;
574}
575arch_initcall(msic_init);
576
577/*
578 * msic_generic_platform_data - sets generic platform data for the block
579 * @info: pointer to the SFI device table entry for this block
580 * @block: MSIC block
581 *
582 * Function sets IRQ number from the SFI table entry for given device to
583 * the MSIC platform data.
584 */
585static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
586{
587 struct sfi_device_table_entry *entry = info;
588
589 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
590 msic_pdata.irq[block] = entry->irq;
591
592 return no_platform_data(info);
593}
594
595static void *msic_battery_platform_data(void *info)
596{
597 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
598}
599
600static void *msic_gpio_platform_data(void *info)
601{
602 static struct intel_msic_gpio_pdata pdata;
603 int gpio = get_gpio_by_name("msic_gpio_base");
604
605 if (gpio < 0)
606 return NULL;
607
608 pdata.gpio_base = gpio;
609 msic_pdata.gpio = &pdata;
610
611 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
612}
613
614static void *msic_audio_platform_data(void *info)
615{
616 struct platform_device *pdev;
617
618 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
619 if (IS_ERR(pdev)) {
620 pr_err("failed to create audio platform device\n");
621 return NULL;
622 }
623
624 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
625}
626
627static void *msic_power_btn_platform_data(void *info)
628{
629 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
630}
631
632static void *msic_ocd_platform_data(void *info)
633{
634 static struct intel_msic_ocd_pdata pdata;
635 int gpio = get_gpio_by_name("ocd_gpio");
636
637 if (gpio < 0)
638 return NULL;
639
640 pdata.gpio = gpio;
641 msic_pdata.ocd = &pdata;
642
643 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
644}
645
483static const struct devs_id __initconst device_ids[] = { 646static const struct devs_id __initconst device_ids[] = {
647 {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
484 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, 648 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
485 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, 649 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
486 {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, 650 {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
@@ -488,7 +652,14 @@ static const struct devs_id __initconst device_ids[] = {
488 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, 652 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
489 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, 653 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
490 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 654 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
491 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 655
656 /* MSIC subdevices */
657 {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
658 {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
659 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
660 {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
661 {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
662
492 {}, 663 {},
493}; 664};
494 665
@@ -555,6 +726,9 @@ static void __init intel_scu_i2c_device_register(int bus,
555 i2c_devs[i2c_next_dev++] = new_dev; 726 i2c_devs[i2c_next_dev++] = new_dev;
556} 727}
557 728
729BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
730EXPORT_SYMBOL_GPL(intel_scu_notifier);
731
558/* Called by IPC driver */ 732/* Called by IPC driver */
559void intel_scu_devices_create(void) 733void intel_scu_devices_create(void)
560{ 734{
@@ -579,6 +753,7 @@ void intel_scu_devices_create(void)
579 } else 753 } else
580 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); 754 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
581 } 755 }
756 intel_scu_notifier_post(SCU_AVAILABLE, 0L);
582} 757}
583EXPORT_SYMBOL_GPL(intel_scu_devices_create); 758EXPORT_SYMBOL_GPL(intel_scu_devices_create);
584 759
@@ -587,6 +762,8 @@ void intel_scu_devices_destroy(void)
587{ 762{
588 int i; 763 int i;
589 764
765 intel_scu_notifier_post(SCU_DOWN, 0L);
766
590 for (i = 0; i < ipc_next_dev; i++) 767 for (i = 0; i < ipc_next_dev; i++)
591 platform_device_del(ipc_devs[i]); 768 platform_device_del(ipc_devs[i]);
592} 769}
@@ -603,19 +780,37 @@ static void __init install_irq_resource(struct platform_device *pdev, int irq)
603 platform_device_add_resources(pdev, &res, 1); 780 platform_device_add_resources(pdev, &res, 1);
604} 781}
605 782
606static void __init sfi_handle_ipc_dev(struct platform_device *pdev) 783static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
607{ 784{
608 const struct devs_id *dev = device_ids; 785 const struct devs_id *dev = device_ids;
786 struct platform_device *pdev;
609 void *pdata = NULL; 787 void *pdata = NULL;
610 788
611 while (dev->name[0]) { 789 while (dev->name[0]) {
612 if (dev->type == SFI_DEV_TYPE_IPC && 790 if (dev->type == SFI_DEV_TYPE_IPC &&
613 !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { 791 !strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
614 pdata = dev->get_platform_data(pdev); 792 pdata = dev->get_platform_data(entry);
615 break; 793 break;
616 } 794 }
617 dev++; 795 dev++;
618 } 796 }
797
798 /*
799 * On Medfield the platform device creation is handled by the MSIC
800 * MFD driver so we don't need to do it here.
801 */
802 if (mrst_has_msic())
803 return;
804
805 /* ID as IRQ is a hack that will go away */
806 pdev = platform_device_alloc(entry->name, entry->irq);
807 if (pdev == NULL) {
808 pr_err("out of memory for SFI platform device '%s'.\n",
809 entry->name);
810 return;
811 }
812 install_irq_resource(pdev, entry->irq);
813
619 pdev->dev.platform_data = pdata; 814 pdev->dev.platform_data = pdata;
620 intel_scu_device_register(pdev); 815 intel_scu_device_register(pdev);
621} 816}
@@ -668,7 +863,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
668 struct sfi_device_table_entry *pentry; 863 struct sfi_device_table_entry *pentry;
669 struct spi_board_info spi_info; 864 struct spi_board_info spi_info;
670 struct i2c_board_info i2c_info; 865 struct i2c_board_info i2c_info;
671 struct platform_device *pdev;
672 int num, i, bus; 866 int num, i, bus;
673 int ioapic; 867 int ioapic;
674 struct io_apic_irq_attr irq_attr; 868 struct io_apic_irq_attr irq_attr;
@@ -678,36 +872,32 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
678 pentry = (struct sfi_device_table_entry *)sb->pentry; 872 pentry = (struct sfi_device_table_entry *)sb->pentry;
679 873
680 for (i = 0; i < num; i++, pentry++) { 874 for (i = 0; i < num; i++, pentry++) {
681 if (pentry->irq != (u8)0xff) { /* native RTE case */ 875 int irq = pentry->irq;
876
877 if (irq != (u8)0xff) { /* native RTE case */
682 /* these SPI2 devices are not exposed to system as PCI 878 /* these SPI2 devices are not exposed to system as PCI
683 * devices, but they have separate RTE entry in IOAPIC 879 * devices, but they have separate RTE entry in IOAPIC
684 * so we have to enable them one by one here 880 * so we have to enable them one by one here
685 */ 881 */
686 ioapic = mp_find_ioapic(pentry->irq); 882 ioapic = mp_find_ioapic(irq);
687 irq_attr.ioapic = ioapic; 883 irq_attr.ioapic = ioapic;
688 irq_attr.ioapic_pin = pentry->irq; 884 irq_attr.ioapic_pin = irq;
689 irq_attr.trigger = 1; 885 irq_attr.trigger = 1;
690 irq_attr.polarity = 1; 886 irq_attr.polarity = 1;
691 io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); 887 io_apic_set_pci_routing(NULL, irq, &irq_attr);
692 } 888 } else
889 irq = 0; /* No irq */
890
693 switch (pentry->type) { 891 switch (pentry->type) {
694 case SFI_DEV_TYPE_IPC: 892 case SFI_DEV_TYPE_IPC:
695 /* ID as IRQ is a hack that will go away */
696 pdev = platform_device_alloc(pentry->name, pentry->irq);
697 if (pdev == NULL) {
698 pr_err("out of memory for SFI platform device '%s'.\n",
699 pentry->name);
700 continue;
701 }
702 install_irq_resource(pdev, pentry->irq);
703 pr_debug("info[%2d]: IPC bus, name = %16.16s, " 893 pr_debug("info[%2d]: IPC bus, name = %16.16s, "
704 "irq = 0x%2x\n", i, pentry->name, pentry->irq); 894 "irq = 0x%2x\n", i, pentry->name, pentry->irq);
705 sfi_handle_ipc_dev(pdev); 895 sfi_handle_ipc_dev(pentry);
706 break; 896 break;
707 case SFI_DEV_TYPE_SPI: 897 case SFI_DEV_TYPE_SPI:
708 memset(&spi_info, 0, sizeof(spi_info)); 898 memset(&spi_info, 0, sizeof(spi_info));
709 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); 899 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
710 spi_info.irq = pentry->irq; 900 spi_info.irq = irq;
711 spi_info.bus_num = pentry->host_num; 901 spi_info.bus_num = pentry->host_num;
712 spi_info.chip_select = pentry->addr; 902 spi_info.chip_select = pentry->addr;
713 spi_info.max_speed_hz = pentry->max_freq; 903 spi_info.max_speed_hz = pentry->max_freq;
@@ -724,7 +914,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
724 memset(&i2c_info, 0, sizeof(i2c_info)); 914 memset(&i2c_info, 0, sizeof(i2c_info));
725 bus = pentry->host_num; 915 bus = pentry->host_num;
726 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); 916 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
727 i2c_info.irq = pentry->irq; 917 i2c_info.irq = irq;
728 i2c_info.addr = pentry->addr; 918 i2c_info.addr = pentry->addr;
729 pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " 919 pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, "
730 "irq = 0x%2x, addr = 0x%x\n", i, bus, 920 "irq = 0x%2x, addr = 0x%x\n", i, bus,
diff --git a/arch/x86/platform/mrst/pmu.c b/arch/x86/platform/mrst/pmu.c
new file mode 100644
index 000000000000..c0ac06da57ac
--- /dev/null
+++ b/arch/x86/platform/mrst/pmu.c
@@ -0,0 +1,817 @@
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
33struct 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 */
43static 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 */
74static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
75static 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() */
79static spinlock_t mrst_pmu_power_state_lock;
80
81static unsigned int wake_counters[MRST_NUM_LSS]; /* DEBUG only */
82static unsigned int pmu_irq_stats[INT_INVALID + 1]; /* DEBUG only */
83
84static int graphics_is_off;
85static int lss_s0i3_enabled;
86static bool mrst_pmu_s0i3_enable;
87
88/* debug counters */
89static u32 pmu_wait_ready_calls;
90static u32 pmu_wait_ready_udelays;
91static u32 pmu_wait_ready_udelays_max;
92static u32 pmu_wait_done_calls;
93static u32 pmu_wait_done_udelays;
94static u32 pmu_wait_done_udelays_max;
95static u32 pmu_set_power_state_entry;
96static u32 pmu_set_power_state_send_cmd;
97
98static 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
132int 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 */
163static 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
176int 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 */
192static 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 */
218static 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
244u32 mrst_pmu_msi_is_disabled(void)
245{
246 return pmu_msi_is_disabled();
247}
248
249void 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 */
258static 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 */
289static 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
310static 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
355static 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
379int 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);
464ret:
465 spin_unlock(&mrst_pmu_power_state_lock);
466 return status;
467}
468
469#ifdef CONFIG_DEBUG_FS
470static char *d0ix_names[] = {"D0", "D0i1", "D0i2", "D0i3"};
471
472static inline const char *d0ix_name(int state)
473{
474 return d0ix_names[(int) state];
475}
476
477static 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
588static int debug_mrst_pmu_open(struct inode *inode, struct file *file)
589{
590 return single_open(file, debug_mrst_pmu_show, NULL);
591}
592
593static 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 */
606static 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 */
653static 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
708out_err3:
709 free_irq(pdev->irq, NULL);
710 pci_iounmap(pdev, pmu_reg);
711 pmu_reg = NULL;
712out_err2:
713 pci_release_region(pdev, 0);
714out_err1:
715 pci_disable_device(pdev);
716 return ret;
717}
718
719static 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
734static DEFINE_PCI_DEVICE_TABLE(pmu_pci_ids) = {
735 { PCI_VDEVICE(INTEL, PCI_DEV_ID_MRST_PMU), 0 },
736 { }
737};
738
739MODULE_DEVICE_TABLE(pci, pmu_pci_ids);
740
741static 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 */
751static 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() */
757fs_initcall(pmu_pci_register);
758
759static void __exit mid_pci_cleanup(void)
760{
761 pci_unregister_driver(&driver);
762}
763
764static int ia_major;
765static int ia_minor;
766
767static 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
780static 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}
816late_initcall(scu_fw_check);
817module_exit(mid_pci_cleanup);
diff --git a/arch/x86/platform/mrst/pmu.h b/arch/x86/platform/mrst/pmu.h
new file mode 100644
index 000000000000..bfbfe64b167b
--- /dev/null
+++ b/arch/x86/platform/mrst/pmu.h
@@ -0,0 +1,234 @@
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
98enum cm_mode {
99 CM_NOP, /* ignore the config mode value */
100 CM_IMMEDIATE,
101 CM_DELAY,
102 CM_TRIGGER,
103 CM_INVALID
104};
105
106enum 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
117enum 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 */
129static 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
144static inline u32 pmu_read_sts(void) { return readl(&pmu_reg->pm_sts); }
145static inline u32 pmu_read_ics(void) { return readl(&pmu_reg->pm_ics); }
146static inline u32 pmu_read_wks(void) { return readl(&pmu_reg->pm_wks[0]); }
147static inline u32 pmu_read_sss(void) { return readl(&pmu_reg->pm_sss[0]); }
148
149static inline void pmu_write_cmd(u32 arg) { writel(arg, &pmu_reg->pm_cmd); }
150static inline void pmu_write_ics(u32 arg) { writel(arg, &pmu_reg->pm_ics); }
151static inline void pmu_write_wkc(u32 arg) { writel(arg, &pmu_reg->pm_wkc[0]); }
152static inline void pmu_write_ssc(u32 arg) { writel(arg, &pmu_reg->pm_ssc[0]); }
153static inline void pmu_write_wssc(u32 arg)
154 { writel(arg, &pmu_reg->pm_wssc[0]); }
155
156static inline void pmu_msi_enable(void) { writel(0, &pmu_reg->pm_msi_disable); }
157static inline u32 pmu_msi_is_disabled(void)
158 { return readl(&pmu_reg->pm_msi_disable); }
159
160union 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
170static 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
179union 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
189static 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 */
199struct 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
209struct 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
221union 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
230extern int mrst_s0i3_entry(u32 regval, u32 *regaddr);
231#else
232static inline int mrst_s0i3_entry(u32 regval, u32 *regaddr) { return -1; }
233#endif
234#endif
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index 73d70d65e76e..225bd0f0f675 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -18,6 +18,7 @@
18 */ 18 */
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/export.h>
21#include <linux/init.h> 22#include <linux/init.h>
22#include <linux/sfi.h> 23#include <linux/sfi.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
@@ -58,8 +59,11 @@ EXPORT_SYMBOL_GPL(vrtc_cmos_write);
58unsigned long vrtc_get_time(void) 59unsigned long vrtc_get_time(void)
59{ 60{
60 u8 sec, min, hour, mday, mon; 61 u8 sec, min, hour, mday, mon;
62 unsigned long flags;
61 u32 year; 63 u32 year;
62 64
65 spin_lock_irqsave(&rtc_lock, flags);
66
63 while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) 67 while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
64 cpu_relax(); 68 cpu_relax();
65 69
@@ -70,8 +74,10 @@ unsigned long vrtc_get_time(void)
70 mon = vrtc_cmos_read(RTC_MONTH); 74 mon = vrtc_cmos_read(RTC_MONTH);
71 year = vrtc_cmos_read(RTC_YEAR); 75 year = vrtc_cmos_read(RTC_YEAR);
72 76
73 /* vRTC YEAR reg contains the offset to 1960 */ 77 spin_unlock_irqrestore(&rtc_lock, flags);
74 year += 1960; 78
79 /* vRTC YEAR reg contains the offset to 1972 */
80 year += 1972;
75 81
76 printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " 82 printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
77 "mon: %d year: %d\n", sec, min, hour, mday, mon, year); 83 "mon: %d year: %d\n", sec, min, hour, mday, mon, year);
@@ -83,8 +89,10 @@ unsigned long vrtc_get_time(void)
83int vrtc_set_mmss(unsigned long nowtime) 89int vrtc_set_mmss(unsigned long nowtime)
84{ 90{
85 int real_sec, real_min; 91 int real_sec, real_min;
92 unsigned long flags;
86 int vrtc_min; 93 int vrtc_min;
87 94
95 spin_lock_irqsave(&rtc_lock, flags);
88 vrtc_min = vrtc_cmos_read(RTC_MINUTES); 96 vrtc_min = vrtc_cmos_read(RTC_MINUTES);
89 97
90 real_sec = nowtime % 60; 98 real_sec = nowtime % 60;
@@ -95,6 +103,8 @@ int vrtc_set_mmss(unsigned long nowtime)
95 103
96 vrtc_cmos_write(real_sec, RTC_SECONDS); 104 vrtc_cmos_write(real_sec, RTC_SECONDS);
97 vrtc_cmos_write(real_min, RTC_MINUTES); 105 vrtc_cmos_write(real_min, RTC_MINUTES);
106 spin_unlock_irqrestore(&rtc_lock, flags);
107
98 return 0; 108 return 0;
99} 109}
100 110
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index 81c5e2165c24..fd332c533947 100644
--- a/arch/x86/platform/olpc/Makefile
+++ b/arch/x86/platform/olpc/Makefile
@@ -1,2 +1,5 @@
1obj-$(CONFIG_OLPC) += olpc.o olpc_ofw.o olpc_dt.o 1obj-$(CONFIG_OLPC) += olpc.o olpc_ofw.o olpc_dt.o
2obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o 2obj-$(CONFIG_OLPC_XO1_PM) += olpc-xo1-pm.o xo1-wakeup.o
3obj-$(CONFIG_OLPC_XO1_RTC) += olpc-xo1-rtc.o
4obj-$(CONFIG_OLPC_XO1_SCI) += olpc-xo1-sci.o
5obj-$(CONFIG_OLPC_XO15_SCI) += olpc-xo15-sci.o
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
new file mode 100644
index 000000000000..0ce8616c88ae
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -0,0 +1,216 @@
1/*
2 * Support for power management features of the OLPC XO-1 laptop
3 *
4 * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
5 * Copyright (C) 2010 One Laptop per Child
6 * Copyright (C) 2006 Red Hat, Inc.
7 * Copyright (C) 2006 Advanced Micro Devices, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#include <linux/cs5535.h>
16#include <linux/platform_device.h>
17#include <linux/export.h>
18#include <linux/pm.h>
19#include <linux/mfd/core.h>
20#include <linux/suspend.h>
21
22#include <asm/io.h>
23#include <asm/olpc.h>
24
25#define DRV_NAME "olpc-xo1-pm"
26
27static unsigned long acpi_base;
28static unsigned long pms_base;
29
30static u16 wakeup_mask = CS5536_PM_PWRBTN;
31
32static struct {
33 unsigned long address;
34 unsigned short segment;
35} ofw_bios_entry = { 0xF0000 + PAGE_OFFSET, __KERNEL_CS };
36
37/* Set bits in the wakeup mask */
38void olpc_xo1_pm_wakeup_set(u16 value)
39{
40 wakeup_mask |= value;
41}
42EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_set);
43
44/* Clear bits in the wakeup mask */
45void olpc_xo1_pm_wakeup_clear(u16 value)
46{
47 wakeup_mask &= ~value;
48}
49EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
50
51static int xo1_power_state_enter(suspend_state_t pm_state)
52{
53 unsigned long saved_sci_mask;
54 int r;
55
56 /* Only STR is supported */
57 if (pm_state != PM_SUSPEND_MEM)
58 return -EINVAL;
59
60 r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
61 if (r)
62 return r;
63
64 /*
65 * Save SCI mask (this gets lost since PM1_EN is used as a mask for
66 * wakeup events, which is not necessarily the same event set)
67 */
68 saved_sci_mask = inl(acpi_base + CS5536_PM1_STS);
69 saved_sci_mask &= 0xffff0000;
70
71 /* Save CPU state */
72 do_olpc_suspend_lowlevel();
73
74 /* Resume path starts here */
75
76 /* Restore SCI mask (using dword access to CS5536_PM1_EN) */
77 outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
78
79 /* Tell the EC to stop inhibiting SCIs */
80 olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
81
82 /*
83 * Tell the wireless module to restart USB communication.
84 * Must be done twice.
85 */
86 olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
87 olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
88
89 return 0;
90}
91
92asmlinkage int xo1_do_sleep(u8 sleep_state)
93{
94 void *pgd_addr = __va(read_cr3());
95
96 /* Program wakeup mask (using dword access to CS5536_PM1_EN) */
97 outl(wakeup_mask << 16, acpi_base + CS5536_PM1_STS);
98
99 __asm__("movl %0,%%eax" : : "r" (pgd_addr));
100 __asm__("call *(%%edi); cld"
101 : : "D" (&ofw_bios_entry));
102 __asm__("movb $0x34, %al\n\t"
103 "outb %al, $0x70\n\t"
104 "movb $0x30, %al\n\t"
105 "outb %al, $0x71\n\t");
106 return 0;
107}
108
109static void xo1_power_off(void)
110{
111 printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
112
113 /* Enable all of these controls with 0 delay */
114 outl(0x40000000, pms_base + CS5536_PM_SCLK);
115 outl(0x40000000, pms_base + CS5536_PM_IN_SLPCTL);
116 outl(0x40000000, pms_base + CS5536_PM_WKXD);
117 outl(0x40000000, pms_base + CS5536_PM_WKD);
118
119 /* Clear status bits (possibly unnecessary) */
120 outl(0x0002ffff, pms_base + CS5536_PM_SSC);
121 outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
122
123 /* Write SLP_EN bit to start the machinery */
124 outl(0x00002000, acpi_base + CS5536_PM1_CNT);
125}
126
127static int xo1_power_state_valid(suspend_state_t pm_state)
128{
129 /* suspend-to-RAM only */
130 return pm_state == PM_SUSPEND_MEM;
131}
132
133static const struct platform_suspend_ops xo1_suspend_ops = {
134 .valid = xo1_power_state_valid,
135 .enter = xo1_power_state_enter,
136};
137
138static int __devinit xo1_pm_probe(struct platform_device *pdev)
139{
140 struct resource *res;
141 int err;
142
143 /* don't run on non-XOs */
144 if (!machine_is_olpc())
145 return -ENODEV;
146
147 err = mfd_cell_enable(pdev);
148 if (err)
149 return err;
150
151 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
152 if (!res) {
153 dev_err(&pdev->dev, "can't fetch device resource info\n");
154 return -EIO;
155 }
156 if (strcmp(pdev->name, "cs5535-pms") == 0)
157 pms_base = res->start;
158 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
159 acpi_base = res->start;
160
161 /* If we have both addresses, we can override the poweroff hook */
162 if (pms_base && acpi_base) {
163 suspend_set_ops(&xo1_suspend_ops);
164 pm_power_off = xo1_power_off;
165 printk(KERN_INFO "OLPC XO-1 support registered\n");
166 }
167
168 return 0;
169}
170
171static int __devexit xo1_pm_remove(struct platform_device *pdev)
172{
173 mfd_cell_disable(pdev);
174
175 if (strcmp(pdev->name, "cs5535-pms") == 0)
176 pms_base = 0;
177 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
178 acpi_base = 0;
179
180 pm_power_off = NULL;
181 return 0;
182}
183
184static struct platform_driver cs5535_pms_driver = {
185 .driver = {
186 .name = "cs5535-pms",
187 .owner = THIS_MODULE,
188 },
189 .probe = xo1_pm_probe,
190 .remove = __devexit_p(xo1_pm_remove),
191};
192
193static struct platform_driver cs5535_acpi_driver = {
194 .driver = {
195 .name = "olpc-xo1-pm-acpi",
196 .owner = THIS_MODULE,
197 },
198 .probe = xo1_pm_probe,
199 .remove = __devexit_p(xo1_pm_remove),
200};
201
202static int __init xo1_pm_init(void)
203{
204 int r;
205
206 r = platform_driver_register(&cs5535_pms_driver);
207 if (r)
208 return r;
209
210 r = platform_driver_register(&cs5535_acpi_driver);
211 if (r)
212 platform_driver_unregister(&cs5535_pms_driver);
213
214 return r;
215}
216arch_initcall(xo1_pm_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-rtc.c b/arch/x86/platform/olpc/olpc-xo1-rtc.c
new file mode 100644
index 000000000000..a2b4efddd61a
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-rtc.c
@@ -0,0 +1,81 @@
1/*
2 * Support for OLPC XO-1 Real Time Clock (RTC)
3 *
4 * Copyright (C) 2011 One Laptop per Child
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/mc146818rtc.h>
13#include <linux/platform_device.h>
14#include <linux/rtc.h>
15#include <linux/of.h>
16
17#include <asm/msr.h>
18#include <asm/olpc.h>
19
20static void rtc_wake_on(struct device *dev)
21{
22 olpc_xo1_pm_wakeup_set(CS5536_PM_RTC);
23}
24
25static void rtc_wake_off(struct device *dev)
26{
27 olpc_xo1_pm_wakeup_clear(CS5536_PM_RTC);
28}
29
30static struct resource rtc_platform_resource[] = {
31 [0] = {
32 .start = RTC_PORT(0),
33 .end = RTC_PORT(1),
34 .flags = IORESOURCE_IO,
35 },
36 [1] = {
37 .start = RTC_IRQ,
38 .end = RTC_IRQ,
39 .flags = IORESOURCE_IRQ,
40 }
41};
42
43static struct cmos_rtc_board_info rtc_info = {
44 .rtc_day_alarm = 0,
45 .rtc_mon_alarm = 0,
46 .rtc_century = 0,
47 .wake_on = rtc_wake_on,
48 .wake_off = rtc_wake_off,
49};
50
51static struct platform_device xo1_rtc_device = {
52 .name = "rtc_cmos",
53 .id = -1,
54 .num_resources = ARRAY_SIZE(rtc_platform_resource),
55 .dev.platform_data = &rtc_info,
56 .resource = rtc_platform_resource,
57};
58
59static int __init xo1_rtc_init(void)
60{
61 int r;
62 struct device_node *node;
63
64 node = of_find_compatible_node(NULL, NULL, "olpc,xo1-rtc");
65 if (!node)
66 return 0;
67 of_node_put(node);
68
69 pr_info("olpc-xo1-rtc: Initializing OLPC XO-1 RTC\n");
70 rdmsrl(MSR_RTC_DOMA_OFFSET, rtc_info.rtc_day_alarm);
71 rdmsrl(MSR_RTC_MONA_OFFSET, rtc_info.rtc_mon_alarm);
72 rdmsrl(MSR_RTC_CEN_OFFSET, rtc_info.rtc_century);
73
74 r = platform_device_register(&xo1_rtc_device);
75 if (r)
76 return r;
77
78 device_init_wakeup(&xo1_rtc_device.dev, 1);
79 return 0;
80}
81arch_initcall(xo1_rtc_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
new file mode 100644
index 000000000000..1d4c783d7325
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -0,0 +1,614 @@
1/*
2 * Support for OLPC XO-1 System Control Interrupts (SCI)
3 *
4 * Copyright (C) 2010 One Laptop per Child
5 * Copyright (C) 2006 Red Hat, Inc.
6 * Copyright (C) 2006 Advanced Micro Devices, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/cs5535.h>
15#include <linux/device.h>
16#include <linux/gpio.h>
17#include <linux/input.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h>
20#include <linux/pm.h>
21#include <linux/mfd/core.h>
22#include <linux/power_supply.h>
23#include <linux/suspend.h>
24#include <linux/workqueue.h>
25
26#include <asm/io.h>
27#include <asm/msr.h>
28#include <asm/olpc.h>
29
30#define DRV_NAME "olpc-xo1-sci"
31#define PFX DRV_NAME ": "
32
33static unsigned long acpi_base;
34static struct input_dev *power_button_idev;
35static struct input_dev *ebook_switch_idev;
36static struct input_dev *lid_switch_idev;
37
38static int sci_irq;
39
40static bool lid_open;
41static bool lid_inverted;
42static int lid_wake_mode;
43
44enum lid_wake_modes {
45 LID_WAKE_ALWAYS,
46 LID_WAKE_OPEN,
47 LID_WAKE_CLOSE,
48};
49
50static const char * const lid_wake_mode_names[] = {
51 [LID_WAKE_ALWAYS] = "always",
52 [LID_WAKE_OPEN] = "open",
53 [LID_WAKE_CLOSE] = "close",
54};
55
56static void battery_status_changed(void)
57{
58 struct power_supply *psy = power_supply_get_by_name("olpc-battery");
59
60 if (psy) {
61 power_supply_changed(psy);
62 put_device(psy->dev);
63 }
64}
65
66static void ac_status_changed(void)
67{
68 struct power_supply *psy = power_supply_get_by_name("olpc-ac");
69
70 if (psy) {
71 power_supply_changed(psy);
72 put_device(psy->dev);
73 }
74}
75
76/* Report current ebook switch state through input layer */
77static void send_ebook_state(void)
78{
79 unsigned char state;
80
81 if (olpc_ec_cmd(EC_READ_EB_MODE, NULL, 0, &state, 1)) {
82 pr_err(PFX "failed to get ebook state\n");
83 return;
84 }
85
86 input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
87 input_sync(ebook_switch_idev);
88}
89
90static void flip_lid_inverter(void)
91{
92 /* gpio is high; invert so we'll get l->h event interrupt */
93 if (lid_inverted)
94 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
95 else
96 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
97 lid_inverted = !lid_inverted;
98}
99
100static void detect_lid_state(void)
101{
102 /*
103 * the edge detector hookup on the gpio inputs on the geode is
104 * odd, to say the least. See http://dev.laptop.org/ticket/5703
105 * for details, but in a nutshell: we don't use the edge
106 * detectors. instead, we make use of an anomoly: with the both
107 * edge detectors turned off, we still get an edge event on a
108 * positive edge transition. to take advantage of this, we use the
109 * front-end inverter to ensure that that's the edge we're always
110 * going to see next.
111 */
112
113 int state;
114
115 state = cs5535_gpio_isset(OLPC_GPIO_LID, GPIO_READ_BACK);
116 lid_open = !state ^ !lid_inverted; /* x ^^ y */
117 if (!state)
118 return;
119
120 flip_lid_inverter();
121}
122
123/* Report current lid switch state through input layer */
124static void send_lid_state(void)
125{
126 input_report_switch(lid_switch_idev, SW_LID, !lid_open);
127 input_sync(lid_switch_idev);
128}
129
130static ssize_t lid_wake_mode_show(struct device *dev,
131 struct device_attribute *attr, char *buf)
132{
133 const char *mode = lid_wake_mode_names[lid_wake_mode];
134 return sprintf(buf, "%s\n", mode);
135}
136static ssize_t lid_wake_mode_set(struct device *dev,
137 struct device_attribute *attr,
138 const char *buf, size_t count)
139{
140 int i;
141 for (i = 0; i < ARRAY_SIZE(lid_wake_mode_names); i++) {
142 const char *mode = lid_wake_mode_names[i];
143 if (strlen(mode) != count || strncasecmp(mode, buf, count))
144 continue;
145
146 lid_wake_mode = i;
147 return count;
148 }
149 return -EINVAL;
150}
151static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show,
152 lid_wake_mode_set);
153
154/*
155 * Process all items in the EC's SCI queue.
156 *
157 * This is handled in a workqueue because olpc_ec_cmd can be slow (and
158 * can even timeout).
159 *
160 * If propagate_events is false, the queue is drained without events being
161 * generated for the interrupts.
162 */
163static void process_sci_queue(bool propagate_events)
164{
165 int r;
166 u16 data;
167
168 do {
169 r = olpc_ec_sci_query(&data);
170 if (r || !data)
171 break;
172
173 pr_debug(PFX "SCI 0x%x received\n", data);
174
175 switch (data) {
176 case EC_SCI_SRC_BATERR:
177 case EC_SCI_SRC_BATSOC:
178 case EC_SCI_SRC_BATTERY:
179 case EC_SCI_SRC_BATCRIT:
180 battery_status_changed();
181 break;
182 case EC_SCI_SRC_ACPWR:
183 ac_status_changed();
184 break;
185 }
186
187 if (data == EC_SCI_SRC_EBOOK && propagate_events)
188 send_ebook_state();
189 } while (data);
190
191 if (r)
192 pr_err(PFX "Failed to clear SCI queue");
193}
194
195static void process_sci_queue_work(struct work_struct *work)
196{
197 process_sci_queue(true);
198}
199
200static DECLARE_WORK(sci_work, process_sci_queue_work);
201
202static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
203{
204 struct platform_device *pdev = dev_id;
205 u32 sts;
206 u32 gpe;
207
208 sts = inl(acpi_base + CS5536_PM1_STS);
209 outl(sts | 0xffff, acpi_base + CS5536_PM1_STS);
210
211 gpe = inl(acpi_base + CS5536_PM_GPE0_STS);
212 outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
213
214 dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);
215
216 if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) {
217 input_report_key(power_button_idev, KEY_POWER, 1);
218 input_sync(power_button_idev);
219 input_report_key(power_button_idev, KEY_POWER, 0);
220 input_sync(power_button_idev);
221 }
222
223 if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
224 cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
225 schedule_work(&sci_work);
226 }
227
228 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
229 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
230 detect_lid_state();
231 send_lid_state();
232
233 return IRQ_HANDLED;
234}
235
236static int xo1_sci_suspend(struct platform_device *pdev, pm_message_t state)
237{
238 if (device_may_wakeup(&power_button_idev->dev))
239 olpc_xo1_pm_wakeup_set(CS5536_PM_PWRBTN);
240 else
241 olpc_xo1_pm_wakeup_clear(CS5536_PM_PWRBTN);
242
243 if (device_may_wakeup(&ebook_switch_idev->dev))
244 olpc_ec_wakeup_set(EC_SCI_SRC_EBOOK);
245 else
246 olpc_ec_wakeup_clear(EC_SCI_SRC_EBOOK);
247
248 if (!device_may_wakeup(&lid_switch_idev->dev)) {
249 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
250 } else if ((lid_open && lid_wake_mode == LID_WAKE_OPEN) ||
251 (!lid_open && lid_wake_mode == LID_WAKE_CLOSE)) {
252 flip_lid_inverter();
253
254 /* we may have just caused an event */
255 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
256 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
257
258 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
259 }
260
261 return 0;
262}
263
264static int xo1_sci_resume(struct platform_device *pdev)
265{
266 /*
267 * We don't know what may have happened while we were asleep.
268 * Reestablish our lid setup so we're sure to catch all transitions.
269 */
270 detect_lid_state();
271 send_lid_state();
272 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
273
274 /* Enable all EC events */
275 olpc_ec_mask_write(EC_SCI_SRC_ALL);
276
277 /* Power/battery status might have changed too */
278 battery_status_changed();
279 ac_status_changed();
280 return 0;
281}
282
283static int __devinit setup_sci_interrupt(struct platform_device *pdev)
284{
285 u32 lo, hi;
286 u32 sts;
287 int r;
288
289 rdmsr(0x51400020, lo, hi);
290 sci_irq = (lo >> 20) & 15;
291
292 if (sci_irq) {
293 dev_info(&pdev->dev, "SCI is mapped to IRQ %d\n", sci_irq);
294 } else {
295 /* Zero means masked */
296 dev_info(&pdev->dev, "SCI unmapped. Mapping to IRQ 3\n");
297 sci_irq = 3;
298 lo |= 0x00300000;
299 wrmsrl(0x51400020, lo);
300 }
301
302 /* Select level triggered in PIC */
303 if (sci_irq < 8) {
304 lo = inb(CS5536_PIC_INT_SEL1);
305 lo |= 1 << sci_irq;
306 outb(lo, CS5536_PIC_INT_SEL1);
307 } else {
308 lo = inb(CS5536_PIC_INT_SEL2);
309 lo |= 1 << (sci_irq - 8);
310 outb(lo, CS5536_PIC_INT_SEL2);
311 }
312
313 /* Enable SCI from power button, and clear pending interrupts */
314 sts = inl(acpi_base + CS5536_PM1_STS);
315 outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS);
316
317 r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev);
318 if (r)
319 dev_err(&pdev->dev, "can't request interrupt\n");
320
321 return r;
322}
323
324static int __devinit setup_ec_sci(void)
325{
326 int r;
327
328 r = gpio_request(OLPC_GPIO_ECSCI, "OLPC-ECSCI");
329 if (r)
330 return r;
331
332 gpio_direction_input(OLPC_GPIO_ECSCI);
333
334 /* Clear pending EC SCI events */
335 cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
336 cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_POSITIVE_EDGE_STS);
337
338 /*
339 * Enable EC SCI events, and map them to both a PME and the SCI
340 * interrupt.
341 *
342 * Ordinarily, in addition to functioning as GPIOs, Geode GPIOs can
343 * be mapped to regular interrupts *or* Geode-specific Power
344 * Management Events (PMEs) - events that bring the system out of
345 * suspend. In this case, we want both of those things - the system
346 * wakeup, *and* the ability to get an interrupt when an event occurs.
347 *
348 * To achieve this, we map the GPIO to a PME, and then we use one
349 * of the many generic knobs on the CS5535 PIC to additionally map the
350 * PME to the regular SCI interrupt line.
351 */
352 cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_EVENTS_ENABLE);
353
354 /* Set the SCI to cause a PME event on group 7 */
355 cs5535_gpio_setup_event(OLPC_GPIO_ECSCI, 7, 1);
356
357 /* And have group 7 also fire the SCI interrupt */
358 cs5535_pic_unreqz_select_high(7, sci_irq);
359
360 return 0;
361}
362
363static void free_ec_sci(void)
364{
365 gpio_free(OLPC_GPIO_ECSCI);
366}
367
368static int __devinit setup_lid_events(void)
369{
370 int r;
371
372 r = gpio_request(OLPC_GPIO_LID, "OLPC-LID");
373 if (r)
374 return r;
375
376 gpio_direction_input(OLPC_GPIO_LID);
377
378 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
379 lid_inverted = 0;
380
381 /* Clear edge detection and event enable for now */
382 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
383 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN);
384 cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN);
385 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
386 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
387
388 /* Set the LID to cause an PME event on group 6 */
389 cs5535_gpio_setup_event(OLPC_GPIO_LID, 6, 1);
390
391 /* Set PME group 6 to fire the SCI interrupt */
392 cs5535_gpio_set_irq(6, sci_irq);
393
394 /* Enable the event */
395 cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
396
397 return 0;
398}
399
400static void free_lid_events(void)
401{
402 gpio_free(OLPC_GPIO_LID);
403}
404
405static int __devinit setup_power_button(struct platform_device *pdev)
406{
407 int r;
408
409 power_button_idev = input_allocate_device();
410 if (!power_button_idev)
411 return -ENOMEM;
412
413 power_button_idev->name = "Power Button";
414 power_button_idev->phys = DRV_NAME "/input0";
415 set_bit(EV_KEY, power_button_idev->evbit);
416 set_bit(KEY_POWER, power_button_idev->keybit);
417
418 power_button_idev->dev.parent = &pdev->dev;
419 device_init_wakeup(&power_button_idev->dev, 1);
420
421 r = input_register_device(power_button_idev);
422 if (r) {
423 dev_err(&pdev->dev, "failed to register power button: %d\n", r);
424 input_free_device(power_button_idev);
425 }
426
427 return r;
428}
429
430static void free_power_button(void)
431{
432 input_unregister_device(power_button_idev);
433 input_free_device(power_button_idev);
434}
435
436static int __devinit setup_ebook_switch(struct platform_device *pdev)
437{
438 int r;
439
440 ebook_switch_idev = input_allocate_device();
441 if (!ebook_switch_idev)
442 return -ENOMEM;
443
444 ebook_switch_idev->name = "EBook Switch";
445 ebook_switch_idev->phys = DRV_NAME "/input1";
446 set_bit(EV_SW, ebook_switch_idev->evbit);
447 set_bit(SW_TABLET_MODE, ebook_switch_idev->swbit);
448
449 ebook_switch_idev->dev.parent = &pdev->dev;
450 device_set_wakeup_capable(&ebook_switch_idev->dev, true);
451
452 r = input_register_device(ebook_switch_idev);
453 if (r) {
454 dev_err(&pdev->dev, "failed to register ebook switch: %d\n", r);
455 input_free_device(ebook_switch_idev);
456 }
457
458 return r;
459}
460
461static void free_ebook_switch(void)
462{
463 input_unregister_device(ebook_switch_idev);
464 input_free_device(ebook_switch_idev);
465}
466
467static int __devinit setup_lid_switch(struct platform_device *pdev)
468{
469 int r;
470
471 lid_switch_idev = input_allocate_device();
472 if (!lid_switch_idev)
473 return -ENOMEM;
474
475 lid_switch_idev->name = "Lid Switch";
476 lid_switch_idev->phys = DRV_NAME "/input2";
477 set_bit(EV_SW, lid_switch_idev->evbit);
478 set_bit(SW_LID, lid_switch_idev->swbit);
479
480 lid_switch_idev->dev.parent = &pdev->dev;
481 device_set_wakeup_capable(&lid_switch_idev->dev, true);
482
483 r = input_register_device(lid_switch_idev);
484 if (r) {
485 dev_err(&pdev->dev, "failed to register lid switch: %d\n", r);
486 goto err_register;
487 }
488
489 r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
490 if (r) {
491 dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r);
492 goto err_create_attr;
493 }
494
495 return 0;
496
497err_create_attr:
498 input_unregister_device(lid_switch_idev);
499err_register:
500 input_free_device(lid_switch_idev);
501 return r;
502}
503
504static void free_lid_switch(void)
505{
506 device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
507 input_unregister_device(lid_switch_idev);
508 input_free_device(lid_switch_idev);
509}
510
511static int __devinit xo1_sci_probe(struct platform_device *pdev)
512{
513 struct resource *res;
514 int r;
515
516 /* don't run on non-XOs */
517 if (!machine_is_olpc())
518 return -ENODEV;
519
520 r = mfd_cell_enable(pdev);
521 if (r)
522 return r;
523
524 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
525 if (!res) {
526 dev_err(&pdev->dev, "can't fetch device resource info\n");
527 return -EIO;
528 }
529 acpi_base = res->start;
530
531 r = setup_power_button(pdev);
532 if (r)
533 return r;
534
535 r = setup_ebook_switch(pdev);
536 if (r)
537 goto err_ebook;
538
539 r = setup_lid_switch(pdev);
540 if (r)
541 goto err_lid;
542
543 r = setup_lid_events();
544 if (r)
545 goto err_lidevt;
546
547 r = setup_ec_sci();
548 if (r)
549 goto err_ecsci;
550
551 /* Enable PME generation for EC-generated events */
552 outl(CS5536_GPIOM6_PME_EN | CS5536_GPIOM7_PME_EN,
553 acpi_base + CS5536_PM_GPE0_EN);
554
555 /* Clear pending events */
556 outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
557 process_sci_queue(false);
558
559 /* Initial sync */
560 send_ebook_state();
561 detect_lid_state();
562 send_lid_state();
563
564 r = setup_sci_interrupt(pdev);
565 if (r)
566 goto err_sci;
567
568 /* Enable all EC events */
569 olpc_ec_mask_write(EC_SCI_SRC_ALL);
570
571 return r;
572
573err_sci:
574 free_ec_sci();
575err_ecsci:
576 free_lid_events();
577err_lidevt:
578 free_lid_switch();
579err_lid:
580 free_ebook_switch();
581err_ebook:
582 free_power_button();
583 return r;
584}
585
586static int __devexit xo1_sci_remove(struct platform_device *pdev)
587{
588 mfd_cell_disable(pdev);
589 free_irq(sci_irq, pdev);
590 cancel_work_sync(&sci_work);
591 free_ec_sci();
592 free_lid_events();
593 free_lid_switch();
594 free_ebook_switch();
595 free_power_button();
596 acpi_base = 0;
597 return 0;
598}
599
600static struct platform_driver xo1_sci_driver = {
601 .driver = {
602 .name = "olpc-xo1-sci-acpi",
603 },
604 .probe = xo1_sci_probe,
605 .remove = __devexit_p(xo1_sci_remove),
606 .suspend = xo1_sci_suspend,
607 .resume = xo1_sci_resume,
608};
609
610static int __init xo1_sci_init(void)
611{
612 return platform_driver_register(&xo1_sci_driver);
613}
614arch_initcall(xo1_sci_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c
deleted file mode 100644
index ab81fb271760..000000000000
--- a/arch/x86/platform/olpc/olpc-xo1.c
+++ /dev/null
@@ -1,146 +0,0 @@
1/*
2 * Support for features of the OLPC XO-1 laptop
3 *
4 * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
5 * Copyright (C) 2010 One Laptop per Child
6 * Copyright (C) 2006 Red Hat, Inc.
7 * Copyright (C) 2006 Advanced Micro Devices, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/pm.h>
18#include <linux/mfd/core.h>
19
20#include <asm/io.h>
21#include <asm/olpc.h>
22
23#define DRV_NAME "olpc-xo1"
24
25/* PMC registers (PMS block) */
26#define PM_SCLK 0x10
27#define PM_IN_SLPCTL 0x20
28#define PM_WKXD 0x34
29#define PM_WKD 0x30
30#define PM_SSC 0x54
31
32/* PM registers (ACPI block) */
33#define PM1_CNT 0x08
34#define PM_GPE0_STS 0x18
35
36static unsigned long acpi_base;
37static unsigned long pms_base;
38
39static void xo1_power_off(void)
40{
41 printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
42
43 /* Enable all of these controls with 0 delay */
44 outl(0x40000000, pms_base + PM_SCLK);
45 outl(0x40000000, pms_base + PM_IN_SLPCTL);
46 outl(0x40000000, pms_base + PM_WKXD);
47 outl(0x40000000, pms_base + PM_WKD);
48
49 /* Clear status bits (possibly unnecessary) */
50 outl(0x0002ffff, pms_base + PM_SSC);
51 outl(0xffffffff, acpi_base + PM_GPE0_STS);
52
53 /* Write SLP_EN bit to start the machinery */
54 outl(0x00002000, acpi_base + PM1_CNT);
55}
56
57static int __devinit olpc_xo1_probe(struct platform_device *pdev)
58{
59 struct resource *res;
60 int err;
61
62 /* don't run on non-XOs */
63 if (!machine_is_olpc())
64 return -ENODEV;
65
66 err = mfd_cell_enable(pdev);
67 if (err)
68 return err;
69
70 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
71 if (!res) {
72 dev_err(&pdev->dev, "can't fetch device resource info\n");
73 return -EIO;
74 }
75 if (strcmp(pdev->name, "cs5535-pms") == 0)
76 pms_base = res->start;
77 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
78 acpi_base = res->start;
79
80 /* If we have both addresses, we can override the poweroff hook */
81 if (pms_base && acpi_base) {
82 pm_power_off = xo1_power_off;
83 printk(KERN_INFO "OLPC XO-1 support registered\n");
84 }
85
86 return 0;
87}
88
89static int __devexit olpc_xo1_remove(struct platform_device *pdev)
90{
91 mfd_cell_disable(pdev);
92
93 if (strcmp(pdev->name, "cs5535-pms") == 0)
94 pms_base = 0;
95 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
96 acpi_base = 0;
97
98 pm_power_off = NULL;
99 return 0;
100}
101
102static struct platform_driver cs5535_pms_drv = {
103 .driver = {
104 .name = "cs5535-pms",
105 .owner = THIS_MODULE,
106 },
107 .probe = olpc_xo1_probe,
108 .remove = __devexit_p(olpc_xo1_remove),
109};
110
111static struct platform_driver cs5535_acpi_drv = {
112 .driver = {
113 .name = "olpc-xo1-pm-acpi",
114 .owner = THIS_MODULE,
115 },
116 .probe = olpc_xo1_probe,
117 .remove = __devexit_p(olpc_xo1_remove),
118};
119
120static int __init olpc_xo1_init(void)
121{
122 int r;
123
124 r = platform_driver_register(&cs5535_pms_drv);
125 if (r)
126 return r;
127
128 r = platform_driver_register(&cs5535_acpi_drv);
129 if (r)
130 platform_driver_unregister(&cs5535_pms_drv);
131
132 return r;
133}
134
135static void __exit olpc_xo1_exit(void)
136{
137 platform_driver_unregister(&cs5535_acpi_drv);
138 platform_driver_unregister(&cs5535_pms_drv);
139}
140
141MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
142MODULE_LICENSE("GPL");
143MODULE_ALIAS("platform:cs5535-pms");
144
145module_init(olpc_xo1_init);
146module_exit(olpc_xo1_exit);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
new file mode 100644
index 000000000000..2b235b77d9ab
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -0,0 +1,168 @@
1/*
2 * Support for OLPC XO-1.5 System Control Interrupts (SCI)
3 *
4 * Copyright (C) 2009-2010 One Laptop per Child
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/device.h>
13#include <linux/slab.h>
14#include <linux/workqueue.h>
15#include <linux/power_supply.h>
16
17#include <acpi/acpi_bus.h>
18#include <acpi/acpi_drivers.h>
19#include <asm/olpc.h>
20
21#define DRV_NAME "olpc-xo15-sci"
22#define PFX DRV_NAME ": "
23#define XO15_SCI_CLASS DRV_NAME
24#define XO15_SCI_DEVICE_NAME "OLPC XO-1.5 SCI"
25
26static unsigned long xo15_sci_gpe;
27
28static void battery_status_changed(void)
29{
30 struct power_supply *psy = power_supply_get_by_name("olpc-battery");
31
32 if (psy) {
33 power_supply_changed(psy);
34 put_device(psy->dev);
35 }
36}
37
38static void ac_status_changed(void)
39{
40 struct power_supply *psy = power_supply_get_by_name("olpc-ac");
41
42 if (psy) {
43 power_supply_changed(psy);
44 put_device(psy->dev);
45 }
46}
47
48static void process_sci_queue(void)
49{
50 u16 data;
51 int r;
52
53 do {
54 r = olpc_ec_sci_query(&data);
55 if (r || !data)
56 break;
57
58 pr_debug(PFX "SCI 0x%x received\n", data);
59
60 switch (data) {
61 case EC_SCI_SRC_BATERR:
62 case EC_SCI_SRC_BATSOC:
63 case EC_SCI_SRC_BATTERY:
64 case EC_SCI_SRC_BATCRIT:
65 battery_status_changed();
66 break;
67 case EC_SCI_SRC_ACPWR:
68 ac_status_changed();
69 break;
70 }
71 } while (data);
72
73 if (r)
74 pr_err(PFX "Failed to clear SCI queue");
75}
76
77static void process_sci_queue_work(struct work_struct *work)
78{
79 process_sci_queue();
80}
81
82static DECLARE_WORK(sci_work, process_sci_queue_work);
83
84static u32 xo15_sci_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
85{
86 schedule_work(&sci_work);
87 return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
88}
89
90static int xo15_sci_add(struct acpi_device *device)
91{
92 unsigned long long tmp;
93 acpi_status status;
94
95 if (!device)
96 return -EINVAL;
97
98 strcpy(acpi_device_name(device), XO15_SCI_DEVICE_NAME);
99 strcpy(acpi_device_class(device), XO15_SCI_CLASS);
100
101 /* Get GPE bit assignment (EC events). */
102 status = acpi_evaluate_integer(device->handle, "_GPE", NULL, &tmp);
103 if (ACPI_FAILURE(status))
104 return -EINVAL;
105
106 xo15_sci_gpe = tmp;
107 status = acpi_install_gpe_handler(NULL, xo15_sci_gpe,
108 ACPI_GPE_EDGE_TRIGGERED,
109 xo15_sci_gpe_handler, device);
110 if (ACPI_FAILURE(status))
111 return -ENODEV;
112
113 dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe);
114
115 /* Flush queue, and enable all SCI events */
116 process_sci_queue();
117 olpc_ec_mask_write(EC_SCI_SRC_ALL);
118
119 acpi_enable_gpe(NULL, xo15_sci_gpe);
120
121 /* Enable wake-on-EC */
122 if (device->wakeup.flags.valid)
123 device_init_wakeup(&device->dev, true);
124
125 return 0;
126}
127
128static int xo15_sci_remove(struct acpi_device *device, int type)
129{
130 acpi_disable_gpe(NULL, xo15_sci_gpe);
131 acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
132 cancel_work_sync(&sci_work);
133 return 0;
134}
135
136static int xo15_sci_resume(struct acpi_device *device)
137{
138 /* Enable all EC events */
139 olpc_ec_mask_write(EC_SCI_SRC_ALL);
140
141 /* Power/battery status might have changed */
142 battery_status_changed();
143 ac_status_changed();
144
145 return 0;
146}
147
148static const struct acpi_device_id xo15_sci_device_ids[] = {
149 {"XO15EC", 0},
150 {"", 0},
151};
152
153static struct acpi_driver xo15_sci_drv = {
154 .name = DRV_NAME,
155 .class = XO15_SCI_CLASS,
156 .ids = xo15_sci_device_ids,
157 .ops = {
158 .add = xo15_sci_add,
159 .remove = xo15_sci_remove,
160 .resume = xo15_sci_resume,
161 },
162};
163
164static int __init xo15_sci_init(void)
165{
166 return acpi_bus_register_driver(&xo15_sci_drv);
167}
168device_initcall(xo15_sci_init);
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 0060fd59ea00..7cce722667b8 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -19,6 +19,7 @@
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/syscore_ops.h>
22 23
23#include <asm/geode.h> 24#include <asm/geode.h>
24#include <asm/setup.h> 25#include <asm/setup.h>
@@ -30,6 +31,9 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
30 31
31static DEFINE_SPINLOCK(ec_lock); 32static DEFINE_SPINLOCK(ec_lock);
32 33
34/* EC event mask to be applied during suspend (defining wakeup sources). */
35static u16 ec_wakeup_mask;
36
33/* what the timeout *should* be (in ms) */ 37/* what the timeout *should* be (in ms) */
34#define EC_BASE_TIMEOUT 20 38#define EC_BASE_TIMEOUT 20
35 39
@@ -157,13 +161,13 @@ restart:
157 if (inbuf && inlen) { 161 if (inbuf && inlen) {
158 /* write data to EC */ 162 /* write data to EC */
159 for (i = 0; i < inlen; i++) { 163 for (i = 0; i < inlen; i++) {
164 pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]);
165 outb(inbuf[i], 0x68);
160 if (wait_on_ibf(0x6c, 0)) { 166 if (wait_on_ibf(0x6c, 0)) {
161 printk(KERN_ERR "olpc-ec: timeout waiting for" 167 printk(KERN_ERR "olpc-ec: timeout waiting for"
162 " EC accept data!\n"); 168 " EC accept data!\n");
163 goto err; 169 goto err;
164 } 170 }
165 pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]);
166 outb(inbuf[i], 0x68);
167 } 171 }
168 } 172 }
169 if (outbuf && outlen) { 173 if (outbuf && outlen) {
@@ -188,6 +192,88 @@ err:
188} 192}
189EXPORT_SYMBOL_GPL(olpc_ec_cmd); 193EXPORT_SYMBOL_GPL(olpc_ec_cmd);
190 194
195void olpc_ec_wakeup_set(u16 value)
196{
197 ec_wakeup_mask |= value;
198}
199EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
200
201void olpc_ec_wakeup_clear(u16 value)
202{
203 ec_wakeup_mask &= ~value;
204}
205EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
206
207/*
208 * Returns true if the compile and runtime configurations allow for EC events
209 * to wake the system.
210 */
211bool olpc_ec_wakeup_available(void)
212{
213 if (!machine_is_olpc())
214 return false;
215
216 /*
217 * XO-1 EC wakeups are available when olpc-xo1-sci driver is
218 * compiled in
219 */
220#ifdef CONFIG_OLPC_XO1_SCI
221 if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
222 return true;
223#endif
224
225 /*
226 * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
227 * compiled in
228 */
229#ifdef CONFIG_OLPC_XO15_SCI
230 if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */
231 return true;
232#endif
233
234 return false;
235}
236EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
237
238int olpc_ec_mask_write(u16 bits)
239{
240 if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
241 __be16 ec_word = cpu_to_be16(bits);
242 return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
243 NULL, 0);
244 } else {
245 unsigned char ec_byte = bits & 0xff;
246 return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
247 }
248}
249EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
250
251int olpc_ec_sci_query(u16 *sci_value)
252{
253 int ret;
254
255 if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
256 __be16 ec_word;
257 ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
258 NULL, 0, (void *) &ec_word, 2);
259 if (ret == 0)
260 *sci_value = be16_to_cpu(ec_word);
261 } else {
262 unsigned char ec_byte;
263 ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
264 if (ret == 0)
265 *sci_value = ec_byte;
266 }
267
268 return ret;
269}
270EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
271
272static int olpc_ec_suspend(void)
273{
274 return olpc_ec_mask_write(ec_wakeup_mask);
275}
276
191static bool __init check_ofw_architecture(struct device_node *root) 277static bool __init check_ofw_architecture(struct device_node *root)
192{ 278{
193 const char *olpc_arch; 279 const char *olpc_arch;
@@ -242,6 +328,10 @@ static int __init add_xo1_platform_devices(void)
242 return 0; 328 return 0;
243} 329}
244 330
331static struct syscore_ops olpc_syscore_ops = {
332 .suspend = olpc_ec_suspend,
333};
334
245static int __init olpc_init(void) 335static int __init olpc_init(void)
246{ 336{
247 int r = 0; 337 int r = 0;
@@ -266,6 +356,9 @@ static int __init olpc_init(void)
266 !cs5535_has_vsa2()) 356 !cs5535_has_vsa2())
267 x86_init.pci.arch_init = pci_olpc_init; 357 x86_init.pci.arch_init = pci_olpc_init;
268#endif 358#endif
359 /* EC version 0x5f adds support for wide SCI mask */
360 if (olpc_platform_info.ecver >= 0x5f)
361 olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
269 362
270 printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", 363 printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
271 ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", 364 ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
@@ -278,6 +371,8 @@ static int __init olpc_init(void)
278 return r; 371 return r;
279 } 372 }
280 373
374 register_syscore_ops(&olpc_syscore_ops);
375
281 return 0; 376 return 0;
282} 377}
283 378
diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c
index d39f63d017d2..d6ee92986920 100644
--- a/arch/x86/platform/olpc/olpc_dt.c
+++ b/arch/x86/platform/olpc/olpc_dt.c
@@ -165,6 +165,107 @@ static struct of_pdt_ops prom_olpc_ops __initdata = {
165 .pkg2path = olpc_dt_pkg2path, 165 .pkg2path = olpc_dt_pkg2path,
166}; 166};
167 167
168static phandle __init olpc_dt_finddevice(const char *path)
169{
170 phandle node;
171 const void *args[] = { path };
172 void *res[] = { &node };
173
174 if (olpc_ofw("finddevice", args, res)) {
175 pr_err("olpc_dt: finddevice failed!\n");
176 return 0;
177 }
178
179 if ((s32) node == -1)
180 return 0;
181
182 return node;
183}
184
185static int __init olpc_dt_interpret(const char *words)
186{
187 int result;
188 const void *args[] = { words };
189 void *res[] = { &result };
190
191 if (olpc_ofw("interpret", args, res)) {
192 pr_err("olpc_dt: interpret failed!\n");
193 return -1;
194 }
195
196 return result;
197}
198
199/*
200 * Extract board revision directly from OFW device tree.
201 * We can't use olpc_platform_info because that hasn't been set up yet.
202 */
203static u32 __init olpc_dt_get_board_revision(void)
204{
205 phandle node;
206 __be32 rev;
207 int r;
208
209 node = olpc_dt_finddevice("/");
210 if (!node)
211 return 0;
212
213 r = olpc_dt_getproperty(node, "board-revision-int",
214 (char *) &rev, sizeof(rev));
215 if (r < 0)
216 return 0;
217
218 return be32_to_cpu(rev);
219}
220
221void __init olpc_dt_fixup(void)
222{
223 int r;
224 char buf[64];
225 phandle node;
226 u32 board_rev;
227
228 node = olpc_dt_finddevice("/battery@0");
229 if (!node)
230 return;
231
232 /*
233 * If the battery node has a compatible property, we are running a new
234 * enough firmware and don't have fixups to make.
235 */
236 r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
237 if (r > 0)
238 return;
239
240 pr_info("PROM DT: Old firmware detected, applying fixes\n");
241
242 /* Add olpc,xo1-battery compatible marker to battery node */
243 olpc_dt_interpret("\" /battery@0\" find-device"
244 " \" olpc,xo1-battery\" +compatible"
245 " device-end");
246
247 board_rev = olpc_dt_get_board_revision();
248 if (!board_rev)
249 return;
250
251 if (board_rev >= olpc_board_pre(0xd0)) {
252 /* XO-1.5: add dcon device */
253 olpc_dt_interpret("\" /pci/display@1\" find-device"
254 " new-device"
255 " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
256 " finish-device device-end");
257 } else {
258 /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
259 olpc_dt_interpret("\" /pci/display@1,1\" find-device"
260 " new-device"
261 " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
262 " finish-device device-end"
263 " \" /rtc\" find-device"
264 " \" olpc,xo1-rtc\" +compatible"
265 " device-end");
266 }
267}
268
168void __init olpc_dt_build_devicetree(void) 269void __init olpc_dt_build_devicetree(void)
169{ 270{
170 phandle root; 271 phandle root;
@@ -172,6 +273,8 @@ void __init olpc_dt_build_devicetree(void)
172 if (!olpc_ofw_is_installed()) 273 if (!olpc_ofw_is_installed())
173 return; 274 return;
174 275
276 olpc_dt_fixup();
277
175 root = olpc_dt_getsibling(0); 278 root = olpc_dt_getsibling(0);
176 if (!root) { 279 if (!root) {
177 pr_err("PROM: unable to get root node from OFW!\n"); 280 pr_err("PROM: unable to get root node from OFW!\n");
diff --git a/arch/x86/platform/olpc/xo1-wakeup.S b/arch/x86/platform/olpc/xo1-wakeup.S
new file mode 100644
index 000000000000..948deb289753
--- /dev/null
+++ b/arch/x86/platform/olpc/xo1-wakeup.S
@@ -0,0 +1,124 @@
1.text
2#include <linux/linkage.h>
3#include <asm/segment.h>
4#include <asm/page.h>
5#include <asm/pgtable_32.h>
6
7 .macro writepost,value
8 movb $0x34, %al
9 outb %al, $0x70
10 movb $\value, %al
11 outb %al, $0x71
12 .endm
13
14wakeup_start:
15 # OFW lands us here, running in protected mode, with a
16 # kernel-compatible GDT already setup.
17
18 # Clear any dangerous flags
19 pushl $0
20 popfl
21
22 writepost 0x31
23
24 # Set up %cr3
25 movl $initial_page_table - __PAGE_OFFSET, %eax
26 movl %eax, %cr3
27
28 movl saved_cr4, %eax
29 movl %eax, %cr4
30
31 movl saved_cr0, %eax
32 movl %eax, %cr0
33
34 # Control registers were modified, pipeline resync is needed
35 jmp 1f
361:
37
38 movw $__KERNEL_DS, %ax
39 movw %ax, %ss
40 movw %ax, %ds
41 movw %ax, %es
42 movw %ax, %fs
43 movw %ax, %gs
44
45 lgdt saved_gdt
46 lidt saved_idt
47 lldt saved_ldt
48 ljmp $(__KERNEL_CS),$1f
491:
50 movl %cr3, %eax
51 movl %eax, %cr3
52 wbinvd
53
54 # Go back to the return point
55 jmp ret_point
56
57save_registers:
58 sgdt saved_gdt
59 sidt saved_idt
60 sldt saved_ldt
61
62 pushl %edx
63 movl %cr4, %edx
64 movl %edx, saved_cr4
65
66 movl %cr0, %edx
67 movl %edx, saved_cr0
68
69 popl %edx
70
71 movl %ebx, saved_context_ebx
72 movl %ebp, saved_context_ebp
73 movl %esi, saved_context_esi
74 movl %edi, saved_context_edi
75
76 pushfl
77 popl saved_context_eflags
78
79 ret
80
81restore_registers:
82 movl saved_context_ebp, %ebp
83 movl saved_context_ebx, %ebx
84 movl saved_context_esi, %esi
85 movl saved_context_edi, %edi
86
87 pushl saved_context_eflags
88 popfl
89
90 ret
91
92ENTRY(do_olpc_suspend_lowlevel)
93 call save_processor_state
94 call save_registers
95
96 # This is the stack context we want to remember
97 movl %esp, saved_context_esp
98
99 pushl $3
100 call xo1_do_sleep
101
102 jmp wakeup_start
103 .p2align 4,,7
104ret_point:
105 movl saved_context_esp, %esp
106
107 writepost 0x32
108
109 call restore_registers
110 call restore_processor_state
111 ret
112
113.data
114saved_gdt: .long 0,0
115saved_idt: .long 0,0
116saved_ldt: .long 0
117saved_cr4: .long 0
118saved_cr0: .long 0
119saved_context_esp: .long 0
120saved_context_edi: .long 0
121saved_context_esi: .long 0
122saved_context_ebx: .long 0
123saved_context_ebp: .long 0
124saved_context_eflags: .long 0
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 8bc57baaa9ad..766612137a62 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <linux/efi.h> 22#include <linux/efi.h>
23#include <linux/export.h>
23#include <asm/efi.h> 24#include <asm/efi.h>
24#include <linux/io.h> 25#include <linux/io.h>
25#include <asm/uv/bios.h> 26#include <asm/uv/bios.h>
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 68e467f69fec..5b552198f774 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
115 115
116/* base pnode in this partition */ 116/* base pnode in this partition */
117static int uv_base_pnode __read_mostly; 117static int uv_base_pnode __read_mostly;
118/* position of pnode (which is nasid>>1): */
119static int uv_nshift __read_mostly;
120static unsigned long uv_mmask __read_mostly;
121 118
122static DEFINE_PER_CPU(struct ptc_stats, ptcstats); 119static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
123static DEFINE_PER_CPU(struct bau_control, bau_control); 120static DEFINE_PER_CPU(struct bau_control, bau_control);
@@ -296,14 +293,18 @@ static void bau_process_message(struct msg_desc *mdp,
296} 293}
297 294
298/* 295/*
299 * Determine the first cpu on a uvhub. 296 * Determine the first cpu on a pnode.
300 */ 297 */
301static int uvhub_to_first_cpu(int uvhub) 298static int pnode_to_first_cpu(int pnode, struct bau_control *smaster)
302{ 299{
303 int cpu; 300 int cpu;
304 for_each_present_cpu(cpu) 301 struct hub_and_pnode *hpp;
305 if (uvhub == uv_cpu_to_blade_id(cpu)) 302
303 for_each_present_cpu(cpu) {
304 hpp = &smaster->thp[cpu];
305 if (pnode == hpp->pnode)
306 return cpu; 306 return cpu;
307 }
307 return -1; 308 return -1;
308} 309}
309 310
@@ -366,28 +367,32 @@ static void do_reset(void *ptr)
366 * Use IPI to get all target uvhubs to release resources held by 367 * Use IPI to get all target uvhubs to release resources held by
367 * a given sending cpu number. 368 * a given sending cpu number.
368 */ 369 */
369static void reset_with_ipi(struct bau_targ_hubmask *distribution, int sender) 370static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
370{ 371{
371 int uvhub; 372 int pnode;
373 int apnode;
372 int maskbits; 374 int maskbits;
373 cpumask_t mask; 375 int sender = bcp->cpu;
376 cpumask_t *mask = bcp->uvhub_master->cpumask;
377 struct bau_control *smaster = bcp->socket_master;
374 struct reset_args reset_args; 378 struct reset_args reset_args;
375 379
376 reset_args.sender = sender; 380 reset_args.sender = sender;
377 cpus_clear(mask); 381 cpus_clear(*mask);
378 /* find a single cpu for each uvhub in this distribution mask */ 382 /* find a single cpu for each uvhub in this distribution mask */
379 maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE; 383 maskbits = sizeof(struct pnmask) * BITSPERBYTE;
380 for (uvhub = 0; uvhub < maskbits; uvhub++) { 384 /* each bit is a pnode relative to the partition base pnode */
385 for (pnode = 0; pnode < maskbits; pnode++) {
381 int cpu; 386 int cpu;
382 if (!bau_uvhub_isset(uvhub, distribution)) 387 if (!bau_uvhub_isset(pnode, distribution))
383 continue; 388 continue;
384 /* find a cpu for this uvhub */ 389 apnode = pnode + bcp->partition_base_pnode;
385 cpu = uvhub_to_first_cpu(uvhub); 390 cpu = pnode_to_first_cpu(apnode, smaster);
386 cpu_set(cpu, mask); 391 cpu_set(cpu, *mask);
387 } 392 }
388 393
389 /* IPI all cpus; preemption is already disabled */ 394 /* IPI all cpus; preemption is already disabled */
390 smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1); 395 smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
391 return; 396 return;
392} 397}
393 398
@@ -604,7 +609,7 @@ static void destination_plugged(struct bau_desc *bau_desc,
604 quiesce_local_uvhub(hmaster); 609 quiesce_local_uvhub(hmaster);
605 610
606 spin_lock(&hmaster->queue_lock); 611 spin_lock(&hmaster->queue_lock);
607 reset_with_ipi(&bau_desc->distribution, bcp->cpu); 612 reset_with_ipi(&bau_desc->distribution, bcp);
608 spin_unlock(&hmaster->queue_lock); 613 spin_unlock(&hmaster->queue_lock);
609 614
610 end_uvhub_quiesce(hmaster); 615 end_uvhub_quiesce(hmaster);
@@ -626,7 +631,7 @@ static void destination_timeout(struct bau_desc *bau_desc,
626 quiesce_local_uvhub(hmaster); 631 quiesce_local_uvhub(hmaster);
627 632
628 spin_lock(&hmaster->queue_lock); 633 spin_lock(&hmaster->queue_lock);
629 reset_with_ipi(&bau_desc->distribution, bcp->cpu); 634 reset_with_ipi(&bau_desc->distribution, bcp);
630 spin_unlock(&hmaster->queue_lock); 635 spin_unlock(&hmaster->queue_lock);
631 636
632 end_uvhub_quiesce(hmaster); 637 end_uvhub_quiesce(hmaster);
@@ -1334,9 +1339,10 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
1334 1339
1335 instr[count] = '\0'; 1340 instr[count] = '\0';
1336 1341
1337 bcp = &per_cpu(bau_control, smp_processor_id()); 1342 cpu = get_cpu();
1338 1343 bcp = &per_cpu(bau_control, cpu);
1339 ret = parse_tunables_write(bcp, instr, count); 1344 ret = parse_tunables_write(bcp, instr, count);
1345 put_cpu();
1340 if (ret) 1346 if (ret)
1341 return ret; 1347 return ret;
1342 1348
@@ -1426,7 +1432,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
1426{ 1432{
1427 int i; 1433 int i;
1428 int cpu; 1434 int cpu;
1429 unsigned long pa; 1435 unsigned long gpa;
1430 unsigned long m; 1436 unsigned long m;
1431 unsigned long n; 1437 unsigned long n;
1432 size_t dsize; 1438 size_t dsize;
@@ -1442,9 +1448,9 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
1442 bau_desc = kmalloc_node(dsize, GFP_KERNEL, node); 1448 bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
1443 BUG_ON(!bau_desc); 1449 BUG_ON(!bau_desc);
1444 1450
1445 pa = uv_gpa(bau_desc); /* need the real nasid*/ 1451 gpa = uv_gpa(bau_desc);
1446 n = pa >> uv_nshift; 1452 n = uv_gpa_to_gnode(gpa);
1447 m = pa & uv_mmask; 1453 m = uv_gpa_to_offset(gpa);
1448 1454
1449 /* the 14-bit pnode */ 1455 /* the 14-bit pnode */
1450 write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m)); 1456 write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
@@ -1516,9 +1522,9 @@ static void pq_init(int node, int pnode)
1516 bcp->queue_last = pqp + (DEST_Q_SIZE - 1); 1522 bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
1517 } 1523 }
1518 /* 1524 /*
1519 * need the pnode of where the memory was really allocated 1525 * need the gnode of where the memory was really allocated
1520 */ 1526 */
1521 pn = uv_gpa(pqp) >> uv_nshift; 1527 pn = uv_gpa_to_gnode(uv_gpa(pqp));
1522 first = uv_physnodeaddr(pqp); 1528 first = uv_physnodeaddr(pqp);
1523 pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first; 1529 pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
1524 last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1)); 1530 last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
@@ -1687,6 +1693,16 @@ static void make_per_cpu_thp(struct bau_control *smaster)
1687} 1693}
1688 1694
1689/* 1695/*
1696 * Each uvhub is to get a local cpumask.
1697 */
1698static void make_per_hub_cpumask(struct bau_control *hmaster)
1699{
1700 int sz = sizeof(cpumask_t);
1701
1702 hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
1703}
1704
1705/*
1690 * Initialize all the per_cpu information for the cpu's on a given socket, 1706 * Initialize all the per_cpu information for the cpu's on a given socket,
1691 * given what has been gathered into the socket_desc struct. 1707 * given what has been gathered into the socket_desc struct.
1692 * And reports the chosen hub and socket masters back to the caller. 1708 * And reports the chosen hub and socket masters back to the caller.
@@ -1751,11 +1767,12 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
1751 sdp = &bdp->socket[socket]; 1767 sdp = &bdp->socket[socket];
1752 if (scan_sock(sdp, bdp, &smaster, &hmaster)) 1768 if (scan_sock(sdp, bdp, &smaster, &hmaster))
1753 return 1; 1769 return 1;
1770 make_per_cpu_thp(smaster);
1754 } 1771 }
1755 socket++; 1772 socket++;
1756 socket_mask = (socket_mask >> 1); 1773 socket_mask = (socket_mask >> 1);
1757 make_per_cpu_thp(smaster);
1758 } 1774 }
1775 make_per_hub_cpumask(hmaster);
1759 } 1776 }
1760 return 0; 1777 return 0;
1761} 1778}
@@ -1777,15 +1794,20 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
1777 uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL); 1794 uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
1778 1795
1779 if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask)) 1796 if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
1780 return 1; 1797 goto fail;
1781 1798
1782 if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask)) 1799 if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask))
1783 return 1; 1800 goto fail;
1784 1801
1785 kfree(uvhub_descs); 1802 kfree(uvhub_descs);
1786 kfree(uvhub_mask); 1803 kfree(uvhub_mask);
1787 init_per_cpu_tunables(); 1804 init_per_cpu_tunables();
1788 return 0; 1805 return 0;
1806
1807fail:
1808 kfree(uvhub_descs);
1809 kfree(uvhub_mask);
1810 return 1;
1789} 1811}
1790 1812
1791/* 1813/*
@@ -1812,8 +1834,6 @@ static int __init uv_bau_init(void)
1812 zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu)); 1834 zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
1813 } 1835 }
1814 1836
1815 uv_nshift = uv_hub_info->m_val;
1816 uv_mmask = (1UL << uv_hub_info->m_val) - 1;
1817 nuvhubs = uv_num_possible_blades(); 1837 nuvhubs = uv_num_possible_blades();
1818 spin_lock_init(&disable_lock); 1838 spin_lock_init(&disable_lock);
1819 congested_cycles = usec_2_cycles(congested_respns_us); 1839 congested_cycles = usec_2_cycles(congested_respns_us);