aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/platform')
-rw-r--r--arch/x86/platform/efi/efi.c90
-rw-r--r--arch/x86/platform/mrst/Makefile1
-rw-r--r--arch/x86/platform/mrst/mrst.c24
-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.c9
-rw-r--r--arch/x86/platform/olpc/Makefile5
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-pm.c215
-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/tlb_uv.c86
16 files changed, 2616 insertions, 200 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 899e393d8e7..3ae4128013e 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -51,7 +51,17 @@
51int efi_enabled; 51int efi_enabled;
52EXPORT_SYMBOL(efi_enabled); 52EXPORT_SYMBOL(efi_enabled);
53 53
54struct efi efi; 54struct efi __read_mostly efi = {
55 .mps = EFI_INVALID_TABLE_ADDR,
56 .acpi = EFI_INVALID_TABLE_ADDR,
57 .acpi20 = EFI_INVALID_TABLE_ADDR,
58 .smbios = EFI_INVALID_TABLE_ADDR,
59 .sal_systab = EFI_INVALID_TABLE_ADDR,
60 .boot_info = EFI_INVALID_TABLE_ADDR,
61 .hcdp = EFI_INVALID_TABLE_ADDR,
62 .uga = EFI_INVALID_TABLE_ADDR,
63 .uv_systab = EFI_INVALID_TABLE_ADDR,
64};
55EXPORT_SYMBOL(efi); 65EXPORT_SYMBOL(efi);
56 66
57struct efi_memory_map memmap; 67struct efi_memory_map memmap;
@@ -79,26 +89,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
79 89
80static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) 90static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
81{ 91{
82 return efi_call_virt2(get_time, tm, tc); 92 unsigned long flags;
93 efi_status_t status;
94
95 spin_lock_irqsave(&rtc_lock, flags);
96 status = efi_call_virt2(get_time, tm, tc);
97 spin_unlock_irqrestore(&rtc_lock, flags);
98 return status;
83} 99}
84 100
85static efi_status_t virt_efi_set_time(efi_time_t *tm) 101static efi_status_t virt_efi_set_time(efi_time_t *tm)
86{ 102{
87 return efi_call_virt1(set_time, tm); 103 unsigned long flags;
104 efi_status_t status;
105
106 spin_lock_irqsave(&rtc_lock, flags);
107 status = efi_call_virt1(set_time, tm);
108 spin_unlock_irqrestore(&rtc_lock, flags);
109 return status;
88} 110}
89 111
90static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, 112static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
91 efi_bool_t *pending, 113 efi_bool_t *pending,
92 efi_time_t *tm) 114 efi_time_t *tm)
93{ 115{
94 return efi_call_virt3(get_wakeup_time, 116 unsigned long flags;
95 enabled, pending, tm); 117 efi_status_t status;
118
119 spin_lock_irqsave(&rtc_lock, flags);
120 status = efi_call_virt3(get_wakeup_time,
121 enabled, pending, tm);
122 spin_unlock_irqrestore(&rtc_lock, flags);
123 return status;
96} 124}
97 125
98static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) 126static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
99{ 127{
100 return efi_call_virt2(set_wakeup_time, 128 unsigned long flags;
101 enabled, tm); 129 efi_status_t status;
130
131 spin_lock_irqsave(&rtc_lock, flags);
132 status = efi_call_virt2(set_wakeup_time,
133 enabled, tm);
134 spin_unlock_irqrestore(&rtc_lock, flags);
135 return status;
102} 136}
103 137
104static efi_status_t virt_efi_get_variable(efi_char16_t *name, 138static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -122,7 +156,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
122 156
123static efi_status_t virt_efi_set_variable(efi_char16_t *name, 157static efi_status_t virt_efi_set_variable(efi_char16_t *name,
124 efi_guid_t *vendor, 158 efi_guid_t *vendor,
125 unsigned long attr, 159 u32 attr,
126 unsigned long data_size, 160 unsigned long data_size,
127 void *data) 161 void *data)
128{ 162{
@@ -131,6 +165,18 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
131 data_size, data); 165 data_size, data);
132} 166}
133 167
168static efi_status_t virt_efi_query_variable_info(u32 attr,
169 u64 *storage_space,
170 u64 *remaining_space,
171 u64 *max_variable_size)
172{
173 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
174 return EFI_UNSUPPORTED;
175
176 return efi_call_virt4(query_variable_info, attr, storage_space,
177 remaining_space, max_variable_size);
178}
179
134static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) 180static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
135{ 181{
136 return efi_call_virt1(get_next_high_mono_count, count); 182 return efi_call_virt1(get_next_high_mono_count, count);
@@ -145,6 +191,28 @@ static void virt_efi_reset_system(int reset_type,
145 data_size, data); 191 data_size, data);
146} 192}
147 193
194static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
195 unsigned long count,
196 unsigned long sg_list)
197{
198 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
199 return EFI_UNSUPPORTED;
200
201 return efi_call_virt3(update_capsule, capsules, count, sg_list);
202}
203
204static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
205 unsigned long count,
206 u64 *max_size,
207 int *reset_type)
208{
209 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
210 return EFI_UNSUPPORTED;
211
212 return efi_call_virt4(query_capsule_caps, capsules, count, max_size,
213 reset_type);
214}
215
148static efi_status_t __init phys_efi_set_virtual_address_map( 216static efi_status_t __init phys_efi_set_virtual_address_map(
149 unsigned long memory_map_size, 217 unsigned long memory_map_size,
150 unsigned long descriptor_size, 218 unsigned long descriptor_size,
@@ -164,11 +232,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, 232static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
165 efi_time_cap_t *tc) 233 efi_time_cap_t *tc)
166{ 234{
235 unsigned long flags;
167 efi_status_t status; 236 efi_status_t status;
168 237
238 spin_lock_irqsave(&rtc_lock, flags);
169 efi_call_phys_prelog(); 239 efi_call_phys_prelog();
170 status = efi_call_phys2(efi_phys.get_time, tm, tc); 240 status = efi_call_phys2(efi_phys.get_time, tm, tc);
171 efi_call_phys_epilog(); 241 efi_call_phys_epilog();
242 spin_unlock_irqrestore(&rtc_lock, flags);
172 return status; 243 return status;
173} 244}
174 245
@@ -669,6 +740,9 @@ void __init efi_enter_virtual_mode(void)
669 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; 740 efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
670 efi.reset_system = virt_efi_reset_system; 741 efi.reset_system = virt_efi_reset_system;
671 efi.set_virtual_address_map = NULL; 742 efi.set_virtual_address_map = NULL;
743 efi.query_variable_info = virt_efi_query_variable_info;
744 efi.update_capsule = virt_efi_update_capsule;
745 efi.query_capsule_caps = virt_efi_query_capsule_caps;
672 if (__supported_pte_mask & _PAGE_NX) 746 if (__supported_pte_mask & _PAGE_NX)
673 runtime_code_page_mkexec(); 747 runtime_code_page_mkexec();
674 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); 748 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
index f61ccdd4934..1ea38775a6d 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 7000e74b308..fe73276e026 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -678,36 +678,40 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
678 pentry = (struct sfi_device_table_entry *)sb->pentry; 678 pentry = (struct sfi_device_table_entry *)sb->pentry;
679 679
680 for (i = 0; i < num; i++, pentry++) { 680 for (i = 0; i < num; i++, pentry++) {
681 if (pentry->irq != (u8)0xff) { /* native RTE case */ 681 int irq = pentry->irq;
682
683 if (irq != (u8)0xff) { /* native RTE case */
682 /* these SPI2 devices are not exposed to system as PCI 684 /* these SPI2 devices are not exposed to system as PCI
683 * devices, but they have separate RTE entry in IOAPIC 685 * devices, but they have separate RTE entry in IOAPIC
684 * so we have to enable them one by one here 686 * so we have to enable them one by one here
685 */ 687 */
686 ioapic = mp_find_ioapic(pentry->irq); 688 ioapic = mp_find_ioapic(irq);
687 irq_attr.ioapic = ioapic; 689 irq_attr.ioapic = ioapic;
688 irq_attr.ioapic_pin = pentry->irq; 690 irq_attr.ioapic_pin = irq;
689 irq_attr.trigger = 1; 691 irq_attr.trigger = 1;
690 irq_attr.polarity = 1; 692 irq_attr.polarity = 1;
691 io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); 693 io_apic_set_pci_routing(NULL, irq, &irq_attr);
692 } 694 } else
695 irq = 0; /* No irq */
696
693 switch (pentry->type) { 697 switch (pentry->type) {
694 case SFI_DEV_TYPE_IPC: 698 case SFI_DEV_TYPE_IPC:
695 /* ID as IRQ is a hack that will go away */ 699 /* ID as IRQ is a hack that will go away */
696 pdev = platform_device_alloc(pentry->name, pentry->irq); 700 pdev = platform_device_alloc(pentry->name, irq);
697 if (pdev == NULL) { 701 if (pdev == NULL) {
698 pr_err("out of memory for SFI platform device '%s'.\n", 702 pr_err("out of memory for SFI platform device '%s'.\n",
699 pentry->name); 703 pentry->name);
700 continue; 704 continue;
701 } 705 }
702 install_irq_resource(pdev, pentry->irq); 706 install_irq_resource(pdev, irq);
703 pr_debug("info[%2d]: IPC bus, name = %16.16s, " 707 pr_debug("info[%2d]: IPC bus, name = %16.16s, "
704 "irq = 0x%2x\n", i, pentry->name, pentry->irq); 708 "irq = 0x%2x\n", i, pentry->name, irq);
705 sfi_handle_ipc_dev(pdev); 709 sfi_handle_ipc_dev(pdev);
706 break; 710 break;
707 case SFI_DEV_TYPE_SPI: 711 case SFI_DEV_TYPE_SPI:
708 memset(&spi_info, 0, sizeof(spi_info)); 712 memset(&spi_info, 0, sizeof(spi_info));
709 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); 713 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
710 spi_info.irq = pentry->irq; 714 spi_info.irq = irq;
711 spi_info.bus_num = pentry->host_num; 715 spi_info.bus_num = pentry->host_num;
712 spi_info.chip_select = pentry->addr; 716 spi_info.chip_select = pentry->addr;
713 spi_info.max_speed_hz = pentry->max_freq; 717 spi_info.max_speed_hz = pentry->max_freq;
@@ -724,7 +728,7 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
724 memset(&i2c_info, 0, sizeof(i2c_info)); 728 memset(&i2c_info, 0, sizeof(i2c_info));
725 bus = pentry->host_num; 729 bus = pentry->host_num;
726 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); 730 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
727 i2c_info.irq = pentry->irq; 731 i2c_info.irq = irq;
728 i2c_info.addr = pentry->addr; 732 i2c_info.addr = pentry->addr;
729 pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " 733 pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, "
730 "irq = 0x%2x, addr = 0x%x\n", i, bus, 734 "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 00000000000..9281da7d91b
--- /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 MeeGo 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 00000000000..bfbfe64b167
--- /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 73d70d65e76..6d5dbcdd444 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -58,8 +58,11 @@ EXPORT_SYMBOL_GPL(vrtc_cmos_write);
58unsigned long vrtc_get_time(void) 58unsigned long vrtc_get_time(void)
59{ 59{
60 u8 sec, min, hour, mday, mon; 60 u8 sec, min, hour, mday, mon;
61 unsigned long flags;
61 u32 year; 62 u32 year;
62 63
64 spin_lock_irqsave(&rtc_lock, flags);
65
63 while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) 66 while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
64 cpu_relax(); 67 cpu_relax();
65 68
@@ -70,6 +73,8 @@ unsigned long vrtc_get_time(void)
70 mon = vrtc_cmos_read(RTC_MONTH); 73 mon = vrtc_cmos_read(RTC_MONTH);
71 year = vrtc_cmos_read(RTC_YEAR); 74 year = vrtc_cmos_read(RTC_YEAR);
72 75
76 spin_unlock_irqrestore(&rtc_lock, flags);
77
73 /* vRTC YEAR reg contains the offset to 1960 */ 78 /* vRTC YEAR reg contains the offset to 1960 */
74 year += 1960; 79 year += 1960;
75 80
@@ -83,8 +88,10 @@ unsigned long vrtc_get_time(void)
83int vrtc_set_mmss(unsigned long nowtime) 88int vrtc_set_mmss(unsigned long nowtime)
84{ 89{
85 int real_sec, real_min; 90 int real_sec, real_min;
91 unsigned long flags;
86 int vrtc_min; 92 int vrtc_min;
87 93
94 spin_lock_irqsave(&rtc_lock, flags);
88 vrtc_min = vrtc_cmos_read(RTC_MINUTES); 95 vrtc_min = vrtc_cmos_read(RTC_MINUTES);
89 96
90 real_sec = nowtime % 60; 97 real_sec = nowtime % 60;
@@ -95,6 +102,8 @@ int vrtc_set_mmss(unsigned long nowtime)
95 102
96 vrtc_cmos_write(real_sec, RTC_SECONDS); 103 vrtc_cmos_write(real_sec, RTC_SECONDS);
97 vrtc_cmos_write(real_min, RTC_MINUTES); 104 vrtc_cmos_write(real_min, RTC_MINUTES);
105 spin_unlock_irqrestore(&rtc_lock, flags);
106
98 return 0; 107 return 0;
99} 108}
100 109
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index 81c5e2165c2..fd332c53394 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 00000000000..6f3855a5a2f
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -0,0 +1,215 @@
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/pm.h>
18#include <linux/mfd/core.h>
19#include <linux/suspend.h>
20
21#include <asm/io.h>
22#include <asm/olpc.h>
23
24#define DRV_NAME "olpc-xo1-pm"
25
26static unsigned long acpi_base;
27static unsigned long pms_base;
28
29static u16 wakeup_mask = CS5536_PM_PWRBTN;
30
31static struct {
32 unsigned long address;
33 unsigned short segment;
34} ofw_bios_entry = { 0xF0000 + PAGE_OFFSET, __KERNEL_CS };
35
36/* Set bits in the wakeup mask */
37void olpc_xo1_pm_wakeup_set(u16 value)
38{
39 wakeup_mask |= value;
40}
41EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_set);
42
43/* Clear bits in the wakeup mask */
44void olpc_xo1_pm_wakeup_clear(u16 value)
45{
46 wakeup_mask &= ~value;
47}
48EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
49
50static int xo1_power_state_enter(suspend_state_t pm_state)
51{
52 unsigned long saved_sci_mask;
53 int r;
54
55 /* Only STR is supported */
56 if (pm_state != PM_SUSPEND_MEM)
57 return -EINVAL;
58
59 r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
60 if (r)
61 return r;
62
63 /*
64 * Save SCI mask (this gets lost since PM1_EN is used as a mask for
65 * wakeup events, which is not necessarily the same event set)
66 */
67 saved_sci_mask = inl(acpi_base + CS5536_PM1_STS);
68 saved_sci_mask &= 0xffff0000;
69
70 /* Save CPU state */
71 do_olpc_suspend_lowlevel();
72
73 /* Resume path starts here */
74
75 /* Restore SCI mask (using dword access to CS5536_PM1_EN) */
76 outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
77
78 /* Tell the EC to stop inhibiting SCIs */
79 olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
80
81 /*
82 * Tell the wireless module to restart USB communication.
83 * Must be done twice.
84 */
85 olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
86 olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
87
88 return 0;
89}
90
91asmlinkage int xo1_do_sleep(u8 sleep_state)
92{
93 void *pgd_addr = __va(read_cr3());
94
95 /* Program wakeup mask (using dword access to CS5536_PM1_EN) */
96 outl(wakeup_mask << 16, acpi_base + CS5536_PM1_STS);
97
98 __asm__("movl %0,%%eax" : : "r" (pgd_addr));
99 __asm__("call *(%%edi); cld"
100 : : "D" (&ofw_bios_entry));
101 __asm__("movb $0x34, %al\n\t"
102 "outb %al, $0x70\n\t"
103 "movb $0x30, %al\n\t"
104 "outb %al, $0x71\n\t");
105 return 0;
106}
107
108static void xo1_power_off(void)
109{
110 printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
111
112 /* Enable all of these controls with 0 delay */
113 outl(0x40000000, pms_base + CS5536_PM_SCLK);
114 outl(0x40000000, pms_base + CS5536_PM_IN_SLPCTL);
115 outl(0x40000000, pms_base + CS5536_PM_WKXD);
116 outl(0x40000000, pms_base + CS5536_PM_WKD);
117
118 /* Clear status bits (possibly unnecessary) */
119 outl(0x0002ffff, pms_base + CS5536_PM_SSC);
120 outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
121
122 /* Write SLP_EN bit to start the machinery */
123 outl(0x00002000, acpi_base + CS5536_PM1_CNT);
124}
125
126static int xo1_power_state_valid(suspend_state_t pm_state)
127{
128 /* suspend-to-RAM only */
129 return pm_state == PM_SUSPEND_MEM;
130}
131
132static const struct platform_suspend_ops xo1_suspend_ops = {
133 .valid = xo1_power_state_valid,
134 .enter = xo1_power_state_enter,
135};
136
137static int __devinit xo1_pm_probe(struct platform_device *pdev)
138{
139 struct resource *res;
140 int err;
141
142 /* don't run on non-XOs */
143 if (!machine_is_olpc())
144 return -ENODEV;
145
146 err = mfd_cell_enable(pdev);
147 if (err)
148 return err;
149
150 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
151 if (!res) {
152 dev_err(&pdev->dev, "can't fetch device resource info\n");
153 return -EIO;
154 }
155 if (strcmp(pdev->name, "cs5535-pms") == 0)
156 pms_base = res->start;
157 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
158 acpi_base = res->start;
159
160 /* If we have both addresses, we can override the poweroff hook */
161 if (pms_base && acpi_base) {
162 suspend_set_ops(&xo1_suspend_ops);
163 pm_power_off = xo1_power_off;
164 printk(KERN_INFO "OLPC XO-1 support registered\n");
165 }
166
167 return 0;
168}
169
170static int __devexit xo1_pm_remove(struct platform_device *pdev)
171{
172 mfd_cell_disable(pdev);
173
174 if (strcmp(pdev->name, "cs5535-pms") == 0)
175 pms_base = 0;
176 else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
177 acpi_base = 0;
178
179 pm_power_off = NULL;
180 return 0;
181}
182
183static struct platform_driver cs5535_pms_driver = {
184 .driver = {
185 .name = "cs5535-pms",
186 .owner = THIS_MODULE,
187 },
188 .probe = xo1_pm_probe,
189 .remove = __devexit_p(xo1_pm_remove),
190};
191
192static struct platform_driver cs5535_acpi_driver = {
193 .driver = {
194 .name = "olpc-xo1-pm-acpi",
195 .owner = THIS_MODULE,
196 },
197 .probe = xo1_pm_probe,
198 .remove = __devexit_p(xo1_pm_remove),
199};
200
201static int __init xo1_pm_init(void)
202{
203 int r;
204
205 r = platform_driver_register(&cs5535_pms_driver);
206 if (r)
207 return r;
208
209 r = platform_driver_register(&cs5535_acpi_driver);
210 if (r)
211 platform_driver_unregister(&cs5535_pms_driver);
212
213 return r;
214}
215arch_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 00000000000..a2b4efddd61
--- /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 00000000000..1d4c783d732
--- /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 ab81fb27176..00000000000
--- 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 00000000000..2b235b77d9a
--- /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 0060fd59ea0..7cce722667b 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 d39f63d017d..d6ee9298692 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 00000000000..948deb28975
--- /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/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 68e467f69fe..5b552198f77 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);