Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
#include "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
#include "io.h"
7
#include "imm.h"
8
#include "../port/error.h"
9
#include "../ppc/uartsmc.h"
10
 
11
/*
12
 * PowerPC 8260 SMC UART
13
 */
14
 
15
enum {
16
	/* SMC Mode Registers */
17
	Clen		= 0x7800,	/* Character length */
18
	Sl		= 0x0400,	/* Stop length, 0: one stop bit, 1: two */
19
	Pen		= 0x0200,	/* Parity enable */
20
	Pm		= 0x0100,	/* Parity mode, 0 is odd */
21
	Sm		= 0x0030,	/* SMC mode, two bits */
22
	SMUart	= 0x0020,	/* SMC mode, 0b10 is uart */
23
	Dm		= 0x000c,	/* Diagnostic mode, 00 is normal */
24
	Ten		= 0x0002,	/* Transmit enable, 1 is enabled */
25
	Ren		= 0x0001,	/* Receive enable, 1 is enabled */
26
 
27
	/* SMC Event/Mask Registers */
28
	ce_Brke	= 0x0040,	/* Break end */
29
	ce_Br	= 0x0020,	/* Break character received */
30
	ce_Bsy	= 0x0004,	/* Busy condition */
31
	ce_Txb	= 0x0002,	/* Tx buffer */
32
	ce_Rxb	= 0x0001,	/* Rx buffer */
33
 
34
	/* Receive/Transmit Buffer Descriptor Control bits */
35
	BDContin=	1<<9,
36
	BDIdle=		1<<8,
37
	BDPreamble=	1<<8,
38
	BDBreak=	1<<5,
39
	BDFrame=	1<<4,
40
	BDParity=	1<<3,
41
	BDOverrun=	1<<1,
42
 
43
	/* Tx and Rx buffer sizes (32 bytes) */
44
	Rxsize=		CACHELINESZ,
45
	Txsize=		CACHELINESZ,
46
};
47
 
48
extern PhysUart smcphysuart;
49
 
50
Uart smcuart[Nuart] = {
51
	{
52
		.name = "SMC1",
53
		.baud = 115200,
54
		.bits = 8,
55
		.stop = 1,
56
		.parity = 'n',
57
		.phys = &smcphysuart,
58
		.special = 0,
59
	},
60
/*	Only configure SMC1 for now
61
	{
62
		.name = "SMC2",
63
		.baud = 115200,
64
		.bits = 8,
65
		.stop = 1,
66
		.parity = 'n',
67
		.phys = &smcphysuart,
68
		.special = 0,
69
	},
70
*/
71
};
72
 
73
int uartinited = 0;
74
 
75
static void smcinterrupt(Ureg*, void*);
76
static void smcputc(Uart *uart, int c);
77
 
78
int
79
baudgen(int baud)
80
{
81
	int d;
82
 
83
	d = ((m->brghz+(baud>>1))/baud)>>4;
84
	if(d >= (1<<12))
85
		return ((d+15)>>3)|1;
86
	return d<<1;
87
}
88
 
89
static Uart*
90
smcpnp(void)
91
{
92
	int i;
93
 
94
	for (i = 0; i < nelem(smcuart) - 1; i++)
95
		smcuart[i].next = smcuart + i + 1;
96
	return smcuart;
97
}
98
 
99
void
100
smcsetup(Uart *uart)
101
{
102
	Uartsmc *p;
103
	SMC *smc;
104
	UartData *ud;
105
 
106
	ud = uart->regs;
107
 
108
	/* magic addresses */
109
 
110
	p = &m->immr->uartsmc[ud->smcno];
111
	smc = imm->smc + ud->smcno;	/* SMC1 */
112
	ud->smc = smc;
113
	ud->usmc = p;
114
 
115
	/* step 0: disable rx/tx */
116
	smc->smcmr &= ~3;
117
 
118
	ioplock();
119
 
120
	/* step 1, Using Port D */
121
	if (ud->smcno != 0)
122
		panic("Don't know how to set Port D bits");
123
	imm->port[SMC1PORT].ppar |= SMRXD1|SMTXD1;
124
	imm->port[SMC1PORT].pdir |= SMTXD1;
125
	imm->port[SMC1PORT].pdir &= ~SMRXD1;
126
	imm->port[SMC1PORT].psor &= ~(SMRXD1|SMTXD1);
127
 
128
	/* step 2: set up brgc1 */
129
	imm->brgc[ud->smcno]  = baudgen(uart->baud) | 0x10000;
130
 
131
	/* step 3: route clock to SMC1 */
132
	imm->cmxsmr &= (ud->smcno == 0) ? ~0xb0 : ~0xb;	/* clear smcx and smcxcs */
133
 
134
	iopunlock();
135
 
136
	/* step 4: assign a pointer to the SMCparameter RAM */
137
	m->immr->param[ud->smcno].smcbase = (ulong)p - IMMR;
138
 
139
	/* step 6: issue command to CP */
140
	if (ud->smcno == 0)
141
		cpmop(InitRxTx, SMC1ID, 0);
142
	else
143
		cpmop(InitRxTx, SMC2ID, 0);
144
 
145
	/* step 7: protocol parameters */
146
	p->rfcr = 0x30;
147
	p->tfcr = 0x30;
148
}
149
 
150
void
151
smcinit(Uart *uart)
152
{
153
	Uartsmc *p;
154
	SMC *smc;
155
	UartData *ud;
156
	ulong lcr;
157
	int bits;
158
 
159
	ud = uart->regs;
160
 
161
	if (ud->initialized)
162
		return;
163
 
164
	smcsetup(uart);	/* Steps 1 through 4, PPC-dependent */
165
	p = ud->usmc;
166
	smc = ud->smc;
167
 
168
	/* step 5: set up buffer descriptors */
169
	/* setup my uart structure */
170
	if (ud->rxb == nil)
171
		ud->rxb = bdalloc(1);
172
	if (ud->txb == nil)
173
		ud->txb = bdalloc(1);
174
 
175
	p->rbase = ((ulong)ud->rxb) - (ulong)IMMR;
176
	p->tbase = ((ulong)ud->txb) - (ulong)IMMR;
177
 
178
	/* step 8: receive buffer size */
179
	p->mrblr = Rxsize;
180
 
181
	/* step 9: */
182
	p->maxidl = 15;
183
 
184
	/* step 10: */
185
	p->brkln = 0;
186
	p->brkec = 0;
187
 
188
	/* step 11: */
189
	p->brkcr = 0;
190
 
191
	/* step 12: setup receive buffer */
192
	ud->rxb->status = BDEmpty|BDWrap|BDInt;
193
	ud->rxb->length = 0;
194
	ud->rxbuf = xspanalloc(Rxsize, 0, CACHELINESZ);
195
	ud->rxb->addr = PADDR(ud->rxbuf);
196
 
197
	/* step 13: step transmit buffer */
198
	ud->txb->status = BDWrap|BDInt;
199
	ud->txb->length = 0;
200
	ud->txbuf = xspanalloc(Txsize, 0, CACHELINESZ);
201
	ud->txb->addr = PADDR(ud->txbuf);
202
 
203
	/* step 14: clear events */
204
	smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
205
 
206
	/* 
207
	 * step 15: enable interrupts (done later)
208
	 * smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
209
	 */
210
 
211
	/* step 17: set parity, no of bits, UART mode, ... */
212
	lcr = SMUart;
213
	bits = uart->bits + 1;
214
 
215
	switch(uart->parity){
216
	case 'e':
217
		lcr |= (Pen|Pm);
218
		bits +=1;
219
		break;
220
	case 'o':
221
		lcr |= Pen;
222
		bits +=1;
223
		break;
224
	case 'n':
225
	default:
226
		break;
227
	}
228
 
229
	if(uart->stop == 2){
230
		lcr |= Sl;
231
		bits += 1;
232
	}
233
 
234
	/* Set new value and reenable if device was previously enabled */
235
	smc->smcmr = lcr |  bits <<11 | 0x3;
236
 
237
	ud->initialized = 1;
238
}
239
 
240
static void
241
smcenable(Uart *uart, int intenb)
242
{
243
	UartData *ud;
244
	SMC *smc;
245
	int nr;
246
 
247
	nr = uart - smcuart;
248
	if (nr < 0 || nr > Nuart)
249
		panic("No SMC %d", nr);
250
	ud = uartdata + nr;
251
	ud->smcno = nr;
252
	uart->regs = ud;
253
	if (ud->initialized == 0)
254
		smcinit(uart);
255
	if (ud->enabled || intenb == 0)
256
		return;
257
	smc = ud->smc;
258
	/* clear events */
259
	smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
260
	/* enable interrupts */
261
	smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
262
	intrenable(VecSMC1 + ud->smcno, smcinterrupt, uart, uart->name);
263
	ud->enabled = 1;
264
}
265
 
266
static long
267
smcstatus(Uart* uart, void* buf, long n, long offset)
268
{
269
	SMC *sp;
270
	char p[128];
271
 
272
	sp = ((UartData*)uart->regs)->smc;
273
	snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
274
		"dev(%d) type(%d) framing(%d) overruns(%d)\n",
275
 
276
		uart->baud,
277
		uart->hup_dcd, 
278
		uart->hup_dsr,
279
		((sp->smcmr & Clen) >>11) - ((sp->smcmr&Pen) ? 1 : 0) - ((sp->smcmr&Sl) ? 2 : 1),
280
		(sp->smcmr & Pen) ? ((sp->smcmr & Pm) ? 'e': 'o'): 'n',
281
		(sp->smcmr & Sl) ? 2: 1,
282
 
283
		uart->dev,
284
		uart->type,
285
		uart->ferr,
286
		uart->oerr 
287
	);
288
	n = readstr(offset, buf, n, p);
289
	free(p);
290
 
291
	return n;
292
}
293
 
294
static void
295
smcfifo(Uart*, int)
296
{
297
	/*
298
	 * Toggle FIFOs:
299
	 * if none, do nothing;
300
	 * reset the Rx and Tx FIFOs;
301
	 * empty the Rx buffer and clear any interrupt conditions;
302
	 * if enabling, try to turn them on.
303
	 */
304
	return;
305
}
306
 
307
static void
308
smcdtr(Uart*, int)
309
{
310
}
311
 
312
static void
313
smcrts(Uart*, int)
314
{
315
}
316
 
317
static void
318
smcmodemctl(Uart*, int)
319
{
320
}
321
 
322
static int
323
smcparity(Uart* uart, int parity)
324
{
325
	int lcr;
326
	SMC *sp;
327
 
328
	sp = ((UartData*)uart->regs)->smc;
329
 
330
	lcr = sp->smcmr & ~(Pen|Pm);
331
 
332
	/* Disable transmitter/receiver. */
333
	sp->smcmr &= ~(Ren | Ten);
334
 
335
	switch(parity){
336
	case 'e':
337
		lcr |= (Pen|Pm);
338
		break;
339
	case 'o':
340
		lcr |= Pen;
341
		break;
342
	case 'n':
343
	default:
344
		break;
345
	}
346
	/* Set new value and reenable if device was previously enabled */
347
	sp->smcmr = lcr;
348
 
349
	uart->parity = parity;
350
 
351
	return 0;
352
}
353
 
354
static int
355
smcstop(Uart* uart, int stop)
356
{
357
	int lcr, bits;
358
	SMC *sp;
359
 
360
	sp = ((UartData*)uart->regs)->smc;
361
	lcr = sp->smcmr & ~(Sl | Clen);
362
 
363
	/* Disable transmitter/receiver. */
364
	sp->smcmr &= ~(Ren | Ten);
365
 
366
	switch(stop){
367
	case 1:
368
		break;
369
	case 2:
370
		lcr |= Sl;
371
		break;
372
	default:
373
		return -1;
374
	}
375
 
376
	bits = uart->bits + ((lcr & Pen) ? 1 : 0) + ((lcr & Sl) ? 2 : 1);
377
	lcr |= bits<<11;
378
 
379
	/* Set new value and reenable if device was previously enabled */
380
	sp->smcmr = lcr;
381
 
382
	uart->stop = stop;
383
 
384
	return 0;
385
}
386
 
387
static int
388
smcbits(Uart* uart, int bits)
389
{
390
	int lcr, b;
391
	SMC *sp;
392
 
393
	if (bits < 5 || bits > 14)
394
		return -1;
395
 
396
	sp = ((UartData*)uart->regs)->smc;
397
	lcr = sp->smcmr & ~Clen;
398
 
399
	b = bits + ((sp->smcmr & Pen) ? 1 : 0) + ((sp->smcmr & Sl) ? 2 : 1);
400
 
401
	if (b > 15)
402
		return -1;
403
 
404
	/* Disable transmitter/receiver */
405
	sp->smcmr &= ~(Ren | Ten);
406
 
407
	/* Set new value and reenable if device was previously enabled */
408
	sp->smcmr = lcr |  b<<11;
409
 
410
	uart->bits = bits;
411
 
412
	return 0;
413
}
414
 
415
static int
416
smcbaud(Uart* uart, int baud)
417
{
418
	int i;
419
	SMC *sp;
420
 
421
	if (uart->enabled){
422
		sp = ((UartData*)uart->regs)->smc;
423
 
424
		if(uart->freq == 0 || baud <= 0)
425
			return -1;
426
 
427
		i = sp - imm->smc;
428
		imm->brgc[i] = (((m->brghz >> 4) / baud) << 1) | 0x00010000;
429
	}
430
	uart->baud = baud;
431
 
432
	return 0;
433
}
434
 
435
static void
436
smcbreak(Uart*, int)
437
{
438
}
439
 
440
static void
441
smckick(Uart *uart)
442
{
443
	BD *txb;
444
	UartData *ud;
445
	int i;
446
 
447
	if(uart->blocked)
448
		return;
449
 
450
	ud = uart->regs;
451
	txb = ud->txb;
452
 
453
	if (txb->status & BDReady)
454
		return;	/* Still busy */
455
 
456
	for(i = 0; i < Txsize; i++){
457
		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
458
			break;
459
		ud->txbuf[i] = *(uart->op++);
460
	}
461
	if (i == 0)
462
		return;
463
	dcflush(ud->txbuf, Txsize);
464
	txb->length = i;
465
	sync();
466
	txb->status |= BDReady|BDInt;
467
}
468
 
469
static void
470
smcinterrupt(Ureg*, void* u)
471
{
472
	int i, nc;
473
	char *buf;
474
	BD *rxb;
475
	UartData *ud;
476
	Uart *uart;
477
	uchar events;
478
 
479
	uart = u;
480
	if (uart == nil)
481
		panic("uart is nil");
482
	ud = uart->regs;
483
	if (ud == nil)
484
		panic("ud is nil");
485
 
486
	events = ud->smc->smce;
487
	ud->smc->smce = events;	/* Clear events */
488
 
489
	if (events & 0x10)
490
		iprint("smc%d: break\n", ud->smcno);
491
	if (events & 0x4)
492
		uart->oerr++;
493
	if (events & 0x1){
494
		/* Receive characters
495
		*/
496
		rxb = ud->rxb;
497
		buf = ud->rxbuf;
498
		dczap(buf, Rxsize);	/* invalidate data cache before copying */
499
		if ((rxb->status & BDEmpty) == 0){
500
			nc = rxb->length;
501
			for (i=0; i<nc; i++)
502
				uartrecv(uart, *buf++);
503
			sync();
504
			rxb->status |= BDEmpty;
505
		}else{
506
			iprint("uartsmc: unexpected receive event\n");
507
		}
508
	}
509
	if (events & 0x2){
510
		if ((ud->txb->status & BDReady) == 0)
511
			uartkick(uart);
512
	}
513
}
514
 
515
static void
516
smcdisable(Uart* uart)
517
{
518
	SMC *sp;
519
 
520
	sp = ((UartData*)uart->regs)->smc;
521
	sp->smcmr &= ~(Ren | Ten);
522
}
523
 
524
static int
525
getchars(Uart *uart, uchar *cbuf)
526
{
527
	int i, nc;
528
	char *buf;
529
	BD *rxb;
530
	UartData *ud;
531
 
532
	ud = uart->regs;
533
	rxb = ud->rxb;
534
 
535
	/* Wait for character to show up.
536
	*/
537
	buf = ud->rxbuf;
538
	while (rxb->status & BDEmpty)
539
		;
540
	nc = rxb->length;
541
	for (i=0; i<nc; i++)
542
		*cbuf++ = *buf++;
543
	sync();
544
	rxb->status |= BDEmpty;
545
 
546
	return(nc);
547
}
548
 
549
static int
550
smcgetc(Uart *uart)
551
{
552
	static uchar buf[128], *p;
553
	static int cnt;
554
	char	c;
555
 
556
	if (cnt <= 0) {
557
		cnt = getchars(uart, buf);
558
		p = buf;
559
	}
560
	c = *p++;
561
	cnt--;
562
 
563
	return(c);
564
}
565
 
566
static void
567
smcputc(Uart *uart, int c)
568
{
569
	BD *txb;
570
	UartData *ud;
571
	SMC *smc;
572
 
573
	ud = uart->regs;
574
	txb = ud->txb;
575
	smc = ud->smc;
576
	smc->smcm = 0;
577
 
578
	/* Wait for last character to go.
579
	*/
580
	while (txb->status & BDReady)
581
		;
582
 
583
	ud->txbuf[0] = c;
584
	dcflush(ud->txbuf, 1);
585
	txb->length = 1;
586
	sync();
587
	txb->status |= BDReady;
588
 
589
	while (txb->status & BDReady)
590
		;
591
}
592
 
593
PhysUart smcphysuart = {
594
	.name		= "smc",
595
	.pnp			= smcpnp,
596
	.enable		= smcenable,
597
	.disable		= smcdisable,
598
	.kick			= smckick,
599
	.dobreak		= smcbreak,
600
	.baud		= smcbaud,
601
	.bits			= smcbits,
602
	.stop			= smcstop,
603
	.parity		= smcparity,
604
	.modemctl	= smcmodemctl,
605
	.rts			= smcrts,
606
	.dtr			= smcdtr,
607
	.status		= smcstatus,
608
	.fifo			= smcfifo,
609
	.getc			= smcgetc,
610
	.putc			= smcputc,
611
};
612
 
613
void
614
console(void)
615
{
616
	Uart *uart;
617
	int n;
618
	char *cmd, *p;
619
 
620
	if((p = getconf("console")) == nil)
621
		return;
622
	n = strtoul(p, &cmd, 0);
623
	if(p == cmd)
624
		return;
625
	if(n < 0 || n >= nelem(smcuart))
626
		return;
627
	uart = smcuart + n;
628
 
629
/*	uartctl(uart, "b115200 l8 pn s1"); */
630
	if(*cmd != '\0')
631
		uartctl(uart, cmd);
632
	(*uart->phys->enable)(uart, 0);
633
 
634
	consuart = uart;
635
	uart->console = 1;
636
}