1157299Smarcel/*- 2157299Smarcel * Copyright (c) 2004-2006 Marcel Moolenaar 3157299Smarcel * All rights reserved. 4157299Smarcel * 5157299Smarcel * Redistribution and use in source and binary forms, with or without 6157299Smarcel * modification, are permitted provided that the following conditions 7157299Smarcel * are met: 8157299Smarcel * 9157299Smarcel * 1. Redistributions of source code must retain the above copyright 10157299Smarcel * notice, this list of conditions and the following disclaimer. 11157299Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12157299Smarcel * notice, this list of conditions and the following disclaimer in the 13157299Smarcel * documentation and/or other materials provided with the distribution. 14157299Smarcel * 15157299Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16157299Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17157299Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18157299Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19157299Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20157299Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21157299Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22157299Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23157299Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24157299Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25157299Smarcel */ 26157299Smarcel 27157299Smarcel#include <sys/cdefs.h> 28157299Smarcel__FBSDID("$FreeBSD$"); 29157299Smarcel 30157299Smarcel#include <sys/param.h> 31157299Smarcel#include <sys/systm.h> 32157299Smarcel#include <sys/bus.h> 33157299Smarcel#include <sys/conf.h> 34157299Smarcel#include <machine/bus.h> 35157299Smarcel#include <sys/rman.h> 36157299Smarcel#include <sys/serial.h> 37157299Smarcel 38157299Smarcel#include <dev/scc/scc_bfe.h> 39157299Smarcel#include <dev/scc/scc_bus.h> 40157299Smarcel 41157299Smarcel#include <dev/ic/sab82532.h> 42157299Smarcel 43157299Smarcel#include "scc_if.h" 44157299Smarcel 45157299Smarcelstatic int sab82532_bfe_attach(struct scc_softc *, int); 46157299Smarcelstatic int sab82532_bfe_iclear(struct scc_softc *, struct scc_chan *); 47157299Smarcelstatic int sab82532_bfe_ipend(struct scc_softc *); 48157299Smarcelstatic int sab82532_bfe_probe(struct scc_softc *); 49157299Smarcel 50157299Smarcelstatic kobj_method_t sab82532_methods[] = { 51157299Smarcel KOBJMETHOD(scc_attach, sab82532_bfe_attach), 52157299Smarcel KOBJMETHOD(scc_iclear, sab82532_bfe_iclear), 53157299Smarcel KOBJMETHOD(scc_ipend, sab82532_bfe_ipend), 54157299Smarcel KOBJMETHOD(scc_probe, sab82532_bfe_probe), 55254160Smarius KOBJMETHOD_END 56157299Smarcel}; 57157299Smarcel 58157299Smarcelstruct scc_class scc_sab82532_class = { 59157299Smarcel "sab82532 class", 60157299Smarcel sab82532_methods, 61157299Smarcel sizeof(struct scc_softc), 62157299Smarcel .cl_channels = SAB_NCHAN, 63157299Smarcel .cl_class = SCC_CLASS_SAB82532, 64157299Smarcel .cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC, 65157299Smarcel .cl_range = SAB_CHANLEN, 66157299Smarcel}; 67157299Smarcel 68157299Smarcelstatic int 69254160Smariussab82532_bfe_attach(struct scc_softc *sc __unused, int reset __unused) 70157299Smarcel{ 71157299Smarcel 72157299Smarcel return (0); 73157299Smarcel} 74157299Smarcel 75157299Smarcelstatic int 76157299Smarcelsab82532_bfe_iclear(struct scc_softc *sc, struct scc_chan *ch) 77157299Smarcel{ 78254160Smarius struct scc_bas *bas; 79254160Smarius int i, ofs, rbcl; 80157299Smarcel 81254160Smarius bas = &sc->sc_bas; 82254160Smarius ofs = (ch->ch_nr - 1) * SAB_CHANLEN; 83254160Smarius mtx_lock_spin(&sc->sc_hwmtx); 84254160Smarius if (ch->ch_ipend & SER_INT_RXREADY) { 85254160Smarius if (scc_getreg(bas, ofs + SAB_STAR) & SAB_STAR_RFNE) { 86254160Smarius rbcl = scc_getreg(bas, ofs + SAB_RBCL) & 31; 87254160Smarius if (rbcl == 0) 88254160Smarius rbcl = 32; 89254160Smarius for (i = 0; i < rbcl; i += 2) { 90254160Smarius (void)scc_getreg(bas, ofs + SAB_RFIFO); 91254160Smarius (void)scc_getreg(bas, ofs + SAB_RFIFO + 1); 92254160Smarius } 93254160Smarius } 94254160Smarius while (scc_getreg(bas, ofs + SAB_STAR) & SAB_STAR_CEC) 95254160Smarius ; 96254160Smarius scc_setreg(bas, ofs + SAB_CMDR, SAB_CMDR_RMC); 97254160Smarius scc_barrier(bas); 98254160Smarius } 99254160Smarius mtx_unlock_spin(&sc->sc_hwmtx); 100157299Smarcel return (0); 101157299Smarcel} 102157299Smarcel 103157299Smarcelstatic int 104157299Smarcelsab82532_bfe_ipend(struct scc_softc *sc) 105157299Smarcel{ 106157299Smarcel struct scc_bas *bas; 107157299Smarcel struct scc_chan *ch; 108157299Smarcel int ipend; 109157299Smarcel int c, ofs; 110157299Smarcel uint8_t isr0, isr1; 111157299Smarcel 112157299Smarcel bas = &sc->sc_bas; 113157299Smarcel ipend = 0; 114157299Smarcel for (c = 0; c < SAB_NCHAN; c++) { 115157299Smarcel ch = &sc->sc_chan[c]; 116157299Smarcel ofs = c * SAB_CHANLEN; 117157299Smarcel mtx_lock_spin(&sc->sc_hwmtx); 118157299Smarcel isr0 = scc_getreg(bas, ofs + SAB_ISR0); 119157299Smarcel isr1 = scc_getreg(bas, ofs + SAB_ISR1); 120157299Smarcel scc_barrier(bas); 121157299Smarcel if (isr0 & SAB_ISR0_TIME) { 122157299Smarcel while (scc_getreg(bas, ofs + SAB_STAR) & SAB_STAR_CEC) 123157299Smarcel ; 124157299Smarcel scc_setreg(bas, ofs + SAB_CMDR, SAB_CMDR_RFRD); 125157299Smarcel scc_barrier(bas); 126157299Smarcel } 127157299Smarcel mtx_unlock_spin(&sc->sc_hwmtx); 128157299Smarcel 129157299Smarcel ch->ch_ipend = 0; 130157299Smarcel if (isr1 & SAB_ISR1_BRKT) 131157299Smarcel ch->ch_ipend |= SER_INT_BREAK; 132157299Smarcel if (isr0 & SAB_ISR0_RFO) 133157299Smarcel ch->ch_ipend |= SER_INT_OVERRUN; 134157299Smarcel if (isr0 & (SAB_ISR0_TCD|SAB_ISR0_RPF)) 135157299Smarcel ch->ch_ipend |= SER_INT_RXREADY; 136157299Smarcel if ((isr0 & SAB_ISR0_CDSC) || (isr1 & SAB_ISR1_CSC)) 137157299Smarcel ch->ch_ipend |= SER_INT_SIGCHG; 138157299Smarcel if (isr1 & SAB_ISR1_ALLS) 139157299Smarcel ch->ch_ipend |= SER_INT_TXIDLE; 140157299Smarcel ipend |= ch->ch_ipend; 141157299Smarcel } 142157299Smarcel return (ipend); 143157299Smarcel} 144157299Smarcel 145157299Smarcelstatic int 146254160Smariussab82532_bfe_probe(struct scc_softc *sc __unused) 147157299Smarcel{ 148157299Smarcel 149157299Smarcel return (0); 150157299Smarcel} 151