xref: /netbsd-src/sys/arch/hpcmips/dev/ucb1200.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: ucb1200.c,v 1.21 2021/08/07 16:18:54 thorpej Exp $ */
2ce3b031dSuch 
358f851eeSuch /*-
458f851eeSuch  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5ce3b031dSuch  * All rights reserved.
6ce3b031dSuch  *
758f851eeSuch  * This code is derived from software contributed to The NetBSD Foundation
858f851eeSuch  * by UCHIYAMA Yasushi.
958f851eeSuch  *
10ce3b031dSuch  * Redistribution and use in source and binary forms, with or without
11ce3b031dSuch  * modification, are permitted provided that the following conditions
12ce3b031dSuch  * are met:
13ce3b031dSuch  * 1. Redistributions of source code must retain the above copyright
14ce3b031dSuch  *    notice, this list of conditions and the following disclaimer.
1558f851eeSuch  * 2. Redistributions in binary form must reproduce the above copyright
1658f851eeSuch  *    notice, this list of conditions and the following disclaimer in the
1758f851eeSuch  *    documentation and/or other materials provided with the distribution.
18ce3b031dSuch  *
1958f851eeSuch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2058f851eeSuch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2158f851eeSuch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2258f851eeSuch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2358f851eeSuch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2458f851eeSuch  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2558f851eeSuch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2658f851eeSuch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2758f851eeSuch  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2858f851eeSuch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2958f851eeSuch  * POSSIBILITY OF SUCH DAMAGE.
30ce3b031dSuch  */
31ce3b031dSuch 
32ce3b031dSuch /*
33ce3b031dSuch  * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end
34ce3b031dSuch  */
35ce3b031dSuch 
360c82163cSlukem #include <sys/cdefs.h>
37*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: ucb1200.c,v 1.21 2021/08/07 16:18:54 thorpej Exp $");
380c82163cSlukem 
39ce3b031dSuch #include <sys/param.h>
40ce3b031dSuch #include <sys/systm.h>
41ce3b031dSuch #include <sys/device.h>
42ce3b031dSuch 
43ce3b031dSuch #include <machine/bus.h>
44ce3b031dSuch #include <machine/intr.h>
45ce3b031dSuch 
46ce3b031dSuch #include <hpcmips/tx/tx39var.h>
47ce3b031dSuch #include <hpcmips/tx/tx39sibvar.h>
48ce3b031dSuch #include <hpcmips/tx/tx39sibreg.h>
49ce3b031dSuch 
50ce3b031dSuch #include <hpcmips/dev/ucb1200var.h>
51ce3b031dSuch #include <hpcmips/dev/ucb1200reg.h>
52ce3b031dSuch 
537d170993Such #ifdef	UCB1200_DEBUG
547d170993Such #define DPRINTF_ENABLE
557d170993Such #define DPRINTF_DEBUG	ucb1200_debug
56ce3b031dSuch #endif
577d170993Such #include <machine/debug.h>
58ce3b031dSuch 
59dce2bc94Such struct ucbchild_state {
60fc9212e5Such 	int (*cs_busy)(void *);
61dce2bc94Such 	void *cs_arg;
62dce2bc94Such };
63dce2bc94Such 
64dce2bc94Such struct ucb1200_softc {
65cbab9cadSchs 	device_t	sc_parent; /* parent (TX39 SIB module) */
66dce2bc94Such 	tx_chipset_tag_t sc_tc;
67dce2bc94Such 
68dce2bc94Such 	int		sc_snd_rate; /* passed down from SIB module */
69dce2bc94Such 	int		sc_tel_rate;
70dce2bc94Such 
71dce2bc94Such 	/* inquire child module state */
72dce2bc94Such 	struct ucbchild_state sc_child[UCB1200_MODULE_MAX];
73dce2bc94Such };
74dce2bc94Such 
75cbab9cadSchs int	ucb1200_match(device_t, cfdata_t, void *);
76cbab9cadSchs void	ucb1200_attach(device_t, device_t, void *);
77fc9212e5Such int	ucb1200_print(void *, const char *);
78cbab9cadSchs int	ucb1200_search(device_t, cfdata_t, const int *, void *);
79fc9212e5Such int	ucb1200_check_id(u_int16_t, int);
80ce3b031dSuch 
817d170993Such #ifdef UCB1200_DEBUG
82fc9212e5Such void	ucb1200_dump(struct ucb1200_softc *);
83dc8f1b2cSuch #endif
84ce3b031dSuch 
85cbab9cadSchs CFATTACH_DECL_NEW(ucb, sizeof(struct ucb1200_softc),
86c5e91d44Sthorpej     ucb1200_match, ucb1200_attach, NULL, NULL);
87ce3b031dSuch 
8844b86d33Such const struct ucb_id {
8944b86d33Such 	u_int16_t	id;
9044b86d33Such 	const char	*product;
9144b86d33Such } ucb_id[] = {
9244b86d33Such 	{ UCB1100_ID,	"PHILIPS UCB1100" },
9344b86d33Such 	{ UCB1200_ID,	"PHILIPS UCB1200" },
9444b86d33Such 	{ UCB1300_ID,	"PHILIPS UCB1300" },
9544b86d33Such 	{ TC35413F_ID,	"TOSHIBA TC35413F" },
9644b86d33Such 	{ 0, 0 }
9744b86d33Such };
9844b86d33Such 
99ce3b031dSuch int
ucb1200_match(device_t parent,cfdata_t cf,void * aux)100cbab9cadSchs ucb1200_match(device_t parent, cfdata_t cf, void *aux)
101ce3b031dSuch {
102ce3b031dSuch 	struct txsib_attach_args *sa = aux;
103dce2bc94Such 	u_int16_t reg;
104ce3b031dSuch 
105ce3b031dSuch 	if (sa->sa_slot != 0) /* UCB1200 must be subframe 0 */
10658f851eeSuch 		return (0);
107dce2bc94Such 	reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG);
108ce3b031dSuch 
10944b86d33Such 	return (ucb1200_check_id(reg, 0));
110ce3b031dSuch }
111ce3b031dSuch 
112ce3b031dSuch void
ucb1200_attach(device_t parent,device_t self,void * aux)113cbab9cadSchs ucb1200_attach(device_t parent, device_t self, void *aux)
114ce3b031dSuch {
115ce3b031dSuch 	struct txsib_attach_args *sa = aux;
116cbab9cadSchs 	struct ucb1200_softc *sc = device_private(self);
11744b86d33Such 	u_int16_t reg;
118ce3b031dSuch 
11944b86d33Such 	printf(": ");
120ce3b031dSuch 	sc->sc_tc = sa->sa_tc;
121ce3b031dSuch 	sc->sc_parent = parent;
122dce2bc94Such 	sc->sc_snd_rate = sa->sa_snd_rate;
123dce2bc94Such 	sc->sc_tel_rate = sa->sa_tel_rate;
124ce3b031dSuch 
125dce2bc94Such 	tx39sib_enable1(sc->sc_parent);
126dce2bc94Such 	tx39sib_enable2(sc->sc_parent);
127ce3b031dSuch 
1287d170993Such #ifdef UCB1200_DEBUG
1297d170993Such 	if (ucb1200_debug)
130ce3b031dSuch 		ucb1200_dump(sc);
131ce3b031dSuch #endif
13244b86d33Such 	reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG);
13344b86d33Such 	(void)ucb1200_check_id(reg, 1);
134ce3b031dSuch 	printf("\n");
135ce3b031dSuch 
1362685996bSthorpej 	config_search(self, NULL,
137*c7fb772bSthorpej 	    CFARGS(.search = ucb1200_search));
138ce3b031dSuch }
139ce3b031dSuch 
140ce3b031dSuch int
ucb1200_search(device_t parent,cfdata_t cf,const int * ldesc,void * aux)141cbab9cadSchs ucb1200_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
142ce3b031dSuch {
143cbab9cadSchs 	struct ucb1200_softc *sc = device_private(parent);
144dce2bc94Such 	struct ucb1200_attach_args ucba;
145ce3b031dSuch 
146dce2bc94Such 	ucba.ucba_tc = sc->sc_tc;
147dce2bc94Such 	ucba.ucba_snd_rate = sc->sc_snd_rate;
148dce2bc94Such 	ucba.ucba_tel_rate = sc->sc_tel_rate;
149dce2bc94Such 	ucba.ucba_sib	   = sc->sc_parent;
150dce2bc94Such 	ucba.ucba_ucb	   = parent;
151ce3b031dSuch 
1522685996bSthorpej 	if (config_probe(parent, cf, &ucba))
153*c7fb772bSthorpej 		config_attach(parent, cf, &ucba, ucb1200_print, CFARGS_NONE);
154ce3b031dSuch 
15558f851eeSuch 	return (0);
156ce3b031dSuch }
157ce3b031dSuch 
158ce3b031dSuch int
ucb1200_print(void * aux,const char * pnp)159fc9212e5Such ucb1200_print(void *aux, const char *pnp)
160ce3b031dSuch {
16158f851eeSuch 
16258f851eeSuch 	return (pnp ? QUIET : UNCONF);
163ce3b031dSuch }
164ce3b031dSuch 
16544b86d33Such int
ucb1200_check_id(u_int16_t idreg,int print)166fc9212e5Such ucb1200_check_id(u_int16_t idreg, int print)
16744b86d33Such {
16844b86d33Such 	int i;
16944b86d33Such 
17044b86d33Such 	for (i = 0; ucb_id[i].product; i++) {
17144b86d33Such 		if (ucb_id[i].id == idreg) {
17244b86d33Such 			if (print) {
17344b86d33Such 				printf("%s", ucb_id[i].product);
17444b86d33Such 			}
17544b86d33Such 
17644b86d33Such 			return (1);
17744b86d33Such 		}
17844b86d33Such 	}
17944b86d33Such 
18058f851eeSuch 	return (0);
18144b86d33Such }
18244b86d33Such 
183ce3b031dSuch void
ucb1200_state_install(device_t dev,int (* sfun)(void *),void * sarg,int sid)184cbab9cadSchs ucb1200_state_install(device_t dev, int (*sfun)(void *), void *sarg,
185fc9212e5Such     int sid)
186ce3b031dSuch {
187cbab9cadSchs 	struct ucb1200_softc *sc = device_private(dev);
188dce2bc94Such 
189dce2bc94Such 	sc->sc_child[sid].cs_busy = sfun;
190dce2bc94Such 	sc->sc_child[sid].cs_arg = sarg;
191ce3b031dSuch }
192ce3b031dSuch 
193ce3b031dSuch int
ucb1200_state_idle(device_t dev)194cbab9cadSchs ucb1200_state_idle(device_t dev)
195ce3b031dSuch {
196cbab9cadSchs 	struct ucb1200_softc *sc = device_private(dev);
197dce2bc94Such 	struct ucbchild_state *cs;
198dce2bc94Such 	int i;
199dce2bc94Such 
200dce2bc94Such 	cs = sc->sc_child;
201dce2bc94Such 	for (i = 0; i < UCB1200_MODULE_MAX; i++, cs++)
202dce2bc94Such 		if (cs->cs_busy)
203dce2bc94Such 			if ((*cs->cs_busy)(cs->cs_arg))
20458f851eeSuch 				return (0);
205dce2bc94Such 
20658f851eeSuch 	return (1); /* idle state */
207ce3b031dSuch }
208ce3b031dSuch 
2097d170993Such #ifdef UCB1200_DEBUG
210ce3b031dSuch void
ucb1200_dump(struct ucb1200_softc * sc)211fc9212e5Such ucb1200_dump(struct ucb1200_softc *sc)
212ce3b031dSuch {
213560a78f6Syamt 	static const char *const regname[] = {
214ce3b031dSuch                 "IO_DATA        ",
215ce3b031dSuch                 "IO_DIR         ",
216ce3b031dSuch                 "POSINTEN       ",
217ce3b031dSuch                 "NEGINTEN       ",
218ce3b031dSuch                 "INTSTAT        ",
219ce3b031dSuch                 "TELECOMCTRLA   ",
220ce3b031dSuch                 "TELECOMCTRLB   ",
221ce3b031dSuch                 "AUDIOCTRLA     ",
222ce3b031dSuch                 "AUDIOCTRLB     ",
223ce3b031dSuch                 "TOUCHSCREENCTRL",
224ce3b031dSuch                 "ADCCTRL        ",
225ce3b031dSuch                 "ADCDATA        ",
226ce3b031dSuch                 "ID             ",
227ce3b031dSuch                 "MODE           ",
228ce3b031dSuch                 "RESERVED       ",
229ce3b031dSuch                 "NULL           "
230ce3b031dSuch 	};
231fc9212e5Such 	tx_chipset_tag_t tc;
232ce3b031dSuch 	u_int16_t reg;
233ce3b031dSuch 	int i;
234ce3b031dSuch 
235fc9212e5Such 	tc = sc->sc_tc;
236fc9212e5Such 
237dce2bc94Such 	printf("\n\t[UCB1200 register]\n");
238ce3b031dSuch 	for (i = 0; i < 16; i++) {
239ce3b031dSuch 		reg = txsibsf0_reg_read(tc, i);
240ce3b031dSuch 		printf("%s(%02d) 0x%04x ", regname[i], i, reg);
2417d170993Such 		dbg_bit_print(reg);
242ce3b031dSuch 	}
243ce3b031dSuch }
2447d170993Such #endif /* UCB1200_DEBUG */
245