diff options
author | Jesper Nilsson <jespern@axis.com> | 2014-10-08 09:52:49 -0400 |
---|---|---|
committer | Jesper Nilsson <jespern@axis.com> | 2014-12-19 18:05:49 -0500 |
commit | 4729d77332a4383770c780b7709d5e14f12a4d1e (patch) | |
tree | bcea3bc26897cf5bb6ae005e66a8cf2206f13936 /arch/cris/arch-v32 | |
parent | 421d085252613c4caf9c4f2fda3c722a9f5bc554 (diff) |
CRISv32: Implement early console
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Diffstat (limited to 'arch/cris/arch-v32')
-rw-r--r-- | arch/cris/arch-v32/kernel/debugport.c | 82 |
1 files changed, 56 insertions, 26 deletions
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c index 610909b003f6..02e33ebe51ec 100644 --- a/arch/cris/arch-v32/kernel/debugport.c +++ b/arch/cris/arch-v32/kernel/debugport.c | |||
@@ -3,7 +3,9 @@ | |||
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> |
@@ -65,6 +67,7 @@ struct dbg_port ports[] = | |||
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]; |
@@ -97,14 +100,19 @@ static struct dbg_port *kgdb_port = | |||
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) |
@@ -118,36 +126,24 @@ start_port(struct dbg_port* p) | |||
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 | } |
@@ -161,8 +157,7 @@ start_port(struct dbg_port* p) | |||
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 }; |
@@ -179,8 +174,7 @@ getDebugChar(void) | |||
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 { |
@@ -190,12 +184,48 @@ putDebugChar(int 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 | }; | ||
220 | |||
193 | /* Register console for printk's, etc. */ | 221 | /* Register console for printk's, etc. */ |
194 | int __init | 222 | int __init init_etrax_debug(void) |
195 | init_etrax_debug(void) | ||
196 | { | 223 | { |
197 | start_port(port); | 224 | start_port(port); |
198 | 225 | ||
226 | /* Register an early console if a debug port was chosen. */ | ||
227 | register_console(&early_console_dev); | ||
228 | |||
199 | #ifdef CONFIG_ETRAX_KGDB | 229 | #ifdef CONFIG_ETRAX_KGDB |
200 | start_port(kgdb_port); | 230 | start_port(kgdb_port); |
201 | #endif /* CONFIG_ETRAX_KGDB */ | 231 | #endif /* CONFIG_ETRAX_KGDB */ |