1 /* $NetBSD: ucb1200.c,v 1.5 2000/10/22 10:42:31 uch Exp $ */ 2 3 /* 4 * Copyright (c) 2000, by UCHIYAMA Yasushi 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the developer may NOT be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end 31 */ 32 #define UCB1200DEBUG 33 #include "opt_tx39_debug.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/device.h> 38 39 #include <machine/bus.h> 40 #include <machine/intr.h> 41 42 #include <hpcmips/tx/tx39var.h> 43 #include <hpcmips/tx/tx39sibvar.h> 44 #include <hpcmips/tx/tx39sibreg.h> 45 46 #include <hpcmips/dev/ucb1200var.h> 47 #include <hpcmips/dev/ucb1200reg.h> 48 49 #ifdef UCB1200DEBUG 50 int ucb1200debug = 1; 51 #define DPRINTF(arg) if (ucb1200debug) printf arg; 52 #define DPRINTFN(n, arg) if (ucb1200debug > (n)) printf arg; 53 #else 54 #define DPRINTF(arg) 55 #define DPRINTFN(n, arg) 56 #endif 57 58 struct ucbchild_state { 59 int (*cs_busy)(void *); 60 void *cs_arg; 61 }; 62 63 struct ucb1200_softc { 64 struct device sc_dev; 65 struct device *sc_parent; /* parent (TX39 SIB module) */ 66 tx_chipset_tag_t sc_tc; 67 68 int sc_snd_rate; /* passed down from SIB module */ 69 int sc_tel_rate; 70 71 /* inquire child module state */ 72 struct ucbchild_state sc_child[UCB1200_MODULE_MAX]; 73 }; 74 75 int ucb1200_match(struct device *, struct cfdata *, void *); 76 void ucb1200_attach(struct device *, struct device *, void *); 77 int ucb1200_print(void *, const char *); 78 int ucb1200_search(struct device *, struct cfdata *, void *); 79 int ucb1200_check_id(u_int16_t, int); 80 81 #ifdef UCB1200DEBUG 82 void ucb1200_dump(struct ucb1200_softc *); 83 #endif 84 85 struct cfattach ucb_ca = { 86 sizeof(struct ucb1200_softc), ucb1200_match, ucb1200_attach 87 }; 88 89 const struct ucb_id { 90 u_int16_t id; 91 const char *product; 92 } ucb_id[] = { 93 { UCB1100_ID, "PHILIPS UCB1100" }, 94 { UCB1200_ID, "PHILIPS UCB1200" }, 95 { UCB1300_ID, "PHILIPS UCB1300" }, 96 { TC35413F_ID, "TOSHIBA TC35413F" }, 97 { 0, 0 } 98 }; 99 100 int 101 ucb1200_match(struct device *parent, struct cfdata *cf, void *aux) 102 { 103 struct txsib_attach_args *sa = aux; 104 u_int16_t reg; 105 106 if (sa->sa_slot != 0) /* UCB1200 must be subframe 0 */ 107 return 0; 108 reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG); 109 110 return (ucb1200_check_id(reg, 0)); 111 } 112 113 void 114 ucb1200_attach(struct device *parent, struct device *self, void *aux) 115 { 116 struct txsib_attach_args *sa = aux; 117 struct ucb1200_softc *sc = (void*)self; 118 u_int16_t reg; 119 120 printf(": "); 121 sc->sc_tc = sa->sa_tc; 122 sc->sc_parent = parent; 123 sc->sc_snd_rate = sa->sa_snd_rate; 124 sc->sc_tel_rate = sa->sa_tel_rate; 125 126 tx39sib_enable1(sc->sc_parent); 127 tx39sib_enable2(sc->sc_parent); 128 129 #ifdef UCB1200DEBUG 130 if (ucb1200debug) 131 ucb1200_dump(sc); 132 #endif 133 reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG); 134 (void)ucb1200_check_id(reg, 1); 135 printf("\n"); 136 137 config_search(ucb1200_search, self, ucb1200_print); 138 } 139 140 int 141 ucb1200_search(struct device *parent, struct cfdata *cf, void *aux) 142 { 143 struct ucb1200_softc *sc = (void*)parent; 144 struct ucb1200_attach_args ucba; 145 146 ucba.ucba_tc = sc->sc_tc; 147 ucba.ucba_snd_rate = sc->sc_snd_rate; 148 ucba.ucba_tel_rate = sc->sc_tel_rate; 149 ucba.ucba_sib = sc->sc_parent; 150 ucba.ucba_ucb = parent; 151 152 if ((*cf->cf_attach->ca_match)(parent, cf, &ucba)) 153 config_attach(parent, cf, &ucba, ucb1200_print); 154 155 return 0; 156 } 157 158 int 159 ucb1200_print(void *aux, const char *pnp) 160 { 161 return pnp ? QUIET : UNCONF; 162 } 163 164 int 165 ucb1200_check_id(u_int16_t idreg, int print) 166 { 167 int i; 168 169 for (i = 0; ucb_id[i].product; i++) { 170 if (ucb_id[i].id == idreg) { 171 if (print) { 172 printf("%s", ucb_id[i].product); 173 } 174 175 return (1); 176 } 177 } 178 179 return 0; 180 } 181 182 void 183 ucb1200_state_install(struct device *dev, int (*sfun)(void *), void *sarg, 184 int sid) 185 { 186 struct ucb1200_softc *sc = (void*)dev; 187 188 sc->sc_child[sid].cs_busy = sfun; 189 sc->sc_child[sid].cs_arg = sarg; 190 } 191 192 int 193 ucb1200_state_idle(dev) 194 struct device *dev; 195 { 196 struct ucb1200_softc *sc = (void*)dev; 197 struct ucbchild_state *cs; 198 int i; 199 200 cs = sc->sc_child; 201 for (i = 0; i < UCB1200_MODULE_MAX; i++, cs++) 202 if (cs->cs_busy) 203 if ((*cs->cs_busy)(cs->cs_arg)) 204 return 0; 205 206 return 1; /* idle state */ 207 } 208 209 #ifdef UCB1200DEBUG 210 void 211 ucb1200_dump(struct ucb1200_softc *sc) 212 { 213 const char *regname[] = { 214 "IO_DATA ", 215 "IO_DIR ", 216 "POSINTEN ", 217 "NEGINTEN ", 218 "INTSTAT ", 219 "TELECOMCTRLA ", 220 "TELECOMCTRLB ", 221 "AUDIOCTRLA ", 222 "AUDIOCTRLB ", 223 "TOUCHSCREENCTRL", 224 "ADCCTRL ", 225 "ADCDATA ", 226 "ID ", 227 "MODE ", 228 "RESERVED ", 229 "NULL " 230 }; 231 tx_chipset_tag_t tc; 232 u_int16_t reg; 233 int i; 234 235 tc = sc->sc_tc; 236 237 printf("\n\t[UCB1200 register]\n"); 238 for (i = 0; i < 16; i++) { 239 reg = txsibsf0_reg_read(tc, i); 240 printf("%s(%02d) 0x%04x ", regname[i], i, reg); 241 bitdisp(reg); 242 } 243 } 244 #endif /* UCB1200DEBUG */ 245