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