Merge branch 'x86-olpc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-olpc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, olpc: XO-1 uses/depends on PCI
x86, olpc: Register XO-1 platform devices
x86, olpc: Add XO-1 poweroff support
x86, olpc: Don't retry EC commands forever
x86, olpc: Rework BIOS signature check
x86, olpc: Only enable PCI configuration type override on XO-1

+217 -38
+9 -2
arch/x86/Kconfig
··· 1927 1927 bool "Direct" 1928 1928 1929 1929 config PCI_GOOLPC 1930 - bool "OLPC" 1930 + bool "OLPC XO-1" 1931 1931 depends on OLPC 1932 1932 1933 1933 config PCI_GOANY ··· 2088 2088 config OLPC 2089 2089 bool "One Laptop Per Child support" 2090 2090 select GPIOLIB 2091 + select OLPC_OPENFIRMWARE 2091 2092 ---help--- 2092 2093 Add support for detecting the unique features of the OLPC 2093 2094 XO hardware. 2094 2095 2096 + config OLPC_XO1 2097 + tristate "OLPC XO-1 support" 2098 + depends on OLPC && PCI 2099 + ---help--- 2100 + Add support for non-essential features of the OLPC XO-1 laptop. 2101 + 2095 2102 config OLPC_OPENFIRMWARE 2096 2103 bool "Support for OLPC's Open Firmware" 2097 2104 depends on !X86_64 && !X86_PAE 2098 - default y if OLPC 2105 + default n 2099 2106 help 2100 2107 This option adds support for the implementation of Open Firmware 2101 2108 that is used on the OLPC XO-1 Children's Machine.
+4
arch/x86/include/asm/olpc_ofw.h
··· 21 21 /* install OFW's pde permanently into the kernel's pgtable */ 22 22 extern void setup_olpc_ofw_pgd(void); 23 23 24 + /* check if OFW was detected during boot */ 25 + extern bool olpc_ofw_present(void); 26 + 24 27 #else /* !CONFIG_OLPC_OPENFIRMWARE */ 25 28 26 29 static inline void olpc_ofw_detect(void) { } 27 30 static inline void setup_olpc_ofw_pgd(void) { } 31 + static inline bool olpc_ofw_present(void) { return false; } 28 32 29 33 #endif /* !CONFIG_OLPC_OPENFIRMWARE */ 30 34
+1
arch/x86/kernel/Makefile
··· 108 108 scx200-y += scx200_32.o 109 109 110 110 obj-$(CONFIG_OLPC) += olpc.o 111 + obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o 111 112 obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o 112 113 obj-$(CONFIG_X86_MRST) += mrst.o 113 114
+140
arch/x86/kernel/olpc-xo1.c
··· 1 + /* 2 + * Support for features of the OLPC XO-1 laptop 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/module.h> 15 + #include <linux/pci.h> 16 + #include <linux/pci_ids.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/pm.h> 19 + 20 + #include <asm/io.h> 21 + #include <asm/olpc.h> 22 + 23 + #define DRV_NAME "olpc-xo1" 24 + 25 + #define PMS_BAR 4 26 + #define ACPI_BAR 5 27 + 28 + /* PMC registers (PMS block) */ 29 + #define PM_SCLK 0x10 30 + #define PM_IN_SLPCTL 0x20 31 + #define PM_WKXD 0x34 32 + #define PM_WKD 0x30 33 + #define PM_SSC 0x54 34 + 35 + /* PM registers (ACPI block) */ 36 + #define PM1_CNT 0x08 37 + #define PM_GPE0_STS 0x18 38 + 39 + static unsigned long acpi_base; 40 + static unsigned long pms_base; 41 + 42 + static void xo1_power_off(void) 43 + { 44 + printk(KERN_INFO "OLPC XO-1 power off sequence...\n"); 45 + 46 + /* Enable all of these controls with 0 delay */ 47 + outl(0x40000000, pms_base + PM_SCLK); 48 + outl(0x40000000, pms_base + PM_IN_SLPCTL); 49 + outl(0x40000000, pms_base + PM_WKXD); 50 + outl(0x40000000, pms_base + PM_WKD); 51 + 52 + /* Clear status bits (possibly unnecessary) */ 53 + outl(0x0002ffff, pms_base + PM_SSC); 54 + outl(0xffffffff, acpi_base + PM_GPE0_STS); 55 + 56 + /* Write SLP_EN bit to start the machinery */ 57 + outl(0x00002000, acpi_base + PM1_CNT); 58 + } 59 + 60 + /* Read the base addresses from the PCI BAR info */ 61 + static int __devinit setup_bases(struct pci_dev *pdev) 62 + { 63 + int r; 64 + 65 + r = pci_enable_device_io(pdev); 66 + if (r) { 67 + dev_err(&pdev->dev, "can't enable device IO\n"); 68 + return r; 69 + } 70 + 71 + r = pci_request_region(pdev, ACPI_BAR, DRV_NAME); 72 + if (r) { 73 + dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR); 74 + return r; 75 + } 76 + 77 + r = pci_request_region(pdev, PMS_BAR, DRV_NAME); 78 + if (r) { 79 + dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR); 80 + pci_release_region(pdev, ACPI_BAR); 81 + return r; 82 + } 83 + 84 + acpi_base = pci_resource_start(pdev, ACPI_BAR); 85 + pms_base = pci_resource_start(pdev, PMS_BAR); 86 + 87 + return 0; 88 + } 89 + 90 + static int __devinit olpc_xo1_probe(struct platform_device *pdev) 91 + { 92 + struct pci_dev *pcidev; 93 + int r; 94 + 95 + pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 96 + NULL); 97 + if (!pdev) 98 + return -ENODEV; 99 + 100 + r = setup_bases(pcidev); 101 + if (r) 102 + return r; 103 + 104 + pm_power_off = xo1_power_off; 105 + 106 + printk(KERN_INFO "OLPC XO-1 support registered\n"); 107 + return 0; 108 + } 109 + 110 + static int __devexit olpc_xo1_remove(struct platform_device *pdev) 111 + { 112 + pm_power_off = NULL; 113 + return 0; 114 + } 115 + 116 + static struct platform_driver olpc_xo1_driver = { 117 + .driver = { 118 + .name = DRV_NAME, 119 + .owner = THIS_MODULE, 120 + }, 121 + .probe = olpc_xo1_probe, 122 + .remove = __devexit_p(olpc_xo1_remove), 123 + }; 124 + 125 + static int __init olpc_xo1_init(void) 126 + { 127 + return platform_driver_register(&olpc_xo1_driver); 128 + } 129 + 130 + static void __exit olpc_xo1_exit(void) 131 + { 132 + platform_driver_unregister(&olpc_xo1_driver); 133 + } 134 + 135 + MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); 136 + MODULE_LICENSE("GPL"); 137 + MODULE_ALIAS("platform:olpc-xo1"); 138 + 139 + module_init(olpc_xo1_init); 140 + module_exit(olpc_xo1_exit);
+56 -35
arch/x86/kernel/olpc.c
··· 17 17 #include <linux/spinlock.h> 18 18 #include <linux/io.h> 19 19 #include <linux/string.h> 20 + #include <linux/platform_device.h> 20 21 21 22 #include <asm/geode.h> 22 23 #include <asm/setup.h> ··· 115 114 unsigned long flags; 116 115 int ret = -EIO; 117 116 int i; 117 + int restarts = 0; 118 118 119 119 spin_lock_irqsave(&ec_lock, flags); 120 120 ··· 171 169 if (wait_on_obf(0x6c, 1)) { 172 170 printk(KERN_ERR "olpc-ec: timeout waiting for" 173 171 " EC to provide data!\n"); 174 - goto restart; 172 + if (restarts++ < 10) 173 + goto restart; 174 + goto err; 175 175 } 176 176 outbuf[i] = inb(0x68); 177 177 pr_devel("olpc-ec: received 0x%x\n", outbuf[i]); ··· 187 183 } 188 184 EXPORT_SYMBOL_GPL(olpc_ec_cmd); 189 185 190 - #ifdef CONFIG_OLPC_OPENFIRMWARE 191 - static void __init platform_detect(void) 186 + static bool __init check_ofw_architecture(void) 187 + { 188 + size_t propsize; 189 + char olpc_arch[5]; 190 + const void *args[] = { NULL, "architecture", olpc_arch, (void *)5 }; 191 + void *res[] = { &propsize }; 192 + 193 + if (olpc_ofw("getprop", args, res)) { 194 + printk(KERN_ERR "ofw: getprop call failed!\n"); 195 + return false; 196 + } 197 + return propsize == 5 && strncmp("OLPC", olpc_arch, 5) == 0; 198 + } 199 + 200 + static u32 __init get_board_revision(void) 192 201 { 193 202 size_t propsize; 194 203 __be32 rev; ··· 210 193 211 194 if (olpc_ofw("getprop", args, res) || propsize != 4) { 212 195 printk(KERN_ERR "ofw: getprop call failed!\n"); 213 - rev = cpu_to_be32(0); 196 + return cpu_to_be32(0); 214 197 } 215 - olpc_platform_info.boardrev = be32_to_cpu(rev); 198 + return be32_to_cpu(rev); 216 199 } 217 - #else 218 - static void __init platform_detect(void) 200 + 201 + static bool __init platform_detect(void) 219 202 { 220 - /* stopgap until OFW support is added to the kernel */ 221 - olpc_platform_info.boardrev = olpc_board(0xc2); 203 + if (!check_ofw_architecture()) 204 + return false; 205 + olpc_platform_info.flags |= OLPC_F_PRESENT; 206 + olpc_platform_info.boardrev = get_board_revision(); 207 + return true; 222 208 } 223 - #endif 209 + 210 + static int __init add_xo1_platform_devices(void) 211 + { 212 + struct platform_device *pdev; 213 + 214 + pdev = platform_device_register_simple("xo1-rfkill", -1, NULL, 0); 215 + if (IS_ERR(pdev)) 216 + return PTR_ERR(pdev); 217 + 218 + pdev = platform_device_register_simple("olpc-xo1", -1, NULL, 0); 219 + if (IS_ERR(pdev)) 220 + return PTR_ERR(pdev); 221 + 222 + return 0; 223 + } 224 224 225 225 static int __init olpc_init(void) 226 226 { 227 - unsigned char *romsig; 227 + int r = 0; 228 228 229 - /* The ioremap check is dangerous; limit what we run it on */ 230 - if (!is_geode() || cs5535_has_vsa2()) 229 + if (!olpc_ofw_present() || !platform_detect()) 231 230 return 0; 232 231 233 232 spin_lock_init(&ec_lock); 234 - 235 - romsig = ioremap(0xffffffc0, 16); 236 - if (!romsig) 237 - return 0; 238 - 239 - if (strncmp(romsig, "CL1 Q", 7)) 240 - goto unmap; 241 - if (strncmp(romsig+6, romsig+13, 3)) { 242 - printk(KERN_INFO "OLPC BIOS signature looks invalid. " 243 - "Assuming not OLPC\n"); 244 - goto unmap; 245 - } 246 - 247 - printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig); 248 - olpc_platform_info.flags |= OLPC_F_PRESENT; 249 - 250 - /* get the platform revision */ 251 - platform_detect(); 252 233 253 234 /* assume B1 and above models always have a DCON */ 254 235 if (olpc_board_at_least(olpc_board(0xb1))) ··· 257 242 (unsigned char *) &olpc_platform_info.ecver, 1); 258 243 259 244 #ifdef CONFIG_PCI_OLPC 260 - /* If the VSA exists let it emulate PCI, if not emulate in kernel */ 261 - if (!cs5535_has_vsa2()) 245 + /* If the VSA exists let it emulate PCI, if not emulate in kernel. 246 + * XO-1 only. */ 247 + if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) && 248 + !cs5535_has_vsa2()) 262 249 x86_init.pci.arch_init = pci_olpc_init; 263 250 #endif 264 251 ··· 269 252 olpc_platform_info.boardrev >> 4, 270 253 olpc_platform_info.ecver); 271 254 272 - unmap: 273 - iounmap(romsig); 255 + if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */ 256 + r = add_xo1_platform_devices(); 257 + if (r) 258 + return r; 259 + } 260 + 274 261 return 0; 275 262 } 276 263
+6
arch/x86/kernel/olpc_ofw.c
··· 74 74 } 75 75 EXPORT_SYMBOL_GPL(__olpc_ofw); 76 76 77 + bool olpc_ofw_present(void) 78 + { 79 + return olpc_ofw_cif != NULL; 80 + } 81 + EXPORT_SYMBOL_GPL(olpc_ofw_present); 82 + 77 83 /* OFW cif _should_ be above this address */ 78 84 #define OFW_MIN 0xff000000 79 85
+1 -1
arch/x86/pci/olpc.c
··· 304 304 305 305 int __init pci_olpc_init(void) 306 306 { 307 - printk(KERN_INFO "PCI: Using configuration type OLPC\n"); 307 + printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n"); 308 308 raw_pci_ops = &pci_olpc_conf; 309 309 is_lx = is_geode_lx(); 310 310 return 0;