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