Date: Thu, 21 Aug 2003 23:57:21 -0700 (PDT) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 36647 for review Message-ID: <200308220657.h7M6vLc3071728@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=36647 Change 36647 by marcel@marcel_nfs on 2003/08/21 23:56:39 Rough implementation of the sab82532 driver for bus access. This allows us to boot single- and multi-user. Lacking are: o reading and writing modem/line signals o flushing of the transmitter/receiver Affected files ... .. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#10 edit Differences ... ==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#10 (text+ko) ==== @@ -180,7 +180,7 @@ sab82532_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { - uint8_t pvr; + uint8_t ccr0, pvr; if (bas->rclk == 0) bas->rclk = DEFAULT_RCLK; @@ -188,18 +188,61 @@ /* Set all pins, except DTR pins to be inputs. */ uart_setreg(bas, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B)); uart_barrier(bas); - /* Disable port interrupts */ + /* Disable port interrupts. */ uart_setreg(bas, SAB_PIM, 0xff); uart_barrier(bas); /* Interrupts are active low. */ uart_setreg(bas, SAB_IPC, SAB_IPC_ICPL); uart_barrier(bas); + /* Set DTR. */ + pvr = uart_getreg(bas, SAB_PVR); + pvr |= IS_CHANNEL_A(bas) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B; + uart_setreg(bas, SAB_PVR, pvr); + uart_barrier(bas); + + /* power down */ + uart_setreg(bas, SAB_CCR0, 0); + uart_barrier(bas); + + /* set basic configuration */ + ccr0 = SAB_CCR0_MCE|SAB_CCR0_SC_NRZ|SAB_CCR0_SM_ASYNC; + uart_setreg(bas, SAB_CCR0, ccr0); + uart_barrier(bas); + uart_setreg(bas, SAB_CCR1, SAB_CCR1_ODS|SAB_CCR1_BCR|SAB_CCR1_CM_7); + uart_barrier(bas); + uart_setreg(bas, SAB_CCR2, SAB_CCR2_BDF|SAB_CCR2_SSEL|SAB_CCR2_TOE); + uart_barrier(bas); + uart_setreg(bas, SAB_CCR3, 0); + uart_barrier(bas); + uart_setreg(bas, SAB_CCR4, SAB_CCR4_MCK4|SAB_CCR4_EBRG); + uart_barrier(bas); + uart_setreg(bas, SAB_MODE, SAB_MODE_RTS|SAB_MODE_FCTS|SAB_MODE_RAC); + uart_barrier(bas); + uart_setreg(bas, SAB_RFC, SAB_RFC_DPS|SAB_RFC_RFDF| + SAB_RFC_RFTH_32CHAR); + uart_barrier(bas); + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; + uart_setreg(bas, SAB_CMDR, SAB_CMDR_XRES); + uart_barrier(bas); + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; + uart_setreg(bas, SAB_CMDR, SAB_CMDR_RRES); + uart_barrier(bas); + sab82532_param(bas, baudrate, databits, stopbits, parity); - pvr = uart_getreg(bas, SAB_PVR); - pvr |= IS_CHANNEL_A(bas) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B; - uart_setreg(bas, SAB_PVR, pvr); + /* Clear interrupts. */ + uart_setreg(bas, SAB_IMR0, 0xff); + uart_setreg(bas, SAB_IMR1, 0xff); + uart_barrier(bas); + uart_getreg(bas, SAB_ISR0); + uart_getreg(bas, SAB_ISR1); + uart_barrier(bas); + + /* Power up. */ + uart_setreg(bas, SAB_CCR0, ccr0|SAB_CCR0_PU); uart_barrier(bas); } @@ -250,8 +293,8 @@ while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE)) DELAY(delay); - while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)) - DELAY(delay); + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD); uart_barrier(bas); @@ -263,9 +306,8 @@ uart_barrier(bas); /* Blow away everything left in the FIFO... */ - while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)) - DELAY(delay); - + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC); uart_barrier(bas); return (c); @@ -318,10 +360,16 @@ struct uart_bas *bas; bas = &sc->sc_bas; - if (!sc->sc_console && !sc->sc_dbgport) sab82532_init(bas, 9600, 8, 1, UART_PARITY_NONE); + sc->sc_rxfifosz = 32; + sc->sc_txfifosz = 32; + + uart_setreg(bas, SAB_IMR0, SAB_IMR0_PERR|SAB_IMR0_FERR|SAB_IMR0_PLLA); + uart_setreg(bas, SAB_IMR1, SAB_IMR1_BRK|SAB_IMR1_XDU|SAB_IMR1_TIN| + SAB_IMR1_XMR|SAB_IMR1_XPR); + uart_barrier(bas); return (0); } @@ -331,9 +379,14 @@ struct uart_bas *bas; bas = &sc->sc_bas; - - uart_setreg(bas, SAB_IPC, SAB_IPC_ICPL | SAB_IPC_VIS); - uart_setreg(bas, SAB_RFC, uart_getreg(bas, SAB_RFC) & ~SAB_RFC_RFDF); + uart_setreg(bas, SAB_IMR0, 0xff); + uart_setreg(bas, SAB_IMR1, 0xff); + uart_barrier(bas); + uart_getreg(bas, SAB_ISR0); + uart_getreg(bas, SAB_ISR1); + uart_barrier(bas); + uart_setreg(bas, SAB_CCR0, 0); + uart_barrier(bas); return (0); } @@ -354,8 +407,35 @@ static int sab82532_bus_ipend(struct uart_softc *sc) { + struct uart_bas *bas; + int ipend; + uint8_t isr0, isr1; - return (0); + bas = &sc->sc_bas; + isr0 = uart_getreg(bas, SAB_ISR0); + isr1 = uart_getreg(bas, SAB_ISR1); + uart_barrier(bas); + + if (isr0 & SAB_ISR0_TIME) { + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; + uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD); + uart_barrier(bas); + } + + ipend = 0; + if (isr1 & SAB_ISR1_BRKT) + ipend |= UART_IPEND_BREAK; + if (isr0 & SAB_ISR0_RFO) + ipend |= UART_IPEND_OVERRUN; + if (isr0 & (SAB_ISR0_TCD|SAB_ISR0_RPF)) + ipend |= UART_IPEND_RXREADY; + if ((isr0 & SAB_ISR0_CDSC) || (isr1 & SAB_ISR1_CSC)) + ipend |= UART_IPEND_SIGCHG; + if (isr1 & SAB_ISR1_ALLS) + ipend |= UART_IPEND_TXIDLE; + + return (ipend); } static int @@ -397,7 +477,36 @@ static int sab82532_bus_receive(struct uart_softc *sc) { + struct uart_bas *bas; + int count, xc; + uint8_t s; + bas = &sc->sc_bas; + count = uart_getreg(bas, SAB_RBCL) & 31; + if (count == 0) + count = 32; + while (count && !uart_rx_full(sc)) { + xc = uart_getreg(bas, SAB_RFIFO); + s = uart_getreg(bas, SAB_RFIFO); + if (s & SAB_RSTAT_FE) + xc |= UART_STAT_FRAMERR; + if (s & SAB_RSTAT_PE) + xc |= UART_STAT_PARERR; + uart_rx_put(sc, xc); + count -= 2; + } + /* + * Oops, we couldn't get all data from the FIFO. Mark an overflow + * condition and let upper layers deal with this. We need to free + * the Rx FIFO. Sorry... + */ + if (count) + sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; + + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; + uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC); + uart_barrier(bas); return (0); } @@ -411,6 +520,16 @@ static int sab82532_bus_transmit(struct uart_softc *sc) { + struct uart_bas *bas; + int i; + bas = &sc->sc_bas; + for (i = 0; i < sc->sc_txdatasz; i++) + uart_setreg(bas, SAB_XFIFO + i, sc->sc_txbuf[i]); + uart_barrier(bas); + while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC) + ; + uart_setreg(bas, SAB_CMDR, SAB_CMDR_XF); + sc->sc_txbusy = 1; return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308220657.h7M6vLc3071728>