PERFORCE change 156942 for review
Andrew Turner
andrew at FreeBSD.org
Fri Jan 30 20:25:38 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=156942
Change 156942 by andrew at andrew_bender on 2009/01/31 04:24:57
Get the S3c24x0 uart driver working on real hardware
Affected files ...
.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c2xx0reg.h#2 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/uart_bus_s3c2410.c#3 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/uart_dev_s3c2410.c#7 edit
Differences ...
==== //depot/projects/arm/src/sys/arm/s3c2xx0/s3c2xx0reg.h#2 (text+ko) ====
@@ -103,9 +103,9 @@
#define UTRSTAT_TXEMPTY (1<<1) /* TX fifo or buffer empty */
#define UTRSTAT_RXREADY (1<<0) /* RX fifo or buffer is not empty */
#define SSCOM_UERSTAT 0x14 /* Error status register */
-#define UERSTAT_BREAK (1<<3) /* Break signal */
+#define UERSTAT_BREAK (1<<3) /* Break signal, not 2410 */
#define UERSTAT_FRAME (1<<2) /* Frame error */
-#define UERSTAT_PARITY (1<<1) /* Parity error */
+#define UERSTAT_PARITY (1<<1) /* Parity error, not 2410 */
#define UERSTAT_OVERRUN (1<<0) /* Overrun */
#define UERSTAT_ALL_ERRORS (UERSTAT_OVERRUN|UERSTAT_BREAK|UERSTAT_FRAME|UERSTAT_PARITY)
#define SSCOM_UFSTAT 0x18 /* Fifo status register */
@@ -115,6 +115,13 @@
#define UFSTAT_TXCOUNT (0x0f<<UFSTAT_TXCOUNT_SHIFT)
#define UFSTAT_RXCOUNT_SHIFT 0 /* RX FIFO count */
#define UFSTAT_RXCOUNT (0x0f<<UFSTAT_RXCOUNT_SHIFT)
+#if 0
+/* These are differend on the 244x */
+#define UFSTAT_TXFULL (1<<14)
+#define UFSTAT_TXCOUNT_SHIFT 8
+#define UFSTAT_TXCOUNT (0x3f<<UFSTAT_TXCOUNT_SHIFT)
+#define UFSTAT_RXCOUNT (0x3f<<UFSTAT_RXCOUNT_SHIFT)
+#endif
#define SSCOM_UMSTAT 0x1c /* Modem status register */
/* UMSTAT_DCTS is defined in s3c{2800,24x0}reg.h */
#define UMSTAT_CTS (1<<0) /* Clear to send */
==== //depot/projects/arm/src/sys/arm/s3c2xx0/uart_bus_s3c2410.c#3 (text+ko) ====
@@ -11,8 +11,6 @@
#include <sys/rman.h>
#include <machine/resource.h>
-#include <dev/pci/pcivar.h>
-
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
==== //depot/projects/arm/src/sys/arm/s3c2xx0/uart_dev_s3c2410.c#7 (text+ko) ====
@@ -46,6 +46,9 @@
#define DEFAULT_RCLK 3686400
+static int sscomspeed(long, long);
+static int s3c24x0_uart_param(struct uart_bas *, int, int, int, int);
+
/*
* Low-level UART interface.
*/
@@ -58,22 +61,7 @@
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
-struct uart_ops uart_s3c2410_ops = {
- .probe = s3c2410_probe,
- .init = s3c2410_init,
- .term = s3c2410_term,
- .putc = s3c2410_putc,
- .rxready = s3c2410_rxready,
- .getc = s3c2410_getc,
-};
-
static int
-s3c2410_probe(struct uart_bas *bas)
-{
- return (0);
-}
-
-static int
sscomspeed(long speed, long frequency)
{
#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
@@ -92,22 +80,88 @@
#undef divrnd
}
+
+static int
+s3c24x0_uart_param(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int brd, ulcon;
+
+ ulcon = 0;
+
+ switch(databits) {
+ case 5:
+ ulcon |= ULCON_LENGTH_5;
+ break;
+ case 6:
+ ulcon |= ULCON_LENGTH_6;
+ break;
+ case 7:
+ ulcon |= ULCON_LENGTH_7;
+ break;
+ case 8:
+ ulcon |= ULCON_LENGTH_8;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (parity) {
+ case UART_PARITY_NONE:
+ ulcon |= ULCON_PARITY_NONE;
+ break;
+ case UART_PARITY_ODD:
+ ulcon |= ULCON_PARITY_ODD;
+ break;
+ case UART_PARITY_EVEN:
+ ulcon |= ULCON_PARITY_EVEN;
+ break;
+ case UART_PARITY_MARK:
+ case UART_PARITY_SPACE:
+ default:
+ return (EINVAL);
+ }
+
+ if (stopbits == 2)
+ ulcon |= ULCON_STOP;
+
+ uart_setreg(bas, SSCOM_ULCON, ulcon);
+
+ brd = sscomspeed(baudrate, bas->rclk);
+ uart_setreg(bas, SSCOM_UBRDIV, brd);
+
+ return (0);
+}
+
+struct uart_ops uart_s3c2410_ops = {
+ .probe = s3c2410_probe,
+ .init = s3c2410_init,
+ .term = s3c2410_term,
+ .putc = s3c2410_putc,
+ .rxready = s3c2410_rxready,
+ .getc = s3c2410_getc,
+};
+
+static int
+s3c2410_probe(struct uart_bas *bas)
+{
+ return (0);
+}
+
static void
s3c2410_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
{
- int brd;
-
if (bas->rclk == 0)
bas->rclk = DEFAULT_RCLK;
- uart_setreg(bas, SSCOM_ULCON, 0x23);
+
uart_setreg(bas, SSCOM_UCON, 0);
uart_setreg(bas, SSCOM_UFCON,
UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 |
UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET |
UFCON_FIFO_ENABLE);
- brd = sscomspeed(baudrate, bas->rclk);
- uart_setreg(bas, SSCOM_UBRDIV, brd);
+ s3c24x0_uart_param(bas, baudrate, databits, stopbits, parity);
+
/* Enable UART. */
uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT|UCON_TOINT);
uart_setreg(bas, SSCOM_UMCON, UMCON_RTS);
@@ -122,9 +176,9 @@
static void
s3c2410_putc(struct uart_bas *bas, int c)
{
-#if 0
- while (uart_getreg(bas, SSCOM_UFSTAT) & UFSTAT_TXFULL);
-#endif
+ while (!(uart_getreg(bas, SSCOM_UTRSTAT) & UTRSTAT_TXEMPTY))
+ continue;
+
uart_setreg(bas, SSCOM_UTXH, c);
}
@@ -138,11 +192,10 @@
static int
s3c2410_getc(struct uart_bas *bas, struct mtx *mtx)
{
- int c;
+ while (!sscom_rxrdy(bas->bst, bas->bsh))
+ continue;
- while (!sscom_rxrdy(bas->bst, bas->bsh));
return sscom_getc(bas->bst, bas->bsh);
- return (c);
}
static int s3c2410_bus_probe(struct uart_softc *sc);
@@ -180,29 +233,39 @@
static int
s3c2410_bus_attach(struct uart_softc *sc)
{
- bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+ bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
- sc->sc_txfifosz = 3;
- sc->sc_rxfifosz = 1;
- sc->sc_hwiflow = 0;
+ /*
+ * TODO: The S3C2410 has a 16 byte fifo, the s3c2440 has a
+ * 64 byte fifo. figure out which CPU we are on to set this
+ */
+ sc->sc_txfifosz = 16;
+ sc->sc_rxfifosz = 16;
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
return (0);
}
+
static int
s3c2410_bus_transmit(struct uart_softc *sc)
{
- sc->sc_txbusy = 1;
+ uart_lock(sc->sc_hwmtx);
for (int i = 0; i < sc->sc_txdatasz; i++) {
s3c2410_putc(&sc->sc_bas, sc->sc_txbuf[i]);
uart_barrier(&sc->sc_bas);
}
+ sc->sc_txbusy = 1;
+ uart_unlock(sc->sc_hwmtx);
return (0);
}
+
static int
s3c2410_bus_setsig(struct uart_softc *sc, int sig)
{
return (0);
}
+
static int
s3c2410_bus_receive(struct uart_softc *sc)
{
@@ -210,30 +273,41 @@
uart_rx_put(sc, uart_getreg(&sc->sc_bas, SSCOM_URXH));
return (0);
}
+
static int
s3c2410_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
-
- return (0);
+ int error;
+
+ uart_lock(sc->sc_hwmtx);
+ error = s3c24x0_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
+ parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
}
+
static int
s3c2410_bus_ipend(struct uart_softc *sc)
{
+ uint32_t utrstat;
int ipend = 0;
- int sr;
- sr = uart_getreg(&sc->sc_bas, SSCOM_UFSTAT);
+ uart_lock(sc->sc_hwmtx);
+ utrstat = uart_getreg(&sc->sc_bas, SSCOM_UTRSTAT);
+ uart_unlock(sc->sc_hwmtx);
- if ((sr & UFSTAT_TXCOUNT) == 0 && sc->sc_txbusy) {
+ if ((utrstat & UTRSTAT_TXEMPTY) == UTRSTAT_TXEMPTY) {
ipend |= SER_INT_TXIDLE;
}
- if ((sr & UFSTAT_RXCOUNT) != 0) {
+ if ((utrstat & UTRSTAT_RXREADY) == UTRSTAT_RXREADY) {
ipend |= SER_INT_RXREADY;
}
return (ipend);
}
+
static int
s3c2410_bus_flush(struct uart_softc *sc, int what)
{
@@ -257,5 +331,5 @@
1,
.uc_ops = &uart_s3c2410_ops,
.uc_range = 8,
- .uc_rclk = 3686400
+ .uc_rclk = DEFAULT_RCLK
};
More information about the p4-projects
mailing list