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