summaryrefslogtreecommitdiff
path: root/arch/mips/pmc-sierra/yosemite/dbg_io.c
blob: 6362c702e3890a6788878a7d70e6823f5fe17025 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Copyright 2003 PMC-Sierra
 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
 *
 *  This program is free software; you can redistribute  it and/or modify it
 *  under  the terms of  the GNU General  Public License as published by the
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 *  option) any later version.
 *
 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  You should have received a copy of the  GNU General Public License along
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * Support for KGDB for the Yosemite board. We make use of single serial
 * port to be used for KGDB as well as console. The second serial port
 * seems to be having a problem. Single IRQ is allocated for both the
 * ports. Hence, the interrupt routing code needs to figure out whether
 * the interrupt came from channel A or B.
 */

#include <asm/serial.h>

/*
 * Baud rate, Parity, Data and Stop bit settings for the
 * serial port on the Yosemite. Note that the Early printk
 * patch has been added. So, we should be all set to go
 */
#define	YOSEMITE_BAUD_2400	2400
#define	YOSEMITE_BAUD_4800	4800
#define	YOSEMITE_BAUD_9600	9600
#define	YOSEMITE_BAUD_19200	19200
#define	YOSEMITE_BAUD_38400	38400
#define	YOSEMITE_BAUD_57600	57600
#define	YOSEMITE_BAUD_115200	115200

#define	YOSEMITE_PARITY_NONE	0
#define	YOSEMITE_PARITY_ODD	0x08
#define	YOSEMITE_PARITY_EVEN	0x18
#define	YOSEMITE_PARITY_MARK	0x28
#define	YOSEMITE_PARITY_SPACE	0x38

#define	YOSEMITE_DATA_5BIT	0x0
#define	YOSEMITE_DATA_6BIT	0x1
#define	YOSEMITE_DATA_7BIT	0x2
#define	YOSEMITE_DATA_8BIT	0x3

#define	YOSEMITE_STOP_1BIT	0x0
#define	YOSEMITE_STOP_2BIT	0x4

/* This is crucial */
#define	SERIAL_REG_OFS		0x1

#define	SERIAL_RCV_BUFFER	0x0
#define	SERIAL_TRANS_HOLD	0x0
#define	SERIAL_SEND_BUFFER	0x0
#define	SERIAL_INTR_ENABLE	(1 * SERIAL_REG_OFS)
#define	SERIAL_INTR_ID		(2 * SERIAL_REG_OFS)
#define	SERIAL_DATA_FORMAT	(3 * SERIAL_REG_OFS)
#define	SERIAL_LINE_CONTROL	(3 * SERIAL_REG_OFS)
#define	SERIAL_MODEM_CONTROL	(4 * SERIAL_REG_OFS)
#define	SERIAL_RS232_OUTPUT	(4 * SERIAL_REG_OFS)
#define	SERIAL_LINE_STATUS	(5 * SERIAL_REG_OFS)
#define	SERIAL_MODEM_STATUS	(6 * SERIAL_REG_OFS)
#define	SERIAL_RS232_INPUT	(6 * SERIAL_REG_OFS)
#define	SERIAL_SCRATCH_PAD	(7 * SERIAL_REG_OFS)

#define	SERIAL_DIVISOR_LSB	(0 * SERIAL_REG_OFS)
#define	SERIAL_DIVISOR_MSB	(1 * SERIAL_REG_OFS)

/*
 * Functions to READ and WRITE to serial port 0
 */
#define	SERIAL_READ(ofs)		(*((volatile unsigned char*)	\
					(TITAN_SERIAL_BASE + ofs)))

#define	SERIAL_WRITE(ofs, val)		((*((volatile unsigned char*)	\
					(TITAN_SERIAL_BASE + ofs))) = val)

/*
 * Functions to READ and WRITE to serial port 1
 */
#define	SERIAL_READ_1(ofs)		(*((volatile unsigned char*)	\
					(TITAN_SERIAL_BASE_1 + ofs)))

#define	SERIAL_WRITE_1(ofs, val)	((*((volatile unsigned char*)	\
					(TITAN_SERIAL_BASE_1 + ofs))) = val)

/*
 * Second serial port initialization
 */
void init_second_port(void)
{
	/* Disable Interrupts */
	SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
	SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);

	{
		unsigned int divisor;

		SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
		divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
		SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);

		SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
			       (divisor & 0xff00) >> 8);
		SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
	}

	SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
		       YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);

	/* Enable Interrupts */
	SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
}

/* Initialize the serial port for KGDB debugging */
void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
	       unsigned char stop)
{
	/* Disable Interrupts */
	SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
	SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);

	{
		unsigned int divisor;

		SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);

		divisor = TITAN_SERIAL_BASE_BAUD / baud;
		SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);

		SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
		SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
	}

	SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
}

static int remoteDebugInitialized = 0;

unsigned char getDebugChar(void)
{
	if (!remoteDebugInitialized) {
		remoteDebugInitialized = 1;
		debugInit(YOSEMITE_BAUD_115200,
			  YOSEMITE_DATA_8BIT,
			  YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
	}

	while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
	return SERIAL_READ(SERIAL_RCV_BUFFER);
}

int putDebugChar(unsigned char byte)
{
	if (!remoteDebugInitialized) {
		remoteDebugInitialized = 1;
		debugInit(YOSEMITE_BAUD_115200,
			  YOSEMITE_DATA_8BIT,
			  YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
	}

	while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
	SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);

	return 1;
}