Home | History | Annotate | Line # | Download | only in dev
ucb1200.c revision 1.5
      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