Commit 4729d77332a4383770c780b7709d5e14f12a4d1e
1 parent
421d085252
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
CRISv32: Implement early console
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Showing 1 changed file with 56 additions and 26 deletions Side-by-side Diff
arch/cris/arch-v32/kernel/debugport.c
... | ... | @@ -3,7 +3,9 @@ |
3 | 3 | */ |
4 | 4 | |
5 | 5 | #include <linux/console.h> |
6 | +#include <linux/kernel.h> | |
6 | 7 | #include <linux/init.h> |
8 | +#include <linux/string.h> | |
7 | 9 | #include <hwregs/reg_rdwr.h> |
8 | 10 | #include <hwregs/reg_map.h> |
9 | 11 | #include <hwregs/ser_defs.h> |
... | ... | @@ -65,6 +67,7 @@ |
65 | 67 | }, |
66 | 68 | #endif |
67 | 69 | }; |
70 | + | |
68 | 71 | static struct dbg_port *port = |
69 | 72 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) |
70 | 73 | &ports[0]; |
71 | 74 | |
72 | 75 | |
73 | 76 | |
... | ... | @@ -97,14 +100,19 @@ |
97 | 100 | #endif |
98 | 101 | #endif |
99 | 102 | |
100 | -static void | |
101 | -start_port(struct dbg_port* p) | |
103 | +static void start_port(struct dbg_port *p) | |
102 | 104 | { |
103 | - if (!p) | |
104 | - return; | |
105 | + /* Set up serial port registers */ | |
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 | 114 | return; |
115 | + | |
108 | 116 | p->started = 1; |
109 | 117 | |
110 | 118 | if (p->nbr == 1) |
111 | 119 | |
112 | 120 | |
113 | 121 | |
... | ... | @@ -118,36 +126,24 @@ |
118 | 126 | crisv32_pinmux_alloc_fixed(pinmux_ser4); |
119 | 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 | 129 | tr_ctrl.base_freq = rec_ctrl.base_freq = regk_ser_f29_493; |
130 | 130 | tr_dma_en.en = rec_ctrl.dma_mode = regk_ser_no; |
131 | 131 | tr_baud_div.div = rec_baud_div.div = 29493000 / p->baudrate / 8; |
132 | 132 | tr_ctrl.en = rec_ctrl.en = 1; |
133 | 133 | |
134 | - if (p->parity == 'O') | |
135 | - { | |
134 | + if (p->parity == 'O') { | |
136 | 135 | tr_ctrl.par_en = regk_ser_yes; |
137 | 136 | tr_ctrl.par = regk_ser_odd; |
138 | 137 | rec_ctrl.par_en = regk_ser_yes; |
139 | 138 | rec_ctrl.par = regk_ser_odd; |
140 | - } | |
141 | - else if (p->parity == 'E') | |
142 | - { | |
139 | + } else if (p->parity == 'E') { | |
143 | 140 | tr_ctrl.par_en = regk_ser_yes; |
144 | 141 | tr_ctrl.par = regk_ser_even; |
145 | 142 | rec_ctrl.par_en = regk_ser_yes; |
146 | 143 | rec_ctrl.par = regk_ser_odd; |
147 | 144 | } |
148 | 145 | |
149 | - if (p->bits == 7) | |
150 | - { | |
146 | + if (p->bits == 7) { | |
151 | 147 | tr_ctrl.data_bits = regk_ser_bits7; |
152 | 148 | rec_ctrl.data_bits = regk_ser_bits7; |
153 | 149 | } |
... | ... | @@ -161,8 +157,7 @@ |
161 | 157 | |
162 | 158 | #ifdef CONFIG_ETRAX_KGDB |
163 | 159 | /* Use polling to get a single character from the kernel debug port */ |
164 | -int | |
165 | -getDebugChar(void) | |
160 | +int getDebugChar(void) | |
166 | 161 | { |
167 | 162 | reg_ser_rs_stat_din stat; |
168 | 163 | reg_ser_rw_ack_intr ack_intr = { 0 }; |
... | ... | @@ -179,8 +174,7 @@ |
179 | 174 | } |
180 | 175 | |
181 | 176 | /* Use polling to put a single character to the kernel debug port */ |
182 | -void | |
183 | -putDebugChar(int val) | |
177 | +void putDebugChar(int val) | |
184 | 178 | { |
185 | 179 | reg_ser_r_stat_din stat; |
186 | 180 | do { |
187 | 181 | |
188 | 182 | |
... | ... | @@ -190,11 +184,47 @@ |
190 | 184 | } |
191 | 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 | +}; | |
220 | + | |
193 | 221 | /* Register console for printk's, etc. */ |
194 | -int __init | |
195 | -init_etrax_debug(void) | |
222 | +int __init init_etrax_debug(void) | |
196 | 223 | { |
197 | 224 | start_port(port); |
225 | + | |
226 | + /* Register an early console if a debug port was chosen. */ | |
227 | + register_console(&early_console_dev); | |
198 | 228 | |
199 | 229 | #ifdef CONFIG_ETRAX_KGDB |
200 | 230 | start_port(kgdb_port); |