xref: /netbsd-src/sys/arch/hpcmips/dev/ucb1200.c (revision 4472dbe5e3bd91ef2540bada7a7ca7384627ff9b)
1 /*	$NetBSD: ucb1200.c,v 1.4 2000/03/12 15:36:11 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 = 0;
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) __P((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	__P((struct device*, struct cfdata*, void*));
76 void	ucb1200_attach	__P((struct device*, struct device*, void*));
77 int	ucb1200_print	__P((void*, const char*));
78 int	ucb1200_search	__P((struct device*, struct cfdata*, void*));
79 int	ucb1200_check_id __P((u_int16_t, int));
80 
81 #ifdef UCB1200DEBUG
82 void	ucb1200_dump	__P((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(parent, cf, aux)
102 	struct device *parent;
103 	struct cfdata *cf;
104 	void *aux;
105 {
106 	struct txsib_attach_args *sa = aux;
107 	u_int16_t reg;
108 
109 	if (sa->sa_slot != 0) /* UCB1200 must be subframe 0 */
110 		return 0;
111 	reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG);
112 
113 	return (ucb1200_check_id(reg, 0));
114 }
115 
116 void
117 ucb1200_attach(parent, self, aux)
118 	struct device *parent;
119 	struct device *self;
120 	void *aux;
121 {
122 	struct txsib_attach_args *sa = aux;
123 	struct ucb1200_softc *sc = (void*)self;
124 	u_int16_t reg;
125 
126 	printf(": ");
127 	sc->sc_tc = sa->sa_tc;
128 	sc->sc_parent = parent;
129 	sc->sc_snd_rate = sa->sa_snd_rate;
130 	sc->sc_tel_rate = sa->sa_tel_rate;
131 
132 	tx39sib_enable1(sc->sc_parent);
133 	tx39sib_enable2(sc->sc_parent);
134 
135 #ifdef UCB1200DEBUG
136 	if (ucb1200debug)
137 		ucb1200_dump(sc);
138 #endif
139 	reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG);
140 	(void)ucb1200_check_id(reg, 1);
141 	printf("\n");
142 
143 	config_search(ucb1200_search, self, ucb1200_print);
144 }
145 
146 int
147 ucb1200_search(parent, cf, aux)
148 	struct device *parent;
149 	struct cfdata *cf;
150 	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 ((*cf->cf_attach->ca_match)(parent, cf, &ucba))
162 		config_attach(parent, cf, &ucba, ucb1200_print);
163 
164 	return 0;
165 }
166 
167 int
168 ucb1200_print(aux, pnp)
169 	void *aux;
170 	const char *pnp;
171 {
172 	return pnp ? QUIET : UNCONF;
173 }
174 
175 int
176 ucb1200_check_id(idreg, print)
177 	u_int16_t idreg;
178 	int print;
179 {
180 	int i;
181 
182 	for (i = 0; ucb_id[i].product; i++) {
183 		if (ucb_id[i].id == idreg) {
184 			if (print) {
185 				printf("%s", ucb_id[i].product);
186 			}
187 
188 			return (1);
189 		}
190 	}
191 
192 	return 0;
193 }
194 
195 void
196 ucb1200_state_install(dev, sfun, sarg, sid)
197 	struct device *dev;
198 	int (*sfun) __P((void*));
199 	void *sarg;
200 	int sid;
201 {
202 	struct ucb1200_softc *sc = (void*)dev;
203 
204 	sc->sc_child[sid].cs_busy = sfun;
205 	sc->sc_child[sid].cs_arg = sarg;
206 }
207 
208 int
209 ucb1200_state_idle(dev)
210 	struct device *dev;
211 {
212 	struct ucb1200_softc *sc = (void*)dev;
213 	struct ucbchild_state *cs;
214 	int i;
215 
216 	cs = sc->sc_child;
217 	for (i = 0; i < UCB1200_MODULE_MAX; i++, cs++)
218 		if (cs->cs_busy)
219 			if ((*cs->cs_busy)(cs->cs_arg))
220 				return 0;
221 
222 	return 1; /* idle state */
223 }
224 
225 #ifdef UCB1200DEBUG
226 void
227 ucb1200_dump(sc)
228 	struct ucb1200_softc *sc;
229 {
230         const char *regname[] = {
231                 "IO_DATA        ",
232                 "IO_DIR         ",
233                 "POSINTEN       ",
234                 "NEGINTEN       ",
235                 "INTSTAT        ",
236                 "TELECOMCTRLA   ",
237                 "TELECOMCTRLB   ",
238                 "AUDIOCTRLA     ",
239                 "AUDIOCTRLB     ",
240                 "TOUCHSCREENCTRL",
241                 "ADCCTRL        ",
242                 "ADCDATA        ",
243                 "ID             ",
244                 "MODE           ",
245                 "RESERVED       ",
246                 "NULL           "
247         };
248 	tx_chipset_tag_t tc = sc->sc_tc;
249 	u_int16_t reg;
250 	int i;
251 
252 	printf("\n\t[UCB1200 register]\n");
253 	for (i = 0; i < 16; i++) {
254 		reg = txsibsf0_reg_read(tc, i);
255 		printf("%s(%02d) 0x%04x ", regname[i], i, reg);
256 		bitdisp(reg);
257 	}
258 }
259 #endif /* UCB1200DEBUG */
260