changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: uartpl011: dont touch line control while uart is enabled

changeset 7196: 9a4da3139862
parent 7195: 8c8392fe3e79
child 7197: babef06a3de5
author: cinap_lenrek@felloff.net
date: Fri, 03 May 2019 21:34:20 +0200
files: sys/src/9/bcm/uartpl011.c
description: uartpl011: dont touch line control while uart is enabled
     1.1--- a/sys/src/9/bcm/uartpl011.c
     1.2+++ b/sys/src/9/bcm/uartpl011.c
     1.3@@ -82,12 +82,63 @@ interrupt(Ureg*, void *arg)
     1.4 	u32int *reg = (u32int*)uart->regs;
     1.5 
     1.6 	coherence();
     1.7-	if((reg[FR] & TXFE) == 0)
     1.8-		uartkick(uart);
     1.9 	while((reg[FR] & RXFE) == 0)
    1.10 		uartrecv(uart, reg[DR] & 0xFF);
    1.11+	if((reg[FR] & TXFF) == 0)
    1.12+		uartkick(uart);
    1.13+	reg[ICR] = 1<<5 | 1<<6 | 1<<7 | 1<<8 | 1<<9 | 1<<10;
    1.14+	coherence();
    1.15+}
    1.16+
    1.17+static void
    1.18+disable(Uart *uart)
    1.19+{
    1.20+	u32int *reg = (u32int*)uart->regs;
    1.21+
    1.22+	/* disable interrupt */
    1.23+	reg[IMSC] = 0;
    1.24+	coherence();
    1.25+
    1.26+	/* clear interrupt */
    1.27+	reg[ICR] = 1<<5 | 1<<6 | 1<<7 | 1<<8 | 1<<9 | 1<<10;
    1.28+	coherence();
    1.29+
    1.30+	/* wait for last transmission to complete */
    1.31+	while((reg[FR] & BUSY) != 0)
    1.32+		delay(1);
    1.33+
    1.34+	/* disable uart */
    1.35+	reg[CR] = 0;
    1.36 	coherence();
    1.37 
    1.38+	/* flush rx fifo */
    1.39+	reg[LCRH] &= ~FEN;
    1.40+	coherence();
    1.41+}
    1.42+
    1.43+static void
    1.44+uartoff(Uart *uart)
    1.45+{
    1.46+	u32int *reg = (u32int*)uart->regs;
    1.47+	u32int im;
    1.48+
    1.49+	im = reg[IMSC];
    1.50+	disable(uart);
    1.51+	reg[IMSC] = im;
    1.52+}
    1.53+
    1.54+static void
    1.55+uarton(Uart *uart)
    1.56+{
    1.57+	u32int *reg = (u32int*)uart->regs;
    1.58+
    1.59+	/* enable fifo */
    1.60+	reg[LCRH] |= FEN;
    1.61+	coherence();
    1.62+
    1.63+	/* enable uart */
    1.64+	reg[CR] = UARTEN | RXE | TXE;
    1.65+	coherence();
    1.66 }
    1.67 
    1.68 static void
    1.69@@ -95,22 +146,26 @@ enable(Uart *uart, int ie)
    1.70 {
    1.71 	u32int *reg = (u32int*)uart->regs;
    1.72 
    1.73-	reg[CR] = UARTEN | RXE | TXE;
    1.74+	disable(uart);
    1.75 	if(ie){
    1.76 		intrenable(IRQuart, interrupt, uart, 0, uart->name);
    1.77 		reg[IMSC] = TXIM|RXIM;
    1.78-	} else {
    1.79-		reg[IMSC] = 0;
    1.80 	}
    1.81+	uarton(uart);
    1.82 }
    1.83 
    1.84 static void
    1.85-disable(Uart *uart)
    1.86+linectl(Uart *uart, u32int set, u32int clr)
    1.87 {
    1.88 	u32int *reg = (u32int*)uart->regs;
    1.89 
    1.90-	reg[IMSC] = 0;
    1.91-	reg[CR] = 0;
    1.92+	if(uart->enabled)
    1.93+		uartoff(uart);
    1.94+
    1.95+	reg[LCRH] = set | (reg[LCRH] & ~clr);
    1.96+
    1.97+	if(uart->enabled)
    1.98+		uarton(uart);
    1.99 }
   1.100 
   1.101 static void
   1.102@@ -132,11 +187,9 @@ kick(Uart *uart)
   1.103 static void
   1.104 dobreak(Uart *uart, int ms)
   1.105 {
   1.106-	u32int *reg = (u32int*)uart->regs;
   1.107-
   1.108-	reg[LCRH] |= BRK;
   1.109+	linectl(uart, BRK, 0);
   1.110 	delay(ms);
   1.111-	reg[LCRH] &= ~BRK;
   1.112+	linectl(uart, 0, BRK);
   1.113 }
   1.114 
   1.115 static int
   1.116@@ -147,8 +200,15 @@ baud(Uart *uart, int n)
   1.117 	if(uart->freq <= 0 || n <= 0)
   1.118 		return -1;
   1.119 
   1.120+	if(uart->enabled)
   1.121+		uartoff(uart);
   1.122+
   1.123 	reg[IBRD] = (uart->freq >> 4) / n;
   1.124 	reg[FBRD] = (uart->freq >> 4) % n;
   1.125+
   1.126+	if(uart->enabled)
   1.127+		uarton(uart);
   1.128+
   1.129 	uart->baud = n;
   1.130 	return 0;
   1.131 }
   1.132@@ -156,20 +216,18 @@ baud(Uart *uart, int n)
   1.133 static int
   1.134 bits(Uart *uart, int n)
   1.135 {
   1.136-	u32int *reg = (u32int*)uart->regs;
   1.137-
   1.138 	switch(n){
   1.139 	case 8:
   1.140-		reg[LCRH] = (reg[LCRH] & ~WLENM) | WLEN8;
   1.141+		linectl(uart, WLEN8, WLENM);
   1.142 		break;
   1.143 	case 7:
   1.144-		reg[LCRH] = (reg[LCRH] & ~WLENM) | WLEN7;
   1.145+		linectl(uart, WLEN7, WLENM);
   1.146 		break;
   1.147 	case 6:
   1.148-		reg[LCRH] = (reg[LCRH] & ~WLENM) | WLEN6;
   1.149+		linectl(uart, WLEN6, WLENM);
   1.150 		break;
   1.151 	case 5:
   1.152-		reg[LCRH] = (reg[LCRH] & ~WLENM) | WLEN5;
   1.153+		linectl(uart, WLEN5, WLENM);
   1.154 		break;
   1.155 	default:
   1.156 		return -1;
   1.157@@ -181,14 +239,12 @@ bits(Uart *uart, int n)
   1.158 static int
   1.159 stop(Uart *uart, int n)
   1.160 {
   1.161-	u32int *reg = (u32int*)uart->regs;
   1.162-
   1.163 	switch(n){
   1.164 	case 1:
   1.165-		reg[LCRH] &= ~STP2;
   1.166+		linectl(uart, 0, STP2);
   1.167 		break;
   1.168 	case 2:
   1.169-		reg[LCRH] |= STP2;
   1.170+		linectl(uart, STP2, 0);
   1.171 		break;
   1.172 	default:
   1.173 		return -1;
   1.174@@ -200,17 +256,15 @@ stop(Uart *uart, int n)
   1.175 static int
   1.176 parity(Uart *uart, int n)
   1.177 {
   1.178-	u32int *reg = (u32int*)uart->regs;
   1.179-
   1.180 	switch(n){
   1.181 	case 'n':
   1.182-		reg[LCRH] &= ~PEN;
   1.183+		linectl(uart, 0, PEN);
   1.184 		break;
   1.185 	case 'e':
   1.186-		reg[LCRH] |= EPS | PEN;
   1.187+		linectl(uart, EPS|PEN, 0);
   1.188 		break;
   1.189 	case 'o':
   1.190-		reg[LCRH] = (reg[LCRH] & ~EPS) | PEN;
   1.191+		linectl(uart, PEN, EPS);
   1.192 		break;
   1.193 	default:
   1.194 		return -1;