PERFORCE change 36460 for review

Marcel Moolenaar marcel at FreeBSD.org
Tue Aug 19 18:54:00 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=36460

Change 36460 by marcel at marcel_nfs on 2003/08/19 18:53:10

	Start fleshing out the sab driver. calculate the divisor
	based on the baudrate and rclk and add code to program the
	line parameters.
	Have each device assign a default rclk if one is not given
	(ie is 0). Continue to use the ns8250 default for z8530.

Affected files ...

.. //depot/projects/uart/dev/uart/uart_dev_ns8250.c#17 edit
.. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#8 edit
.. //depot/projects/uart/dev/uart/uart_dev_z8530.c#4 edit

Differences ...

==== //depot/projects/uart/dev/uart/uart_dev_ns8250.c#17 (text+ko) ====

@@ -40,6 +40,8 @@
 
 #include "uart_if.h"
 
+#define	DEFAULT_RCLK	1843200
+
 static int
 ns8250_delay(struct uart_bas *bas)
 {
@@ -240,6 +242,8 @@
 {
 	uint8_t iir;
 
+	if (bas->rclk == 0)
+		bas->rclk = DEFAULT_RCLK;
 	ns8250_param(bas, baudrate, databits, stopbits, parity);
 
 	/* Disable all interrupt sources. */
@@ -361,7 +365,7 @@
 	ns8250_methods,
 	sizeof(struct ns8250_softc),
 	.uc_range = 8,
-	.uc_rclk = 1843200
+	.uc_rclk = DEFAULT_RCLK
 };
 
 #define	SIGCHG(c, i, s, d)				\

==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#8 (text+ko) ====

@@ -40,6 +40,88 @@
 
 #include "uart_if.h"
 
+#define	DEFAULT_RCLK	29491200
+
+static int
+sab82532_divisor(int rclk, int baudrate)
+{
+	int act_baud, act_div, divisor;
+	int error, m, n;
+
+	if (baudrate == 0)
+		return (0);
+
+	divisor = (rclk / (baudrate << 3) + 1) >> 1;
+	if (divisor < 2 || divisor >= 1048576)
+		return (0);
+
+	/* Find the best (N+1,M) pair. */
+	for (m = 1; m < 15; m++) {
+		n = divisor / (1<<m);
+		if (n < 1 || n > 63)
+			continue;
+		act_div = n * (1<<m);
+		act_baud = rclk / (act_div << 4);
+
+		/* 10 times error in percent: */
+		error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
+
+		/* 3.0% maximum error tolerance: */
+		if (error < -30 || error > 30)
+			continue;
+
+		/* Got it. */
+		return ((n - 1) | (m << 6));
+	}
+
+	return (0);
+}
+
+static int
+sab82532_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+    int parity)
+{
+	int divisor;
+	uint8_t ccr2, dafo;
+
+	if (databits >= 8)
+		dafo = SAB_DAFO_CHL_CS8;
+	else if (databits == 7)
+		dafo = SAB_DAFO_CHL_CS7;
+	else if (databits == 6)
+		dafo = SAB_DAFO_CHL_CS6;
+	else
+		dafo = SAB_DAFO_CHL_CS5;
+	if (stopbits > 1)
+		dafo |= SAB_DAFO_STOP;
+	switch (parity) {
+	case UART_PARITY_EVEN:	dafo |= SAB_DAFO_PAR_EVEN; break;
+	case UART_PARITY_MARK:	dafo |= SAB_DAFO_PAR_MARK; break;
+	case UART_PARITY_NONE:	dafo |= SAB_DAFO_PAR_NONE; break;
+	case UART_PARITY_ODD:	dafo |= SAB_DAFO_PAR_ODD; break;
+	case UART_PARITY_SPACE:	dafo |= SAB_DAFO_PAR_SPACE; break;
+	default:		return (EINVAL);
+	}
+
+	/* Set baudrate. */
+	if (baudrate > 0) {
+		divisor = sab82532_divisor(bas->rclk, baudrate);
+		if (divisor == 0)
+			return (EINVAL);
+		uart_setreg(bas, SAB_BGR, divisor & 0xff);
+		uart_barrier(bas);
+		ccr2 = uart_getreg(bas, SAB_CCR2);
+		ccr2 &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8);
+		ccr2 |= (divisor >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8);
+		uart_setreg(bas, SAB_CCR2, ccr2);
+		uart_barrier(bas);
+	}
+
+	uart_setreg(bas, SAB_DAFO, dafo);
+	uart_barrier(bas);
+	return (0);
+}
+
 /*
  * Low-level UART interface.
  */
@@ -70,6 +152,10 @@
 sab82532_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
     int parity)
 {
+
+	if (bas->rclk == 0)
+		bas->rclk = DEFAULT_RCLK;
+	sab82532_param(bas, baudrate, databits, stopbits, parity);
 }
 
 static void
@@ -145,7 +231,7 @@
 	sab82532_methods,
 	sizeof(struct sab82532_softc),
 	.uc_range = 64,
-	.uc_rclk = 1843200
+	.uc_rclk = DEFAULT_RCLK
 };
 
 static int
@@ -203,8 +289,10 @@
 sab82532_bus_param(struct uart_softc *sc, int baudrate, int databits,
     int stopbits, int parity)
 {
+	struct uart_bas *bas;
 
-	return (0);
+	bas = &sc->sc_bas;
+	return (sab82532_param(bas, baudrate, databits, stopbits, parity));
 }
 
 static int

==== //depot/projects/uart/dev/uart/uart_dev_z8530.c#4 (text+ko) ====

@@ -40,6 +40,8 @@
 
 #include "uart_if.h"
 
+#define	DEFAULT_RCLK	1843200
+
 /*
  * Low-level UART interface.
  */
@@ -70,6 +72,9 @@
 z8530_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
     int parity)
 {
+
+	if (bas->rclk == 0)
+		bas->rclk = DEFAULT_RCLK;
 }
 
 static void
@@ -133,7 +138,7 @@
 	z8530_methods,
 	sizeof(struct z8530_softc),
 	.uc_range = 64,
-	.uc_rclk = 1843200
+	.uc_rclk = DEFAULT_RCLK
 };
 
 static int


More information about the p4-projects mailing list