ucb1200.c revision 1.12 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