diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 14:16:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 14:16:40 -0400 |
commit | 44bc40e1489622234169786b0ad5a1f4a01e1090 (patch) | |
tree | cd247a6f130b8993e92ac62f76ced2b023491d09 /arch | |
parent | 02171b4a7c5b555d08c3321332e0c45776518276 (diff) | |
parent | ead91d4b8c3b1fb08a73aaa4a191230ecf717ee0 (diff) |
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 platform changes from Ingo Molnar:
"This tree includes assorted platform driver updates and a preparatory
series for a platform with custom DMA remapping semantics (sta2x11 I/O
hub)."
* 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/vsmp: Fix number of CPUs when vsmp is disabled
keyboard: Use BIOS Keyboard variable to set Numlock
x86/olpc/xo1/sci: Report RTC wakeup events
x86/olpc/xo1/sci: Produce wakeup events for buttons and switches
x86, platform: Initial support for sta2x11 I/O hub
x86: Introduce CONFIG_X86_DMA_REMAP
x86-32: Introduce CONFIG_X86_DEV_DMA_OPS
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/include/asm/kbdleds.h | 19 | ||||
-rw-r--r-- | arch/x86/Kconfig | 35 | ||||
-rw-r--r-- | arch/x86/boot/main.c | 18 | ||||
-rw-r--r-- | arch/x86/include/asm/bootparam.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/device.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/dma-mapping.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/kbdleds.h | 17 | ||||
-rw-r--r-- | arch/x86/kernel/vsmp_64.c | 40 | ||||
-rw-r--r-- | arch/x86/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/pci/sta2x11-fixup.c | 366 | ||||
-rw-r--r-- | arch/x86/platform/olpc/olpc-xo1-sci.c | 43 |
11 files changed, 535 insertions, 21 deletions
diff --git a/arch/parisc/include/asm/kbdleds.h b/arch/parisc/include/asm/kbdleds.h new file mode 100644 index 000000000000..2e2e75a83c28 --- /dev/null +++ b/arch/parisc/include/asm/kbdleds.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef _ASM_PARISC_KBDLEDS_H | ||
2 | #define _ASM_PARISC_KBDLEDS_H | ||
3 | |||
4 | /* | ||
5 | * On HIL keyboards of PARISC machines there is no NumLock key and | ||
6 | * everyone expects the keypad to be used for numbers. That's why | ||
7 | * we can safely turn on the NUMLOCK bit. | ||
8 | */ | ||
9 | |||
10 | static inline int kbd_defleds(void) | ||
11 | { | ||
12 | #if defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD) | ||
13 | return 1 << VC_NUMLOCK; | ||
14 | #else | ||
15 | return 0; | ||
16 | #endif | ||
17 | } | ||
18 | |||
19 | #endif /* _ASM_PARISC_KBDLEDS_H */ | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5ab807c1192a..4d37072c498a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -12,6 +12,7 @@ config X86_32 | |||
12 | 12 | ||
13 | config X86_64 | 13 | config X86_64 |
14 | def_bool 64BIT | 14 | def_bool 64BIT |
15 | select X86_DEV_DMA_OPS | ||
15 | 16 | ||
16 | ### Arch settings | 17 | ### Arch settings |
17 | config X86 | 18 | config X86 |
@@ -327,6 +328,7 @@ config X86_EXTENDED_PLATFORM | |||
327 | NUMAQ (IBM/Sequent) | 328 | NUMAQ (IBM/Sequent) |
328 | RDC R-321x SoC | 329 | RDC R-321x SoC |
329 | SGI 320/540 (Visual Workstation) | 330 | SGI 320/540 (Visual Workstation) |
331 | STA2X11-based (e.g. Northville) | ||
330 | Summit/EXA (IBM x440) | 332 | Summit/EXA (IBM x440) |
331 | Unisys ES7000 IA32 series | 333 | Unisys ES7000 IA32 series |
332 | Moorestown MID devices | 334 | Moorestown MID devices |
@@ -373,6 +375,7 @@ config X86_VSMP | |||
373 | select PARAVIRT | 375 | select PARAVIRT |
374 | depends on X86_64 && PCI | 376 | depends on X86_64 && PCI |
375 | depends on X86_EXTENDED_PLATFORM | 377 | depends on X86_EXTENDED_PLATFORM |
378 | depends on SMP | ||
376 | ---help--- | 379 | ---help--- |
377 | Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is | 380 | Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is |
378 | supposed to run on these EM64T-based machines. Only choose this option | 381 | supposed to run on these EM64T-based machines. Only choose this option |
@@ -459,10 +462,10 @@ config X86_32_NON_STANDARD | |||
459 | depends on X86_32 && SMP | 462 | depends on X86_32 && SMP |
460 | depends on X86_EXTENDED_PLATFORM | 463 | depends on X86_EXTENDED_PLATFORM |
461 | ---help--- | 464 | ---help--- |
462 | This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default | 465 | This option compiles in the NUMAQ, Summit, bigsmp, ES7000, |
463 | subarchitectures. It is intended for a generic binary kernel. | 466 | STA2X11, default subarchitectures. It is intended for a generic |
464 | if you select them all, kernel will probe it one by one. and will | 467 | binary kernel. If you select them all, kernel will probe it |
465 | fallback to default. | 468 | one by one and will fallback to default. |
466 | 469 | ||
467 | # Alphabetically sorted list of Non standard 32 bit platforms | 470 | # Alphabetically sorted list of Non standard 32 bit platforms |
468 | 471 | ||
@@ -502,6 +505,22 @@ config X86_VISWS | |||
502 | A kernel compiled for the Visual Workstation will run on general | 505 | A kernel compiled for the Visual Workstation will run on general |
503 | PCs as well. See <file:Documentation/sgi-visws.txt> for details. | 506 | PCs as well. See <file:Documentation/sgi-visws.txt> for details. |
504 | 507 | ||
508 | config STA2X11 | ||
509 | bool "STA2X11 Companion Chip Support" | ||
510 | depends on X86_32_NON_STANDARD && PCI | ||
511 | select X86_DEV_DMA_OPS | ||
512 | select X86_DMA_REMAP | ||
513 | select SWIOTLB | ||
514 | select MFD_STA2X11 | ||
515 | select ARCH_REQUIRE_GPIOLIB | ||
516 | default n | ||
517 | ---help--- | ||
518 | This adds support for boards based on the STA2X11 IO-Hub, | ||
519 | a.k.a. "ConneXt". The chip is used in place of the standard | ||
520 | PC chipset, so all "standard" peripherals are missing. If this | ||
521 | option is selected the kernel will still be able to boot on | ||
522 | standard PC machines. | ||
523 | |||
505 | config X86_SUMMIT | 524 | config X86_SUMMIT |
506 | bool "Summit/EXA (IBM x440)" | 525 | bool "Summit/EXA (IBM x440)" |
507 | depends on X86_32_NON_STANDARD | 526 | depends on X86_32_NON_STANDARD |
@@ -2210,6 +2229,14 @@ config HAVE_TEXT_POKE_SMP | |||
2210 | bool | 2229 | bool |
2211 | select STOP_MACHINE if SMP | 2230 | select STOP_MACHINE if SMP |
2212 | 2231 | ||
2232 | config X86_DEV_DMA_OPS | ||
2233 | bool | ||
2234 | depends on X86_64 || STA2X11 | ||
2235 | |||
2236 | config X86_DMA_REMAP | ||
2237 | bool | ||
2238 | depends on STA2X11 | ||
2239 | |||
2213 | source "net/Kconfig" | 2240 | source "net/Kconfig" |
2214 | 2241 | ||
2215 | source "drivers/Kconfig" | 2242 | source "drivers/Kconfig" |
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c index 40358c8905be..cf6083d444f4 100644 --- a/arch/x86/boot/main.c +++ b/arch/x86/boot/main.c | |||
@@ -57,14 +57,20 @@ static void copy_boot_params(void) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Set the keyboard repeat rate to maximum. Unclear why this | 60 | * Query the keyboard lock status as given by the BIOS, and |
61 | * set the keyboard repeat rate to maximum. Unclear why the latter | ||
61 | * is done here; this might be possible to kill off as stale code. | 62 | * is done here; this might be possible to kill off as stale code. |
62 | */ | 63 | */ |
63 | static void keyboard_set_repeat(void) | 64 | static void keyboard_init(void) |
64 | { | 65 | { |
65 | struct biosregs ireg; | 66 | struct biosregs ireg, oreg; |
66 | initregs(&ireg); | 67 | initregs(&ireg); |
67 | ireg.ax = 0x0305; | 68 | |
69 | ireg.ah = 0x02; /* Get keyboard status */ | ||
70 | intcall(0x16, &ireg, &oreg); | ||
71 | boot_params.kbd_status = oreg.al; | ||
72 | |||
73 | ireg.ax = 0x0305; /* Set keyboard repeat rate */ | ||
68 | intcall(0x16, &ireg, NULL); | 74 | intcall(0x16, &ireg, NULL); |
69 | } | 75 | } |
70 | 76 | ||
@@ -151,8 +157,8 @@ void main(void) | |||
151 | /* Detect memory layout */ | 157 | /* Detect memory layout */ |
152 | detect_memory(); | 158 | detect_memory(); |
153 | 159 | ||
154 | /* Set keyboard repeat rate (why?) */ | 160 | /* Set keyboard repeat rate (why?) and query the lock flags */ |
155 | keyboard_set_repeat(); | 161 | keyboard_init(); |
156 | 162 | ||
157 | /* Query MCA information */ | 163 | /* Query MCA information */ |
158 | query_mca(); | 164 | query_mca(); |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 2f90c51cc49d..eb45aa6b1f27 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -112,7 +112,8 @@ struct boot_params { | |||
112 | __u8 e820_entries; /* 0x1e8 */ | 112 | __u8 e820_entries; /* 0x1e8 */ |
113 | __u8 eddbuf_entries; /* 0x1e9 */ | 113 | __u8 eddbuf_entries; /* 0x1e9 */ |
114 | __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ | 114 | __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ |
115 | __u8 _pad6[6]; /* 0x1eb */ | 115 | __u8 kbd_status; /* 0x1eb */ |
116 | __u8 _pad6[5]; /* 0x1ec */ | ||
116 | struct setup_header hdr; /* setup header */ /* 0x1f1 */ | 117 | struct setup_header hdr; /* setup header */ /* 0x1f1 */ |
117 | __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; | 118 | __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; |
118 | __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ | 119 | __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ |
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index 63a2a03d7d51..93e1c55f14ab 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h | |||
@@ -5,8 +5,8 @@ struct dev_archdata { | |||
5 | #ifdef CONFIG_ACPI | 5 | #ifdef CONFIG_ACPI |
6 | void *acpi_handle; | 6 | void *acpi_handle; |
7 | #endif | 7 | #endif |
8 | #ifdef CONFIG_X86_64 | 8 | #ifdef CONFIG_X86_DEV_DMA_OPS |
9 | struct dma_map_ops *dma_ops; | 9 | struct dma_map_ops *dma_ops; |
10 | #endif | 10 | #endif |
11 | #if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU) | 11 | #if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU) |
12 | void *iommu; /* hook for IOMMU specific extension */ | 12 | void *iommu; /* hook for IOMMU specific extension */ |
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 4b4331d71935..61c0bd25845a 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h | |||
@@ -30,7 +30,7 @@ extern struct dma_map_ops *dma_ops; | |||
30 | 30 | ||
31 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) | 31 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) |
32 | { | 32 | { |
33 | #ifdef CONFIG_X86_32 | 33 | #ifndef CONFIG_X86_DEV_DMA_OPS |
34 | return dma_ops; | 34 | return dma_ops; |
35 | #else | 35 | #else |
36 | if (unlikely(!dev) || !dev->archdata.dma_ops) | 36 | if (unlikely(!dev) || !dev->archdata.dma_ops) |
@@ -62,6 +62,12 @@ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, | |||
62 | dma_addr_t *dma_addr, gfp_t flag, | 62 | dma_addr_t *dma_addr, gfp_t flag, |
63 | struct dma_attrs *attrs); | 63 | struct dma_attrs *attrs); |
64 | 64 | ||
65 | #ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */ | ||
66 | extern bool dma_capable(struct device *dev, dma_addr_t addr, size_t size); | ||
67 | extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr); | ||
68 | extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr); | ||
69 | #else | ||
70 | |||
65 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | 71 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) |
66 | { | 72 | { |
67 | if (!dev->dma_mask) | 73 | if (!dev->dma_mask) |
@@ -79,6 +85,7 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) | |||
79 | { | 85 | { |
80 | return daddr; | 86 | return daddr; |
81 | } | 87 | } |
88 | #endif /* CONFIG_X86_DMA_REMAP */ | ||
82 | 89 | ||
83 | static inline void | 90 | static inline void |
84 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 91 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
diff --git a/arch/x86/include/asm/kbdleds.h b/arch/x86/include/asm/kbdleds.h new file mode 100644 index 000000000000..f27ac5ff597d --- /dev/null +++ b/arch/x86/include/asm/kbdleds.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef _ASM_X86_KBDLEDS_H | ||
2 | #define _ASM_X86_KBDLEDS_H | ||
3 | |||
4 | /* | ||
5 | * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on. | ||
6 | * This seems a good reason to start with NumLock off. That's why on X86 we | ||
7 | * ask the bios for the correct state. | ||
8 | */ | ||
9 | |||
10 | #include <asm/setup.h> | ||
11 | |||
12 | static inline int kbd_defleds(void) | ||
13 | { | ||
14 | return boot_params.kbd_status & 0x20 ? (1 << VC_NUMLOCK) : 0; | ||
15 | } | ||
16 | |||
17 | #endif /* _ASM_X86_KBDLEDS_H */ | ||
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index a1d804bcd483..8eeb55a551b4 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pci_ids.h> | 16 | #include <linux/pci_ids.h> |
17 | #include <linux/pci_regs.h> | 17 | #include <linux/pci_regs.h> |
18 | #include <linux/smp.h> | ||
18 | 19 | ||
19 | #include <asm/apic.h> | 20 | #include <asm/apic.h> |
20 | #include <asm/pci-direct.h> | 21 | #include <asm/pci-direct.h> |
@@ -22,6 +23,8 @@ | |||
22 | #include <asm/paravirt.h> | 23 | #include <asm/paravirt.h> |
23 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
24 | 25 | ||
26 | #define TOPOLOGY_REGISTER_OFFSET 0x10 | ||
27 | |||
25 | #if defined CONFIG_PCI && defined CONFIG_PARAVIRT | 28 | #if defined CONFIG_PCI && defined CONFIG_PARAVIRT |
26 | /* | 29 | /* |
27 | * Interrupt control on vSMPowered systems: | 30 | * Interrupt control on vSMPowered systems: |
@@ -149,12 +152,49 @@ int is_vsmp_box(void) | |||
149 | return 0; | 152 | return 0; |
150 | } | 153 | } |
151 | #endif | 154 | #endif |
155 | |||
156 | static void __init vsmp_cap_cpus(void) | ||
157 | { | ||
158 | #if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP) | ||
159 | void __iomem *address; | ||
160 | unsigned int cfg, topology, node_shift, maxcpus; | ||
161 | |||
162 | /* | ||
163 | * CONFIG_X86_VSMP is not configured, so limit the number CPUs to the | ||
164 | * ones present in the first board, unless explicitly overridden by | ||
165 | * setup_max_cpus | ||
166 | */ | ||
167 | if (setup_max_cpus != NR_CPUS) | ||
168 | return; | ||
169 | |||
170 | /* Read the vSMP Foundation topology register */ | ||
171 | cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0); | ||
172 | address = early_ioremap(cfg + TOPOLOGY_REGISTER_OFFSET, 4); | ||
173 | if (WARN_ON(!address)) | ||
174 | return; | ||
175 | |||
176 | topology = readl(address); | ||
177 | node_shift = (topology >> 16) & 0x7; | ||
178 | if (!node_shift) | ||
179 | /* The value 0 should be decoded as 8 */ | ||
180 | node_shift = 8; | ||
181 | maxcpus = (topology & ((1 << node_shift) - 1)) + 1; | ||
182 | |||
183 | pr_info("vSMP CTL: Capping CPUs to %d (CONFIG_X86_VSMP is unset)\n", | ||
184 | maxcpus); | ||
185 | setup_max_cpus = maxcpus; | ||
186 | early_iounmap(address, 4); | ||
187 | #endif | ||
188 | } | ||
189 | |||
152 | void __init vsmp_init(void) | 190 | void __init vsmp_init(void) |
153 | { | 191 | { |
154 | detect_vsmp_box(); | 192 | detect_vsmp_box(); |
155 | if (!is_vsmp_box()) | 193 | if (!is_vsmp_box()) |
156 | return; | 194 | return; |
157 | 195 | ||
196 | vsmp_cap_cpus(); | ||
197 | |||
158 | set_vsmp_pv_ops(); | 198 | set_vsmp_pv_ops(); |
159 | return; | 199 | return; |
160 | } | 200 | } |
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index e76e18c94a3c..3af5a1e79c9c 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -11,6 +11,8 @@ obj-$(CONFIG_X86_INTEL_CE) += ce4100.o | |||
11 | obj-$(CONFIG_ACPI) += acpi.o | 11 | obj-$(CONFIG_ACPI) += acpi.o |
12 | obj-y += legacy.o irq.o | 12 | obj-y += legacy.o irq.o |
13 | 13 | ||
14 | obj-$(CONFIG_STA2X11) += sta2x11-fixup.o | ||
15 | |||
14 | obj-$(CONFIG_X86_VISWS) += visws.o | 16 | obj-$(CONFIG_X86_VISWS) += visws.o |
15 | 17 | ||
16 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | 18 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o |
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c new file mode 100644 index 000000000000..9d8a509c9730 --- /dev/null +++ b/arch/x86/pci/sta2x11-fixup.c | |||
@@ -0,0 +1,366 @@ | |||
1 | /* | ||
2 | * arch/x86/pci/sta2x11-fixup.c | ||
3 | * glue code for lib/swiotlb.c and DMA translation between STA2x11 | ||
4 | * AMBA memory mapping and the X86 memory mapping | ||
5 | * | ||
6 | * ST Microelectronics ConneXt (STA2X11/STA2X10) | ||
7 | * | ||
8 | * Copyright (c) 2010-2011 Wind River Systems, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | * See the GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/pci.h> | ||
26 | #include <linux/pci_ids.h> | ||
27 | #include <linux/export.h> | ||
28 | #include <linux/list.h> | ||
29 | |||
30 | #define STA2X11_SWIOTLB_SIZE (4*1024*1024) | ||
31 | extern int swiotlb_late_init_with_default_size(size_t default_size); | ||
32 | |||
33 | /* | ||
34 | * We build a list of bus numbers that are under the ConneXt. The | ||
35 | * main bridge hosts 4 busses, which are the 4 endpoints, in order. | ||
36 | */ | ||
37 | #define STA2X11_NR_EP 4 /* 0..3 included */ | ||
38 | #define STA2X11_NR_FUNCS 8 /* 0..7 included */ | ||
39 | #define STA2X11_AMBA_SIZE (512 << 20) | ||
40 | |||
41 | struct sta2x11_ahb_regs { /* saved during suspend */ | ||
42 | u32 base, pexlbase, pexhbase, crw; | ||
43 | }; | ||
44 | |||
45 | struct sta2x11_mapping { | ||
46 | u32 amba_base; | ||
47 | int is_suspended; | ||
48 | struct sta2x11_ahb_regs regs[STA2X11_NR_FUNCS]; | ||
49 | }; | ||
50 | |||
51 | struct sta2x11_instance { | ||
52 | struct list_head list; | ||
53 | int bus0; | ||
54 | struct sta2x11_mapping map[STA2X11_NR_EP]; | ||
55 | }; | ||
56 | |||
57 | static LIST_HEAD(sta2x11_instance_list); | ||
58 | |||
59 | /* At probe time, record new instances of this bridge (likely one only) */ | ||
60 | static void sta2x11_new_instance(struct pci_dev *pdev) | ||
61 | { | ||
62 | struct sta2x11_instance *instance; | ||
63 | |||
64 | instance = kzalloc(sizeof(*instance), GFP_ATOMIC); | ||
65 | if (!instance) | ||
66 | return; | ||
67 | /* This has a subordinate bridge, with 4 more-subordinate ones */ | ||
68 | instance->bus0 = pdev->subordinate->number + 1; | ||
69 | |||
70 | if (list_empty(&sta2x11_instance_list)) { | ||
71 | int size = STA2X11_SWIOTLB_SIZE; | ||
72 | /* First instance: register your own swiotlb area */ | ||
73 | dev_info(&pdev->dev, "Using SWIOTLB (size %i)\n", size); | ||
74 | if (swiotlb_late_init_with_default_size(size)) | ||
75 | dev_emerg(&pdev->dev, "init swiotlb failed\n"); | ||
76 | } | ||
77 | list_add(&instance->list, &sta2x11_instance_list); | ||
78 | } | ||
79 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, 0xcc17, sta2x11_new_instance); | ||
80 | |||
81 | /* | ||
82 | * Utility functions used in this file from below | ||
83 | */ | ||
84 | static struct sta2x11_instance *sta2x11_pdev_to_instance(struct pci_dev *pdev) | ||
85 | { | ||
86 | struct sta2x11_instance *instance; | ||
87 | int ep; | ||
88 | |||
89 | list_for_each_entry(instance, &sta2x11_instance_list, list) { | ||
90 | ep = pdev->bus->number - instance->bus0; | ||
91 | if (ep >= 0 && ep < STA2X11_NR_EP) | ||
92 | return instance; | ||
93 | } | ||
94 | return NULL; | ||
95 | } | ||
96 | |||
97 | static int sta2x11_pdev_to_ep(struct pci_dev *pdev) | ||
98 | { | ||
99 | struct sta2x11_instance *instance; | ||
100 | |||
101 | instance = sta2x11_pdev_to_instance(pdev); | ||
102 | if (!instance) | ||
103 | return -1; | ||
104 | |||
105 | return pdev->bus->number - instance->bus0; | ||
106 | } | ||
107 | |||
108 | static struct sta2x11_mapping *sta2x11_pdev_to_mapping(struct pci_dev *pdev) | ||
109 | { | ||
110 | struct sta2x11_instance *instance; | ||
111 | int ep; | ||
112 | |||
113 | instance = sta2x11_pdev_to_instance(pdev); | ||
114 | if (!instance) | ||
115 | return NULL; | ||
116 | ep = sta2x11_pdev_to_ep(pdev); | ||
117 | return instance->map + ep; | ||
118 | } | ||
119 | |||
120 | /* This is exported, as some devices need to access the MFD registers */ | ||
121 | struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev) | ||
122 | { | ||
123 | return sta2x11_pdev_to_instance(pdev); | ||
124 | } | ||
125 | EXPORT_SYMBOL(sta2x11_get_instance); | ||
126 | |||
127 | |||
128 | /** | ||
129 | * p2a - Translate physical address to STA2x11 AMBA address, | ||
130 | * used for DMA transfers to STA2x11 | ||
131 | * @p: Physical address | ||
132 | * @pdev: PCI device (must be hosted within the connext) | ||
133 | */ | ||
134 | static dma_addr_t p2a(dma_addr_t p, struct pci_dev *pdev) | ||
135 | { | ||
136 | struct sta2x11_mapping *map; | ||
137 | dma_addr_t a; | ||
138 | |||
139 | map = sta2x11_pdev_to_mapping(pdev); | ||
140 | a = p + map->amba_base; | ||
141 | return a; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * a2p - Translate STA2x11 AMBA address to physical address | ||
146 | * used for DMA transfers from STA2x11 | ||
147 | * @a: STA2x11 AMBA address | ||
148 | * @pdev: PCI device (must be hosted within the connext) | ||
149 | */ | ||
150 | static dma_addr_t a2p(dma_addr_t a, struct pci_dev *pdev) | ||
151 | { | ||
152 | struct sta2x11_mapping *map; | ||
153 | dma_addr_t p; | ||
154 | |||
155 | map = sta2x11_pdev_to_mapping(pdev); | ||
156 | p = a - map->amba_base; | ||
157 | return p; | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * sta2x11_swiotlb_alloc_coherent - Allocate swiotlb bounce buffers | ||
162 | * returns virtual address. This is the only "special" function here. | ||
163 | * @dev: PCI device | ||
164 | * @size: Size of the buffer | ||
165 | * @dma_handle: DMA address | ||
166 | * @flags: memory flags | ||
167 | */ | ||
168 | static void *sta2x11_swiotlb_alloc_coherent(struct device *dev, | ||
169 | size_t size, | ||
170 | dma_addr_t *dma_handle, | ||
171 | gfp_t flags, | ||
172 | struct dma_attrs *attrs) | ||
173 | { | ||
174 | void *vaddr; | ||
175 | |||
176 | vaddr = dma_generic_alloc_coherent(dev, size, dma_handle, flags, attrs); | ||
177 | if (!vaddr) | ||
178 | vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, flags); | ||
179 | *dma_handle = p2a(*dma_handle, to_pci_dev(dev)); | ||
180 | return vaddr; | ||
181 | } | ||
182 | |||
183 | /* We have our own dma_ops: the same as swiotlb but from alloc (above) */ | ||
184 | static struct dma_map_ops sta2x11_dma_ops = { | ||
185 | .alloc = sta2x11_swiotlb_alloc_coherent, | ||
186 | .free = swiotlb_free_coherent, | ||
187 | .map_page = swiotlb_map_page, | ||
188 | .unmap_page = swiotlb_unmap_page, | ||
189 | .map_sg = swiotlb_map_sg_attrs, | ||
190 | .unmap_sg = swiotlb_unmap_sg_attrs, | ||
191 | .sync_single_for_cpu = swiotlb_sync_single_for_cpu, | ||
192 | .sync_single_for_device = swiotlb_sync_single_for_device, | ||
193 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, | ||
194 | .sync_sg_for_device = swiotlb_sync_sg_for_device, | ||
195 | .mapping_error = swiotlb_dma_mapping_error, | ||
196 | .dma_supported = NULL, /* FIXME: we should use this instead! */ | ||
197 | }; | ||
198 | |||
199 | /* At setup time, we use our own ops if the device is a ConneXt one */ | ||
200 | static void sta2x11_setup_pdev(struct pci_dev *pdev) | ||
201 | { | ||
202 | struct sta2x11_instance *instance = sta2x11_pdev_to_instance(pdev); | ||
203 | |||
204 | if (!instance) /* either a sta2x11 bridge or another ST device */ | ||
205 | return; | ||
206 | pci_set_consistent_dma_mask(pdev, STA2X11_AMBA_SIZE - 1); | ||
207 | pci_set_dma_mask(pdev, STA2X11_AMBA_SIZE - 1); | ||
208 | pdev->dev.archdata.dma_ops = &sta2x11_dma_ops; | ||
209 | |||
210 | /* We must enable all devices as master, for audio DMA to work */ | ||
211 | pci_set_master(pdev); | ||
212 | } | ||
213 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_setup_pdev); | ||
214 | |||
215 | /* | ||
216 | * The following three functions are exported (used in swiotlb: FIXME) | ||
217 | */ | ||
218 | /** | ||
219 | * dma_capable - Check if device can manage DMA transfers (FIXME: kill it) | ||
220 | * @dev: device for a PCI device | ||
221 | * @addr: DMA address | ||
222 | * @size: DMA size | ||
223 | */ | ||
224 | bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | ||
225 | { | ||
226 | struct sta2x11_mapping *map; | ||
227 | |||
228 | if (dev->archdata.dma_ops != &sta2x11_dma_ops) { | ||
229 | if (!dev->dma_mask) | ||
230 | return false; | ||
231 | return addr + size - 1 <= *dev->dma_mask; | ||
232 | } | ||
233 | |||
234 | map = sta2x11_pdev_to_mapping(to_pci_dev(dev)); | ||
235 | |||
236 | if (!map || (addr < map->amba_base)) | ||
237 | return false; | ||
238 | if (addr + size >= map->amba_base + STA2X11_AMBA_SIZE) { | ||
239 | return false; | ||
240 | } | ||
241 | |||
242 | return true; | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * phys_to_dma - Return the DMA AMBA address used for this STA2x11 device | ||
247 | * @dev: device for a PCI device | ||
248 | * @paddr: Physical address | ||
249 | */ | ||
250 | dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | ||
251 | { | ||
252 | if (dev->archdata.dma_ops != &sta2x11_dma_ops) | ||
253 | return paddr; | ||
254 | return p2a(paddr, to_pci_dev(dev)); | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * dma_to_phys - Return the physical address used for this STA2x11 DMA address | ||
259 | * @dev: device for a PCI device | ||
260 | * @daddr: STA2x11 AMBA DMA address | ||
261 | */ | ||
262 | phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) | ||
263 | { | ||
264 | if (dev->archdata.dma_ops != &sta2x11_dma_ops) | ||
265 | return daddr; | ||
266 | return a2p(daddr, to_pci_dev(dev)); | ||
267 | } | ||
268 | |||
269 | |||
270 | /* | ||
271 | * At boot we must set up the mappings for the pcie-to-amba bridge. | ||
272 | * It involves device access, and the same happens at suspend/resume time | ||
273 | */ | ||
274 | |||
275 | #define AHB_MAPB 0xCA4 | ||
276 | #define AHB_CRW(i) (AHB_MAPB + 0 + (i) * 0x10) | ||
277 | #define AHB_CRW_SZMASK 0xfffffc00UL | ||
278 | #define AHB_CRW_ENABLE (1 << 0) | ||
279 | #define AHB_CRW_WTYPE_MEM (2 << 1) | ||
280 | #define AHB_CRW_ROE (1UL << 3) /* Relax Order Ena */ | ||
281 | #define AHB_CRW_NSE (1UL << 4) /* No Snoop Enable */ | ||
282 | #define AHB_BASE(i) (AHB_MAPB + 4 + (i) * 0x10) | ||
283 | #define AHB_PEXLBASE(i) (AHB_MAPB + 8 + (i) * 0x10) | ||
284 | #define AHB_PEXHBASE(i) (AHB_MAPB + 12 + (i) * 0x10) | ||
285 | |||
286 | /* At probe time, enable mapping for each endpoint, using the pdev */ | ||
287 | static void sta2x11_map_ep(struct pci_dev *pdev) | ||
288 | { | ||
289 | struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev); | ||
290 | int i; | ||
291 | |||
292 | if (!map) | ||
293 | return; | ||
294 | pci_read_config_dword(pdev, AHB_BASE(0), &map->amba_base); | ||
295 | |||
296 | /* Configure AHB mapping */ | ||
297 | pci_write_config_dword(pdev, AHB_PEXLBASE(0), 0); | ||
298 | pci_write_config_dword(pdev, AHB_PEXHBASE(0), 0); | ||
299 | pci_write_config_dword(pdev, AHB_CRW(0), STA2X11_AMBA_SIZE | | ||
300 | AHB_CRW_WTYPE_MEM | AHB_CRW_ENABLE); | ||
301 | |||
302 | /* Disable all the other windows */ | ||
303 | for (i = 1; i < STA2X11_NR_FUNCS; i++) | ||
304 | pci_write_config_dword(pdev, AHB_CRW(i), 0); | ||
305 | |||
306 | dev_info(&pdev->dev, | ||
307 | "sta2x11: Map EP %i: AMBA address %#8x-%#8x\n", | ||
308 | sta2x11_pdev_to_ep(pdev), map->amba_base, | ||
309 | map->amba_base + STA2X11_AMBA_SIZE - 1); | ||
310 | } | ||
311 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, sta2x11_map_ep); | ||
312 | |||
313 | #ifdef CONFIG_PM /* Some register values must be saved and restored */ | ||
314 | |||
315 | static void suspend_mapping(struct pci_dev *pdev) | ||
316 | { | ||
317 | struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev); | ||
318 | int i; | ||
319 | |||
320 | if (!map) | ||
321 | return; | ||
322 | |||
323 | if (map->is_suspended) | ||
324 | return; | ||
325 | map->is_suspended = 1; | ||
326 | |||
327 | /* Save all window configs */ | ||
328 | for (i = 0; i < STA2X11_NR_FUNCS; i++) { | ||
329 | struct sta2x11_ahb_regs *regs = map->regs + i; | ||
330 | |||
331 | pci_read_config_dword(pdev, AHB_BASE(i), ®s->base); | ||
332 | pci_read_config_dword(pdev, AHB_PEXLBASE(i), ®s->pexlbase); | ||
333 | pci_read_config_dword(pdev, AHB_PEXHBASE(i), ®s->pexhbase); | ||
334 | pci_read_config_dword(pdev, AHB_CRW(i), ®s->crw); | ||
335 | } | ||
336 | } | ||
337 | DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, suspend_mapping); | ||
338 | |||
339 | static void resume_mapping(struct pci_dev *pdev) | ||
340 | { | ||
341 | struct sta2x11_mapping *map = sta2x11_pdev_to_mapping(pdev); | ||
342 | int i; | ||
343 | |||
344 | if (!map) | ||
345 | return; | ||
346 | |||
347 | |||
348 | if (!map->is_suspended) | ||
349 | goto out; | ||
350 | map->is_suspended = 0; | ||
351 | |||
352 | /* Restore all window configs */ | ||
353 | for (i = 0; i < STA2X11_NR_FUNCS; i++) { | ||
354 | struct sta2x11_ahb_regs *regs = map->regs + i; | ||
355 | |||
356 | pci_write_config_dword(pdev, AHB_BASE(i), regs->base); | ||
357 | pci_write_config_dword(pdev, AHB_PEXLBASE(i), regs->pexlbase); | ||
358 | pci_write_config_dword(pdev, AHB_PEXHBASE(i), regs->pexhbase); | ||
359 | pci_write_config_dword(pdev, AHB_CRW(i), regs->crw); | ||
360 | } | ||
361 | out: | ||
362 | pci_set_master(pdev); /* Like at boot, enable master on all devices */ | ||
363 | } | ||
364 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, resume_mapping); | ||
365 | |||
366 | #endif /* CONFIG_PM */ | ||
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 1d4c783d7325..04b8c73659c5 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/pm_wakeup.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
23 | #include <linux/suspend.h> | 24 | #include <linux/suspend.h> |
@@ -83,8 +84,12 @@ static void send_ebook_state(void) | |||
83 | return; | 84 | return; |
84 | } | 85 | } |
85 | 86 | ||
87 | if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state) | ||
88 | return; /* Nothing new to report. */ | ||
89 | |||
86 | input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state); | 90 | input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state); |
87 | input_sync(ebook_switch_idev); | 91 | input_sync(ebook_switch_idev); |
92 | pm_wakeup_event(&ebook_switch_idev->dev, 0); | ||
88 | } | 93 | } |
89 | 94 | ||
90 | static void flip_lid_inverter(void) | 95 | static void flip_lid_inverter(void) |
@@ -123,8 +128,12 @@ static void detect_lid_state(void) | |||
123 | /* Report current lid switch state through input layer */ | 128 | /* Report current lid switch state through input layer */ |
124 | static void send_lid_state(void) | 129 | static void send_lid_state(void) |
125 | { | 130 | { |
131 | if (!!test_bit(SW_LID, lid_switch_idev->sw) == !lid_open) | ||
132 | return; /* Nothing new to report. */ | ||
133 | |||
126 | input_report_switch(lid_switch_idev, SW_LID, !lid_open); | 134 | input_report_switch(lid_switch_idev, SW_LID, !lid_open); |
127 | input_sync(lid_switch_idev); | 135 | input_sync(lid_switch_idev); |
136 | pm_wakeup_event(&lid_switch_idev->dev, 0); | ||
128 | } | 137 | } |
129 | 138 | ||
130 | static ssize_t lid_wake_mode_show(struct device *dev, | 139 | static ssize_t lid_wake_mode_show(struct device *dev, |
@@ -213,11 +222,30 @@ static irqreturn_t xo1_sci_intr(int irq, void *dev_id) | |||
213 | 222 | ||
214 | dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe); | 223 | dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe); |
215 | 224 | ||
216 | if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) { | 225 | if (sts & CS5536_PWRBTN_FLAG) { |
217 | input_report_key(power_button_idev, KEY_POWER, 1); | 226 | if (!(sts & CS5536_WAK_FLAG)) { |
218 | input_sync(power_button_idev); | 227 | /* Only report power button input when it was pressed |
219 | input_report_key(power_button_idev, KEY_POWER, 0); | 228 | * during regular operation (as opposed to when it |
220 | input_sync(power_button_idev); | 229 | * was used to wake the system). */ |
230 | input_report_key(power_button_idev, KEY_POWER, 1); | ||
231 | input_sync(power_button_idev); | ||
232 | input_report_key(power_button_idev, KEY_POWER, 0); | ||
233 | input_sync(power_button_idev); | ||
234 | } | ||
235 | /* Report the wakeup event in all cases. */ | ||
236 | pm_wakeup_event(&power_button_idev->dev, 0); | ||
237 | } | ||
238 | |||
239 | if ((sts & (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) == | ||
240 | (CS5536_RTC_FLAG | CS5536_WAK_FLAG)) { | ||
241 | /* When the system is woken by the RTC alarm, report the | ||
242 | * event on the rtc device. */ | ||
243 | struct device *rtc = bus_find_device_by_name( | ||
244 | &platform_bus_type, NULL, "rtc_cmos"); | ||
245 | if (rtc) { | ||
246 | pm_wakeup_event(rtc, 0); | ||
247 | put_device(rtc); | ||
248 | } | ||
221 | } | 249 | } |
222 | 250 | ||
223 | if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */ | 251 | if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */ |
@@ -310,9 +338,10 @@ static int __devinit setup_sci_interrupt(struct platform_device *pdev) | |||
310 | outb(lo, CS5536_PIC_INT_SEL2); | 338 | outb(lo, CS5536_PIC_INT_SEL2); |
311 | } | 339 | } |
312 | 340 | ||
313 | /* Enable SCI from power button, and clear pending interrupts */ | 341 | /* Enable interesting SCI events, and clear pending interrupts */ |
314 | sts = inl(acpi_base + CS5536_PM1_STS); | 342 | sts = inl(acpi_base + CS5536_PM1_STS); |
315 | outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS); | 343 | outl(((CS5536_PM_PWRBTN | CS5536_PM_RTC) << 16) | 0xffff, |
344 | acpi_base + CS5536_PM1_STS); | ||
316 | 345 | ||
317 | r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev); | 346 | r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev); |
318 | if (r) | 347 | if (r) |