xref: /netbsd-src/sys/arch/hpcmips/dev/ucb1200.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
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