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

* 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: sfi: Make local functions static
x86, earlyprintk: Add hsu early console for Intel Medfield platform
x86, earlyprintk: Add earlyprintk for Intel Moorestown platform
x86: Add two helper macros for fixed address mapping
x86, mrst: A function in a header file needs to be marked "inline"

+363 -3
+4
arch/x86/Kconfig.debug
··· 43 with klogd/syslogd or the X server. You should normally N here, 44 unless you want to debug such a crash. 45 46 config EARLY_PRINTK_DBGP 47 bool "Early printk via EHCI debug port" 48 depends on EARLY_PRINTK && PCI
··· 43 with klogd/syslogd or the X server. You should normally N here, 44 unless you want to debug such a crash. 45 46 + config EARLY_PRINTK_MRST 47 + bool "Early printk for MRST platform support" 48 + depends on EARLY_PRINTK && X86_MRST 49 + 50 config EARLY_PRINTK_DBGP 51 bool "Early printk via EHCI debug port" 52 depends on EARLY_PRINTK && PCI
+15
arch/x86/include/asm/fixmap.h
··· 214 BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); 215 return __virt_to_fix(vaddr); 216 } 217 #endif /* !__ASSEMBLY__ */ 218 #endif /* _ASM_X86_FIXMAP_H */
··· 214 BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); 215 return __virt_to_fix(vaddr); 216 } 217 + 218 + /* Return an pointer with offset calculated */ 219 + static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx, 220 + phys_addr_t phys, pgprot_t flags) 221 + { 222 + __set_fixmap(idx, phys, flags); 223 + return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1)); 224 + } 225 + 226 + #define set_fixmap_offset(idx, phys) \ 227 + __set_fixmap_offset(idx, phys, PAGE_KERNEL) 228 + 229 + #define set_fixmap_offset_nocache(idx, phys) \ 230 + __set_fixmap_offset(idx, phys, PAGE_KERNEL_NOCACHE) 231 + 232 #endif /* !__ASSEMBLY__ */ 233 #endif /* _ASM_X86_FIXMAP_H */
+9 -1
arch/x86/include/asm/mrst.h
··· 10 */ 11 #ifndef _ASM_X86_MRST_H 12 #define _ASM_X86_MRST_H 13 extern int pci_mrst_init(void); 14 int __init sfi_parse_mrtc(struct sfi_table_header *table); 15 ··· 29 }; 30 31 extern enum mrst_cpu_type __mrst_cpu_chip; 32 - static enum mrst_cpu_type mrst_identify_cpu(void) 33 { 34 return __mrst_cpu_chip; 35 } ··· 45 #define SFI_MTMR_MAX_NUM 8 46 #define SFI_MRTC_MAX 8 47 48 #endif /* _ASM_X86_MRST_H */
··· 10 */ 11 #ifndef _ASM_X86_MRST_H 12 #define _ASM_X86_MRST_H 13 + 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 ··· 26 }; 27 28 extern enum mrst_cpu_type __mrst_cpu_chip; 29 + static inline enum mrst_cpu_type mrst_identify_cpu(void) 30 { 31 return __mrst_cpu_chip; 32 } ··· 42 #define SFI_MTMR_MAX_NUM 8 43 #define SFI_MRTC_MAX 8 44 45 + extern struct console early_mrst_console; 46 + extern void mrst_early_console_init(void); 47 + 48 + extern struct console early_hsu_console; 49 + extern void hsu_early_console_init(void); 50 #endif /* _ASM_X86_MRST_H */
+1
arch/x86/kernel/Makefile
··· 86 obj-$(CONFIG_KGDB) += kgdb.o 87 obj-$(CONFIG_VM86) += vm86_32.o 88 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 89 90 obj-$(CONFIG_HPET_TIMER) += hpet.o 91 obj-$(CONFIG_APB_TIMER) += apb_timer.o
··· 86 obj-$(CONFIG_KGDB) += kgdb.o 87 obj-$(CONFIG_VM86) += vm86_32.o 88 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 89 + obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o 90 91 obj-$(CONFIG_HPET_TIMER) += hpet.o 92 obj-$(CONFIG_APB_TIMER) += apb_timer.o
+13
arch/x86/kernel/early_printk.c
··· 14 #include <xen/hvc-console.h> 15 #include <asm/pci-direct.h> 16 #include <asm/fixmap.h> 17 #include <asm/pgtable.h> 18 #include <linux/usb/ehci_def.h> 19 ··· 239 #ifdef CONFIG_HVC_XEN 240 if (!strncmp(buf, "xen", 3)) 241 early_console_register(&xenboot_console, keep); 242 #endif 243 buf++; 244 }
··· 14 #include <xen/hvc-console.h> 15 #include <asm/pci-direct.h> 16 #include <asm/fixmap.h> 17 + #include <asm/mrst.h> 18 #include <asm/pgtable.h> 19 #include <linux/usb/ehci_def.h> 20 ··· 238 #ifdef CONFIG_HVC_XEN 239 if (!strncmp(buf, "xen", 3)) 240 early_console_register(&xenboot_console, keep); 241 + #endif 242 + #ifdef CONFIG_X86_MRST_EARLY_PRINTK 243 + if (!strncmp(buf, "mrst", 4)) { 244 + mrst_early_console_init(); 245 + early_console_register(&early_mrst_console, keep); 246 + } 247 + 248 + if (!strncmp(buf, "hsu", 3)) { 249 + hsu_early_console_init(); 250 + early_console_register(&early_hsu_console, keep); 251 + } 252 + 253 #endif 254 buf++; 255 }
+319
arch/x86/kernel/early_printk_mrst.c
···
··· 1 + /* 2 + * early_printk_mrst.c - early consoles for Intel MID platforms 3 + * 4 + * Copyright (c) 2008-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 + 12 + /* 13 + * This file implements two early consoles named mrst and hsu. 14 + * mrst is based on Maxim3110 spi-uart device, it exists in both 15 + * Moorestown and Medfield platforms, while hsu is based on a High 16 + * Speed UART device which only exists in the Medfield platform 17 + */ 18 + 19 + #include <linux/serial_reg.h> 20 + #include <linux/serial_mfd.h> 21 + #include <linux/kmsg_dump.h> 22 + #include <linux/console.h> 23 + #include <linux/kernel.h> 24 + #include <linux/delay.h> 25 + #include <linux/init.h> 26 + #include <linux/io.h> 27 + 28 + #include <asm/fixmap.h> 29 + #include <asm/pgtable.h> 30 + #include <asm/mrst.h> 31 + 32 + #define MRST_SPI_TIMEOUT 0x200000 33 + #define MRST_REGBASE_SPI0 0xff128000 34 + #define MRST_REGBASE_SPI1 0xff128400 35 + #define MRST_CLK_SPI0_REG 0xff11d86c 36 + 37 + /* Bit fields in CTRLR0 */ 38 + #define SPI_DFS_OFFSET 0 39 + 40 + #define SPI_FRF_OFFSET 4 41 + #define SPI_FRF_SPI 0x0 42 + #define SPI_FRF_SSP 0x1 43 + #define SPI_FRF_MICROWIRE 0x2 44 + #define SPI_FRF_RESV 0x3 45 + 46 + #define SPI_MODE_OFFSET 6 47 + #define SPI_SCPH_OFFSET 6 48 + #define SPI_SCOL_OFFSET 7 49 + #define SPI_TMOD_OFFSET 8 50 + #define SPI_TMOD_TR 0x0 /* xmit & recv */ 51 + #define SPI_TMOD_TO 0x1 /* xmit only */ 52 + #define SPI_TMOD_RO 0x2 /* recv only */ 53 + #define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */ 54 + 55 + #define SPI_SLVOE_OFFSET 10 56 + #define SPI_SRL_OFFSET 11 57 + #define SPI_CFS_OFFSET 12 58 + 59 + /* Bit fields in SR, 7 bits */ 60 + #define SR_MASK 0x7f /* cover 7 bits */ 61 + #define SR_BUSY (1 << 0) 62 + #define SR_TF_NOT_FULL (1 << 1) 63 + #define SR_TF_EMPT (1 << 2) 64 + #define SR_RF_NOT_EMPT (1 << 3) 65 + #define SR_RF_FULL (1 << 4) 66 + #define SR_TX_ERR (1 << 5) 67 + #define SR_DCOL (1 << 6) 68 + 69 + struct dw_spi_reg { 70 + u32 ctrl0; 71 + u32 ctrl1; 72 + u32 ssienr; 73 + u32 mwcr; 74 + u32 ser; 75 + u32 baudr; 76 + u32 txfltr; 77 + u32 rxfltr; 78 + u32 txflr; 79 + u32 rxflr; 80 + u32 sr; 81 + u32 imr; 82 + u32 isr; 83 + u32 risr; 84 + u32 txoicr; 85 + u32 rxoicr; 86 + u32 rxuicr; 87 + u32 msticr; 88 + u32 icr; 89 + u32 dmacr; 90 + u32 dmatdlr; 91 + u32 dmardlr; 92 + u32 idr; 93 + u32 version; 94 + 95 + /* Currently operates as 32 bits, though only the low 16 bits matter */ 96 + u32 dr; 97 + } __packed; 98 + 99 + #define dw_readl(dw, name) __raw_readl(&(dw)->name) 100 + #define dw_writel(dw, name, val) __raw_writel((val), &(dw)->name) 101 + 102 + /* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */ 103 + static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0; 104 + 105 + static u32 *pclk_spi0; 106 + /* Always contains an accessable address, start with 0 */ 107 + static struct dw_spi_reg *pspi; 108 + 109 + static struct kmsg_dumper dw_dumper; 110 + static int dumper_registered; 111 + 112 + static void dw_kmsg_dump(struct kmsg_dumper *dumper, 113 + enum kmsg_dump_reason reason, 114 + const char *s1, unsigned long l1, 115 + const char *s2, unsigned long l2) 116 + { 117 + int i; 118 + 119 + /* When run to this, we'd better re-init the HW */ 120 + mrst_early_console_init(); 121 + 122 + for (i = 0; i < l1; i++) 123 + early_mrst_console.write(&early_mrst_console, s1 + i, 1); 124 + for (i = 0; i < l2; i++) 125 + early_mrst_console.write(&early_mrst_console, s2 + i, 1); 126 + } 127 + 128 + /* Set the ratio rate to 115200, 8n1, IRQ disabled */ 129 + static void max3110_write_config(void) 130 + { 131 + u16 config; 132 + 133 + config = 0xc001; 134 + dw_writel(pspi, dr, config); 135 + } 136 + 137 + /* Translate char to a eligible word and send to max3110 */ 138 + static void max3110_write_data(char c) 139 + { 140 + u16 data; 141 + 142 + data = 0x8000 | c; 143 + dw_writel(pspi, dr, data); 144 + } 145 + 146 + void mrst_early_console_init(void) 147 + { 148 + u32 ctrlr0 = 0; 149 + u32 spi0_cdiv; 150 + u32 freq; /* Freqency info only need be searched once */ 151 + 152 + /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */ 153 + pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, 154 + MRST_CLK_SPI0_REG); 155 + spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; 156 + freq = 100000000 / (spi0_cdiv + 1); 157 + 158 + if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL) 159 + mrst_spi_paddr = MRST_REGBASE_SPI1; 160 + 161 + pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, 162 + mrst_spi_paddr); 163 + 164 + /* Disable SPI controller */ 165 + dw_writel(pspi, ssienr, 0); 166 + 167 + /* Set control param, 8 bits, transmit only mode */ 168 + ctrlr0 = dw_readl(pspi, ctrl0); 169 + 170 + ctrlr0 &= 0xfcc0; 171 + ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET) 172 + | (SPI_TMOD_TO << SPI_TMOD_OFFSET); 173 + dw_writel(pspi, ctrl0, ctrlr0); 174 + 175 + /* 176 + * Change the spi0 clk to comply with 115200 bps, use 100000 to 177 + * calculate the clk dividor to make the clock a little slower 178 + * than real baud rate. 179 + */ 180 + dw_writel(pspi, baudr, freq/100000); 181 + 182 + /* Disable all INT for early phase */ 183 + dw_writel(pspi, imr, 0x0); 184 + 185 + /* Set the cs to spi-uart */ 186 + dw_writel(pspi, ser, 0x2); 187 + 188 + /* Enable the HW, the last step for HW init */ 189 + dw_writel(pspi, ssienr, 0x1); 190 + 191 + /* Set the default configuration */ 192 + max3110_write_config(); 193 + 194 + /* Register the kmsg dumper */ 195 + if (!dumper_registered) { 196 + dw_dumper.dump = dw_kmsg_dump; 197 + kmsg_dump_register(&dw_dumper); 198 + dumper_registered = 1; 199 + } 200 + } 201 + 202 + /* Slave select should be called in the read/write function */ 203 + static void early_mrst_spi_putc(char c) 204 + { 205 + unsigned int timeout; 206 + u32 sr; 207 + 208 + timeout = MRST_SPI_TIMEOUT; 209 + /* Early putc needs to make sure the TX FIFO is not full */ 210 + while (--timeout) { 211 + sr = dw_readl(pspi, sr); 212 + if (!(sr & SR_TF_NOT_FULL)) 213 + cpu_relax(); 214 + else 215 + break; 216 + } 217 + 218 + if (!timeout) 219 + pr_warning("MRST earlycon: timed out\n"); 220 + else 221 + max3110_write_data(c); 222 + } 223 + 224 + /* Early SPI only uses polling mode */ 225 + static void early_mrst_spi_write(struct console *con, const char *str, unsigned n) 226 + { 227 + int i; 228 + 229 + for (i = 0; i < n && *str; i++) { 230 + if (*str == '\n') 231 + early_mrst_spi_putc('\r'); 232 + early_mrst_spi_putc(*str); 233 + str++; 234 + } 235 + } 236 + 237 + struct console early_mrst_console = { 238 + .name = "earlymrst", 239 + .write = early_mrst_spi_write, 240 + .flags = CON_PRINTBUFFER, 241 + .index = -1, 242 + }; 243 + 244 + /* 245 + * Following is the early console based on Medfield HSU (High 246 + * Speed UART) device. 247 + */ 248 + #define HSU_PORT2_PADDR 0xffa28180 249 + 250 + static void __iomem *phsu; 251 + 252 + void hsu_early_console_init(void) 253 + { 254 + u8 lcr; 255 + 256 + phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, 257 + HSU_PORT2_PADDR); 258 + 259 + /* Disable FIFO */ 260 + writeb(0x0, phsu + UART_FCR); 261 + 262 + /* Set to default 115200 bps, 8n1 */ 263 + lcr = readb(phsu + UART_LCR); 264 + writeb((0x80 | lcr), phsu + UART_LCR); 265 + writeb(0x18, phsu + UART_DLL); 266 + writeb(lcr, phsu + UART_LCR); 267 + writel(0x3600, phsu + UART_MUL*4); 268 + 269 + writeb(0x8, phsu + UART_MCR); 270 + writeb(0x7, phsu + UART_FCR); 271 + writeb(0x3, phsu + UART_LCR); 272 + 273 + /* Clear IRQ status */ 274 + readb(phsu + UART_LSR); 275 + readb(phsu + UART_RX); 276 + readb(phsu + UART_IIR); 277 + readb(phsu + UART_MSR); 278 + 279 + /* Enable FIFO */ 280 + writeb(0x7, phsu + UART_FCR); 281 + } 282 + 283 + #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) 284 + 285 + static void early_hsu_putc(char ch) 286 + { 287 + unsigned int timeout = 10000; /* 10ms */ 288 + u8 status; 289 + 290 + while (--timeout) { 291 + status = readb(phsu + UART_LSR); 292 + if (status & BOTH_EMPTY) 293 + break; 294 + udelay(1); 295 + } 296 + 297 + /* Only write the char when there was no timeout */ 298 + if (timeout) 299 + writeb(ch, phsu + UART_TX); 300 + } 301 + 302 + static void early_hsu_write(struct console *con, const char *str, unsigned n) 303 + { 304 + int i; 305 + 306 + for (i = 0; i < n && *str; i++) { 307 + if (*str == '\n') 308 + early_hsu_putc('\r'); 309 + early_hsu_putc(*str); 310 + str++; 311 + } 312 + } 313 + 314 + struct console early_hsu_console = { 315 + .name = "earlyhsu", 316 + .write = early_hsu_write, 317 + .flags = CON_PRINTBUFFER, 318 + .index = -1, 319 + };
+2 -2
arch/x86/kernel/sfi.c
··· 34 #ifdef CONFIG_X86_LOCAL_APIC 35 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; 36 37 - void __init mp_sfi_register_lapic_address(unsigned long address) 38 { 39 mp_lapic_addr = address; 40 ··· 46 } 47 48 /* All CPUs enumerated by SFI must be present and enabled */ 49 - void __cpuinit mp_sfi_register_lapic(u8 id) 50 { 51 if (MAX_APICS - id <= 0) { 52 pr_warning("Processor #%d invalid (max %d)\n",
··· 34 #ifdef CONFIG_X86_LOCAL_APIC 35 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; 36 37 + static void __init mp_sfi_register_lapic_address(unsigned long address) 38 { 39 mp_lapic_addr = address; 40 ··· 46 } 47 48 /* All CPUs enumerated by SFI must be present and enabled */ 49 + static void __cpuinit mp_sfi_register_lapic(u8 id) 50 { 51 if (MAX_APICS - id <= 0) { 52 pr_warning("Processor #%d invalid (max %d)\n",