From owner-p4-projects@FreeBSD.ORG Sat Jan 31 04:25:38 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E0BF51065673; Sat, 31 Jan 2009 04:25:37 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 96403106566C for ; Sat, 31 Jan 2009 04:25:37 +0000 (UTC) (envelope-from andrew@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 8381A8FC17 for ; Sat, 31 Jan 2009 04:25:37 +0000 (UTC) (envelope-from andrew@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n0V4Pbg5099267 for ; Sat, 31 Jan 2009 04:25:37 GMT (envelope-from andrew@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n0V4Pbsb099265 for perforce@freebsd.org; Sat, 31 Jan 2009 04:25:37 GMT (envelope-from andrew@freebsd.org) Date: Sat, 31 Jan 2009 04:25:37 GMT Message-Id: <200901310425.n0V4Pbsb099265@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to andrew@freebsd.org using -f From: Andrew Turner To: Perforce Change Reviews Cc: Subject: PERFORCE change 156942 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Jan 2009 04:25:38 -0000 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< #include -#include - #include #include #include ==== //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 };