1 /* $NetBSD: ucb1200.c,v 1.16 2005/12/11 12:17:33 christos 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/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: ucb1200.c,v 1.16 2005/12/11 12:17:33 christos Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/device.h> 49 50 #include <machine/bus.h> 51 #include <machine/intr.h> 52 53 #include <hpcmips/tx/tx39var.h> 54 #include <hpcmips/tx/tx39sibvar.h> 55 #include <hpcmips/tx/tx39sibreg.h> 56 57 #include <hpcmips/dev/ucb1200var.h> 58 #include <hpcmips/dev/ucb1200reg.h> 59 60 #ifdef UCB1200_DEBUG 61 #define DPRINTF_ENABLE 62 #define DPRINTF_DEBUG ucb1200_debug 63 #endif 64 #include <machine/debug.h> 65 66 struct ucbchild_state { 67 int (*cs_busy)(void *); 68 void *cs_arg; 69 }; 70 71 struct ucb1200_softc { 72 struct device sc_dev; 73 struct device *sc_parent; /* parent (TX39 SIB module) */ 74 tx_chipset_tag_t sc_tc; 75 76 int sc_snd_rate; /* passed down from SIB module */ 77 int sc_tel_rate; 78 79 /* inquire child module state */ 80 struct ucbchild_state sc_child[UCB1200_MODULE_MAX]; 81 }; 82 83 int ucb1200_match(struct device *, struct cfdata *, void *); 84 void ucb1200_attach(struct device *, struct device *, void *); 85 int ucb1200_print(void *, const char *); 86 int ucb1200_search(struct device *, struct cfdata *, 87 const int *, void *); 88 int ucb1200_check_id(u_int16_t, int); 89 90 #ifdef UCB1200_DEBUG 91 void ucb1200_dump(struct ucb1200_softc *); 92 #endif 93 94 CFATTACH_DECL(ucb, sizeof(struct ucb1200_softc), 95 ucb1200_match, ucb1200_attach, NULL, NULL); 96 97 const struct ucb_id { 98 u_int16_t id; 99 const char *product; 100 } ucb_id[] = { 101 { UCB1100_ID, "PHILIPS UCB1100" }, 102 { UCB1200_ID, "PHILIPS UCB1200" }, 103 { UCB1300_ID, "PHILIPS UCB1300" }, 104 { TC35413F_ID, "TOSHIBA TC35413F" }, 105 { 0, 0 } 106 }; 107 108 int 109 ucb1200_match(struct device *parent, struct cfdata *cf, void *aux) 110 { 111 struct txsib_attach_args *sa = aux; 112 u_int16_t reg; 113 114 if (sa->sa_slot != 0) /* UCB1200 must be subframe 0 */ 115 return (0); 116 reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG); 117 118 return (ucb1200_check_id(reg, 0)); 119 } 120 121 void 122 ucb1200_attach(struct device *parent, struct device *self, void *aux) 123 { 124 struct txsib_attach_args *sa = aux; 125 struct ucb1200_softc *sc = (void*)self; 126 u_int16_t reg; 127 128 printf(": "); 129 sc->sc_tc = sa->sa_tc; 130 sc->sc_parent = parent; 131 sc->sc_snd_rate = sa->sa_snd_rate; 132 sc->sc_tel_rate = sa->sa_tel_rate; 133 134 tx39sib_enable1(sc->sc_parent); 135 tx39sib_enable2(sc->sc_parent); 136 137 #ifdef UCB1200_DEBUG 138 if (ucb1200_debug) 139 ucb1200_dump(sc); 140 #endif 141 reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG); 142 (void)ucb1200_check_id(reg, 1); 143 printf("\n"); 144 145 config_search_ia(ucb1200_search, self, "ucbif", ucb1200_print); 146 } 147 148 int 149 ucb1200_search(struct device *parent, struct cfdata *cf, 150 const int *ldesc, void *aux) 151 { 152 struct ucb1200_softc *sc = (void*)parent; 153 struct ucb1200_attach_args ucba; 154 155 ucba.ucba_tc = sc->sc_tc; 156 ucba.ucba_snd_rate = sc->sc_snd_rate; 157 ucba.ucba_tel_rate = sc->sc_tel_rate; 158 ucba.ucba_sib = sc->sc_parent; 159 ucba.ucba_ucb = parent; 160 161 if (config_match(parent, cf, &ucba)) 162 config_attach(parent, cf, &ucba, ucb1200_print); 163 164 return (0); 165 } 166 167 int 168 ucb1200_print(void *aux, const char *pnp) 169 { 170 171 return (pnp ? QUIET : UNCONF); 172 } 173 174 int 175 ucb1200_check_id(u_int16_t idreg, int print) 176 { 177 int i; 178 179 for (i = 0; ucb_id[i].product; i++) { 180 if (ucb_id[i].id == idreg) { 181 if (print) { 182 printf("%s", ucb_id[i].product); 183 } 184 185 return (1); 186 } 187 } 188 189 return (0); 190 } 191 192 void 193 ucb1200_state_install(struct device *dev, int (*sfun)(void *), void *sarg, 194 int sid) 195 { 196 struct ucb1200_softc *sc = (void*)dev; 197 198 sc->sc_child[sid].cs_busy = sfun; 199 sc->sc_child[sid].cs_arg = sarg; 200 } 201 202 int 203 ucb1200_state_idle(dev) 204 struct device *dev; 205 { 206 struct ucb1200_softc *sc = (void*)dev; 207 struct ucbchild_state *cs; 208 int i; 209 210 cs = sc->sc_child; 211 for (i = 0; i < UCB1200_MODULE_MAX; i++, cs++) 212 if (cs->cs_busy) 213 if ((*cs->cs_busy)(cs->cs_arg)) 214 return (0); 215 216 return (1); /* idle state */ 217 } 218 219 #ifdef UCB1200_DEBUG 220 void 221 ucb1200_dump(struct ucb1200_softc *sc) 222 { 223 static const char *const regname[] = { 224 "IO_DATA ", 225 "IO_DIR ", 226 "POSINTEN ", 227 "NEGINTEN ", 228 "INTSTAT ", 229 "TELECOMCTRLA ", 230 "TELECOMCTRLB ", 231 "AUDIOCTRLA ", 232 "AUDIOCTRLB ", 233 "TOUCHSCREENCTRL", 234 "ADCCTRL ", 235 "ADCDATA ", 236 "ID ", 237 "MODE ", 238 "RESERVED ", 239 "NULL " 240 }; 241 tx_chipset_tag_t tc; 242 u_int16_t reg; 243 int i; 244 245 tc = sc->sc_tc; 246 247 printf("\n\t[UCB1200 register]\n"); 248 for (i = 0; i < 16; i++) { 249 reg = txsibsf0_reg_read(tc, i); 250 printf("%s(%02d) 0x%04x ", regname[i], i, reg); 251 dbg_bit_print(reg); 252 } 253 } 254 #endif /* UCB1200_DEBUG */ 255