10SN/A/*- 216534Sweijun * Copyright (c) 2006 Juniper Networks 30SN/A * All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 72362SN/A * are met: 80SN/A * 92362SN/A * 1. Redistributions of source code must retain the above copyright 100SN/A * notice, this list of conditions and the following disclaimer. 110SN/A * 2. Redistributions in binary form must reproduce the above copyright 120SN/A * notice, this list of conditions and the following disclaimer in the 130SN/A * documentation and/or other materials provided with the distribution. 140SN/A * 150SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 160SN/A * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 170SN/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 180SN/A * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 190SN/A * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 200SN/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 212362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 222362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 232362SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 240SN/A * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 250SN/A */ 265976SN/A 270SN/A#include <sys/cdefs.h> 280SN/A__FBSDID("$FreeBSD$"); 291803SN/A 3016788Sweijun#include <sys/param.h> 310SN/A#include <sys/systm.h> 320SN/A#include <sys/bus.h> 330SN/A#include <sys/conf.h> 340SN/A#include <sys/endian.h> 350SN/A#include <machine/bus.h> 360SN/A 370SN/A#include <dev/ic/quicc.h> 381803SN/A 390SN/A#include <dev/uart/uart.h> 400SN/A#include <dev/uart/uart_cpu.h> 410SN/A#include <dev/uart/uart_bus.h> 420SN/A 430SN/A#include "uart_if.h" 444644SN/A 452346SN/A#define DEFAULT_RCLK ((266000000 * 2) / 16) 460SN/A 470SN/A#define quicc_read2(bas, reg) \ 4811963Svaleriep bus_space_read_2((bas)->bst, (bas)->bsh, reg) 4911963Svaleriep#define quicc_read4(bas, reg) \ 5011963Svaleriep bus_space_read_4((bas)->bst, (bas)->bsh, reg) 510SN/A 520SN/A#define quicc_write2(bas, reg, val) \ 530SN/A bus_space_write_2((bas)->bst, (bas)->bsh, reg, val) 541803SN/A#define quicc_write4(bas, reg, val) \ 551803SN/A bus_space_write_4((bas)->bst, (bas)->bsh, reg, val) 562346SN/A 572346SN/Astatic int 580SN/Aquicc_divisor(int rclk, int baudrate) 590SN/A{ 602346SN/A int act_baud, divisor, error; 612346SN/A 622346SN/A if (baudrate == 0) 632346SN/A return (-1); 642346SN/A 652346SN/A divisor = rclk / baudrate / 16; 666658SN/A if (divisor > 4096) 6710074SN/A divisor = ((divisor >> 3) - 2) | 1; 6810792Sweijun else if (divisor >= 0) 690SN/A divisor = (divisor - 1) << 1; 704644SN/A if (divisor < 0 || divisor >= 8192) 714644SN/A return (-1); 720SN/A act_baud = rclk / (((divisor >> 1) + 1) << ((divisor & 1) ? 8 : 4)); 7311963Svaleriep 740SN/A /* 10 times error in percent: */ 750SN/A error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1; 760SN/A 778299SN/A /* 3.0% maximum error tolerance: */ 788299SN/A if (error < -30 || error > 30) 790SN/A return (-1); 80903SN/A 815976SN/A return (divisor); 825976SN/A} 83903SN/A 8411658Sweijunstatic int 850SN/Aquicc_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, 860SN/A int parity) 870SN/A{ 8816032Sasmotrak int divisor; 895976SN/A uint16_t psmr; 905976SN/A 9116032Sasmotrak if (baudrate > 0) { 920SN/A divisor = quicc_divisor(bas->rclk, baudrate); 930SN/A if (divisor == -1) 940SN/A return (EINVAL); 950SN/A quicc_write4(bas, QUICC_REG_BRG(bas->chan - 1), 960SN/A divisor | 0x10000); 970SN/A } 980SN/A 990SN/A psmr = 0; 1000SN/A switch (databits) { 1010SN/A case 5: psmr |= 0x0000; break; 1020SN/A case 6: psmr |= 0x1000; break; 1030SN/A case 7: psmr |= 0x2000; break; 1040SN/A case 8: psmr |= 0x3000; break; 1055976SN/A default: return (EINVAL); 1060SN/A } 10711658Sweijun switch (stopbits) { 10811658Sweijun case 1: psmr |= 0x0000; break; 1090SN/A case 2: psmr |= 0x4000; break; 1101706SN/A default: return (EINVAL); 1110SN/A } 1120SN/A switch (parity) { 1130SN/A case UART_PARITY_EVEN: psmr |= 0x1a; break; 1140SN/A case UART_PARITY_MARK: psmr |= 0x1f; break; 1150SN/A case UART_PARITY_NONE: psmr |= 0x00; break; 1160SN/A case UART_PARITY_ODD: psmr |= 0x10; break; 1170SN/A case UART_PARITY_SPACE: psmr |= 0x15; break; 1180SN/A default: return (EINVAL); 1190SN/A } 1200SN/A quicc_write2(bas, QUICC_REG_SCC_PSMR(bas->chan - 1), psmr); 121903SN/A return (0); 122903SN/A} 1230SN/A 1240SN/Astatic void 1250SN/Aquicc_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits, 1260SN/A int parity) 1270SN/A{ 1280SN/A 1290SN/A if (bas->rclk == 0) 1300SN/A bas->rclk = DEFAULT_RCLK; 1310SN/A 13215059Sweijun /* 1330SN/A * GSMR_L = 0x00028034 13411178Svinnie * GSMR_H = 0x00000020 13515208Sweijun */ 1360SN/A quicc_param(bas, baudrate, databits, stopbits, parity); 1370SN/A 1380SN/A quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0); 1390SN/A quicc_write2(bas, QUICC_REG_SCC_SCCM(bas->chan - 1), 0x0027); 1400SN/A} 1410SN/A 1420SN/A/* 1430SN/A * Low-level UART interface. 1440SN/A */ 1450SN/Astatic int quicc_probe(struct uart_bas *bas); 1460SN/Astatic void quicc_init(struct uart_bas *bas, int, int, int, int); 1470SN/Astatic void quicc_term(struct uart_bas *bas); 1480SN/Astatic void quicc_putc(struct uart_bas *bas, int); 149447SN/Astatic int quicc_rxready(struct uart_bas *bas); 1501803SN/Astatic int quicc_getc(struct uart_bas *bas, struct mtx *); 1510SN/A 1520SN/Astatic struct uart_ops uart_quicc_ops = { 1530SN/A .probe = quicc_probe, 1540SN/A .init = quicc_init, 1550SN/A .term = quicc_term, 1560SN/A .putc = quicc_putc, 1570SN/A .rxready = quicc_rxready, 1580SN/A .getc = quicc_getc, 15915325Sweijun}; 16016788Sweijun 1610SN/Astatic int 1620SN/Aquicc_probe(struct uart_bas *bas) 1630SN/A{ 1640SN/A 1653388SN/A return (0); 1660SN/A} 1670SN/A 1683388SN/Astatic void 1693388SN/Aquicc_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 170903SN/A int parity) 17116788Sweijun{ 17216788Sweijun 17316788Sweijun quicc_setup(bas, baudrate, databits, stopbits, parity); 17416788Sweijun} 17516788Sweijun 17616788Sweijunstatic void 17716788Sweijunquicc_term(struct uart_bas *bas) 17816788Sweijun{ 17916788Sweijun} 18016788Sweijun 1811706SN/Astatic void 1823050SN/Aquicc_putc(struct uart_bas *bas, int c) 1832158SN/A{ 18415059Sweijun int unit; 18515059Sweijun uint16_t toseq; 1863050SN/A 18715325Sweijun unit = bas->chan - 1; 18815059Sweijun while (quicc_read2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit)) & 0x2000) 1892117SN/A DELAY(10); 1903050SN/A 19115325Sweijun toseq = 0x2000 | (c & 0xff); 19215059Sweijun quicc_write2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit), toseq); 1932117SN/A} 1943050SN/A 19515325Sweijunstatic int 19615059Sweijunquicc_rxready(struct uart_bas *bas) 1972117SN/A{ 1983050SN/A uint16_t rb; 1992158SN/A 2002117SN/A rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 20115059Sweijun return ((quicc_read2(bas, rb) & 0x8000) ? 0 : 1); 20215059Sweijun} 2033050SN/A 2042117SN/Astatic int 20515059Sweijunquicc_getc(struct uart_bas *bas, struct mtx *hwmtx) 20615059Sweijun{ 2073050SN/A volatile char *buf; 2082158SN/A int c; 2092117SN/A uint16_t rb, sc; 21015059Sweijun 21115059Sweijun uart_lock(hwmtx); 2123050SN/A 2132117SN/A rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 21415325Sweijun 21515059Sweijun while ((sc = quicc_read2(bas, rb)) & 0x8000) { 2162117SN/A uart_unlock(hwmtx); 2178299SN/A DELAY(4); 2188299SN/A uart_lock(hwmtx); 21915059Sweijun } 22015059Sweijun 2213050SN/A buf = (void *)(uintptr_t)quicc_read4(bas, rb + 4); 2222117SN/A c = *buf; 2232117SN/A quicc_write2(bas, rb, sc | 0x8000); 22414704Sweijun 2252117SN/A uart_unlock(hwmtx); 22615059Sweijun 2272117SN/A return (c); 2283050SN/A} 2292117SN/A 23015059Sweijun/* 2312117SN/A * High-level UART interface. 2323050SN/A */ 23315325Sweijunstruct quicc_softc { 23415059Sweijun struct uart_softc base; 2352117SN/A}; 2363050SN/A 2372117SN/Astatic int quicc_bus_attach(struct uart_softc *); 2383050SN/Astatic int quicc_bus_detach(struct uart_softc *); 2392117SN/Astatic int quicc_bus_flush(struct uart_softc *, int); 2403050SN/Astatic int quicc_bus_getsig(struct uart_softc *); 2412346SN/Astatic int quicc_bus_ioctl(struct uart_softc *, int, intptr_t); 2423050SN/Astatic int quicc_bus_ipend(struct uart_softc *); 24315325Sweijunstatic int quicc_bus_param(struct uart_softc *, int, int, int, int); 24415059Sweijunstatic int quicc_bus_probe(struct uart_softc *); 2452346SN/Astatic int quicc_bus_receive(struct uart_softc *); 2462346SN/Astatic int quicc_bus_setsig(struct uart_softc *, int); 2472346SN/Astatic int quicc_bus_transmit(struct uart_softc *); 2483050SN/Astatic void quicc_bus_grab(struct uart_softc *); 2492346SN/Astatic void quicc_bus_ungrab(struct uart_softc *); 25015059Sweijun 25115059Sweijunstatic kobj_method_t quicc_methods[] = { 2523050SN/A KOBJMETHOD(uart_attach, quicc_bus_attach), 2532117SN/A KOBJMETHOD(uart_detach, quicc_bus_detach), 2542117SN/A KOBJMETHOD(uart_flush, quicc_bus_flush), 25515059Sweijun KOBJMETHOD(uart_getsig, quicc_bus_getsig), 2563050SN/A KOBJMETHOD(uart_ioctl, quicc_bus_ioctl), 2572346SN/A KOBJMETHOD(uart_ipend, quicc_bus_ipend), 2582346SN/A KOBJMETHOD(uart_param, quicc_bus_param), 25915059Sweijun KOBJMETHOD(uart_probe, quicc_bus_probe), 26015059Sweijun KOBJMETHOD(uart_receive, quicc_bus_receive), 2613050SN/A KOBJMETHOD(uart_setsig, quicc_bus_setsig), 2622346SN/A KOBJMETHOD(uart_transmit, quicc_bus_transmit), 26315059Sweijun KOBJMETHOD(uart_grab, quicc_bus_grab), 2641706SN/A KOBJMETHOD(uart_ungrab, quicc_bus_ungrab), 2651706SN/A { 0, 0 } 2662117SN/A}; 26710074SN/A 26810074SN/Astruct uart_class uart_quicc_class = { 26910074SN/A "quicc", 27010074SN/A quicc_methods, 2712117SN/A sizeof(struct quicc_softc), 2721706SN/A .uc_ops = &uart_quicc_ops, 2731706SN/A .uc_range = 2, 27410074SN/A .uc_rclk = DEFAULT_RCLK 2751706SN/A}; 2761706SN/A 2771706SN/A#define SIGCHG(c, i, s, d) \ 27810074SN/A if (c) { \ 27910074SN/A i |= (i & s) ? s : s | d; \ 28010074SN/A } else { \ 28110074SN/A i = (i & s) ? (i & ~s) | d : i; \ 28210074SN/A } 28310074SN/A 28410074SN/Astatic int 28510074SN/Aquicc_bus_attach(struct uart_softc *sc) 28610074SN/A{ 28710074SN/A struct uart_bas *bas; 28810074SN/A struct uart_devinfo *di; 28910074SN/A uint16_t st, rb; 29010074SN/A 29110074SN/A bas = &sc->sc_bas; 29210074SN/A if (sc->sc_sysdev != NULL) { 29310074SN/A di = sc->sc_sysdev; 29410074SN/A quicc_param(bas, di->baudrate, di->databits, di->stopbits, 2951706SN/A di->parity); 2961706SN/A } else { 2971706SN/A quicc_setup(bas, 9600, 8, 1, UART_PARITY_NONE); 29810074SN/A } 29910074SN/A 30010074SN/A /* Enable interrupts on the receive buffer. */ 30110074SN/A rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 30210074SN/A st = quicc_read2(bas, rb); 30310074SN/A quicc_write2(bas, rb, st | 0x9000); 30410074SN/A 3052117SN/A (void)quicc_bus_getsig(sc); 3063050SN/A 30715059Sweijun return (0); 3083050SN/A} 30915059Sweijun 3103050SN/Astatic int 31115059Sweijunquicc_bus_detach(struct uart_softc *sc) 3123050SN/A{ 31315059Sweijun 31415059Sweijun return (0); 3153050SN/A} 31615059Sweijun 31715059Sweijunstatic int 3183050SN/Aquicc_bus_flush(struct uart_softc *sc, int what) 31915059Sweijun{ 32015059Sweijun 3213050SN/A return (0); 32215059Sweijun} 3233050SN/A 32415325Sweijunstatic int 3253050SN/Aquicc_bus_getsig(struct uart_softc *sc) 3263050SN/A{ 32715059Sweijun uint32_t new, old, sig; 3283050SN/A uint32_t dummy; 32915059Sweijun 33015059Sweijun do { 33115059Sweijun old = sc->sc_hwsig; 33215059Sweijun sig = old; 3333050SN/A uart_lock(sc->sc_hwmtx); 33415059Sweijun /* XXX SIGNALS */ 33515059Sweijun dummy = 0; 3363050SN/A uart_unlock(sc->sc_hwmtx); 33715059Sweijun SIGCHG(dummy, sig, SER_CTS, SER_DCTS); 3383050SN/A SIGCHG(dummy, sig, SER_DCD, SER_DDCD); 33915059Sweijun SIGCHG(dummy, sig, SER_DSR, SER_DDSR); 3403050SN/A new = sig & ~SER_MASK_DELTA; 34115059Sweijun } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 3423050SN/A return (sig); 34315059Sweijun} 34415059Sweijun 3453050SN/Astatic int 34615059Sweijunquicc_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 3473050SN/A{ 3483050SN/A struct uart_bas *bas; 34915059Sweijun uint32_t brg; 3502117SN/A int baudrate, error; 3512117SN/A 3522117SN/A bas = &sc->sc_bas; 3532117SN/A error = 0; 3542117SN/A uart_lock(sc->sc_hwmtx); 3552117SN/A switch (request) { 3562117SN/A case UART_IOCTL_BREAK: 3572117SN/A break; 3582117SN/A case UART_IOCTL_BAUD: 3592117SN/A brg = quicc_read4(bas, QUICC_REG_BRG(bas->chan - 1)) & 0x1fff; 3602117SN/A brg = (brg & 1) ? (brg + 1) << 3 : (brg + 2) >> 1; 3611706SN/A baudrate = bas->rclk / (brg * 16); 3620SN/A *(int*)data = baudrate; 3630SN/A break; 3640SN/A default: 3650SN/A error = EINVAL; 36616788Sweijun break; 3670SN/A } 3680SN/A uart_unlock(sc->sc_hwmtx); 3690SN/A return (error); 3705976SN/A} 3715976SN/A 3720SN/Astatic int 3730SN/Aquicc_bus_ipend(struct uart_softc *sc) 3740SN/A{ 3750SN/A struct uart_bas *bas; 3760SN/A int ipend; 3770SN/A uint16_t scce; 3785976SN/A 3790SN/A bas = &sc->sc_bas; 3800SN/A ipend = 0; 3815976SN/A 3820SN/A uart_lock(sc->sc_hwmtx); 3830SN/A scce = quicc_read2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1)); 3840SN/A quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0); 3850SN/A uart_unlock(sc->sc_hwmtx); 3860SN/A if (scce & 0x0001) 38710074SN/A ipend |= SER_INT_RXREADY; 3881706SN/A if (scce & 0x0002) 389903SN/A ipend |= SER_INT_TXIDLE; 390903SN/A if (scce & 0x0004) 3910SN/A ipend |= SER_INT_OVERRUN; 3923050SN/A if (scce & 0x0020) 3930SN/A ipend |= SER_INT_BREAK; 3940SN/A /* XXX SIGNALS */ 3950SN/A return (ipend); 3960SN/A} 3970SN/A 3980SN/Astatic int 3990SN/Aquicc_bus_param(struct uart_softc *sc, int baudrate, int databits, 4000SN/A int stopbits, int parity) 4010SN/A{ 40216788Sweijun int error; 4030SN/A 4040SN/A uart_lock(sc->sc_hwmtx); 4050SN/A error = quicc_param(&sc->sc_bas, baudrate, databits, stopbits, 4060SN/A parity); 4070SN/A uart_unlock(sc->sc_hwmtx); 4080SN/A return (error); 4090SN/A} 4100SN/A 4110SN/Astatic int 4120SN/Aquicc_bus_probe(struct uart_softc *sc) 4130SN/A{ 4140SN/A char buf[80]; 4150SN/A int error; 4160SN/A 4170SN/A error = quicc_probe(&sc->sc_bas); 4180SN/A if (error) 41910074SN/A return (error); 4200SN/A 4210SN/A sc->sc_rxfifosz = 1; 4221706SN/A sc->sc_txfifosz = 1; 4230SN/A 42410074SN/A snprintf(buf, sizeof(buf), "quicc, channel %d", sc->sc_bas.chan); 42510074SN/A device_set_desc_copy(sc->sc_dev, buf); 42610074SN/A return (0); 42710074SN/A} 42810074SN/A 42910074SN/Astatic int 43010074SN/Aquicc_bus_receive(struct uart_softc *sc) 43110074SN/A{ 43210074SN/A struct uart_bas *bas; 43310074SN/A volatile char *buf; 43410074SN/A uint16_t st, rb; 43510074SN/A 43610074SN/A bas = &sc->sc_bas; 43710074SN/A uart_lock(sc->sc_hwmtx); 43810074SN/A rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 43910074SN/A st = quicc_read2(bas, rb); 44010074SN/A buf = (void *)(uintptr_t)quicc_read4(bas, rb + 4); 44110074SN/A uart_rx_put(sc, *buf); 44210074SN/A quicc_write2(bas, rb, st | 0x9000); 44310074SN/A uart_unlock(sc->sc_hwmtx); 44410074SN/A return (0); 44510074SN/A} 44610074SN/A 44710074SN/Astatic int 44810074SN/Aquicc_bus_setsig(struct uart_softc *sc, int sig) 44910074SN/A{ 45010074SN/A struct uart_bas *bas; 45110074SN/A uint32_t new, old; 45210074SN/A 45310074SN/A bas = &sc->sc_bas; 45410074SN/A do { 45510074SN/A old = sc->sc_hwsig; 4560SN/A new = old; 4570SN/A if (sig & SER_DDTR) { 4580SN/A SIGCHG(sig & SER_DTR, new, SER_DTR, 4591706SN/A SER_DDTR); 4601706SN/A } 4611706SN/A if (sig & SER_DRTS) { 4622117SN/A SIGCHG(sig & SER_RTS, new, SER_RTS, 4631706SN/A SER_DRTS); 4642117SN/A } 4652117SN/A } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 4661706SN/A 4671706SN/A uart_lock(sc->sc_hwmtx); 4681706SN/A /* XXX SIGNALS */ 4691706SN/A uart_unlock(sc->sc_hwmtx); 4701706SN/A return (0); 4710SN/A} 4721709SN/A 4731709SN/Astatic int 4741709SN/Aquicc_bus_transmit(struct uart_softc *sc) 4751709SN/A{ 4761709SN/A volatile char *buf; 4771709SN/A struct uart_bas *bas; 4781709SN/A uint16_t st, tb; 4791709SN/A 48010074SN/A bas = &sc->sc_bas; 4811709SN/A uart_lock(sc->sc_hwmtx); 4820SN/A tb = quicc_read2(bas, QUICC_PRAM_SCC_TBASE(bas->chan - 1)); 4830SN/A st = quicc_read2(bas, tb); 48410074SN/A buf = (void *)(uintptr_t)quicc_read4(bas, tb + 4); 48510074SN/A *buf = sc->sc_txbuf[0]; 48610074SN/A quicc_write2(bas, tb + 2, 1); 48710074SN/A quicc_write2(bas, tb, st | 0x9000); 48810074SN/A sc->sc_txbusy = 1; 4891706SN/A uart_unlock(sc->sc_hwmtx); 49010074SN/A return (0); 49110074SN/A} 49216788Sweijun 49316788Sweijunstatic void 49415325Sweijunquicc_bus_grab(struct uart_softc *sc) 4951706SN/A{ 49615325Sweijun struct uart_bas *bas; 49715325Sweijun uint16_t st, rb; 49815325Sweijun 49915325Sweijun /* Disable interrupts on the receive buffer. */ 50015325Sweijun bas = &sc->sc_bas; 50115325Sweijun uart_lock(sc->sc_hwmtx); 50215325Sweijun rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 50315325Sweijun st = quicc_read2(bas, rb); 5040SN/A quicc_write2(bas, rb, st & ~0x9000); 5050SN/A uart_unlock(sc->sc_hwmtx); 5061709SN/A} 5070SN/A 5080SN/Astatic void 5090SN/Aquicc_bus_ungrab(struct uart_softc *sc) 5101706SN/A{ 51111178Svinnie struct uart_bas *bas; 5120SN/A uint16_t st, rb; 5131709SN/A 5140SN/A /* Enable interrupts on the receive buffer. */ 5150SN/A bas = &sc->sc_bas; 5161706SN/A uart_lock(sc->sc_hwmtx); 51715208Sweijun rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1)); 5180SN/A st = quicc_read2(bas, rb); 5191709SN/A quicc_write2(bas, rb, st | 0x9000); 5200SN/A uart_unlock(sc->sc_hwmtx); 5210SN/A} 5221706SN/A 5230SN/A