Commit 4729d77332a4383770c780b7709d5e14f12a4d1e

Authored by Jesper Nilsson
1 parent 421d085252

CRISv32: Implement early console

Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>

Showing 1 changed file with 56 additions and 26 deletions Inline Diff

arch/cris/arch-v32/kernel/debugport.c
1 /* 1 /*
2 * Copyright (C) 2003, Axis Communications AB. 2 * Copyright (C) 2003, Axis Communications AB.
3 */ 3 */
4 4
5 #include <linux/console.h> 5 #include <linux/console.h>
6 #include <linux/kernel.h>
6 #include <linux/init.h> 7 #include <linux/init.h>
8 #include <linux/string.h>
7 #include <hwregs/reg_rdwr.h> 9 #include <hwregs/reg_rdwr.h>
8 #include <hwregs/reg_map.h> 10 #include <hwregs/reg_map.h>
9 #include <hwregs/ser_defs.h> 11 #include <hwregs/ser_defs.h>
10 #include <hwregs/dma_defs.h> 12 #include <hwregs/dma_defs.h>
11 #include <mach/pinmux.h> 13 #include <mach/pinmux.h>
12 14
13 struct dbg_port 15 struct dbg_port
14 { 16 {
15 unsigned char nbr; 17 unsigned char nbr;
16 unsigned long instance; 18 unsigned long instance;
17 unsigned int started; 19 unsigned int started;
18 unsigned long baudrate; 20 unsigned long baudrate;
19 unsigned char parity; 21 unsigned char parity;
20 unsigned int bits; 22 unsigned int bits;
21 }; 23 };
22 24
23 struct dbg_port ports[] = 25 struct dbg_port ports[] =
24 { 26 {
25 { 27 {
26 0, 28 0,
27 regi_ser0, 29 regi_ser0,
28 0, 30 0,
29 115200, 31 115200,
30 'N', 32 'N',
31 8 33 8
32 }, 34 },
33 { 35 {
34 1, 36 1,
35 regi_ser1, 37 regi_ser1,
36 0, 38 0,
37 115200, 39 115200,
38 'N', 40 'N',
39 8 41 8
40 }, 42 },
41 { 43 {
42 2, 44 2,
43 regi_ser2, 45 regi_ser2,
44 0, 46 0,
45 115200, 47 115200,
46 'N', 48 'N',
47 8 49 8
48 }, 50 },
49 { 51 {
50 3, 52 3,
51 regi_ser3, 53 regi_ser3,
52 0, 54 0,
53 115200, 55 115200,
54 'N', 56 'N',
55 8 57 8
56 }, 58 },
57 #if CONFIG_ETRAX_SERIAL_PORTS == 5 59 #if CONFIG_ETRAX_SERIAL_PORTS == 5
58 { 60 {
59 4, 61 4,
60 regi_ser4, 62 regi_ser4,
61 0, 63 0,
62 115200, 64 115200,
63 'N', 65 'N',
64 8 66 8
65 }, 67 },
66 #endif 68 #endif
67 }; 69 };
70
68 static struct dbg_port *port = 71 static struct dbg_port *port =
69 #if defined(CONFIG_ETRAX_DEBUG_PORT0) 72 #if defined(CONFIG_ETRAX_DEBUG_PORT0)
70 &ports[0]; 73 &ports[0];
71 #elif defined(CONFIG_ETRAX_DEBUG_PORT1) 74 #elif defined(CONFIG_ETRAX_DEBUG_PORT1)
72 &ports[1]; 75 &ports[1];
73 #elif defined(CONFIG_ETRAX_DEBUG_PORT2) 76 #elif defined(CONFIG_ETRAX_DEBUG_PORT2)
74 &ports[2]; 77 &ports[2];
75 #elif defined(CONFIG_ETRAX_DEBUG_PORT3) 78 #elif defined(CONFIG_ETRAX_DEBUG_PORT3)
76 &ports[3]; 79 &ports[3];
77 #elif defined(CONFIG_ETRAX_DEBUG_PORT4) 80 #elif defined(CONFIG_ETRAX_DEBUG_PORT4)
78 &ports[4]; 81 &ports[4];
79 #else 82 #else
80 NULL; 83 NULL;
81 #endif 84 #endif
82 85
83 #ifdef CONFIG_ETRAX_KGDB 86 #ifdef CONFIG_ETRAX_KGDB
84 static struct dbg_port *kgdb_port = 87 static struct dbg_port *kgdb_port =
85 #if defined(CONFIG_ETRAX_KGDB_PORT0) 88 #if defined(CONFIG_ETRAX_KGDB_PORT0)
86 &ports[0]; 89 &ports[0];
87 #elif defined(CONFIG_ETRAX_KGDB_PORT1) 90 #elif defined(CONFIG_ETRAX_KGDB_PORT1)
88 &ports[1]; 91 &ports[1];
89 #elif defined(CONFIG_ETRAX_KGDB_PORT2) 92 #elif defined(CONFIG_ETRAX_KGDB_PORT2)
90 &ports[2]; 93 &ports[2];
91 #elif defined(CONFIG_ETRAX_KGDB_PORT3) 94 #elif defined(CONFIG_ETRAX_KGDB_PORT3)
92 &ports[3]; 95 &ports[3];
93 #elif defined(CONFIG_ETRAX_KGDB_PORT4) 96 #elif defined(CONFIG_ETRAX_KGDB_PORT4)
94 &ports[4]; 97 &ports[4];
95 #else 98 #else
96 NULL; 99 NULL;
97 #endif 100 #endif
98 #endif 101 #endif
99 102
100 static void 103 static void start_port(struct dbg_port *p)
101 start_port(struct dbg_port* p)
102 { 104 {
103 if (!p) 105 /* Set up serial port registers */
104 return; 106 reg_ser_rw_tr_ctrl tr_ctrl = {0};
107 reg_ser_rw_tr_dma_en tr_dma_en = {0};
105 108
106 if (p->started) 109 reg_ser_rw_rec_ctrl rec_ctrl = {0};
110 reg_ser_rw_tr_baud_div tr_baud_div = {0};
111 reg_ser_rw_rec_baud_div rec_baud_div = {0};
112
113 if (!p || p->started)
107 return; 114 return;
115
108 p->started = 1; 116 p->started = 1;
109 117
110 if (p->nbr == 1) 118 if (p->nbr == 1)
111 crisv32_pinmux_alloc_fixed(pinmux_ser1); 119 crisv32_pinmux_alloc_fixed(pinmux_ser1);
112 else if (p->nbr == 2) 120 else if (p->nbr == 2)
113 crisv32_pinmux_alloc_fixed(pinmux_ser2); 121 crisv32_pinmux_alloc_fixed(pinmux_ser2);
114 else if (p->nbr == 3) 122 else if (p->nbr == 3)
115 crisv32_pinmux_alloc_fixed(pinmux_ser3); 123 crisv32_pinmux_alloc_fixed(pinmux_ser3);
116 #if CONFIG_ETRAX_SERIAL_PORTS == 5 124 #if CONFIG_ETRAX_SERIAL_PORTS == 5
117 else if (p->nbr == 4) 125 else if (p->nbr == 4)
118 crisv32_pinmux_alloc_fixed(pinmux_ser4); 126 crisv32_pinmux_alloc_fixed(pinmux_ser4);
119 #endif 127 #endif
120 128
121 /* Set up serial port registers */
122 reg_ser_rw_tr_ctrl tr_ctrl = {0};
123 reg_ser_rw_tr_dma_en tr_dma_en = {0};
124
125 reg_ser_rw_rec_ctrl rec_ctrl = {0};
126 reg_ser_rw_tr_baud_div tr_baud_div = {0};
127 reg_ser_rw_rec_baud_div rec_baud_div = {0};
128
129 tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; 129 tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493;
130 tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; 130 tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no;
131 tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; 131 tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8;
132 tr_ctrl.en = rec_ctrl.en = 1; 132 tr_ctrl.en = rec_ctrl.en = 1;
133 133
134 if (p->parity == 'O') 134 if (p->parity == 'O') {
135 {
136 tr_ctrl.par_en = regk_ser_yes; 135 tr_ctrl.par_en = regk_ser_yes;
137 tr_ctrl.par = regk_ser_odd; 136 tr_ctrl.par = regk_ser_odd;
138 rec_ctrl.par_en = regk_ser_yes; 137 rec_ctrl.par_en = regk_ser_yes;
139 rec_ctrl.par = regk_ser_odd; 138 rec_ctrl.par = regk_ser_odd;
140 } 139 } else if (p->parity == 'E') {
141 else if (p->parity == 'E')
142 {
143 tr_ctrl.par_en = regk_ser_yes; 140 tr_ctrl.par_en = regk_ser_yes;
144 tr_ctrl.par = regk_ser_even; 141 tr_ctrl.par = regk_ser_even;
145 rec_ctrl.par_en = regk_ser_yes; 142 rec_ctrl.par_en = regk_ser_yes;
146 rec_ctrl.par = regk_ser_odd; 143 rec_ctrl.par = regk_ser_odd;
147 } 144 }
148 145
149 if (p->bits == 7) 146 if (p->bits == 7) {
150 {
151 tr_ctrl.data_bits = regk_ser_bits7; 147 tr_ctrl.data_bits = regk_ser_bits7;
152 rec_ctrl.data_bits = regk_ser_bits7; 148 rec_ctrl.data_bits = regk_ser_bits7;
153 } 149 }
154 150
155 REG_WR (ser, p->instance, rw_tr_baud_div, tr_baud_div); 151 REG_WR (ser, p->instance, rw_tr_baud_div, tr_baud_div);
156 REG_WR (ser, p->instance, rw_rec_baud_div, rec_baud_div); 152 REG_WR (ser, p->instance, rw_rec_baud_div, rec_baud_div);
157 REG_WR (ser, p->instance, rw_tr_dma_en, tr_dma_en); 153 REG_WR (ser, p->instance, rw_tr_dma_en, tr_dma_en);
158 REG_WR (ser, p->instance, rw_tr_ctrl, tr_ctrl); 154 REG_WR (ser, p->instance, rw_tr_ctrl, tr_ctrl);
159 REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); 155 REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl);
160 } 156 }
161 157
162 #ifdef CONFIG_ETRAX_KGDB 158 #ifdef CONFIG_ETRAX_KGDB
163 /* Use polling to get a single character from the kernel debug port */ 159 /* Use polling to get a single character from the kernel debug port */
164 int 160 int getDebugChar(void)
165 getDebugChar(void)
166 { 161 {
167 reg_ser_rs_stat_din stat; 162 reg_ser_rs_stat_din stat;
168 reg_ser_rw_ack_intr ack_intr = { 0 }; 163 reg_ser_rw_ack_intr ack_intr = { 0 };
169 164
170 do { 165 do {
171 stat = REG_RD(ser, kgdb_port->instance, rs_stat_din); 166 stat = REG_RD(ser, kgdb_port->instance, rs_stat_din);
172 } while (!stat.dav); 167 } while (!stat.dav);
173 168
174 /* Ack the data_avail interrupt. */ 169 /* Ack the data_avail interrupt. */
175 ack_intr.dav = 1; 170 ack_intr.dav = 1;
176 REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr); 171 REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr);
177 172
178 return stat.data; 173 return stat.data;
179 } 174 }
180 175
181 /* Use polling to put a single character to the kernel debug port */ 176 /* Use polling to put a single character to the kernel debug port */
182 void 177 void putDebugChar(int val)
183 putDebugChar(int val)
184 { 178 {
185 reg_ser_r_stat_din stat; 179 reg_ser_r_stat_din stat;
186 do { 180 do {
187 stat = REG_RD(ser, kgdb_port->instance, r_stat_din); 181 stat = REG_RD(ser, kgdb_port->instance, r_stat_din);
188 } while (!stat.tr_rdy); 182 } while (!stat.tr_rdy);
189 REG_WR_INT(ser, kgdb_port->instance, rw_dout, val); 183 REG_WR_INT(ser, kgdb_port->instance, rw_dout, val);
190 } 184 }
191 #endif /* CONFIG_ETRAX_KGDB */ 185 #endif /* CONFIG_ETRAX_KGDB */
192 186
187 static void __init early_putch(int c)
188 {
189 reg_ser_r_stat_din stat;
190 /* Wait until transmitter is ready and send. */
191 do
192 stat = REG_RD(ser, port->instance, r_stat_din);
193 while (!stat.tr_rdy);
194 REG_WR_INT(ser, port->instance, rw_dout, c);
195 }
196
197 static void __init
198 early_console_write(struct console *con, const char *s, unsigned n)
199 {
200 extern void reset_watchdog(void);
201 int i;
202
203 /* Send data. */
204 for (i = 0; i < n; i++) {
205 /* TODO: the '\n' -> '\n\r' translation should be done at the
206 receiver. Remove it when the serial driver removes it. */
207 if (s[i] == '\n')
208 early_putch('\r');
209 early_putch(s[i]);
210 reset_watchdog();
211 }
212 }
213
214 static struct console early_console_dev __initdata = {
215 .name = "early",
216 .write = early_console_write,
217 .flags = CON_PRINTBUFFER | CON_BOOT,
218 .index = -1
219 };