xref: /plan9/sys/src/9/bcm/uartmini.c (revision b4d1cf41cd5301e4c76aef9c04ddee28ac168a8e)
15d9de2d3SDavid du Colombier /*
25d9de2d3SDavid du Colombier  * bcm2835 mini uart (UART1)
35d9de2d3SDavid du Colombier  */
45d9de2d3SDavid du Colombier 
55d9de2d3SDavid du Colombier #include "u.h"
65d9de2d3SDavid du Colombier #include "../port/lib.h"
75d9de2d3SDavid du Colombier #include "../port/error.h"
85d9de2d3SDavid du Colombier #include "mem.h"
95d9de2d3SDavid du Colombier #include "dat.h"
105d9de2d3SDavid du Colombier #include "fns.h"
115d9de2d3SDavid du Colombier #include "io.h"
125d9de2d3SDavid du Colombier 
135d9de2d3SDavid du Colombier #define GPIOREGS	(VIRTIO+0x200000)
145d9de2d3SDavid du Colombier #define AUXREGS		(VIRTIO+0x215000)
155d9de2d3SDavid du Colombier #define	OkLed		16
165d9de2d3SDavid du Colombier #define	TxPin		14
175d9de2d3SDavid du Colombier #define	RxPin		15
185d9de2d3SDavid du Colombier 
195d9de2d3SDavid du Colombier /* GPIO regs */
205d9de2d3SDavid du Colombier enum {
215d9de2d3SDavid du Colombier 	Fsel0	= 0x00>>2,
225d9de2d3SDavid du Colombier 		FuncMask= 0x7,
235d9de2d3SDavid du Colombier 		Input	= 0x0,
245d9de2d3SDavid du Colombier 		Output	= 0x1,
255d9de2d3SDavid du Colombier 		Alt0	= 0x4,
265d9de2d3SDavid du Colombier 		Alt1	= 0x5,
275d9de2d3SDavid du Colombier 		Alt2	= 0x6,
285d9de2d3SDavid du Colombier 		Alt3	= 0x7,
295d9de2d3SDavid du Colombier 		Alt4	= 0x3,
305d9de2d3SDavid du Colombier 		Alt5	= 0x2,
315d9de2d3SDavid du Colombier 	Set0	= 0x1c>>2,
325d9de2d3SDavid du Colombier 	Clr0	= 0x28>>2,
335d9de2d3SDavid du Colombier 	Lev0	= 0x34>>2,
345d9de2d3SDavid du Colombier 	PUD	= 0x94>>2,
355d9de2d3SDavid du Colombier 		Off	= 0x0,
365d9de2d3SDavid du Colombier 		Pulldown= 0x1,
375d9de2d3SDavid du Colombier 		Pullup	= 0x2,
385d9de2d3SDavid du Colombier 	PUDclk0	= 0x98>>2,
395d9de2d3SDavid du Colombier 	PUDclk1	= 0x9c>>2,
405d9de2d3SDavid du Colombier };
415d9de2d3SDavid du Colombier 
425d9de2d3SDavid du Colombier /* AUX regs */
435d9de2d3SDavid du Colombier enum {
445d9de2d3SDavid du Colombier 	Irq	= 0x00>>2,
455d9de2d3SDavid du Colombier 		UartIrq	= 1<<0,
465d9de2d3SDavid du Colombier 	Enables	= 0x04>>2,
475d9de2d3SDavid du Colombier 		UartEn	= 1<<0,
485d9de2d3SDavid du Colombier 	MuIo	= 0x40>>2,
495d9de2d3SDavid du Colombier 	MuIer	= 0x44>>2,
505d9de2d3SDavid du Colombier 		RxIen	= 1<<0,
515d9de2d3SDavid du Colombier 		TxIen	= 1<<1,
525d9de2d3SDavid du Colombier 	MuIir	= 0x48>>2,
535d9de2d3SDavid du Colombier 	MuLcr	= 0x4c>>2,
545d9de2d3SDavid du Colombier 		Bitsmask= 3<<0,
555d9de2d3SDavid du Colombier 		Bits7	= 2<<0,
565d9de2d3SDavid du Colombier 		Bits8	= 3<<0,
575d9de2d3SDavid du Colombier 	MuMcr	= 0x50>>2,
585d9de2d3SDavid du Colombier 		RtsN	= 1<<1,
595d9de2d3SDavid du Colombier 	MuLsr	= 0x54>>2,
605d9de2d3SDavid du Colombier 		TxDone	= 1<<6,
615d9de2d3SDavid du Colombier 		TxRdy	= 1<<5,
625d9de2d3SDavid du Colombier 		RxRdy	= 1<<0,
635d9de2d3SDavid du Colombier 	MuCntl	= 0x60>>2,
645d9de2d3SDavid du Colombier 		CtsFlow	= 1<<3,
655d9de2d3SDavid du Colombier 		TxEn	= 1<<1,
665d9de2d3SDavid du Colombier 		RxEn	= 1<<0,
675d9de2d3SDavid du Colombier 	MuBaud	= 0x68>>2,
685d9de2d3SDavid du Colombier };
695d9de2d3SDavid du Colombier 
705d9de2d3SDavid du Colombier extern PhysUart miniphysuart;
715d9de2d3SDavid du Colombier 
725d9de2d3SDavid du Colombier static Uart miniuart = {
735d9de2d3SDavid du Colombier 	.regs	= (u32int*)AUXREGS,
745d9de2d3SDavid du Colombier 	.name	= "uart0",
755d9de2d3SDavid du Colombier 	.freq	= 250000000,
765d9de2d3SDavid du Colombier 	.phys	= &miniphysuart,
775d9de2d3SDavid du Colombier };
785d9de2d3SDavid du Colombier 
795d9de2d3SDavid du Colombier void
gpiosel(uint pin,int func)805d9de2d3SDavid du Colombier gpiosel(uint pin, int func)
815d9de2d3SDavid du Colombier {
825d9de2d3SDavid du Colombier 	u32int *gp, *fsel;
835d9de2d3SDavid du Colombier 	int off;
845d9de2d3SDavid du Colombier 
855d9de2d3SDavid du Colombier 	gp = (u32int*)GPIOREGS;
865d9de2d3SDavid du Colombier 	fsel = &gp[Fsel0 + pin/10];
875d9de2d3SDavid du Colombier 	off = (pin % 10) * 3;
885d9de2d3SDavid du Colombier 	*fsel = (*fsel & ~(FuncMask<<off)) | func<<off;
895d9de2d3SDavid du Colombier }
905d9de2d3SDavid du Colombier 
915d9de2d3SDavid du Colombier void
gpiopulloff(uint pin)925d9de2d3SDavid du Colombier gpiopulloff(uint pin)
935d9de2d3SDavid du Colombier {
945d9de2d3SDavid du Colombier 	u32int *gp, *reg;
955d9de2d3SDavid du Colombier 	u32int mask;
965d9de2d3SDavid du Colombier 
975d9de2d3SDavid du Colombier 	gp = (u32int*)GPIOREGS;
985d9de2d3SDavid du Colombier 	reg = &gp[PUDclk0 + pin/32];
995d9de2d3SDavid du Colombier 	mask = 1 << (pin % 32);
1005d9de2d3SDavid du Colombier 	gp[PUD] = Off;
1015d9de2d3SDavid du Colombier 	microdelay(1);
1025d9de2d3SDavid du Colombier 	*reg = mask;
1035d9de2d3SDavid du Colombier 	microdelay(1);
1045d9de2d3SDavid du Colombier 	*reg = 0;
1055d9de2d3SDavid du Colombier }
1065d9de2d3SDavid du Colombier 
1075d9de2d3SDavid du Colombier void
gpioout(uint pin,int set)1085d9de2d3SDavid du Colombier gpioout(uint pin, int set)
1095d9de2d3SDavid du Colombier {
1105d9de2d3SDavid du Colombier 	u32int *gp;
1115d9de2d3SDavid du Colombier 	int v;
1125d9de2d3SDavid du Colombier 
1135d9de2d3SDavid du Colombier 	gp = (u32int*)GPIOREGS;
1145d9de2d3SDavid du Colombier 	v = set? Set0 : Clr0;
1155d9de2d3SDavid du Colombier 	gp[v + pin/32] = 1 << (pin % 32);
1165d9de2d3SDavid du Colombier }
1175d9de2d3SDavid du Colombier 
1185d9de2d3SDavid du Colombier int
gpioin(uint pin)1195d9de2d3SDavid du Colombier gpioin(uint pin)
1205d9de2d3SDavid du Colombier {
1215d9de2d3SDavid du Colombier 	u32int *gp;
1225d9de2d3SDavid du Colombier 
1235d9de2d3SDavid du Colombier 	gp = (u32int*)GPIOREGS;
1245d9de2d3SDavid du Colombier 	return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0;
1255d9de2d3SDavid du Colombier }
1265d9de2d3SDavid du Colombier 
1275d9de2d3SDavid du Colombier static void
interrupt(Ureg *,void * arg)1285d9de2d3SDavid du Colombier interrupt(Ureg*, void *arg)
1295d9de2d3SDavid du Colombier {
1305d9de2d3SDavid du Colombier 	Uart *uart;
1315d9de2d3SDavid du Colombier 	u32int *ap;
1325d9de2d3SDavid du Colombier 
1335d9de2d3SDavid du Colombier 	uart = arg;
1345d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
1355d9de2d3SDavid du Colombier 
1365d9de2d3SDavid du Colombier 	coherence();
1375d9de2d3SDavid du Colombier 	if(0 && (ap[Irq] & UartIrq) == 0)
1385d9de2d3SDavid du Colombier 		return;
1395d9de2d3SDavid du Colombier 	if(ap[MuLsr] & TxRdy)
1405d9de2d3SDavid du Colombier 		uartkick(uart);
1415d9de2d3SDavid du Colombier 	if(ap[MuLsr] & RxRdy){
142*b4d1cf41SDavid du Colombier 		if(uart->console){
1435d9de2d3SDavid du Colombier 			if(uart->opens == 1)
1445d9de2d3SDavid du Colombier 				uart->putc = kbdcr2nl;
1455d9de2d3SDavid du Colombier 			else
1465d9de2d3SDavid du Colombier 				uart->putc = nil;
147*b4d1cf41SDavid du Colombier 		}
1485d9de2d3SDavid du Colombier 		do{
1495d9de2d3SDavid du Colombier 			uartrecv(uart, ap[MuIo] & 0xFF);
1505d9de2d3SDavid du Colombier 		}while(ap[MuLsr] & RxRdy);
1515d9de2d3SDavid du Colombier 	}
1525d9de2d3SDavid du Colombier 	coherence();
1535d9de2d3SDavid du Colombier }
1545d9de2d3SDavid du Colombier 
1555d9de2d3SDavid du Colombier static Uart*
pnp(void)1565d9de2d3SDavid du Colombier pnp(void)
1575d9de2d3SDavid du Colombier {
1585d9de2d3SDavid du Colombier 	Uart *uart;
1595d9de2d3SDavid du Colombier 
1605d9de2d3SDavid du Colombier 	uart = &miniuart;
1615d9de2d3SDavid du Colombier 	if(uart->console == 0)
1625d9de2d3SDavid du Colombier 		kbdq = qopen(8*1024, 0, nil, nil);
1635d9de2d3SDavid du Colombier 	return uart;
1645d9de2d3SDavid du Colombier }
1655d9de2d3SDavid du Colombier 
1665d9de2d3SDavid du Colombier static void
enable(Uart * uart,int ie)1675d9de2d3SDavid du Colombier enable(Uart *uart, int ie)
1685d9de2d3SDavid du Colombier {
1695d9de2d3SDavid du Colombier 	u32int *ap;
1705d9de2d3SDavid du Colombier 
1715d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
1725d9de2d3SDavid du Colombier 	delay(10);
1735d9de2d3SDavid du Colombier 	gpiosel(TxPin, Alt5);
1745d9de2d3SDavid du Colombier 	gpiosel(RxPin, Alt5);
1755d9de2d3SDavid du Colombier 	gpiopulloff(TxPin);
1765d9de2d3SDavid du Colombier 	gpiopulloff(RxPin);
1775d9de2d3SDavid du Colombier 	ap[Enables] |= UartEn;
1785d9de2d3SDavid du Colombier 	ap[MuIir] = 6;
1795d9de2d3SDavid du Colombier 	ap[MuLcr] = Bits8;
1805d9de2d3SDavid du Colombier 	ap[MuCntl] = TxEn|RxEn;
1815d9de2d3SDavid du Colombier 	ap[MuBaud] = 250000000/(115200*8) - 1;
1825d9de2d3SDavid du Colombier 	if(ie){
1835d9de2d3SDavid du Colombier 		intrenable(IRQaux, interrupt, uart, 0, "uart");
1845d9de2d3SDavid du Colombier 		ap[MuIer] = RxIen|TxIen;
1855d9de2d3SDavid du Colombier 	}else
1865d9de2d3SDavid du Colombier 		ap[MuIer] = 0;
1875d9de2d3SDavid du Colombier }
1885d9de2d3SDavid du Colombier 
1895d9de2d3SDavid du Colombier static void
disable(Uart * uart)1905d9de2d3SDavid du Colombier disable(Uart *uart)
1915d9de2d3SDavid du Colombier {
1925d9de2d3SDavid du Colombier 	u32int *ap;
1935d9de2d3SDavid du Colombier 
1945d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
1955d9de2d3SDavid du Colombier 	ap[MuCntl] = 0;
1965d9de2d3SDavid du Colombier 	ap[MuIer] = 0;
1975d9de2d3SDavid du Colombier }
1985d9de2d3SDavid du Colombier 
1995d9de2d3SDavid du Colombier static void
kick(Uart * uart)2005d9de2d3SDavid du Colombier kick(Uart *uart)
2015d9de2d3SDavid du Colombier {
2025d9de2d3SDavid du Colombier 	u32int *ap;
2035d9de2d3SDavid du Colombier 
2045d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
2055d9de2d3SDavid du Colombier 	if(uart->blocked)
2065d9de2d3SDavid du Colombier 		return;
2075d9de2d3SDavid du Colombier 	coherence();
2085d9de2d3SDavid du Colombier 	while(ap[MuLsr] & TxRdy){
2095d9de2d3SDavid du Colombier 		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
2105d9de2d3SDavid du Colombier 			break;
2115d9de2d3SDavid du Colombier 		ap[MuIo] = *(uart->op++);
2125d9de2d3SDavid du Colombier 	}
2135d9de2d3SDavid du Colombier 	if(ap[MuLsr] & TxDone)
2145d9de2d3SDavid du Colombier 		ap[MuIer] &= ~TxIen;
2155d9de2d3SDavid du Colombier 	else
2165d9de2d3SDavid du Colombier 		ap[MuIer] |= TxIen;
2175d9de2d3SDavid du Colombier 	coherence();
2185d9de2d3SDavid du Colombier }
2195d9de2d3SDavid du Colombier 
2205d9de2d3SDavid du Colombier /* TODO */
2215d9de2d3SDavid du Colombier static void
dobreak(Uart * uart,int ms)2225d9de2d3SDavid du Colombier dobreak(Uart *uart, int ms)
2235d9de2d3SDavid du Colombier {
2245d9de2d3SDavid du Colombier 	USED(uart, ms);
2255d9de2d3SDavid du Colombier }
2265d9de2d3SDavid du Colombier 
2275d9de2d3SDavid du Colombier static int
baud(Uart * uart,int n)2285d9de2d3SDavid du Colombier baud(Uart *uart, int n)
2295d9de2d3SDavid du Colombier {
2305d9de2d3SDavid du Colombier 	u32int *ap;
2315d9de2d3SDavid du Colombier 
2325d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
2335d9de2d3SDavid du Colombier 	if(uart->freq == 0 || n <= 0)
2345d9de2d3SDavid du Colombier 		return -1;
2355d9de2d3SDavid du Colombier 	ap[MuBaud] = (uart->freq + 4*n - 1) / (8 * n) - 1;
2365d9de2d3SDavid du Colombier 	uart->baud = n;
2375d9de2d3SDavid du Colombier 	return 0;
2385d9de2d3SDavid du Colombier }
2395d9de2d3SDavid du Colombier 
2405d9de2d3SDavid du Colombier static int
bits(Uart * uart,int n)2415d9de2d3SDavid du Colombier bits(Uart *uart, int n)
2425d9de2d3SDavid du Colombier {
2435d9de2d3SDavid du Colombier 	u32int *ap;
2445d9de2d3SDavid du Colombier 	int set;
2455d9de2d3SDavid du Colombier 
2465d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
2475d9de2d3SDavid du Colombier 	switch(n){
2485d9de2d3SDavid du Colombier 	case 7:
2495d9de2d3SDavid du Colombier 		set = Bits7;
2505d9de2d3SDavid du Colombier 		break;
2515d9de2d3SDavid du Colombier 	case 8:
2525d9de2d3SDavid du Colombier 		set = Bits8;
2535d9de2d3SDavid du Colombier 		break;
2545d9de2d3SDavid du Colombier 	default:
2555d9de2d3SDavid du Colombier 		return -1;
2565d9de2d3SDavid du Colombier 	}
2575d9de2d3SDavid du Colombier 	ap[MuLcr] = (ap[MuLcr] & ~Bitsmask) | set;
2585d9de2d3SDavid du Colombier 	uart->bits = n;
2595d9de2d3SDavid du Colombier 	return 0;
2605d9de2d3SDavid du Colombier }
2615d9de2d3SDavid du Colombier 
2625d9de2d3SDavid du Colombier static int
stop(Uart * uart,int n)2635d9de2d3SDavid du Colombier stop(Uart *uart, int n)
2645d9de2d3SDavid du Colombier {
2655d9de2d3SDavid du Colombier 	if(n != 1)
2665d9de2d3SDavid du Colombier 		return -1;
2675d9de2d3SDavid du Colombier 	uart->stop = n;
2685d9de2d3SDavid du Colombier 	return 0;
2695d9de2d3SDavid du Colombier }
2705d9de2d3SDavid du Colombier 
2715d9de2d3SDavid du Colombier static int
parity(Uart * uart,int n)2725d9de2d3SDavid du Colombier parity(Uart *uart, int n)
2735d9de2d3SDavid du Colombier {
2745d9de2d3SDavid du Colombier 	if(n != 'n')
2755d9de2d3SDavid du Colombier 		return -1;
2765d9de2d3SDavid du Colombier 	uart->parity = n;
2775d9de2d3SDavid du Colombier 	return 0;
2785d9de2d3SDavid du Colombier }
2795d9de2d3SDavid du Colombier 
2805d9de2d3SDavid du Colombier /*
2815d9de2d3SDavid du Colombier  * cts/rts flow control
2825d9de2d3SDavid du Colombier  *   need to bring signals to gpio pins before enabling this
2835d9de2d3SDavid du Colombier  */
2845d9de2d3SDavid du Colombier 
2855d9de2d3SDavid du Colombier static void
modemctl(Uart * uart,int on)2865d9de2d3SDavid du Colombier modemctl(Uart *uart, int on)
2875d9de2d3SDavid du Colombier {
2885d9de2d3SDavid du Colombier 	u32int *ap;
2895d9de2d3SDavid du Colombier 
2905d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
2915d9de2d3SDavid du Colombier 	if(on)
2925d9de2d3SDavid du Colombier 		ap[MuCntl] |= CtsFlow;
2935d9de2d3SDavid du Colombier 	else
2945d9de2d3SDavid du Colombier 		ap[MuCntl] &= ~CtsFlow;
2955d9de2d3SDavid du Colombier 	uart->modem = on;
2965d9de2d3SDavid du Colombier }
2975d9de2d3SDavid du Colombier 
2985d9de2d3SDavid du Colombier static void
rts(Uart * uart,int on)2995d9de2d3SDavid du Colombier rts(Uart *uart, int on)
3005d9de2d3SDavid du Colombier {
3015d9de2d3SDavid du Colombier 	u32int *ap;
3025d9de2d3SDavid du Colombier 
3035d9de2d3SDavid du Colombier 	ap = (u32int*)uart->regs;
3045d9de2d3SDavid du Colombier 	if(on)
3055d9de2d3SDavid du Colombier 		ap[MuMcr] &= ~RtsN;
3065d9de2d3SDavid du Colombier 	else
3075d9de2d3SDavid du Colombier 		ap[MuMcr] |= RtsN;
3085d9de2d3SDavid du Colombier }
3095d9de2d3SDavid du Colombier 
3105d9de2d3SDavid du Colombier static long
status(Uart * uart,void * buf,long n,long offset)3115d9de2d3SDavid du Colombier status(Uart *uart, void *buf, long n, long offset)
3125d9de2d3SDavid du Colombier {
3135d9de2d3SDavid du Colombier 	char *p;
3145d9de2d3SDavid du Colombier 
3155d9de2d3SDavid du Colombier 	p = malloc(READSTR);
3165d9de2d3SDavid du Colombier 	if(p == nil)
3175d9de2d3SDavid du Colombier 		error(Enomem);
3185d9de2d3SDavid du Colombier 	snprint(p, READSTR,
3195d9de2d3SDavid du Colombier 		"b%d\n"
3205d9de2d3SDavid du Colombier 		"dev(%d) type(%d) framing(%d) overruns(%d) "
3215d9de2d3SDavid du Colombier 		"berr(%d) serr(%d)\n",
3225d9de2d3SDavid du Colombier 
3235d9de2d3SDavid du Colombier 		uart->baud,
3245d9de2d3SDavid du Colombier 		uart->dev,
3255d9de2d3SDavid du Colombier 		uart->type,
3265d9de2d3SDavid du Colombier 		uart->ferr,
3275d9de2d3SDavid du Colombier 		uart->oerr,
3285d9de2d3SDavid du Colombier 		uart->berr,
3295d9de2d3SDavid du Colombier 		uart->serr
3305d9de2d3SDavid du Colombier 	);
3315d9de2d3SDavid du Colombier 	n = readstr(offset, buf, n, p);
3325d9de2d3SDavid du Colombier 	free(p);
3335d9de2d3SDavid du Colombier 
3345d9de2d3SDavid du Colombier 	return n;
3355d9de2d3SDavid du Colombier }
3365d9de2d3SDavid du Colombier 
3375d9de2d3SDavid du Colombier static void
donothing(Uart *,int)3385d9de2d3SDavid du Colombier donothing(Uart*, int)
3395d9de2d3SDavid du Colombier {
3405d9de2d3SDavid du Colombier }
3415d9de2d3SDavid du Colombier 
3425d9de2d3SDavid du Colombier void
putc(Uart *,int c)3435d9de2d3SDavid du Colombier putc(Uart*, int c)
3445d9de2d3SDavid du Colombier {
3455d9de2d3SDavid du Colombier 	u32int *ap;
3465d9de2d3SDavid du Colombier 
3475d9de2d3SDavid du Colombier 	ap = (u32int*)AUXREGS;
3485d9de2d3SDavid du Colombier 	while((ap[MuLsr] & TxRdy) == 0)
3495d9de2d3SDavid du Colombier 		;
3505d9de2d3SDavid du Colombier 	ap[MuIo] = c;
3515d9de2d3SDavid du Colombier 	while((ap[MuLsr] & TxRdy) == 0)
3525d9de2d3SDavid du Colombier 		;
3535d9de2d3SDavid du Colombier }
3545d9de2d3SDavid du Colombier 
3555d9de2d3SDavid du Colombier int
getc(Uart *)3565d9de2d3SDavid du Colombier getc(Uart*)
3575d9de2d3SDavid du Colombier {
3585d9de2d3SDavid du Colombier 	u32int *ap;
3595d9de2d3SDavid du Colombier 
3605d9de2d3SDavid du Colombier 	ap = (u32int*)AUXREGS;
3615d9de2d3SDavid du Colombier 	while((ap[MuLsr] & RxRdy) == 0)
3625d9de2d3SDavid du Colombier 		;
3635d9de2d3SDavid du Colombier 	return ap[MuIo] & 0xFF;
3645d9de2d3SDavid du Colombier }
3655d9de2d3SDavid du Colombier 
3665d9de2d3SDavid du Colombier void
uartconsinit(void)3675d9de2d3SDavid du Colombier uartconsinit(void)
3685d9de2d3SDavid du Colombier {
3695d9de2d3SDavid du Colombier 	Uart *uart;
3705d9de2d3SDavid du Colombier 	int n;
3715d9de2d3SDavid du Colombier 	char *p, *cmd;
3725d9de2d3SDavid du Colombier 
3735d9de2d3SDavid du Colombier 	if((p = getconf("console")) == nil)
3745d9de2d3SDavid du Colombier 		return;
3755d9de2d3SDavid du Colombier 	n = strtoul(p, &cmd, 0);
3765d9de2d3SDavid du Colombier 	if(p == cmd)
3775d9de2d3SDavid du Colombier 		return;
3785d9de2d3SDavid du Colombier 	switch(n){
3795d9de2d3SDavid du Colombier 	default:
3805d9de2d3SDavid du Colombier 		return;
3815d9de2d3SDavid du Colombier 	case 0:
3825d9de2d3SDavid du Colombier 		uart = &miniuart;
3835d9de2d3SDavid du Colombier 		break;
3845d9de2d3SDavid du Colombier 	}
3855d9de2d3SDavid du Colombier 
3865d9de2d3SDavid du Colombier 	if(!uart->enabled)
3875d9de2d3SDavid du Colombier 		(*uart->phys->enable)(uart, 0);
3885d9de2d3SDavid du Colombier 	uartctl(uart, "b9600 l8 pn s1");
3895d9de2d3SDavid du Colombier 	if(*cmd != '\0')
3905d9de2d3SDavid du Colombier 		uartctl(uart, cmd);
3915d9de2d3SDavid du Colombier 
3925d9de2d3SDavid du Colombier 	consuart = uart;
3935d9de2d3SDavid du Colombier 	uart->console = 1;
3945d9de2d3SDavid du Colombier }
3955d9de2d3SDavid du Colombier 
3965d9de2d3SDavid du Colombier PhysUart miniphysuart = {
3975d9de2d3SDavid du Colombier 	.name		= "miniuart",
3985d9de2d3SDavid du Colombier 	.pnp		= pnp,
3995d9de2d3SDavid du Colombier 	.enable		= enable,
4005d9de2d3SDavid du Colombier 	.disable	= disable,
4015d9de2d3SDavid du Colombier 	.kick		= kick,
4025d9de2d3SDavid du Colombier 	.dobreak	= dobreak,
4035d9de2d3SDavid du Colombier 	.baud		= baud,
4045d9de2d3SDavid du Colombier 	.bits		= bits,
4055d9de2d3SDavid du Colombier 	.stop		= stop,
4065d9de2d3SDavid du Colombier 	.parity		= parity,
4075d9de2d3SDavid du Colombier 	.modemctl	= donothing,
4085d9de2d3SDavid du Colombier 	.rts		= rts,
4095d9de2d3SDavid du Colombier 	.dtr		= donothing,
4105d9de2d3SDavid du Colombier 	.status		= status,
4115d9de2d3SDavid du Colombier 	.fifo		= donothing,
4125d9de2d3SDavid du Colombier 	.getc		= getc,
4135d9de2d3SDavid du Colombier 	.putc		= putc,
4145d9de2d3SDavid du Colombier };
4155d9de2d3SDavid du Colombier 
4165d9de2d3SDavid du Colombier void
okay(int on)4175d9de2d3SDavid du Colombier okay(int on)
4185d9de2d3SDavid du Colombier {
4195d9de2d3SDavid du Colombier 	static int first;
4205d9de2d3SDavid du Colombier 
4215d9de2d3SDavid du Colombier 	if(!first++)
4225d9de2d3SDavid du Colombier 		gpiosel(OkLed, Output);
4235d9de2d3SDavid du Colombier 	gpioout(OkLed, !on);
4245d9de2d3SDavid du Colombier }
425