Commit 991cfffa7c19aa648546aff666595af896e568ba
Committed by
Thomas Gleixner
1 parent
e4d2ebcab1
Exists in
master
and in
7 other branches
x86, earlyprintk: Move mrst early console to platform/ and fix a typo
Move the code to arch/x86/platform/mrst/. Also fix a typo to use the correct config option: ONFIG_EARLY_PRINTK_MRST Signed-off-by: Feng Tang <feng.tang@intel.com> Cc: alan@linux.intel.com LKML-Reference: <1291348298-21263-1-git-send-email-feng.tang@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 5 changed files with 321 additions and 322 deletions Side-by-side Diff
arch/x86/kernel/Makefile
... | ... | @@ -84,7 +84,6 @@ |
84 | 84 | obj-$(CONFIG_KGDB) += kgdb.o |
85 | 85 | obj-$(CONFIG_VM86) += vm86_32.o |
86 | 86 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
87 | -obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o | |
88 | 87 | |
89 | 88 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
90 | 89 | obj-$(CONFIG_APB_TIMER) += apb_timer.o |
arch/x86/kernel/early_printk.c
... | ... | @@ -240,7 +240,7 @@ |
240 | 240 | if (!strncmp(buf, "xen", 3)) |
241 | 241 | early_console_register(&xenboot_console, keep); |
242 | 242 | #endif |
243 | -#ifdef CONFIG_X86_MRST_EARLY_PRINTK | |
243 | +#ifdef CONFIG_EARLY_PRINTK_MRST | |
244 | 244 | if (!strncmp(buf, "mrst", 4)) { |
245 | 245 | mrst_early_console_init(); |
246 | 246 | early_console_register(&early_mrst_console, keep); |
... | ... | @@ -250,7 +250,6 @@ |
250 | 250 | hsu_early_console_init(); |
251 | 251 | early_console_register(&early_hsu_console, keep); |
252 | 252 | } |
253 | - | |
254 | 253 | #endif |
255 | 254 | buf++; |
256 | 255 | } |
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 | -}; |
arch/x86/platform/mrst/Makefile
arch/x86/platform/mrst/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 | +}; |