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