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