Commit 991cfffa7c19aa648546aff666595af896e568ba

Authored by Feng Tang
Committed by Thomas Gleixner
1 parent e4d2ebcab1

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
1 1 obj-$(CONFIG_X86_MRST) += mrst.o
2 2 obj-$(CONFIG_X86_MRST) += vrtc.o
  3 +obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
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 +};