1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2004-2006 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/bus.h> 32 #include <sys/conf.h> 33 #include <machine/bus.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/rman.h> 37 #include <sys/serial.h> 38 39 #include <dev/scc/scc_bfe.h> 40 #include <dev/scc/scc_bus.h> 41 42 #include <dev/ic/quicc.h> 43 44 #include "scc_if.h" 45 46 #define quicc_read2(bas, reg) \ 47 bus_space_read_2((bas)->bst, (bas)->bsh, reg) 48 #define quicc_read4(bas, reg) \ 49 bus_space_read_4((bas)->bst, (bas)->bsh, reg) 50 51 #define quicc_write2(bas, reg, val) \ 52 bus_space_write_2((bas)->bst, (bas)->bsh, reg, val) 53 #define quicc_write4(bas, reg, val) \ 54 bus_space_write_4((bas)->bst, (bas)->bsh, reg, val) 55 56 static int quicc_bfe_attach(struct scc_softc *, int); 57 static int quicc_bfe_enabled(struct scc_softc *, struct scc_chan *); 58 static int quicc_bfe_iclear(struct scc_softc *, struct scc_chan *); 59 static int quicc_bfe_ipend(struct scc_softc *); 60 static int quicc_bfe_probe(struct scc_softc *); 61 62 static kobj_method_t quicc_methods[] = { 63 KOBJMETHOD(scc_attach, quicc_bfe_attach), 64 KOBJMETHOD(scc_enabled, quicc_bfe_enabled), 65 KOBJMETHOD(scc_iclear, quicc_bfe_iclear), 66 KOBJMETHOD(scc_ipend, quicc_bfe_ipend), 67 KOBJMETHOD(scc_probe, quicc_bfe_probe), 68 KOBJMETHOD_END 69 }; 70 71 struct scc_class scc_quicc_class = { 72 "QUICC class", 73 quicc_methods, 74 sizeof(struct scc_softc), 75 .cl_channels = 4, 76 .cl_class = SCC_CLASS_QUICC, 77 .cl_modes = SCC_MODE_ASYNC | SCC_MODE_BISYNC | SCC_MODE_HDLC, 78 .cl_range = 0, 79 }; 80 81 static int 82 quicc_bfe_attach(struct scc_softc *sc __unused, int reset __unused) 83 { 84 85 return (0); 86 } 87 88 static int 89 quicc_bfe_enabled(struct scc_softc *sc, struct scc_chan *ch) 90 { 91 struct scc_bas *bas; 92 int unit; 93 uint16_t val0, val1; 94 95 bas = &sc->sc_bas; 96 unit = ch->ch_nr - 1; 97 val0 = quicc_read2(bas, QUICC_REG_SCC_TODR(unit)); 98 quicc_write2(bas, QUICC_REG_SCC_TODR(unit), ~val0); 99 val1 = quicc_read2(bas, QUICC_REG_SCC_TODR(unit)); 100 quicc_write2(bas, QUICC_REG_SCC_TODR(unit), val0); 101 return (((val0 | val1) == 0x8000) ? 1 : 0); 102 } 103 104 static int 105 quicc_bfe_iclear(struct scc_softc *sc, struct scc_chan *ch) 106 { 107 struct scc_bas *bas; 108 uint16_t rb, st; 109 110 bas = &sc->sc_bas; 111 mtx_lock_spin(&sc->sc_hwmtx); 112 if (ch->ch_ipend & SER_INT_RXREADY) { 113 rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(ch->ch_nr - 1)); 114 st = quicc_read2(bas, rb); 115 (void)quicc_read4(bas, rb + 4); 116 quicc_write2(bas, rb, st | 0x9000); 117 } 118 mtx_unlock_spin(&sc->sc_hwmtx); 119 return (0); 120 } 121 122 static int 123 quicc_bfe_ipend(struct scc_softc *sc) 124 { 125 struct scc_bas *bas; 126 struct scc_chan *ch; 127 int c, ipend; 128 uint16_t scce; 129 130 bas = &sc->sc_bas; 131 ipend = 0; 132 for (c = 0; c < 4; c++) { 133 ch = &sc->sc_chan[c]; 134 if (!ch->ch_enabled) 135 continue; 136 ch->ch_ipend = 0; 137 mtx_lock_spin(&sc->sc_hwmtx); 138 scce = quicc_read2(bas, QUICC_REG_SCC_SCCE(c)); 139 quicc_write2(bas, QUICC_REG_SCC_SCCE(c), ~0); 140 mtx_unlock_spin(&sc->sc_hwmtx); 141 if (scce & 0x0001) 142 ch->ch_ipend |= SER_INT_RXREADY; 143 if (scce & 0x0002) 144 ch->ch_ipend |= SER_INT_TXIDLE; 145 if (scce & 0x0004) 146 ch->ch_ipend |= SER_INT_OVERRUN; 147 if (scce & 0x0020) 148 ch->ch_ipend |= SER_INT_BREAK; 149 /* XXX SIGNALS */ 150 ipend |= ch->ch_ipend; 151 } 152 return (ipend); 153 } 154 155 static int 156 quicc_bfe_probe(struct scc_softc *sc __unused) 157 { 158 159 return (0); 160 } 161