Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * marvell kirkwood uart (supposed to be a 16550)
3
 */
4
#include "u.h"
5
#include "../port/lib.h"
6
#include "mem.h"
7
#include "dat.h"
8
#include "fns.h"
9
#include "io.h"
10
#include "../port/error.h"
11
// #include "../port/uart.h"
12
 
13
enum {
14
	UartFREQ =	0, // xxx
15
 
16
	IERrx		= 1<<0,
17
	IERtx		= 1<<1,
18
 
19
	IRRintrmask	= (1<<4)-1,
20
	IRRnointr	= 1,
21
	IRRthrempty	= 2,
22
	IRRrxdata	= 4,
23
	IRRrxstatus	= 6,
24
	IRRtimeout	= 12,
25
 
26
	IRRfifomask	= 3<<6,
27
	IRRfifoenable	= 3<<6,
28
 
29
	FCRenable	= 1<<0,
30
	FCRrxreset	= 1<<1,
31
	FCRtxreset	= 1<<2,
32
	/* reserved */
33
	FCRrxtriggermask	= 3<<6,
34
	FCRrxtrigger1	= 0<<6,
35
	FCRrxtrigger4	= 1<<6,
36
	FCRrxtrigger8	= 2<<6,
37
	FCRrxtrigger14	= 3<<6,
38
 
39
	LCRbpcmask	= 3<<0,
40
	LCRbpc5		= 0<<0,
41
	LCRbpc6		= 1<<0,
42
	LCRbpc7		= 2<<0,
43
	LCRbpc8		= 3<<0,
44
	LCRstop2b	= 1<<2,
45
	LCRparity	= 1<<3,
46
	LCRparityeven	= 1<<4,
47
	LCRbreak	= 1<<6,
48
	LCRdivlatch	= 1<<7,
49
 
50
	LSRrx		= 1<<0,
51
	LSRrunerr	= 1<<1,
52
	LSRparerr	= 1<<2,
53
	LSRframeerr	= 1<<3,
54
	LSRbi		= 1<<4,
55
	LSRthre		= 1<<5,
56
	LSRtxempty	= 1<<6,
57
	LSRfifoerr	= 1<<7,
58
};
59
 
60
extern PhysUart kwphysuart;
61
 
62
typedef struct UartReg UartReg;
63
struct UartReg
64
{
65
	union {
66
		ulong	thr;
67
		ulong	dll;
68
		ulong	rbr;
69
	};
70
	union {
71
		ulong	ier;
72
		ulong	dlh;
73
	};
74
	union {
75
		ulong	iir;
76
		ulong	fcr;
77
	};
78
	ulong	lcr;
79
	ulong	mcr;
80
	ulong	lsr;
81
	ulong	scr;
82
};
83
 
84
typedef struct Ctlr Ctlr;
85
struct Ctlr {
86
	UartReg*regs;
87
	int	irq;
88
	Lock;
89
};
90
 
91
static Ctlr kirkwoodctlr[] = {
92
{
93
	.regs   = nil,			/* filled in below */
94
	.irq    = IRQ1uart0, },
95
};
96
 
97
static Uart kirkwooduart[] = {
98
{
99
	.regs	= &kirkwoodctlr[0],
100
	.name	= "eia0",
101
	.freq	= UartFREQ,
102
	.phys	= &kwphysuart,
103
	.special= 0,
104
	.console= 1,
105
	.next	= nil, },
106
};
107
 
108
static void
109
kw_read(Uart *uart)
110
{
111
	Ctlr *ctlr = uart->regs;
112
	UartReg *regs = ctlr->regs;
113
	ulong lsr;
114
	char c;
115
 
116
	while ((lsr = regs->lsr) & LSRrx) {
117
		if(lsr&LSRrunerr)
118
			uart->oerr++;
119
		if(lsr&LSRparerr)
120
			uart->perr++;
121
		if(lsr&LSRframeerr)
122
			uart->ferr++;
123
		c = regs->rbr;
124
		if((lsr & (LSRbi|LSRframeerr|LSRparerr)) == 0)
125
			uartrecv(uart, c);
126
	}
127
}
128
 
129
static void
130
kw_intr(Ureg*, void *arg)
131
{
132
	Uart *uart = arg;
133
	Ctlr *ctlr = uart->regs;
134
	UartReg *regs = ctlr->regs;
135
	ulong v;
136
 
137
	if(regs == 0) {
138
		kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
139
		regs = (UartReg *)soc.uart[0];		/* caution */
140
		coherence();
141
	}
142
	v = regs->iir;
143
	if(v & IRRthrempty)
144
		uartkick(uart);
145
	if(v & IRRrxdata)
146
		kw_read(uart);
147
 
148
	intrclear(Irqhi, ctlr->irq);
149
}
150
 
151
static Uart*
152
kw_pnp(void)
153
{
154
	kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
155
	coherence();
156
	return kirkwooduart;
157
}
158
 
159
static void
160
kw_enable(Uart* uart, int ie)
161
{
162
	Ctlr *ctlr = uart->regs;
163
	UartReg *regs = ctlr->regs;
164
 
165
	if(regs == 0) {
166
		kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
167
		regs = (UartReg *)soc.uart[0];		/* caution */
168
		coherence();
169
	}
170
	USED(ie);
171
	regs->fcr = FCRenable|FCRrxtrigger4;
172
	regs->ier = IERrx|IERtx;
173
	intrenable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
174
 
175
	(*uart->phys->dtr)(uart, 1);
176
	(*uart->phys->rts)(uart, 1);
177
}
178
 
179
static void
180
kw_disable(Uart* uart)
181
{
182
	Ctlr *ctlr = uart->regs;
183
 
184
	(*uart->phys->dtr)(uart, 0);
185
	(*uart->phys->rts)(uart, 0);
186
	(*uart->phys->fifo)(uart, 0);
187
 
188
	intrdisable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
189
}
190
 
191
static void
192
kw_kick(Uart* uart)
193
{
194
	Ctlr *ctlr = uart->regs;
195
	UartReg *regs = ctlr->regs;
196
	int i;
197
 
198
	if(uart->cts == 0 || uart->blocked)
199
		return;
200
 
201
	for(i = 0; i < 16; i++) {
202
		if((regs->lsr & LSRthre) == 0 ||
203
		    uart->op >= uart->oe && uartstageoutput(uart) == 0)
204
			break;
205
		regs->thr = *uart->op++;
206
	}
207
}
208
 
209
static void
210
kw_break(Uart* uart, int ms)
211
{
212
	USED(uart, ms);
213
}
214
 
215
static int
216
kw_baud(Uart* uart, int baud)
217
{
218
	USED(uart, baud);
219
	return 0;
220
}
221
 
222
static int
223
kw_bits(Uart* uart, int bits)
224
{
225
	USED(uart, bits);
226
	return 0;
227
}
228
 
229
static int
230
kw_stop(Uart* uart, int stop)
231
{
232
	USED(uart, stop);
233
	return 0;
234
}
235
 
236
static int
237
kw_parity(Uart* uart, int parity)
238
{
239
	USED(uart, parity);
240
	return 0;
241
}
242
 
243
static void
244
kw_modemctl(Uart* uart, int on)
245
{
246
	USED(uart, on);
247
}
248
 
249
static void
250
kw_rts(Uart* uart, int on)
251
{
252
	USED(uart, on);
253
}
254
 
255
static void
256
kw_dtr(Uart* uart, int on)
257
{
258
	USED(uart, on);
259
}
260
 
261
static long
262
kw_status(Uart* uart, void* buf, long n, long offset)
263
{
264
	USED(uart, buf, n, offset);
265
	return 0;
266
}
267
 
268
static void
269
kw_fifo(Uart* uart, int level)
270
{
271
	USED(uart, level);
272
}
273
 
274
static int
275
kw_getc(Uart *uart)
276
{
277
	Ctlr *ctlr = uart->regs;
278
	UartReg *regs = ctlr->regs;
279
 
280
	while((regs->lsr&LSRrx) == 0)
281
		;
282
	return regs->rbr;
283
}
284
 
285
static void
286
kw_putc(Uart *uart, int c)
287
{
288
	Ctlr *ctlr = uart->regs;
289
	UartReg *regs = ctlr->regs;
290
 
291
	/* can be called from iprint, among many other places */
292
	if(regs == 0) {
293
		kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
294
		regs = (UartReg *)soc.uart[0];		/* caution */
295
		coherence();
296
	}
297
	while((regs->lsr&LSRthre) == 0)
298
		;
299
	regs->thr = c;
300
	coherence();
301
}
302
 
303
PhysUart kwphysuart = {
304
	.name		= "kirkwood",
305
	.pnp		= kw_pnp,
306
	.enable		= kw_enable,
307
	.disable	= kw_disable,
308
	.kick		= kw_kick,
309
	.dobreak	= kw_break,
310
	.baud		= kw_baud,
311
	.bits		= kw_bits,
312
	.stop		= kw_stop,
313
	.parity		= kw_parity,
314
	.modemctl	= kw_modemctl,
315
	.rts		= kw_rts,
316
	.dtr		= kw_dtr,
317
	.status		= kw_status,
318
	.fifo		= kw_fifo,
319
	.getc		= kw_getc,
320
	.putc		= kw_putc,
321
};
322
 
323
void
324
uartkirkwoodconsole(void)
325
{
326
	Uart *uart;
327
 
328
	uart = &kirkwooduart[0];
329
	(*uart->phys->enable)(uart, 0);
330
	uartctl(uart, "b115200 l8 pn s1 i1");
331
	uart->console = 1;
332
	consuart = uart;
333
//serialputs("uart0 kirkwood\n", strlen("uart0 kirkwood\n"));
334
}
335
 
336
void
337
serialputc(int c)
338
{
339
	int cnt, s;
340
	UartReg *regs = (UartReg *)soc.uart[0];
341
 
342
	s = splhi();
343
	cnt = m->cpuhz;
344
	if (cnt <= 0)			/* cpuhz not set yet? */
345
		cnt = 1000000;
346
	while((regs->lsr & LSRthre) == 0 && --cnt > 0)
347
		;
348
	regs->thr = c;
349
	coherence();
350
	delay(1);
351
	splx(s);
352
}
353
 
354
void
355
serialputs(char *p, int len)
356
{
357
	while(--len >= 0) {
358
		if(*p == '\n')
359
			serialputc('\r');
360
		serialputc(*p++);
361
	}
362
}