Merge branch 'x86/platform' into x86/apic-cleanups

Reason: apic cleanup series depends on x86/apic, x86/amd-nb and x86/platform

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

+1934 -18
+1
Documentation/x86/boot.txt
··· 600 0x00000001 lguest 601 0x00000002 Xen 602 0x00000003 Moorestown MID 603 604 Field name: hardware_subarch_data 605 Type: write (subarch-dependent)
··· 600 0x00000001 lguest 601 0x00000002 Xen 602 0x00000003 Moorestown MID 603 + 0x00000004 CE4100 TV Platform 604 605 Field name: hardware_subarch_data 606 Type: write (subarch-dependent)
+29
arch/x86/Kconfig
··· 377 378 If unsure, choose "PC-compatible" instead. 379 380 config X86_MRST 381 bool "Moorestown MID platform" 382 depends on PCI ··· 397 depends on X86_EXTENDED_PLATFORM 398 depends on X86_IO_APIC 399 select APB_TIMER 400 ---help--- 401 Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin 402 Internet Device(MID) platform. Moorestown consists of two chips: ··· 481 ---help--- 482 Support for Unisys ES7000 systems. Say 'Y' here if this kernel is 483 supposed to run on an IA32-based Unisys ES7000 system. 484 485 config SCHED_OMIT_FRAME_POINTER 486 def_bool y
··· 377 378 If unsure, choose "PC-compatible" instead. 379 380 + config X86_INTEL_CE 381 + bool "CE4100 TV platform" 382 + depends on PCI 383 + depends on PCI_GODIRECT 384 + depends on X86_32 385 + depends on X86_EXTENDED_PLATFORM 386 + select X86_REBOOTFIXUPS 387 + ---help--- 388 + Select for the Intel CE media processor (CE4100) SOC. 389 + This option compiles in support for the CE4100 SOC for settop 390 + boxes and media devices. 391 + 392 config X86_MRST 393 bool "Moorestown MID platform" 394 depends on PCI ··· 385 depends on X86_EXTENDED_PLATFORM 386 depends on X86_IO_APIC 387 select APB_TIMER 388 + select I2C 389 + select SPI 390 + select INTEL_SCU_IPC 391 + select X86_PLATFORM_DEVICES 392 ---help--- 393 Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin 394 Internet Device(MID) platform. Moorestown consists of two chips: ··· 465 ---help--- 466 Support for Unisys ES7000 systems. Say 'Y' here if this kernel is 467 supposed to run on an IA32-based Unisys ES7000 system. 468 + 469 + config X86_32_IRIS 470 + tristate "Eurobraille/Iris poweroff module" 471 + depends on X86_32 472 + ---help--- 473 + The Iris machines from EuroBraille do not have APM or ACPI support 474 + to shut themselves down properly. A special I/O sequence is 475 + needed to do so, which is what this module does at 476 + kernel shutdown. 477 + 478 + This is only for Iris machines from EuroBraille. 479 + 480 + If unused, say N. 481 482 config SCHED_OMIT_FRAME_POINTER 483 def_bool y
+1
arch/x86/include/asm/bootparam.h
··· 124 X86_SUBARCH_LGUEST, 125 X86_SUBARCH_XEN, 126 X86_SUBARCH_MRST, 127 X86_NR_SUBARCHS, 128 }; 129
··· 124 X86_SUBARCH_LGUEST, 125 X86_SUBARCH_XEN, 126 X86_SUBARCH_MRST, 127 + X86_SUBARCH_CE4100, 128 X86_NR_SUBARCHS, 129 }; 130
+4
arch/x86/include/asm/fixmap.h
··· 117 FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ 118 FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ 119 __end_of_permanent_fixed_addresses, 120 /* 121 * 256 temporary boot-time mappings, used by early_ioremap(), 122 * before ioremap() is functional.
··· 117 FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ 118 FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ 119 __end_of_permanent_fixed_addresses, 120 + 121 + #ifdef CONFIG_X86_MRST 122 + FIX_LNW_VRTC, 123 + #endif 124 /* 125 * 256 temporary boot-time mappings, used by early_ioremap(), 126 * before ioremap() is functional.
+9
arch/x86/include/asm/mrst-vrtc.h
···
··· 1 + #ifndef _MRST_VRTC_H 2 + #define _MRST_VRTC_H 3 + 4 + extern unsigned char vrtc_cmos_read(unsigned char reg); 5 + extern void vrtc_cmos_write(unsigned char val, unsigned char reg); 6 + extern unsigned long vrtc_get_time(void); 7 + extern int vrtc_set_mmss(unsigned long nowtime); 8 + 9 + #endif
+13 -1
arch/x86/include/asm/mrst.h
··· 14 #include <linux/sfi.h> 15 16 extern int pci_mrst_init(void); 17 - int __init sfi_parse_mrtc(struct sfi_table_header *table); 18 19 /* 20 * Medfield is the follow-up of Moorestown, it combines two chip solution into ··· 52 53 extern struct console early_hsu_console; 54 extern void hsu_early_console_init(void); 55 #endif /* _ASM_X86_MRST_H */
··· 14 #include <linux/sfi.h> 15 16 extern int pci_mrst_init(void); 17 + extern int __init sfi_parse_mrtc(struct sfi_table_header *table); 18 + extern int sfi_mrtc_num; 19 + extern struct sfi_rtc_table_entry sfi_mrtc_array[]; 20 21 /* 22 * Medfield is the follow-up of Moorestown, it combines two chip solution into ··· 50 51 extern struct console early_hsu_console; 52 extern void hsu_early_console_init(void); 53 + 54 + extern void intel_scu_devices_create(void); 55 + extern void intel_scu_devices_destroy(void); 56 + 57 + /* VRTC timer */ 58 + #define MRST_VRTC_MAP_SZ (1024) 59 + /*#define MRST_VRTC_PGOFFSET (0xc00) */ 60 + 61 + extern void mrst_rtc_init(void); 62 + 63 #endif /* _ASM_X86_MRST_H */
+6
arch/x86/include/asm/setup.h
··· 53 static inline void x86_mrst_early_setup(void) { } 54 #endif 55 56 #ifndef _SETUP 57 58 /*
··· 53 static inline void x86_mrst_early_setup(void) { } 54 #endif 55 56 + #ifdef CONFIG_X86_INTEL_CE 57 + extern void x86_ce4100_early_setup(void); 58 + #else 59 + static inline void x86_ce4100_early_setup(void) { } 60 + #endif 61 + 62 #ifndef _SETUP 63 64 /*
-1
arch/x86/kernel/Makefile
··· 84 obj-$(CONFIG_KGDB) += kgdb.o 85 obj-$(CONFIG_VM86) += vm86_32.o 86 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 87 - obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o 88 89 obj-$(CONFIG_HPET_TIMER) += hpet.o 90 obj-$(CONFIG_APB_TIMER) += apb_timer.o
··· 84 obj-$(CONFIG_KGDB) += kgdb.o 85 obj-$(CONFIG_VM86) += vm86_32.o 86 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 87 88 obj-$(CONFIG_HPET_TIMER) += hpet.o 89 obj-$(CONFIG_APB_TIMER) += apb_timer.o
+1
arch/x86/kernel/apb_timer.c
··· 315 316 if (system_state == SYSTEM_BOOTING) { 317 irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); 318 /* APB timer irqs are set up as mp_irqs, timer is edge type */ 319 __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); 320 if (request_irq(adev->irq, apbt_interrupt_handler,
··· 315 316 if (system_state == SYSTEM_BOOTING) { 317 irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); 318 + irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); 319 /* APB timer irqs are set up as mp_irqs, timer is edge type */ 320 __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); 321 if (request_irq(adev->irq, apbt_interrupt_handler,
+1 -2
arch/x86/kernel/early_printk.c
··· 240 if (!strncmp(buf, "xen", 3)) 241 early_console_register(&xenboot_console, keep); 242 #endif 243 - #ifdef CONFIG_X86_MRST_EARLY_PRINTK 244 if (!strncmp(buf, "mrst", 4)) { 245 mrst_early_console_init(); 246 early_console_register(&early_mrst_console, keep); ··· 250 hsu_early_console_init(); 251 early_console_register(&early_hsu_console, keep); 252 } 253 - 254 #endif 255 buf++; 256 }
··· 240 if (!strncmp(buf, "xen", 3)) 241 early_console_register(&xenboot_console, keep); 242 #endif 243 + #ifdef CONFIG_EARLY_PRINTK_MRST 244 if (!strncmp(buf, "mrst", 4)) { 245 mrst_early_console_init(); 246 early_console_register(&early_mrst_console, keep); ··· 250 hsu_early_console_init(); 251 early_console_register(&early_hsu_console, keep); 252 } 253 #endif 254 buf++; 255 }
arch/x86/kernel/early_printk_mrst.c arch/x86/platform/mrst/early_printk_mrst.c
+3
arch/x86/kernel/head32.c
··· 61 case X86_SUBARCH_MRST: 62 x86_mrst_early_setup(); 63 break; 64 default: 65 i386_default_early_setup(); 66 break;
··· 61 case X86_SUBARCH_MRST: 62 x86_mrst_early_setup(); 63 break; 64 + case X86_SUBARCH_CE4100: 65 + x86_ce4100_early_setup(); 66 + break; 67 default: 68 i386_default_early_setup(); 69 break;
+16
arch/x86/kernel/reboot_fixups_32.c
··· 43 outb(1, 0x92); 44 } 45 46 struct device_fixup { 47 unsigned int vendor; 48 unsigned int device; 49 void (*reboot_fixup)(struct pci_dev *); 50 }; 51 52 static const struct device_fixup fixups_table[] = { 53 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, 54 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, 55 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, 56 { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, 57 }; 58 59 /*
··· 43 outb(1, 0x92); 44 } 45 46 + static void ce4100_reset(struct pci_dev *dev) 47 + { 48 + int i; 49 + 50 + for (i = 0; i < 10; i++) { 51 + outb(0x2, 0xcf9); 52 + udelay(50); 53 + } 54 + } 55 + 56 struct device_fixup { 57 unsigned int vendor; 58 unsigned int device; 59 void (*reboot_fixup)(struct pci_dev *); 60 }; 61 62 + /* 63 + * PCI ids solely used for fixups_table go here 64 + */ 65 + #define PCI_DEVICE_ID_INTEL_CE4100 0x0708 66 + 67 static const struct device_fixup fixups_table[] = { 68 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, 69 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, 70 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, 71 { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, 72 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100, ce4100_reset }, 73 }; 74 75 /*
+1
arch/x86/pci/Makefile
··· 7 obj-$(CONFIG_PCI_XEN) += xen.o 8 9 obj-y += fixup.o 10 obj-$(CONFIG_ACPI) += acpi.o 11 obj-y += legacy.o irq.o 12
··· 7 obj-$(CONFIG_PCI_XEN) += xen.o 8 9 obj-y += fixup.o 10 + obj-$(CONFIG_X86_INTEL_CE) += ce4100.o 11 obj-$(CONFIG_ACPI) += acpi.o 12 obj-y += legacy.o irq.o 13
+315
arch/x86/pci/ce4100.c
···
··· 1 + /* 2 + * GPL LICENSE SUMMARY 3 + * 4 + * Copyright(c) 2010 Intel Corporation. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of version 2 of the GNU General Public License as 8 + * published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, but 11 + * WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 + * General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 + * The full GNU General Public License is included in this distribution 19 + * in the file called LICENSE.GPL. 20 + * 21 + * Contact Information: 22 + * Intel Corporation 23 + * 2200 Mission College Blvd. 24 + * Santa Clara, CA 97052 25 + * 26 + * This provides access methods for PCI registers that mis-behave on 27 + * the CE4100. Each register can be assigned a private init, read and 28 + * write routine. The exception to this is the bridge device. The 29 + * bridge device is the only device on bus zero (0) that requires any 30 + * fixup so it is a special case ATM 31 + */ 32 + 33 + #include <linux/kernel.h> 34 + #include <linux/pci.h> 35 + #include <linux/init.h> 36 + 37 + #include <asm/pci_x86.h> 38 + 39 + struct sim_reg { 40 + u32 value; 41 + u32 mask; 42 + }; 43 + 44 + struct sim_dev_reg { 45 + int dev_func; 46 + int reg; 47 + void (*init)(struct sim_dev_reg *reg); 48 + void (*read)(struct sim_dev_reg *reg, u32 *value); 49 + void (*write)(struct sim_dev_reg *reg, u32 value); 50 + struct sim_reg sim_reg; 51 + }; 52 + 53 + struct sim_reg_op { 54 + void (*init)(struct sim_dev_reg *reg); 55 + void (*read)(struct sim_dev_reg *reg, u32 value); 56 + void (*write)(struct sim_dev_reg *reg, u32 value); 57 + }; 58 + 59 + #define MB (1024 * 1024) 60 + #define KB (1024) 61 + #define SIZE_TO_MASK(size) (~(size - 1)) 62 + 63 + #define DEFINE_REG(device, func, offset, size, init_op, read_op, write_op)\ 64 + { PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\ 65 + {0, SIZE_TO_MASK(size)} }, 66 + 67 + static void reg_init(struct sim_dev_reg *reg) 68 + { 69 + pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4, 70 + &reg->sim_reg.value); 71 + } 72 + 73 + static void reg_read(struct sim_dev_reg *reg, u32 *value) 74 + { 75 + unsigned long flags; 76 + 77 + raw_spin_lock_irqsave(&pci_config_lock, flags); 78 + *value = reg->sim_reg.value; 79 + raw_spin_unlock_irqrestore(&pci_config_lock, flags); 80 + } 81 + 82 + static void reg_write(struct sim_dev_reg *reg, u32 value) 83 + { 84 + unsigned long flags; 85 + 86 + raw_spin_lock_irqsave(&pci_config_lock, flags); 87 + reg->sim_reg.value = (value & reg->sim_reg.mask) | 88 + (reg->sim_reg.value & ~reg->sim_reg.mask); 89 + raw_spin_unlock_irqrestore(&pci_config_lock, flags); 90 + } 91 + 92 + static void sata_reg_init(struct sim_dev_reg *reg) 93 + { 94 + pci_direct_conf1.read(0, 1, PCI_DEVFN(14, 0), 0x10, 4, 95 + &reg->sim_reg.value); 96 + reg->sim_reg.value += 0x400; 97 + } 98 + 99 + static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value) 100 + { 101 + reg_read(reg, value); 102 + if (*value != reg->sim_reg.mask) 103 + *value |= 0x100; 104 + } 105 + 106 + void sata_revid_init(struct sim_dev_reg *reg) 107 + { 108 + reg->sim_reg.value = 0x01060100; 109 + reg->sim_reg.mask = 0; 110 + } 111 + 112 + static void sata_revid_read(struct sim_dev_reg *reg, u32 *value) 113 + { 114 + reg_read(reg, value); 115 + } 116 + 117 + static struct sim_dev_reg bus1_fixups[] = { 118 + DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write) 119 + DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write) 120 + DEFINE_REG(2, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) 121 + DEFINE_REG(3, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) 122 + DEFINE_REG(4, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) 123 + DEFINE_REG(4, 1, 0x10, (128*KB), reg_init, reg_read, reg_write) 124 + DEFINE_REG(6, 0, 0x10, (512*KB), reg_init, reg_read, reg_write) 125 + DEFINE_REG(6, 1, 0x10, (512*KB), reg_init, reg_read, reg_write) 126 + DEFINE_REG(6, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) 127 + DEFINE_REG(8, 0, 0x10, (1*MB), reg_init, reg_read, reg_write) 128 + DEFINE_REG(8, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) 129 + DEFINE_REG(8, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) 130 + DEFINE_REG(9, 0, 0x10 , (1*MB), reg_init, reg_read, reg_write) 131 + DEFINE_REG(9, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) 132 + DEFINE_REG(10, 0, 0x10, (256), reg_init, reg_read, reg_write) 133 + DEFINE_REG(10, 0, 0x14, (256*MB), reg_init, reg_read, reg_write) 134 + DEFINE_REG(11, 0, 0x10, (256), reg_init, reg_read, reg_write) 135 + DEFINE_REG(11, 0, 0x14, (256), reg_init, reg_read, reg_write) 136 + DEFINE_REG(11, 1, 0x10, (256), reg_init, reg_read, reg_write) 137 + DEFINE_REG(11, 2, 0x10, (256), reg_init, reg_read, reg_write) 138 + DEFINE_REG(11, 2, 0x14, (256), reg_init, reg_read, reg_write) 139 + DEFINE_REG(11, 2, 0x18, (256), reg_init, reg_read, reg_write) 140 + DEFINE_REG(11, 3, 0x10, (256), reg_init, reg_read, reg_write) 141 + DEFINE_REG(11, 3, 0x14, (256), reg_init, reg_read, reg_write) 142 + DEFINE_REG(11, 4, 0x10, (256), reg_init, reg_read, reg_write) 143 + DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write) 144 + DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write) 145 + DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write) 146 + DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) 147 + DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write) 148 + DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write) 149 + DEFINE_REG(13, 0, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) 150 + DEFINE_REG(13, 1, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) 151 + DEFINE_REG(14, 0, 0x8, 0, sata_revid_init, sata_revid_read, 0) 152 + DEFINE_REG(14, 0, 0x10, 0, reg_init, reg_read, reg_write) 153 + DEFINE_REG(14, 0, 0x14, 0, reg_init, reg_read, reg_write) 154 + DEFINE_REG(14, 0, 0x18, 0, reg_init, reg_read, reg_write) 155 + DEFINE_REG(14, 0, 0x1C, 0, reg_init, reg_read, reg_write) 156 + DEFINE_REG(14, 0, 0x20, 0, reg_init, reg_read, reg_write) 157 + DEFINE_REG(14, 0, 0x24, (0x200), sata_reg_init, reg_read, reg_write) 158 + DEFINE_REG(15, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) 159 + DEFINE_REG(15, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) 160 + DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) 161 + DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write) 162 + DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write) 163 + DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) 164 + DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write) 165 + }; 166 + 167 + static void __init init_sim_regs(void) 168 + { 169 + int i; 170 + 171 + for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { 172 + if (bus1_fixups[i].init) 173 + bus1_fixups[i].init(&bus1_fixups[i]); 174 + } 175 + } 176 + 177 + static inline void extract_bytes(u32 *value, int reg, int len) 178 + { 179 + uint32_t mask; 180 + 181 + *value >>= ((reg & 3) * 8); 182 + mask = 0xFFFFFFFF >> ((4 - len) * 8); 183 + *value &= mask; 184 + } 185 + 186 + int bridge_read(unsigned int devfn, int reg, int len, u32 *value) 187 + { 188 + u32 av_bridge_base, av_bridge_limit; 189 + int retval = 0; 190 + 191 + switch (reg) { 192 + /* Make BARs appear to not request any memory. */ 193 + case PCI_BASE_ADDRESS_0: 194 + case PCI_BASE_ADDRESS_0 + 1: 195 + case PCI_BASE_ADDRESS_0 + 2: 196 + case PCI_BASE_ADDRESS_0 + 3: 197 + *value = 0; 198 + break; 199 + 200 + /* Since subordinate bus number register is hardwired 201 + * to zero and read only, so do the simulation. 202 + */ 203 + case PCI_PRIMARY_BUS: 204 + if (len == 4) 205 + *value = 0x00010100; 206 + break; 207 + 208 + case PCI_SUBORDINATE_BUS: 209 + *value = 1; 210 + break; 211 + 212 + case PCI_MEMORY_BASE: 213 + case PCI_MEMORY_LIMIT: 214 + /* Get the A/V bridge base address. */ 215 + pci_direct_conf1.read(0, 0, devfn, 216 + PCI_BASE_ADDRESS_0, 4, &av_bridge_base); 217 + 218 + av_bridge_limit = av_bridge_base + (512*MB - 1); 219 + av_bridge_limit >>= 16; 220 + av_bridge_limit &= 0xFFF0; 221 + 222 + av_bridge_base >>= 16; 223 + av_bridge_base &= 0xFFF0; 224 + 225 + if (reg == PCI_MEMORY_LIMIT) 226 + *value = av_bridge_limit; 227 + else if (len == 2) 228 + *value = av_bridge_base; 229 + else 230 + *value = (av_bridge_limit << 16) | av_bridge_base; 231 + break; 232 + /* Make prefetchable memory limit smaller than prefetchable 233 + * memory base, so not claim prefetchable memory space. 234 + */ 235 + case PCI_PREF_MEMORY_BASE: 236 + *value = 0xFFF0; 237 + break; 238 + case PCI_PREF_MEMORY_LIMIT: 239 + *value = 0x0; 240 + break; 241 + /* Make IO limit smaller than IO base, so not claim IO space. */ 242 + case PCI_IO_BASE: 243 + *value = 0xF0; 244 + break; 245 + case PCI_IO_LIMIT: 246 + *value = 0; 247 + break; 248 + default: 249 + retval = 1; 250 + } 251 + return retval; 252 + } 253 + 254 + static int ce4100_conf_read(unsigned int seg, unsigned int bus, 255 + unsigned int devfn, int reg, int len, u32 *value) 256 + { 257 + int i, retval = 1; 258 + 259 + if (bus == 1) { 260 + for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { 261 + if (bus1_fixups[i].dev_func == devfn && 262 + bus1_fixups[i].reg == (reg & ~3) && 263 + bus1_fixups[i].read) { 264 + bus1_fixups[i].read(&(bus1_fixups[i]), 265 + value); 266 + extract_bytes(value, reg, len); 267 + return 0; 268 + } 269 + } 270 + } 271 + 272 + if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) && 273 + !bridge_read(devfn, reg, len, value)) 274 + return 0; 275 + 276 + return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); 277 + } 278 + 279 + static int ce4100_conf_write(unsigned int seg, unsigned int bus, 280 + unsigned int devfn, int reg, int len, u32 value) 281 + { 282 + int i; 283 + 284 + if (bus == 1) { 285 + for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { 286 + if (bus1_fixups[i].dev_func == devfn && 287 + bus1_fixups[i].reg == (reg & ~3) && 288 + bus1_fixups[i].write) { 289 + bus1_fixups[i].write(&(bus1_fixups[i]), 290 + value); 291 + return 0; 292 + } 293 + } 294 + } 295 + 296 + /* Discard writes to A/V bridge BAR. */ 297 + if (bus == 0 && PCI_DEVFN(1, 0) == devfn && 298 + ((reg & ~3) == PCI_BASE_ADDRESS_0)) 299 + return 0; 300 + 301 + return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); 302 + } 303 + 304 + struct pci_raw_ops ce4100_pci_conf = { 305 + .read = ce4100_conf_read, 306 + .write = ce4100_conf_write, 307 + }; 308 + 309 + static int __init ce4100_pci_init(void) 310 + { 311 + init_sim_regs(); 312 + raw_pci_ops = &ce4100_pci_conf; 313 + return 0; 314 + } 315 + subsys_initcall(ce4100_pci_init);
+2
arch/x86/platform/Makefile
··· 1 # Platform specific code goes here 2 obj-y += efi/ 3 obj-y += mrst/ 4 obj-y += olpc/ 5 obj-y += scx200/
··· 1 # Platform specific code goes here 2 + obj-y += ce4100/ 3 obj-y += efi/ 4 + obj-y += iris/ 5 obj-y += mrst/ 6 obj-y += olpc/ 7 obj-y += scx200/
+1
arch/x86/platform/ce4100/Makefile
···
··· 1 + obj-$(CONFIG_X86_INTEL_CE) += ce4100.o
+132
arch/x86/platform/ce4100/ce4100.c
···
··· 1 + /* 2 + * Intel CE4100 platform specific setup code 3 + * 4 + * (C) Copyright 2010 Intel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; version 2 9 + * of the License. 10 + */ 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/irq.h> 14 + #include <linux/module.h> 15 + #include <linux/serial_reg.h> 16 + #include <linux/serial_8250.h> 17 + 18 + #include <asm/setup.h> 19 + #include <asm/io.h> 20 + 21 + static int ce4100_i8042_detect(void) 22 + { 23 + return 0; 24 + } 25 + 26 + static void __init sdv_find_smp_config(void) 27 + { 28 + } 29 + 30 + #ifdef CONFIG_SERIAL_8250 31 + 32 + 33 + static unsigned int mem_serial_in(struct uart_port *p, int offset) 34 + { 35 + offset = offset << p->regshift; 36 + return readl(p->membase + offset); 37 + } 38 + 39 + /* 40 + * The UART Tx interrupts are not set under some conditions and therefore serial 41 + * transmission hangs. This is a silicon issue and has not been root caused. The 42 + * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT 43 + * bit of LSR register in interrupt handler to see whether at least one of these 44 + * two bits is set, if so then process the transmit request. If this workaround 45 + * is not applied, then the serial transmission may hang. This workaround is for 46 + * errata number 9 in Errata - B step. 47 + */ 48 + 49 + static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset) 50 + { 51 + unsigned int ret, ier, lsr; 52 + 53 + if (offset == UART_IIR) { 54 + offset = offset << p->regshift; 55 + ret = readl(p->membase + offset); 56 + if (ret & UART_IIR_NO_INT) { 57 + /* see if the TX interrupt should have really set */ 58 + ier = mem_serial_in(p, UART_IER); 59 + /* see if the UART's XMIT interrupt is enabled */ 60 + if (ier & UART_IER_THRI) { 61 + lsr = mem_serial_in(p, UART_LSR); 62 + /* now check to see if the UART should be 63 + generating an interrupt (but isn't) */ 64 + if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) 65 + ret &= ~UART_IIR_NO_INT; 66 + } 67 + } 68 + } else 69 + ret = mem_serial_in(p, offset); 70 + return ret; 71 + } 72 + 73 + static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value) 74 + { 75 + offset = offset << p->regshift; 76 + writel(value, p->membase + offset); 77 + } 78 + 79 + static void ce4100_serial_fixup(int port, struct uart_port *up, 80 + unsigned short *capabilites) 81 + { 82 + #ifdef CONFIG_EARLY_PRINTK 83 + /* 84 + * Over ride the legacy port configuration that comes from 85 + * asm/serial.h. Using the ioport driver then switching to the 86 + * PCI memmaped driver hangs the IOAPIC 87 + */ 88 + if (up->iotype != UPIO_MEM32) { 89 + up->uartclk = 14745600; 90 + up->mapbase = 0xdffe0200; 91 + set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, 92 + up->mapbase & PAGE_MASK); 93 + up->membase = 94 + (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); 95 + up->membase += up->mapbase & ~PAGE_MASK; 96 + up->iotype = UPIO_MEM32; 97 + up->regshift = 2; 98 + } 99 + #endif 100 + up->iobase = 0; 101 + up->serial_in = ce4100_mem_serial_in; 102 + up->serial_out = ce4100_mem_serial_out; 103 + 104 + *capabilites |= (1 << 12); 105 + } 106 + 107 + static __init void sdv_serial_fixup(void) 108 + { 109 + serial8250_set_isa_configurator(ce4100_serial_fixup); 110 + } 111 + 112 + #else 113 + static inline void sdv_serial_fixup(void); 114 + #endif 115 + 116 + static void __init sdv_arch_setup(void) 117 + { 118 + sdv_serial_fixup(); 119 + } 120 + 121 + /* 122 + * CE4100 specific x86_init function overrides and early setup 123 + * calls. 124 + */ 125 + void __init x86_ce4100_early_setup(void) 126 + { 127 + x86_init.oem.arch_setup = sdv_arch_setup; 128 + x86_platform.i8042_detect = ce4100_i8042_detect; 129 + x86_init.resources.probe_roms = x86_init_noop; 130 + x86_init.mpparse.get_smp_config = x86_init_uint_noop; 131 + x86_init.mpparse.find_smp_config = sdv_find_smp_config; 132 + }
+1
arch/x86/platform/iris/Makefile
···
··· 1 + obj-$(CONFIG_X86_32_IRIS) += iris.o
+91
arch/x86/platform/iris/iris.c
···
··· 1 + /* 2 + * Eurobraille/Iris power off support. 3 + * 4 + * Eurobraille's Iris machine is a PC with no APM or ACPI support. 5 + * It is shutdown by a special I/O sequence which this module provides. 6 + * 7 + * Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org> 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 + * 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. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with the program ; if not, write to the Free Software 21 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 + */ 23 + 24 + #include <linux/moduleparam.h> 25 + #include <linux/module.h> 26 + #include <linux/kernel.h> 27 + #include <linux/errno.h> 28 + #include <linux/delay.h> 29 + #include <linux/init.h> 30 + #include <linux/pm.h> 31 + #include <asm/io.h> 32 + 33 + #define IRIS_GIO_BASE 0x340 34 + #define IRIS_GIO_INPUT IRIS_GIO_BASE 35 + #define IRIS_GIO_OUTPUT (IRIS_GIO_BASE + 1) 36 + #define IRIS_GIO_PULSE 0x80 /* First byte to send */ 37 + #define IRIS_GIO_REST 0x00 /* Second byte to send */ 38 + #define IRIS_GIO_NODEV 0xff /* Likely not an Iris */ 39 + 40 + MODULE_LICENSE("GPL"); 41 + MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>"); 42 + MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille"); 43 + MODULE_SUPPORTED_DEVICE("Eurobraille/Iris"); 44 + 45 + static int force; 46 + 47 + module_param(force, bool, 0); 48 + MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation."); 49 + 50 + static void (*old_pm_power_off)(void); 51 + 52 + static void iris_power_off(void) 53 + { 54 + outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT); 55 + msleep(850); 56 + outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT); 57 + } 58 + 59 + /* 60 + * Before installing the power_off handler, try to make sure the OS is 61 + * running on an Iris. Since Iris does not support DMI, this is done 62 + * by reading its input port and seeing whether the read value is 63 + * meaningful. 64 + */ 65 + static int iris_init(void) 66 + { 67 + unsigned char status; 68 + if (force != 1) { 69 + printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n"); 70 + return -ENODEV; 71 + } 72 + status = inb(IRIS_GIO_INPUT); 73 + if (status == IRIS_GIO_NODEV) { 74 + printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n"); 75 + return -ENODEV; 76 + } 77 + old_pm_power_off = pm_power_off; 78 + pm_power_off = &iris_power_off; 79 + printk(KERN_INFO "Iris power_off handler installed.\n"); 80 + 81 + return 0; 82 + } 83 + 84 + static void iris_exit(void) 85 + { 86 + pm_power_off = old_pm_power_off; 87 + printk(KERN_INFO "Iris power_off handler uninstalled.\n"); 88 + } 89 + 90 + module_init(iris_init); 91 + module_exit(iris_exit);
+2
arch/x86/platform/mrst/Makefile
··· 1 obj-$(CONFIG_X86_MRST) += mrst.o
··· 1 obj-$(CONFIG_X86_MRST) += mrst.o 2 + obj-$(CONFIG_X86_MRST) += vrtc.o 3 + obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
+535 -11
arch/x86/platform/mrst/mrst.c
··· 9 * as published by the Free Software Foundation; version 2 10 * of the License. 11 */ 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/sfi.h> 15 #include <linux/irq.h> 16 #include <linux/module.h> 17 ··· 33 #include <asm/mrst.h> 34 #include <asm/io.h> 35 #include <asm/i8259.h> 36 #include <asm/apb_timer.h> 37 38 /* 39 * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, ··· 114 memcpy(sfi_mtimer_array, pentry, totallen); 115 } 116 117 - printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num); 118 pentry = sfi_mtimer_array; 119 for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { 120 - printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz," 121 " irq = %d\n", totallen, (u32)pentry->phys_addr, 122 pentry->freq_hz, pentry->irq); 123 if (!pentry->irq) ··· 188 memcpy(sfi_mrtc_array, pentry, totallen); 189 } 190 191 - printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num); 192 pentry = sfi_mrtc_array; 193 for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { 194 - printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n", 195 totallen, (u32)pentry->phys_addr, pentry->irq); 196 mp_irq.type = MP_IOAPIC; 197 mp_irq.irqtype = mp_INT; 198 - mp_irq.irqflag = 0; 199 mp_irq.srcbus = 0; 200 mp_irq.srcbusirq = pentry->irq; /* IRQ */ 201 mp_irq.dstapic = MP_APIC_ALL; ··· 221 222 void __init mrst_time_init(void) 223 { 224 switch (mrst_timer_options) { 225 case MRST_TIMER_APBT_ONLY: 226 break; ··· 237 return; 238 } 239 /* we need at least one APB timer */ 240 - sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); 241 pre_init_apic_IRQ0(); 242 apbt_time_init(); 243 - } 244 - 245 - void __init mrst_rtc_init(void) 246 - { 247 - sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); 248 } 249 250 void __cpuinit mrst_arch_setup(void) ··· 261 static int mrst_i8042_detect(void) 262 { 263 return 0; 264 } 265 266 /* ··· 298 x86_init.pci.fixup_irqs = x86_init_noop; 299 300 legacy_pic = &null_legacy_pic; 301 302 /* Avoid searching for BIOS MP tables */ 303 x86_init.mpparse.find_smp_config = x86_init_noop; ··· 331 return 0; 332 } 333 __setup("x86_mrst_timer=", setup_x86_mrst_timer);
··· 9 * as published by the Free Software Foundation; version 2 10 * of the License. 11 */ 12 + 13 + #define pr_fmt(fmt) "mrst: " fmt 14 + 15 #include <linux/init.h> 16 #include <linux/kernel.h> 17 #include <linux/sfi.h> 18 + #include <linux/intel_pmic_gpio.h> 19 + #include <linux/spi/spi.h> 20 + #include <linux/i2c.h> 21 + #include <linux/i2c/pca953x.h> 22 + #include <linux/gpio_keys.h> 23 + #include <linux/input.h> 24 + #include <linux/platform_device.h> 25 #include <linux/irq.h> 26 #include <linux/module.h> 27 ··· 23 #include <asm/mrst.h> 24 #include <asm/io.h> 25 #include <asm/i8259.h> 26 + #include <asm/intel_scu_ipc.h> 27 #include <asm/apb_timer.h> 28 + #include <asm/reboot.h> 29 30 /* 31 * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, ··· 102 memcpy(sfi_mtimer_array, pentry, totallen); 103 } 104 105 + pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); 106 pentry = sfi_mtimer_array; 107 for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { 108 + pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," 109 " irq = %d\n", totallen, (u32)pentry->phys_addr, 110 pentry->freq_hz, pentry->irq); 111 if (!pentry->irq) ··· 176 memcpy(sfi_mrtc_array, pentry, totallen); 177 } 178 179 + pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); 180 pentry = sfi_mrtc_array; 181 for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { 182 + pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", 183 totallen, (u32)pentry->phys_addr, pentry->irq); 184 mp_irq.type = MP_IOAPIC; 185 mp_irq.irqtype = mp_INT; 186 + mp_irq.irqflag = 0xf; /* level trigger and active low */ 187 mp_irq.srcbus = 0; 188 mp_irq.srcbusirq = pentry->irq; /* IRQ */ 189 mp_irq.dstapic = MP_APIC_ALL; ··· 209 210 void __init mrst_time_init(void) 211 { 212 + sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); 213 switch (mrst_timer_options) { 214 case MRST_TIMER_APBT_ONLY: 215 break; ··· 224 return; 225 } 226 /* we need at least one APB timer */ 227 pre_init_apic_IRQ0(); 228 apbt_time_init(); 229 } 230 231 void __cpuinit mrst_arch_setup(void) ··· 254 static int mrst_i8042_detect(void) 255 { 256 return 0; 257 + } 258 + 259 + /* Reboot and power off are handled by the SCU on a MID device */ 260 + static void mrst_power_off(void) 261 + { 262 + intel_scu_ipc_simple_command(0xf1, 1); 263 + } 264 + 265 + static void mrst_reboot(void) 266 + { 267 + intel_scu_ipc_simple_command(0xf1, 0); 268 } 269 270 /* ··· 280 x86_init.pci.fixup_irqs = x86_init_noop; 281 282 legacy_pic = &null_legacy_pic; 283 + 284 + /* Moorestown specific power_off/restart method */ 285 + pm_power_off = mrst_power_off; 286 + machine_ops.emergency_restart = mrst_reboot; 287 288 /* Avoid searching for BIOS MP tables */ 289 x86_init.mpparse.find_smp_config = x86_init_noop; ··· 309 return 0; 310 } 311 __setup("x86_mrst_timer=", setup_x86_mrst_timer); 312 + 313 + /* 314 + * Parsing GPIO table first, since the DEVS table will need this table 315 + * to map the pin name to the actual pin. 316 + */ 317 + static struct sfi_gpio_table_entry *gpio_table; 318 + static int gpio_num_entry; 319 + 320 + static int __init sfi_parse_gpio(struct sfi_table_header *table) 321 + { 322 + struct sfi_table_simple *sb; 323 + struct sfi_gpio_table_entry *pentry; 324 + int num, i; 325 + 326 + if (gpio_table) 327 + return 0; 328 + sb = (struct sfi_table_simple *)table; 329 + num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); 330 + pentry = (struct sfi_gpio_table_entry *)sb->pentry; 331 + 332 + gpio_table = (struct sfi_gpio_table_entry *) 333 + kmalloc(num * sizeof(*pentry), GFP_KERNEL); 334 + if (!gpio_table) 335 + return -1; 336 + memcpy(gpio_table, pentry, num * sizeof(*pentry)); 337 + gpio_num_entry = num; 338 + 339 + pr_debug("GPIO pin info:\n"); 340 + for (i = 0; i < num; i++, pentry++) 341 + pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," 342 + " pin = %d\n", i, 343 + pentry->controller_name, 344 + pentry->pin_name, 345 + pentry->pin_no); 346 + return 0; 347 + } 348 + 349 + static int get_gpio_by_name(const char *name) 350 + { 351 + struct sfi_gpio_table_entry *pentry = gpio_table; 352 + int i; 353 + 354 + if (!pentry) 355 + return -1; 356 + for (i = 0; i < gpio_num_entry; i++, pentry++) { 357 + if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) 358 + return pentry->pin_no; 359 + } 360 + return -1; 361 + } 362 + 363 + /* 364 + * Here defines the array of devices platform data that IAFW would export 365 + * through SFI "DEVS" table, we use name and type to match the device and 366 + * its platform data. 367 + */ 368 + struct devs_id { 369 + char name[SFI_NAME_LEN + 1]; 370 + u8 type; 371 + u8 delay; 372 + void *(*get_platform_data)(void *info); 373 + }; 374 + 375 + /* the offset for the mapping of global gpio pin to irq */ 376 + #define MRST_IRQ_OFFSET 0x100 377 + 378 + static void __init *pmic_gpio_platform_data(void *info) 379 + { 380 + static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; 381 + int gpio_base = get_gpio_by_name("pmic_gpio_base"); 382 + 383 + if (gpio_base == -1) 384 + gpio_base = 64; 385 + pmic_gpio_pdata.gpio_base = gpio_base; 386 + pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; 387 + pmic_gpio_pdata.gpiointr = 0xffffeff8; 388 + 389 + return &pmic_gpio_pdata; 390 + } 391 + 392 + static void __init *max3111_platform_data(void *info) 393 + { 394 + struct spi_board_info *spi_info = info; 395 + int intr = get_gpio_by_name("max3111_int"); 396 + 397 + if (intr == -1) 398 + return NULL; 399 + spi_info->irq = intr + MRST_IRQ_OFFSET; 400 + return NULL; 401 + } 402 + 403 + /* we have multiple max7315 on the board ... */ 404 + #define MAX7315_NUM 2 405 + static void __init *max7315_platform_data(void *info) 406 + { 407 + static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; 408 + static int nr; 409 + struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; 410 + struct i2c_board_info *i2c_info = info; 411 + int gpio_base, intr; 412 + char base_pin_name[SFI_NAME_LEN + 1]; 413 + char intr_pin_name[SFI_NAME_LEN + 1]; 414 + 415 + if (nr == MAX7315_NUM) { 416 + pr_err("too many max7315s, we only support %d\n", 417 + MAX7315_NUM); 418 + return NULL; 419 + } 420 + /* we have several max7315 on the board, we only need load several 421 + * instances of the same pca953x driver to cover them 422 + */ 423 + strcpy(i2c_info->type, "max7315"); 424 + if (nr++) { 425 + sprintf(base_pin_name, "max7315_%d_base", nr); 426 + sprintf(intr_pin_name, "max7315_%d_int", nr); 427 + } else { 428 + strcpy(base_pin_name, "max7315_base"); 429 + strcpy(intr_pin_name, "max7315_int"); 430 + } 431 + 432 + gpio_base = get_gpio_by_name(base_pin_name); 433 + intr = get_gpio_by_name(intr_pin_name); 434 + 435 + if (gpio_base == -1) 436 + return NULL; 437 + max7315->gpio_base = gpio_base; 438 + if (intr != -1) { 439 + i2c_info->irq = intr + MRST_IRQ_OFFSET; 440 + max7315->irq_base = gpio_base + MRST_IRQ_OFFSET; 441 + } else { 442 + i2c_info->irq = -1; 443 + max7315->irq_base = -1; 444 + } 445 + return max7315; 446 + } 447 + 448 + static void __init *emc1403_platform_data(void *info) 449 + { 450 + static short intr2nd_pdata; 451 + struct i2c_board_info *i2c_info = info; 452 + int intr = get_gpio_by_name("thermal_int"); 453 + int intr2nd = get_gpio_by_name("thermal_alert"); 454 + 455 + if (intr == -1 || intr2nd == -1) 456 + return NULL; 457 + 458 + i2c_info->irq = intr + MRST_IRQ_OFFSET; 459 + intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; 460 + 461 + return &intr2nd_pdata; 462 + } 463 + 464 + static void __init *lis331dl_platform_data(void *info) 465 + { 466 + static short intr2nd_pdata; 467 + struct i2c_board_info *i2c_info = info; 468 + int intr = get_gpio_by_name("accel_int"); 469 + int intr2nd = get_gpio_by_name("accel_2"); 470 + 471 + if (intr == -1 || intr2nd == -1) 472 + return NULL; 473 + 474 + i2c_info->irq = intr + MRST_IRQ_OFFSET; 475 + intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; 476 + 477 + return &intr2nd_pdata; 478 + } 479 + 480 + static void __init *no_platform_data(void *info) 481 + { 482 + return NULL; 483 + } 484 + 485 + static const struct devs_id __initconst device_ids[] = { 486 + {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, 487 + {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, 488 + {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, 489 + {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, 490 + {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, 491 + {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, 492 + {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 493 + {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 494 + {}, 495 + }; 496 + 497 + #define MAX_IPCDEVS 24 498 + static struct platform_device *ipc_devs[MAX_IPCDEVS]; 499 + static int ipc_next_dev; 500 + 501 + #define MAX_SCU_SPI 24 502 + static struct spi_board_info *spi_devs[MAX_SCU_SPI]; 503 + static int spi_next_dev; 504 + 505 + #define MAX_SCU_I2C 24 506 + static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; 507 + static int i2c_bus[MAX_SCU_I2C]; 508 + static int i2c_next_dev; 509 + 510 + static void __init intel_scu_device_register(struct platform_device *pdev) 511 + { 512 + if(ipc_next_dev == MAX_IPCDEVS) 513 + pr_err("too many SCU IPC devices"); 514 + else 515 + ipc_devs[ipc_next_dev++] = pdev; 516 + } 517 + 518 + static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) 519 + { 520 + struct spi_board_info *new_dev; 521 + 522 + if (spi_next_dev == MAX_SCU_SPI) { 523 + pr_err("too many SCU SPI devices"); 524 + return; 525 + } 526 + 527 + new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); 528 + if (!new_dev) { 529 + pr_err("failed to alloc mem for delayed spi dev %s\n", 530 + sdev->modalias); 531 + return; 532 + } 533 + memcpy(new_dev, sdev, sizeof(*sdev)); 534 + 535 + spi_devs[spi_next_dev++] = new_dev; 536 + } 537 + 538 + static void __init intel_scu_i2c_device_register(int bus, 539 + struct i2c_board_info *idev) 540 + { 541 + struct i2c_board_info *new_dev; 542 + 543 + if (i2c_next_dev == MAX_SCU_I2C) { 544 + pr_err("too many SCU I2C devices"); 545 + return; 546 + } 547 + 548 + new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); 549 + if (!new_dev) { 550 + pr_err("failed to alloc mem for delayed i2c dev %s\n", 551 + idev->type); 552 + return; 553 + } 554 + memcpy(new_dev, idev, sizeof(*idev)); 555 + 556 + i2c_bus[i2c_next_dev] = bus; 557 + i2c_devs[i2c_next_dev++] = new_dev; 558 + } 559 + 560 + /* Called by IPC driver */ 561 + void intel_scu_devices_create(void) 562 + { 563 + int i; 564 + 565 + for (i = 0; i < ipc_next_dev; i++) 566 + platform_device_add(ipc_devs[i]); 567 + 568 + for (i = 0; i < spi_next_dev; i++) 569 + spi_register_board_info(spi_devs[i], 1); 570 + 571 + for (i = 0; i < i2c_next_dev; i++) { 572 + struct i2c_adapter *adapter; 573 + struct i2c_client *client; 574 + 575 + adapter = i2c_get_adapter(i2c_bus[i]); 576 + if (adapter) { 577 + client = i2c_new_device(adapter, i2c_devs[i]); 578 + if (!client) 579 + pr_err("can't create i2c device %s\n", 580 + i2c_devs[i]->type); 581 + } else 582 + i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); 583 + } 584 + } 585 + EXPORT_SYMBOL_GPL(intel_scu_devices_create); 586 + 587 + /* Called by IPC driver */ 588 + void intel_scu_devices_destroy(void) 589 + { 590 + int i; 591 + 592 + for (i = 0; i < ipc_next_dev; i++) 593 + platform_device_del(ipc_devs[i]); 594 + } 595 + EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); 596 + 597 + static void __init install_irq_resource(struct platform_device *pdev, int irq) 598 + { 599 + /* Single threaded */ 600 + static struct resource __initdata res = { 601 + .name = "IRQ", 602 + .flags = IORESOURCE_IRQ, 603 + }; 604 + res.start = irq; 605 + platform_device_add_resources(pdev, &res, 1); 606 + } 607 + 608 + static void __init sfi_handle_ipc_dev(struct platform_device *pdev) 609 + { 610 + const struct devs_id *dev = device_ids; 611 + void *pdata = NULL; 612 + 613 + while (dev->name[0]) { 614 + if (dev->type == SFI_DEV_TYPE_IPC && 615 + !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { 616 + pdata = dev->get_platform_data(pdev); 617 + break; 618 + } 619 + dev++; 620 + } 621 + pdev->dev.platform_data = pdata; 622 + intel_scu_device_register(pdev); 623 + } 624 + 625 + static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info) 626 + { 627 + const struct devs_id *dev = device_ids; 628 + void *pdata = NULL; 629 + 630 + while (dev->name[0]) { 631 + if (dev->type == SFI_DEV_TYPE_SPI && 632 + !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) { 633 + pdata = dev->get_platform_data(spi_info); 634 + break; 635 + } 636 + dev++; 637 + } 638 + spi_info->platform_data = pdata; 639 + if (dev->delay) 640 + intel_scu_spi_device_register(spi_info); 641 + else 642 + spi_register_board_info(spi_info, 1); 643 + } 644 + 645 + static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info) 646 + { 647 + const struct devs_id *dev = device_ids; 648 + void *pdata = NULL; 649 + 650 + while (dev->name[0]) { 651 + if (dev->type == SFI_DEV_TYPE_I2C && 652 + !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) { 653 + pdata = dev->get_platform_data(i2c_info); 654 + break; 655 + } 656 + dev++; 657 + } 658 + i2c_info->platform_data = pdata; 659 + 660 + if (dev->delay) 661 + intel_scu_i2c_device_register(bus, i2c_info); 662 + else 663 + i2c_register_board_info(bus, i2c_info, 1); 664 + } 665 + 666 + 667 + static int __init sfi_parse_devs(struct sfi_table_header *table) 668 + { 669 + struct sfi_table_simple *sb; 670 + struct sfi_device_table_entry *pentry; 671 + struct spi_board_info spi_info; 672 + struct i2c_board_info i2c_info; 673 + struct platform_device *pdev; 674 + int num, i, bus; 675 + int ioapic; 676 + struct io_apic_irq_attr irq_attr; 677 + 678 + sb = (struct sfi_table_simple *)table; 679 + num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); 680 + pentry = (struct sfi_device_table_entry *)sb->pentry; 681 + 682 + for (i = 0; i < num; i++, pentry++) { 683 + if (pentry->irq != (u8)0xff) { /* native RTE case */ 684 + /* these SPI2 devices are not exposed to system as PCI 685 + * devices, but they have separate RTE entry in IOAPIC 686 + * so we have to enable them one by one here 687 + */ 688 + ioapic = mp_find_ioapic(pentry->irq); 689 + irq_attr.ioapic = ioapic; 690 + irq_attr.ioapic_pin = pentry->irq; 691 + irq_attr.trigger = 1; 692 + irq_attr.polarity = 1; 693 + io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); 694 + } 695 + switch (pentry->type) { 696 + case SFI_DEV_TYPE_IPC: 697 + /* ID as IRQ is a hack that will go away */ 698 + pdev = platform_device_alloc(pentry->name, pentry->irq); 699 + if (pdev == NULL) { 700 + pr_err("out of memory for SFI platform device '%s'.\n", 701 + pentry->name); 702 + continue; 703 + } 704 + install_irq_resource(pdev, pentry->irq); 705 + pr_debug("info[%2d]: IPC bus, name = %16.16s, " 706 + "irq = 0x%2x\n", i, pentry->name, pentry->irq); 707 + sfi_handle_ipc_dev(pdev); 708 + break; 709 + case SFI_DEV_TYPE_SPI: 710 + memset(&spi_info, 0, sizeof(spi_info)); 711 + strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); 712 + spi_info.irq = pentry->irq; 713 + spi_info.bus_num = pentry->host_num; 714 + spi_info.chip_select = pentry->addr; 715 + spi_info.max_speed_hz = pentry->max_freq; 716 + pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, " 717 + "irq = 0x%2x, max_freq = %d, cs = %d\n", i, 718 + spi_info.bus_num, 719 + spi_info.modalias, 720 + spi_info.irq, 721 + spi_info.max_speed_hz, 722 + spi_info.chip_select); 723 + sfi_handle_spi_dev(&spi_info); 724 + break; 725 + case SFI_DEV_TYPE_I2C: 726 + memset(&i2c_info, 0, sizeof(i2c_info)); 727 + bus = pentry->host_num; 728 + strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); 729 + i2c_info.irq = pentry->irq; 730 + i2c_info.addr = pentry->addr; 731 + pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " 732 + "irq = 0x%2x, addr = 0x%x\n", i, bus, 733 + i2c_info.type, 734 + i2c_info.irq, 735 + i2c_info.addr); 736 + sfi_handle_i2c_dev(bus, &i2c_info); 737 + break; 738 + case SFI_DEV_TYPE_UART: 739 + case SFI_DEV_TYPE_HSI: 740 + default: 741 + ; 742 + } 743 + } 744 + return 0; 745 + } 746 + 747 + static int __init mrst_platform_init(void) 748 + { 749 + sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); 750 + sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); 751 + return 0; 752 + } 753 + arch_initcall(mrst_platform_init); 754 + 755 + /* 756 + * we will search these buttons in SFI GPIO table (by name) 757 + * and register them dynamically. Please add all possible 758 + * buttons here, we will shrink them if no GPIO found. 759 + */ 760 + static struct gpio_keys_button gpio_button[] = { 761 + {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, 762 + {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, 763 + {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, 764 + {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, 765 + {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, 766 + {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, 767 + {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, 768 + {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, 769 + {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, 770 + {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, 771 + }; 772 + 773 + static struct gpio_keys_platform_data mrst_gpio_keys = { 774 + .buttons = gpio_button, 775 + .rep = 1, 776 + .nbuttons = -1, /* will fill it after search */ 777 + }; 778 + 779 + static struct platform_device pb_device = { 780 + .name = "gpio-keys", 781 + .id = -1, 782 + .dev = { 783 + .platform_data = &mrst_gpio_keys, 784 + }, 785 + }; 786 + 787 + /* 788 + * Shrink the non-existent buttons, register the gpio button 789 + * device if there is some 790 + */ 791 + static int __init pb_keys_init(void) 792 + { 793 + struct gpio_keys_button *gb = gpio_button; 794 + int i, num, good = 0; 795 + 796 + num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); 797 + for (i = 0; i < num; i++) { 798 + gb[i].gpio = get_gpio_by_name(gb[i].desc); 799 + if (gb[i].gpio == -1) 800 + continue; 801 + 802 + if (i != good) 803 + gb[good] = gb[i]; 804 + good++; 805 + } 806 + 807 + if (good) { 808 + mrst_gpio_keys.nbuttons = good; 809 + return platform_device_register(&pb_device); 810 + } 811 + return 0; 812 + } 813 + late_initcall(pb_keys_init);
+165
arch/x86/platform/mrst/vrtc.c
···
··· 1 + /* 2 + * vrtc.c: Driver for virtual RTC device on Intel MID platform 3 + * 4 + * (C) Copyright 2009 Intel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; version 2 9 + * of the License. 10 + * 11 + * Note: 12 + * VRTC is emulated by system controller firmware, the real HW 13 + * RTC is located in the PMIC device. SCU FW shadows PMIC RTC 14 + * in a memory mapped IO space that is visible to the host IA 15 + * processor. 16 + * 17 + * This driver is based on RTC CMOS driver. 18 + */ 19 + 20 + #include <linux/kernel.h> 21 + #include <linux/init.h> 22 + #include <linux/sfi.h> 23 + #include <linux/platform_device.h> 24 + 25 + #include <asm/mrst.h> 26 + #include <asm/mrst-vrtc.h> 27 + #include <asm/time.h> 28 + #include <asm/fixmap.h> 29 + 30 + static unsigned char __iomem *vrtc_virt_base; 31 + 32 + unsigned char vrtc_cmos_read(unsigned char reg) 33 + { 34 + unsigned char retval; 35 + 36 + /* vRTC's registers range from 0x0 to 0xD */ 37 + if (reg > 0xd || !vrtc_virt_base) 38 + return 0xff; 39 + 40 + lock_cmos_prefix(reg); 41 + retval = __raw_readb(vrtc_virt_base + (reg << 2)); 42 + lock_cmos_suffix(reg); 43 + return retval; 44 + } 45 + EXPORT_SYMBOL_GPL(vrtc_cmos_read); 46 + 47 + void vrtc_cmos_write(unsigned char val, unsigned char reg) 48 + { 49 + if (reg > 0xd || !vrtc_virt_base) 50 + return; 51 + 52 + lock_cmos_prefix(reg); 53 + __raw_writeb(val, vrtc_virt_base + (reg << 2)); 54 + lock_cmos_suffix(reg); 55 + } 56 + EXPORT_SYMBOL_GPL(vrtc_cmos_write); 57 + 58 + unsigned long vrtc_get_time(void) 59 + { 60 + u8 sec, min, hour, mday, mon; 61 + u32 year; 62 + 63 + while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) 64 + cpu_relax(); 65 + 66 + sec = vrtc_cmos_read(RTC_SECONDS); 67 + min = vrtc_cmos_read(RTC_MINUTES); 68 + hour = vrtc_cmos_read(RTC_HOURS); 69 + mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); 70 + mon = vrtc_cmos_read(RTC_MONTH); 71 + year = vrtc_cmos_read(RTC_YEAR); 72 + 73 + /* vRTC YEAR reg contains the offset to 1960 */ 74 + year += 1960; 75 + 76 + printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " 77 + "mon: %d year: %d\n", sec, min, hour, mday, mon, year); 78 + 79 + return mktime(year, mon, mday, hour, min, sec); 80 + } 81 + 82 + /* Only care about the minutes and seconds */ 83 + int vrtc_set_mmss(unsigned long nowtime) 84 + { 85 + int real_sec, real_min; 86 + int vrtc_min; 87 + 88 + vrtc_min = vrtc_cmos_read(RTC_MINUTES); 89 + 90 + real_sec = nowtime % 60; 91 + real_min = nowtime / 60; 92 + if (((abs(real_min - vrtc_min) + 15)/30) & 1) 93 + real_min += 30; 94 + real_min %= 60; 95 + 96 + vrtc_cmos_write(real_sec, RTC_SECONDS); 97 + vrtc_cmos_write(real_min, RTC_MINUTES); 98 + return 0; 99 + } 100 + 101 + void __init mrst_rtc_init(void) 102 + { 103 + unsigned long rtc_paddr; 104 + void __iomem *virt_base; 105 + 106 + sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); 107 + if (!sfi_mrtc_num) 108 + return; 109 + 110 + rtc_paddr = sfi_mrtc_array[0].phys_addr; 111 + 112 + /* vRTC's register address may not be page aligned */ 113 + set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr); 114 + 115 + virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC); 116 + virt_base += rtc_paddr & ~PAGE_MASK; 117 + vrtc_virt_base = virt_base; 118 + 119 + x86_platform.get_wallclock = vrtc_get_time; 120 + x86_platform.set_wallclock = vrtc_set_mmss; 121 + } 122 + 123 + /* 124 + * The Moorestown platform has a memory mapped virtual RTC device that emulates 125 + * the programming interface of the RTC. 126 + */ 127 + 128 + static struct resource vrtc_resources[] = { 129 + [0] = { 130 + .flags = IORESOURCE_MEM, 131 + }, 132 + [1] = { 133 + .flags = IORESOURCE_IRQ, 134 + } 135 + }; 136 + 137 + static struct platform_device vrtc_device = { 138 + .name = "rtc_mrst", 139 + .id = -1, 140 + .resource = vrtc_resources, 141 + .num_resources = ARRAY_SIZE(vrtc_resources), 142 + }; 143 + 144 + /* Register the RTC device if appropriate */ 145 + static int __init mrst_device_create(void) 146 + { 147 + /* No Moorestown, no device */ 148 + if (!mrst_identify_cpu()) 149 + return -ENODEV; 150 + /* No timer, no device */ 151 + if (!sfi_mrtc_num) 152 + return -ENODEV; 153 + 154 + /* iomem resource */ 155 + vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; 156 + vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + 157 + MRST_VRTC_MAP_SZ; 158 + /* irq resource */ 159 + vrtc_resources[1].start = sfi_mrtc_array[0].irq; 160 + vrtc_resources[1].end = sfi_mrtc_array[0].irq; 161 + 162 + return platform_device_register(&vrtc_device); 163 + } 164 + 165 + module_init(mrst_device_create);
+5
drivers/platform/x86/intel_scu_ipc.c
··· 26 #include <linux/sfi.h> 27 #include <asm/mrst.h> 28 #include <asm/intel_scu_ipc.h> 29 30 /* IPC defines the following message types */ 31 #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */ ··· 700 iounmap(ipcdev.ipc_base); 701 return -ENOMEM; 702 } 703 return 0; 704 } 705 ··· 724 iounmap(ipcdev.ipc_base); 725 iounmap(ipcdev.i2c_base); 726 ipcdev.pdev = NULL; 727 } 728 729 static const struct pci_device_id pci_ids[] = {
··· 26 #include <linux/sfi.h> 27 #include <asm/mrst.h> 28 #include <asm/intel_scu_ipc.h> 29 + #include <asm/mrst.h> 30 31 /* IPC defines the following message types */ 32 #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */ ··· 699 iounmap(ipcdev.ipc_base); 700 return -ENOMEM; 701 } 702 + 703 + intel_scu_devices_create(); 704 + 705 return 0; 706 } 707 ··· 720 iounmap(ipcdev.ipc_base); 721 iounmap(ipcdev.i2c_base); 722 ipcdev.pdev = NULL; 723 + intel_scu_devices_destroy(); 724 } 725 726 static const struct pci_device_id pci_ids[] = {
+12
drivers/rtc/Kconfig
··· 463 This driver can also be built as a module. If so, the module 464 will be called rtc-cmos. 465 466 config RTC_DRV_DS1216 467 tristate "Dallas DS1216" 468 depends on SNI_RM
··· 463 This driver can also be built as a module. If so, the module 464 will be called rtc-cmos. 465 466 + config RTC_DRV_VRTC 467 + tristate "Virtual RTC for Moorestown platforms" 468 + depends on X86_MRST 469 + default y if X86_MRST 470 + 471 + help 472 + Say "yes" here to get direct support for the real time clock 473 + found on Moorestown platforms. The VRTC is a emulated RTC that 474 + derives its clock source from a real RTC in the PMIC. The MC146818 475 + style programming interface is mostly conserved, but any 476 + updates are done via IPC calls to the system controller FW. 477 + 478 config RTC_DRV_DS1216 479 tristate "Dallas DS1216" 480 depends on SNI_RM
+1
drivers/rtc/Makefile
··· 30 obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o 31 obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o 32 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o 33 obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 34 obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o 35 obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
··· 30 obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o 31 obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o 32 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o 33 + obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o 34 obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 35 obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o 36 obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
+582
drivers/rtc/rtc-mrst.c
···
··· 1 + /* 2 + * rtc-mrst.c: Driver for Moorestown virtual RTC 3 + * 4 + * (C) Copyright 2009 Intel Corporation 5 + * Author: Jacob Pan (jacob.jun.pan@intel.com) 6 + * Feng Tang (feng.tang@intel.com) 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * as published by the Free Software Foundation; version 2 11 + * of the License. 12 + * 13 + * Note: 14 + * VRTC is emulated by system controller firmware, the real HW 15 + * RTC is located in the PMIC device. SCU FW shadows PMIC RTC 16 + * in a memory mapped IO space that is visible to the host IA 17 + * processor. 18 + * 19 + * This driver is based upon drivers/rtc/rtc-cmos.c 20 + */ 21 + 22 + /* 23 + * Note: 24 + * * vRTC only supports binary mode and 24H mode 25 + * * vRTC only support PIE and AIE, no UIE, and its PIE only happens 26 + * at 23:59:59pm everyday, no support for adjustable frequency 27 + * * Alarm function is also limited to hr/min/sec. 28 + */ 29 + 30 + #include <linux/mod_devicetable.h> 31 + #include <linux/platform_device.h> 32 + #include <linux/interrupt.h> 33 + #include <linux/spinlock.h> 34 + #include <linux/kernel.h> 35 + #include <linux/module.h> 36 + #include <linux/init.h> 37 + #include <linux/sfi.h> 38 + 39 + #include <asm-generic/rtc.h> 40 + #include <asm/intel_scu_ipc.h> 41 + #include <asm/mrst.h> 42 + #include <asm/mrst-vrtc.h> 43 + 44 + struct mrst_rtc { 45 + struct rtc_device *rtc; 46 + struct device *dev; 47 + int irq; 48 + struct resource *iomem; 49 + 50 + u8 enabled_wake; 51 + u8 suspend_ctrl; 52 + }; 53 + 54 + static const char driver_name[] = "rtc_mrst"; 55 + 56 + #define RTC_IRQMASK (RTC_PF | RTC_AF) 57 + 58 + static inline int is_intr(u8 rtc_intr) 59 + { 60 + if (!(rtc_intr & RTC_IRQF)) 61 + return 0; 62 + return rtc_intr & RTC_IRQMASK; 63 + } 64 + 65 + /* 66 + * rtc_time's year contains the increment over 1900, but vRTC's YEAR 67 + * register can't be programmed to value larger than 0x64, so vRTC 68 + * driver chose to use 1960 (1970 is UNIX time start point) as the base, 69 + * and does the translation at read/write time. 70 + * 71 + * Why not just use 1970 as the offset? it's because using 1960 will 72 + * make it consistent in leap year setting for both vrtc and low-level 73 + * physical rtc devices. 74 + */ 75 + static int mrst_read_time(struct device *dev, struct rtc_time *time) 76 + { 77 + unsigned long flags; 78 + 79 + if (rtc_is_updating()) 80 + mdelay(20); 81 + 82 + spin_lock_irqsave(&rtc_lock, flags); 83 + time->tm_sec = vrtc_cmos_read(RTC_SECONDS); 84 + time->tm_min = vrtc_cmos_read(RTC_MINUTES); 85 + time->tm_hour = vrtc_cmos_read(RTC_HOURS); 86 + time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); 87 + time->tm_mon = vrtc_cmos_read(RTC_MONTH); 88 + time->tm_year = vrtc_cmos_read(RTC_YEAR); 89 + spin_unlock_irqrestore(&rtc_lock, flags); 90 + 91 + /* Adjust for the 1960/1900 */ 92 + time->tm_year += 60; 93 + time->tm_mon--; 94 + return RTC_24H; 95 + } 96 + 97 + static int mrst_set_time(struct device *dev, struct rtc_time *time) 98 + { 99 + int ret; 100 + unsigned long flags; 101 + unsigned char mon, day, hrs, min, sec; 102 + unsigned int yrs; 103 + 104 + yrs = time->tm_year; 105 + mon = time->tm_mon + 1; /* tm_mon starts at zero */ 106 + day = time->tm_mday; 107 + hrs = time->tm_hour; 108 + min = time->tm_min; 109 + sec = time->tm_sec; 110 + 111 + if (yrs < 70 || yrs > 138) 112 + return -EINVAL; 113 + yrs -= 60; 114 + 115 + spin_lock_irqsave(&rtc_lock, flags); 116 + 117 + vrtc_cmos_write(yrs, RTC_YEAR); 118 + vrtc_cmos_write(mon, RTC_MONTH); 119 + vrtc_cmos_write(day, RTC_DAY_OF_MONTH); 120 + vrtc_cmos_write(hrs, RTC_HOURS); 121 + vrtc_cmos_write(min, RTC_MINUTES); 122 + vrtc_cmos_write(sec, RTC_SECONDS); 123 + 124 + spin_unlock_irqrestore(&rtc_lock, flags); 125 + 126 + ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); 127 + return ret; 128 + } 129 + 130 + static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) 131 + { 132 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 133 + unsigned char rtc_control; 134 + 135 + if (mrst->irq <= 0) 136 + return -EIO; 137 + 138 + /* Basic alarms only support hour, minute, and seconds fields. 139 + * Some also support day and month, for alarms up to a year in 140 + * the future. 141 + */ 142 + t->time.tm_mday = -1; 143 + t->time.tm_mon = -1; 144 + t->time.tm_year = -1; 145 + 146 + /* vRTC only supports binary mode */ 147 + spin_lock_irq(&rtc_lock); 148 + t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); 149 + t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM); 150 + t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM); 151 + 152 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 153 + spin_unlock_irq(&rtc_lock); 154 + 155 + t->enabled = !!(rtc_control & RTC_AIE); 156 + t->pending = 0; 157 + 158 + return 0; 159 + } 160 + 161 + static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control) 162 + { 163 + unsigned char rtc_intr; 164 + 165 + /* 166 + * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; 167 + * allegedly some older rtcs need that to handle irqs properly 168 + */ 169 + rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS); 170 + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; 171 + if (is_intr(rtc_intr)) 172 + rtc_update_irq(mrst->rtc, 1, rtc_intr); 173 + } 174 + 175 + static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) 176 + { 177 + unsigned char rtc_control; 178 + 179 + /* 180 + * Flush any pending IRQ status, notably for update irqs, 181 + * before we enable new IRQs 182 + */ 183 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 184 + mrst_checkintr(mrst, rtc_control); 185 + 186 + rtc_control |= mask; 187 + vrtc_cmos_write(rtc_control, RTC_CONTROL); 188 + 189 + mrst_checkintr(mrst, rtc_control); 190 + } 191 + 192 + static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) 193 + { 194 + unsigned char rtc_control; 195 + 196 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 197 + rtc_control &= ~mask; 198 + vrtc_cmos_write(rtc_control, RTC_CONTROL); 199 + mrst_checkintr(mrst, rtc_control); 200 + } 201 + 202 + static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) 203 + { 204 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 205 + unsigned char hrs, min, sec; 206 + int ret = 0; 207 + 208 + if (!mrst->irq) 209 + return -EIO; 210 + 211 + hrs = t->time.tm_hour; 212 + min = t->time.tm_min; 213 + sec = t->time.tm_sec; 214 + 215 + spin_lock_irq(&rtc_lock); 216 + /* Next rtc irq must not be from previous alarm setting */ 217 + mrst_irq_disable(mrst, RTC_AIE); 218 + 219 + /* Update alarm */ 220 + vrtc_cmos_write(hrs, RTC_HOURS_ALARM); 221 + vrtc_cmos_write(min, RTC_MINUTES_ALARM); 222 + vrtc_cmos_write(sec, RTC_SECONDS_ALARM); 223 + 224 + spin_unlock_irq(&rtc_lock); 225 + 226 + ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); 227 + if (ret) 228 + return ret; 229 + 230 + spin_lock_irq(&rtc_lock); 231 + if (t->enabled) 232 + mrst_irq_enable(mrst, RTC_AIE); 233 + 234 + spin_unlock_irq(&rtc_lock); 235 + 236 + return 0; 237 + } 238 + 239 + static int mrst_irq_set_state(struct device *dev, int enabled) 240 + { 241 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 242 + unsigned long flags; 243 + 244 + if (!mrst->irq) 245 + return -ENXIO; 246 + 247 + spin_lock_irqsave(&rtc_lock, flags); 248 + 249 + if (enabled) 250 + mrst_irq_enable(mrst, RTC_PIE); 251 + else 252 + mrst_irq_disable(mrst, RTC_PIE); 253 + 254 + spin_unlock_irqrestore(&rtc_lock, flags); 255 + return 0; 256 + } 257 + 258 + #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) 259 + 260 + /* Currently, the vRTC doesn't support UIE ON/OFF */ 261 + static int 262 + mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 263 + { 264 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 265 + unsigned long flags; 266 + 267 + switch (cmd) { 268 + case RTC_AIE_OFF: 269 + case RTC_AIE_ON: 270 + if (!mrst->irq) 271 + return -EINVAL; 272 + break; 273 + default: 274 + /* PIE ON/OFF is handled by mrst_irq_set_state() */ 275 + return -ENOIOCTLCMD; 276 + } 277 + 278 + spin_lock_irqsave(&rtc_lock, flags); 279 + switch (cmd) { 280 + case RTC_AIE_OFF: /* alarm off */ 281 + mrst_irq_disable(mrst, RTC_AIE); 282 + break; 283 + case RTC_AIE_ON: /* alarm on */ 284 + mrst_irq_enable(mrst, RTC_AIE); 285 + break; 286 + } 287 + spin_unlock_irqrestore(&rtc_lock, flags); 288 + return 0; 289 + } 290 + 291 + #else 292 + #define mrst_rtc_ioctl NULL 293 + #endif 294 + 295 + #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) 296 + 297 + static int mrst_procfs(struct device *dev, struct seq_file *seq) 298 + { 299 + unsigned char rtc_control, valid; 300 + 301 + spin_lock_irq(&rtc_lock); 302 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 303 + valid = vrtc_cmos_read(RTC_VALID); 304 + spin_unlock_irq(&rtc_lock); 305 + 306 + return seq_printf(seq, 307 + "periodic_IRQ\t: %s\n" 308 + "alarm\t\t: %s\n" 309 + "BCD\t\t: no\n" 310 + "periodic_freq\t: daily (not adjustable)\n", 311 + (rtc_control & RTC_PIE) ? "on" : "off", 312 + (rtc_control & RTC_AIE) ? "on" : "off"); 313 + } 314 + 315 + #else 316 + #define mrst_procfs NULL 317 + #endif 318 + 319 + static const struct rtc_class_ops mrst_rtc_ops = { 320 + .ioctl = mrst_rtc_ioctl, 321 + .read_time = mrst_read_time, 322 + .set_time = mrst_set_time, 323 + .read_alarm = mrst_read_alarm, 324 + .set_alarm = mrst_set_alarm, 325 + .proc = mrst_procfs, 326 + .irq_set_state = mrst_irq_set_state, 327 + }; 328 + 329 + static struct mrst_rtc mrst_rtc; 330 + 331 + /* 332 + * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in 333 + * Reg B, so no need for this driver to clear it 334 + */ 335 + static irqreturn_t mrst_rtc_irq(int irq, void *p) 336 + { 337 + u8 irqstat; 338 + 339 + spin_lock(&rtc_lock); 340 + /* This read will clear all IRQ flags inside Reg C */ 341 + irqstat = vrtc_cmos_read(RTC_INTR_FLAGS); 342 + spin_unlock(&rtc_lock); 343 + 344 + irqstat &= RTC_IRQMASK | RTC_IRQF; 345 + if (is_intr(irqstat)) { 346 + rtc_update_irq(p, 1, irqstat); 347 + return IRQ_HANDLED; 348 + } 349 + return IRQ_NONE; 350 + } 351 + 352 + static int __init 353 + vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) 354 + { 355 + int retval = 0; 356 + unsigned char rtc_control; 357 + 358 + /* There can be only one ... */ 359 + if (mrst_rtc.dev) 360 + return -EBUSY; 361 + 362 + if (!iomem) 363 + return -ENODEV; 364 + 365 + iomem = request_mem_region(iomem->start, 366 + iomem->end + 1 - iomem->start, 367 + driver_name); 368 + if (!iomem) { 369 + dev_dbg(dev, "i/o mem already in use.\n"); 370 + return -EBUSY; 371 + } 372 + 373 + mrst_rtc.irq = rtc_irq; 374 + mrst_rtc.iomem = iomem; 375 + 376 + mrst_rtc.rtc = rtc_device_register(driver_name, dev, 377 + &mrst_rtc_ops, THIS_MODULE); 378 + if (IS_ERR(mrst_rtc.rtc)) { 379 + retval = PTR_ERR(mrst_rtc.rtc); 380 + goto cleanup0; 381 + } 382 + 383 + mrst_rtc.dev = dev; 384 + dev_set_drvdata(dev, &mrst_rtc); 385 + rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); 386 + 387 + spin_lock_irq(&rtc_lock); 388 + mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); 389 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 390 + spin_unlock_irq(&rtc_lock); 391 + 392 + if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) 393 + dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); 394 + 395 + if (rtc_irq) { 396 + retval = request_irq(rtc_irq, mrst_rtc_irq, 397 + IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), 398 + mrst_rtc.rtc); 399 + if (retval < 0) { 400 + dev_dbg(dev, "IRQ %d is already in use, err %d\n", 401 + rtc_irq, retval); 402 + goto cleanup1; 403 + } 404 + } 405 + dev_dbg(dev, "initialised\n"); 406 + return 0; 407 + 408 + cleanup1: 409 + mrst_rtc.dev = NULL; 410 + rtc_device_unregister(mrst_rtc.rtc); 411 + cleanup0: 412 + release_region(iomem->start, iomem->end + 1 - iomem->start); 413 + dev_err(dev, "rtc-mrst: unable to initialise\n"); 414 + return retval; 415 + } 416 + 417 + static void rtc_mrst_do_shutdown(void) 418 + { 419 + spin_lock_irq(&rtc_lock); 420 + mrst_irq_disable(&mrst_rtc, RTC_IRQMASK); 421 + spin_unlock_irq(&rtc_lock); 422 + } 423 + 424 + static void __exit rtc_mrst_do_remove(struct device *dev) 425 + { 426 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 427 + struct resource *iomem; 428 + 429 + rtc_mrst_do_shutdown(); 430 + 431 + if (mrst->irq) 432 + free_irq(mrst->irq, mrst->rtc); 433 + 434 + rtc_device_unregister(mrst->rtc); 435 + mrst->rtc = NULL; 436 + 437 + iomem = mrst->iomem; 438 + release_region(iomem->start, iomem->end + 1 - iomem->start); 439 + mrst->iomem = NULL; 440 + 441 + mrst->dev = NULL; 442 + dev_set_drvdata(dev, NULL); 443 + } 444 + 445 + #ifdef CONFIG_PM 446 + static int mrst_suspend(struct device *dev, pm_message_t mesg) 447 + { 448 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 449 + unsigned char tmp; 450 + 451 + /* Only the alarm might be a wakeup event source */ 452 + spin_lock_irq(&rtc_lock); 453 + mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); 454 + if (tmp & (RTC_PIE | RTC_AIE)) { 455 + unsigned char mask; 456 + 457 + if (device_may_wakeup(dev)) 458 + mask = RTC_IRQMASK & ~RTC_AIE; 459 + else 460 + mask = RTC_IRQMASK; 461 + tmp &= ~mask; 462 + vrtc_cmos_write(tmp, RTC_CONTROL); 463 + 464 + mrst_checkintr(mrst, tmp); 465 + } 466 + spin_unlock_irq(&rtc_lock); 467 + 468 + if (tmp & RTC_AIE) { 469 + mrst->enabled_wake = 1; 470 + enable_irq_wake(mrst->irq); 471 + } 472 + 473 + dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", 474 + (tmp & RTC_AIE) ? ", alarm may wake" : "", 475 + tmp); 476 + 477 + return 0; 478 + } 479 + 480 + /* 481 + * We want RTC alarms to wake us from the deep power saving state 482 + */ 483 + static inline int mrst_poweroff(struct device *dev) 484 + { 485 + return mrst_suspend(dev, PMSG_HIBERNATE); 486 + } 487 + 488 + static int mrst_resume(struct device *dev) 489 + { 490 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 491 + unsigned char tmp = mrst->suspend_ctrl; 492 + 493 + /* Re-enable any irqs previously active */ 494 + if (tmp & RTC_IRQMASK) { 495 + unsigned char mask; 496 + 497 + if (mrst->enabled_wake) { 498 + disable_irq_wake(mrst->irq); 499 + mrst->enabled_wake = 0; 500 + } 501 + 502 + spin_lock_irq(&rtc_lock); 503 + do { 504 + vrtc_cmos_write(tmp, RTC_CONTROL); 505 + 506 + mask = vrtc_cmos_read(RTC_INTR_FLAGS); 507 + mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; 508 + if (!is_intr(mask)) 509 + break; 510 + 511 + rtc_update_irq(mrst->rtc, 1, mask); 512 + tmp &= ~RTC_AIE; 513 + } while (mask & RTC_AIE); 514 + spin_unlock_irq(&rtc_lock); 515 + } 516 + 517 + dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); 518 + 519 + return 0; 520 + } 521 + 522 + #else 523 + #define mrst_suspend NULL 524 + #define mrst_resume NULL 525 + 526 + static inline int mrst_poweroff(struct device *dev) 527 + { 528 + return -ENOSYS; 529 + } 530 + 531 + #endif 532 + 533 + static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) 534 + { 535 + return vrtc_mrst_do_probe(&pdev->dev, 536 + platform_get_resource(pdev, IORESOURCE_MEM, 0), 537 + platform_get_irq(pdev, 0)); 538 + } 539 + 540 + static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) 541 + { 542 + rtc_mrst_do_remove(&pdev->dev); 543 + return 0; 544 + } 545 + 546 + static void vrtc_mrst_platform_shutdown(struct platform_device *pdev) 547 + { 548 + if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev)) 549 + return; 550 + 551 + rtc_mrst_do_shutdown(); 552 + } 553 + 554 + MODULE_ALIAS("platform:vrtc_mrst"); 555 + 556 + static struct platform_driver vrtc_mrst_platform_driver = { 557 + .probe = vrtc_mrst_platform_probe, 558 + .remove = __exit_p(vrtc_mrst_platform_remove), 559 + .shutdown = vrtc_mrst_platform_shutdown, 560 + .driver = { 561 + .name = (char *) driver_name, 562 + .suspend = mrst_suspend, 563 + .resume = mrst_resume, 564 + } 565 + }; 566 + 567 + static int __init vrtc_mrst_init(void) 568 + { 569 + return platform_driver_register(&vrtc_mrst_platform_driver); 570 + } 571 + 572 + static void __exit vrtc_mrst_exit(void) 573 + { 574 + platform_driver_unregister(&vrtc_mrst_platform_driver); 575 + } 576 + 577 + module_init(vrtc_mrst_init); 578 + module_exit(vrtc_mrst_exit); 579 + 580 + MODULE_AUTHOR("Jacob Pan; Feng Tang"); 581 + MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); 582 + MODULE_LICENSE("GPL");
+5 -3
include/linux/sfi.h
··· 77 #define SFI_OEM_ID_SIZE 6 78 #define SFI_OEM_TABLE_ID_SIZE 8 79 80 #define SFI_SYST_SEARCH_BEGIN 0x000E0000 81 #define SFI_SYST_SEARCH_END 0x000FFFFF 82 ··· 158 u16 addr; 159 u8 irq; 160 u32 max_freq; 161 - char name[16]; 162 } __packed; 163 164 struct sfi_gpio_table_entry { 165 - char controller_name[16]; 166 u16 pin_no; 167 - char pin_name[16]; 168 } __packed; 169 170 typedef int (*sfi_table_handler) (struct sfi_table_header *table);
··· 77 #define SFI_OEM_ID_SIZE 6 78 #define SFI_OEM_TABLE_ID_SIZE 8 79 80 + #define SFI_NAME_LEN 16 81 + 82 #define SFI_SYST_SEARCH_BEGIN 0x000E0000 83 #define SFI_SYST_SEARCH_END 0x000FFFFF 84 ··· 156 u16 addr; 157 u8 irq; 158 u32 max_freq; 159 + char name[SFI_NAME_LEN]; 160 } __packed; 161 162 struct sfi_gpio_table_entry { 163 + char controller_name[SFI_NAME_LEN]; 164 u16 pin_no; 165 + char pin_name[SFI_NAME_LEN]; 166 } __packed; 167 168 typedef int (*sfi_table_handler) (struct sfi_table_header *table);