Date: Sat, 31 Jan 2009 04:25:37 GMT From: Andrew Turner <andrew@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 156942 for review Message-ID: <200901310425.n0V4Pbsb099265@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=156942 Change 156942 by andrew@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 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901310425.n0V4Pbsb099265>