Home | History | Annotate | Line # | Download | only in sa11x0
sa1111.c revision 1.10
      1  1.10     lukem /*      $NetBSD: sa1111.c,v 1.10 2003/07/15 00:24:50 lukem Exp $	*/
      2   1.1       rjs 
      3   1.1       rjs /*-
      4   1.1       rjs  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5   1.1       rjs  * All rights reserved.
      6   1.1       rjs  *
      7   1.1       rjs  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1       rjs  * by IWAMOTO Toshihiro.
      9   1.1       rjs  *
     10   1.1       rjs  * Redistribution and use in source and binary forms, with or without
     11   1.1       rjs  * modification, are permitted provided that the following conditions
     12   1.1       rjs  * are met:
     13   1.1       rjs  * 1. Redistributions of source code must retain the above copyright
     14   1.1       rjs  *    notice, this list of conditions and the following disclaimer.
     15   1.1       rjs  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       rjs  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       rjs  *    documentation and/or other materials provided with the distribution.
     18   1.1       rjs  * 3. All advertising materials mentioning features or use of this software
     19   1.1       rjs  *    must display the following acknowledgement:
     20   1.1       rjs  *        This product includes software developed by the NetBSD
     21   1.1       rjs  *        Foundation, Inc. and its contributors.
     22   1.1       rjs  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1       rjs  *    contributors may be used to endorse or promote products derived
     24   1.1       rjs  *    from this software without specific prior written permission.
     25   1.1       rjs  *
     26   1.1       rjs  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1       rjs  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1       rjs  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1       rjs  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1       rjs  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1       rjs  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1       rjs  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1       rjs  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1       rjs  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1       rjs  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1       rjs  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1       rjs  */
     38   1.1       rjs 
     39   1.1       rjs /*
     40   1.1       rjs  * TODO:
     41   1.1       rjs  *   - separate machine specific attach code
     42   1.1       rjs  *   - introduce bus abstraction to support SA1101
     43   1.1       rjs  */
     44  1.10     lukem 
     45  1.10     lukem #include <sys/cdefs.h>
     46  1.10     lukem __KERNEL_RCSID(0, "$NetBSD: sa1111.c,v 1.10 2003/07/15 00:24:50 lukem Exp $");
     47   1.1       rjs 
     48   1.1       rjs #include <sys/param.h>
     49   1.1       rjs #include <sys/systm.h>
     50   1.1       rjs #include <sys/types.h>
     51   1.1       rjs #include <sys/conf.h>
     52   1.1       rjs #include <sys/device.h>
     53   1.1       rjs #include <sys/kernel.h>
     54   1.1       rjs #include <sys/malloc.h>
     55   1.1       rjs #include <sys/uio.h>
     56   1.1       rjs 
     57   1.1       rjs #include <machine/bus.h>
     58   1.1       rjs #ifdef hpcarm
     59   1.1       rjs #include <machine/platid.h>
     60   1.1       rjs #include <machine/platid_mask.h>
     61   1.1       rjs #endif
     62   1.1       rjs 
     63   1.1       rjs #include <arm/sa11x0/sa11x0_reg.h>
     64   1.1       rjs #include <arm/sa11x0/sa11x0_var.h>
     65   1.1       rjs #include <arm/sa11x0/sa11x0_gpioreg.h>
     66   1.1       rjs #include <arm/sa11x0/sa1111_reg.h>
     67   1.1       rjs #include <arm/sa11x0/sa1111_var.h>
     68   1.1       rjs 
     69   1.2       rjs static	int	sacc_probe(struct device *, struct cfdata *, void *);
     70   1.1       rjs static	void	sacc_attach(struct device *, struct device *, void *);
     71   1.1       rjs static	int	sa1111_search(struct device *, struct cfdata *, void *);
     72   1.1       rjs static	int	sa1111_print(void *, const char *);
     73   1.1       rjs 
     74   1.1       rjs static void	sacc_intr_calculatemasks(struct sacc_softc *);
     75   1.1       rjs static void	sacc_intr_setpolarity(sacc_chipset_tag_t *, int , int);
     76   1.1       rjs int		sacc_intr(void *);
     77   1.1       rjs 
     78   1.4    ichiro #ifndef hpcarm
     79   1.1       rjs void *softintr_establish(int, int (*)(void *), void *);
     80   1.1       rjs void softintr_schedule(void *);
     81   1.1       rjs #endif
     82   1.1       rjs 
     83   1.1       rjs #ifdef hpcarm
     84   1.1       rjs struct platid_data sacc_platid_table[] = {
     85   1.1       rjs 	{ &platid_mask_MACH_HP_JORNADA_720, (void *)1 },
     86   1.1       rjs 	{ &platid_mask_MACH_HP_JORNADA_720JP, (void *)1 },
     87   1.1       rjs 	{ NULL, NULL }
     88   1.1       rjs };
     89   1.1       rjs #endif
     90   1.1       rjs 
     91   1.9   thorpej CFATTACH_DECL(sacc, sizeof(struct sacc_softc),
     92   1.9   thorpej     sacc_probe, sacc_attach, NULL, NULL);
     93   1.1       rjs 
     94   1.1       rjs #ifdef INTR_DEBUG
     95   1.1       rjs #define DPRINTF(arg)	printf arg
     96   1.1       rjs #else
     97   1.1       rjs #define DPRINTF(arg)
     98   1.1       rjs #endif
     99   1.1       rjs 
    100   1.1       rjs static int
    101   1.2       rjs sacc_probe(parent, match, aux)
    102   1.1       rjs 	struct device *parent;
    103   1.1       rjs 	struct cfdata *match;
    104   1.1       rjs 	void *aux;
    105   1.1       rjs {
    106   1.2       rjs 	struct sa11x0_attach_args *sa = aux;
    107   1.2       rjs 	bus_space_handle_t ioh;
    108   1.2       rjs 	u_int32_t skid;
    109   1.2       rjs 
    110   1.2       rjs 	if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &ioh))
    111   1.2       rjs 		return (0);
    112   1.2       rjs 
    113   1.2       rjs 	skid = bus_space_read_4(sa->sa_iot, ioh, SACCSBI_SKID);
    114   1.2       rjs 	bus_space_unmap(sa->sa_iot, ioh, sa->sa_size);
    115   1.2       rjs 
    116   1.2       rjs 	if ((skid & 0xffffff00) != 0x690cc200)
    117   1.2       rjs 		return (0);
    118   1.2       rjs 
    119   1.1       rjs 	return (1);
    120   1.1       rjs }
    121   1.1       rjs 
    122   1.1       rjs static void
    123   1.1       rjs sacc_attach(parent, self, aux)
    124   1.1       rjs 	struct device *parent;
    125   1.1       rjs 	struct device *self;
    126   1.1       rjs 	void *aux;
    127   1.1       rjs {
    128   1.1       rjs 	int i, gpiopin;
    129   1.2       rjs 	u_int32_t skid;
    130   1.1       rjs 	struct sacc_softc *sc = (struct sacc_softc *)self;
    131   1.1       rjs 	struct sa11x0_softc *psc = (struct sa11x0_softc *)parent;
    132   1.1       rjs 	struct sa11x0_attach_args *sa = aux;
    133   1.1       rjs #ifdef hpcarm
    134   1.1       rjs 	struct platid_data *p;
    135   1.1       rjs #endif
    136   1.1       rjs 
    137   1.2       rjs 	printf("\n");
    138   1.2       rjs 
    139   1.1       rjs 	sc->sc_iot = sa->sa_iot;
    140   1.1       rjs 	sc->sc_piot = psc->sc_iot;
    141   1.1       rjs 	sc->sc_gpioh = psc->sc_gpioh;
    142   1.1       rjs #ifdef hpcarm
    143   1.3  takemura 	if ((p = platid_search_data(&platid, sacc_platid_table)) == NULL)
    144   1.1       rjs 		return;
    145   1.1       rjs 
    146   1.2       rjs 	gpiopin = (int) p->data;
    147   1.1       rjs #else
    148   1.1       rjs 	gpiopin = sa->sa_gpio;
    149   1.1       rjs #endif
    150   1.1       rjs 	sc->sc_gpiomask = 1 << gpiopin;
    151   1.1       rjs 
    152   1.1       rjs 	if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0,
    153   1.1       rjs 			  &sc->sc_ioh)) {
    154   1.1       rjs 		printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
    155   1.1       rjs 		return;
    156   1.1       rjs 	}
    157   1.1       rjs 
    158   1.2       rjs 	skid = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCSBI_SKID);
    159   1.2       rjs 
    160   1.2       rjs 	printf("%s: SA1111 rev %d.%d\n", sc->sc_dev.dv_xname,
    161   1.2       rjs 	       (skid & 0xf0) >> 3, skid & 0xf);
    162   1.2       rjs 
    163   1.1       rjs 	for(i = 0; i < SACCIC_LEN; i++)
    164   1.1       rjs 		sc->sc_intrhand[i] = NULL;
    165   1.1       rjs 
    166   1.1       rjs 	/* initialize SA1111 interrupt controller */
    167   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN0, 0);
    168   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN1, 0);
    169   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTTSTSEL, 0);
    170   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    171   1.1       rjs 			  SACCIC_INTSTATCLR0, 0xffffffff);
    172   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    173   1.1       rjs 			  SACCIC_INTSTATCLR1, 0xffffffff);
    174   1.1       rjs 
    175   1.1       rjs 	/* connect to SA1110's GPIO intr */
    176   1.1       rjs 	sa11x0_intr_establish(0, gpiopin, 1, IPL_SERIAL, sacc_intr, sc);
    177   1.1       rjs 
    178   1.1       rjs 	/*
    179   1.1       rjs 	 *  Attach each devices
    180   1.1       rjs 	 */
    181   1.2       rjs 	config_search(sa1111_search, self, NULL);
    182   1.1       rjs }
    183   1.1       rjs 
    184   1.1       rjs static int
    185   1.1       rjs sa1111_search(parent, cf, aux)
    186   1.1       rjs 	struct device *parent;
    187   1.1       rjs 	struct cfdata *cf;
    188   1.1       rjs 	void *aux;
    189   1.1       rjs {
    190   1.6   thorpej         if (config_match(parent, cf, NULL) > 0)
    191   1.1       rjs                 config_attach(parent, cf, NULL, sa1111_print);
    192   1.1       rjs 
    193   1.1       rjs         return 0;
    194   1.1       rjs }
    195   1.1       rjs 
    196   1.1       rjs static int
    197   1.1       rjs sa1111_print(aux, name)
    198   1.1       rjs 	void *aux;
    199   1.1       rjs 	const char *name;
    200   1.1       rjs {
    201   1.1       rjs 	return (UNCONF);
    202   1.1       rjs }
    203   1.1       rjs 
    204   1.1       rjs int
    205   1.1       rjs sacc_intr(arg)
    206   1.1       rjs 	void *arg;
    207   1.1       rjs {
    208   1.1       rjs 	int i;
    209   1.1       rjs 	u_int32_t mask;
    210   1.1       rjs 	struct sacc_intrvec intstat;
    211   1.1       rjs 	struct sacc_softc *sc = arg;
    212   1.1       rjs #ifdef hpcarm
    213   1.1       rjs 	struct sacc_intrhand *ih;
    214   1.1       rjs #endif
    215   1.1       rjs 
    216   1.1       rjs 	intstat.lo =
    217   1.1       rjs 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR0);
    218   1.1       rjs 	intstat.hi =
    219   1.1       rjs 	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR1);
    220   1.1       rjs 	DPRINTF(("sacc_intr_dispatch: %x %x\n", intstat.lo, intstat.hi));
    221   1.1       rjs 
    222   1.5       rjs 	/* clear SA1110's GPIO intr status */
    223   1.5       rjs 	bus_space_write_4(sc->sc_piot, sc->sc_gpioh,
    224   1.5       rjs 			  SAGPIO_EDR, sc->sc_gpiomask);
    225   1.5       rjs 
    226   1.1       rjs 	for(i = 0, mask = 1; i < 32; i++, mask <<= 1)
    227   1.1       rjs 		if (intstat.lo & mask) {
    228   1.1       rjs 			/*
    229   1.1       rjs 			 * Clear intr status before calling intr handlers.
    230   1.1       rjs 			 * This cause stray interrupts, but clearing
    231   1.1       rjs 			 * after calling intr handlers cause intr lossage.
    232   1.1       rjs 			 */
    233   1.1       rjs 			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    234   1.1       rjs 					  SACCIC_INTSTATCLR0, 1 << i);
    235   1.1       rjs 
    236   1.1       rjs #ifdef hpcarm
    237   1.1       rjs 			for(ih = sc->sc_intrhand[i]; ih; ih = ih->ih_next)
    238   1.1       rjs 				softintr_schedule(ih->ih_soft);
    239   1.1       rjs #endif
    240   1.1       rjs 		}
    241   1.1       rjs 	for(i = 0, mask = 1; i < SACCIC_LEN - 32; i++, mask <<= 1)
    242   1.1       rjs 		if (intstat.hi & mask) {
    243   1.1       rjs 			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    244   1.1       rjs 					  SACCIC_INTSTATCLR1, 1 << i);
    245   1.1       rjs #ifdef hpcarm
    246   1.1       rjs 			for(ih = sc->sc_intrhand[i + 32]; ih; ih = ih->ih_next)
    247   1.1       rjs 				softintr_schedule(ih->ih_soft);
    248   1.1       rjs #endif
    249   1.1       rjs 		}
    250   1.1       rjs 	return 1;
    251   1.1       rjs }
    252   1.1       rjs 
    253   1.1       rjs void *
    254   1.1       rjs sacc_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
    255   1.1       rjs 	sacc_chipset_tag_t *ic;
    256   1.1       rjs 	int irq, type, level;
    257   1.1       rjs 	int (*ih_fun)(void *);
    258   1.1       rjs 	void *ih_arg;
    259   1.1       rjs {
    260   1.1       rjs 	int s;
    261   1.1       rjs 	struct sacc_softc *sc = (struct sacc_softc *)ic;
    262   1.1       rjs 	struct sacc_intrhand **p, *ih;
    263   1.1       rjs 
    264   1.1       rjs 	/* no point in sleeping unless someone can free memory. */
    265   1.1       rjs 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    266   1.1       rjs 	if (ih == NULL)
    267   1.1       rjs 		panic("sacc_intr_establish: can't malloc handler info");
    268   1.1       rjs 
    269   1.1       rjs 	if (irq < 0 || irq > SACCIC_LEN ||
    270   1.1       rjs 	    ! (type == IST_EDGE_RAISE || type == IST_EDGE_FALL))
    271   1.1       rjs 		panic("sacc_intr_establish: bogus irq or type");
    272   1.1       rjs 
    273   1.1       rjs 	if (sc->sc_intrhand[irq] == NULL) {
    274   1.1       rjs 		sacc_intr_setpolarity(ic, irq, type);
    275   1.1       rjs 		sc->sc_intrtype[irq] = type;
    276   1.1       rjs 	} else if (sc->sc_intrtype[irq] != type)
    277   1.1       rjs 		/* XXX we should be able to share raising and
    278   1.1       rjs 		 * falling edge intrs */
    279   1.7    provos 		panic("sacc_intr_establish: type must be unique");
    280   1.1       rjs 
    281   1.1       rjs 	/* install intr handler */
    282   1.1       rjs #ifdef hpcarm
    283   1.1       rjs 	ih->ih_soft = softintr_establish(level, (void (*)(void *)) ih_fun,
    284   1.1       rjs 					 ih_arg);
    285   1.1       rjs #endif
    286   1.1       rjs 	ih->ih_irq = irq;
    287   1.1       rjs 	ih->ih_next = NULL;
    288   1.1       rjs 
    289   1.1       rjs 	s = splhigh();
    290   1.1       rjs 	for(p = &sc->sc_intrhand[irq]; *p; p = &(*p)->ih_next)
    291   1.1       rjs 		;
    292   1.1       rjs 
    293   1.1       rjs 	*p = ih;
    294   1.1       rjs 
    295   1.1       rjs 	sacc_intr_calculatemasks(sc);
    296   1.1       rjs 	splx(s);
    297   1.1       rjs 
    298   1.1       rjs 	return(ih);
    299   1.1       rjs }
    300   1.1       rjs 
    301   1.1       rjs void
    302   1.1       rjs sacc_intr_disestablish(ic, arg)
    303   1.1       rjs 	sacc_chipset_tag_t *ic;
    304   1.1       rjs 	void *arg;
    305   1.1       rjs {
    306   1.1       rjs 	int irq, s;
    307   1.1       rjs 	struct sacc_softc *sc = (struct sacc_softc *)ic;
    308   1.1       rjs 	struct sacc_intrhand *ih, **p;
    309   1.1       rjs 
    310   1.1       rjs 	ih = (struct sacc_intrhand *)arg;
    311   1.1       rjs 	irq = ih->ih_irq;
    312   1.1       rjs 
    313   1.1       rjs #ifdef DIAGNOSTIC
    314   1.1       rjs 	if (irq < 0 || irq > SACCIC_LEN)
    315   1.1       rjs 		panic("sacc_intr_disestablish: bogus irq");
    316   1.1       rjs #endif
    317   1.1       rjs 
    318   1.1       rjs 	s = splhigh();
    319   1.1       rjs 
    320   1.1       rjs 	for(p = &sc->sc_intrhand[irq];; p = &(*p)->ih_next) {
    321   1.1       rjs 		if (*p == NULL)
    322   1.1       rjs 			panic("sacc_intr_disestablish: handler not registered");
    323   1.1       rjs 		if (*p == ih)
    324   1.1       rjs 			break;
    325   1.1       rjs 	}
    326   1.1       rjs 	*p = (*p)->ih_next;
    327   1.1       rjs 
    328   1.1       rjs 	sacc_intr_calculatemasks(sc);
    329   1.1       rjs 	splx(s);
    330   1.1       rjs 
    331   1.1       rjs 	free(ih, M_DEVBUF);
    332   1.1       rjs }
    333   1.1       rjs 
    334   1.1       rjs void
    335   1.1       rjs sacc_intr_setpolarity(ic, irq, type)
    336   1.1       rjs 	sacc_chipset_tag_t *ic;
    337   1.1       rjs 	int irq;
    338   1.1       rjs 	int type;
    339   1.1       rjs {
    340   1.1       rjs 	struct sacc_softc *sc = (struct sacc_softc *)ic;
    341   1.1       rjs 	int s;
    342   1.1       rjs 	u_int32_t pol, mask;
    343   1.1       rjs 	int addr;
    344   1.1       rjs 
    345   1.1       rjs 	if (irq >= 32) {
    346   1.1       rjs 		addr = SACCIC_INTPOL1;
    347   1.1       rjs 		irq -= 32;
    348   1.1       rjs 	} else
    349   1.1       rjs 		addr = SACCIC_INTPOL0;
    350   1.1       rjs 
    351   1.1       rjs 	mask = (1 << irq);
    352   1.1       rjs 
    353   1.1       rjs 	s = splhigh();
    354   1.1       rjs 	pol = bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr);
    355   1.1       rjs 	if (type == IST_EDGE_RAISE)
    356   1.1       rjs 		pol &= ~mask;
    357   1.1       rjs 	else
    358   1.1       rjs 		pol |= mask;
    359   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, pol);
    360   1.1       rjs 	splx(s);
    361   1.1       rjs }
    362   1.1       rjs 
    363   1.1       rjs void
    364   1.1       rjs sacc_intr_calculatemasks(sc)
    365   1.1       rjs 	struct sacc_softc *sc;
    366   1.1       rjs {
    367   1.1       rjs 	int irq;
    368   1.1       rjs 
    369   1.1       rjs 	sc->sc_imask.lo = 0;
    370   1.1       rjs 	sc->sc_imask.hi = 0;
    371   1.1       rjs 	for(irq = 0; irq < 32; irq++)
    372   1.1       rjs 		if (sc->sc_intrhand[irq])
    373   1.1       rjs 			sc->sc_imask.lo |= (1 << irq);
    374   1.1       rjs 	for(irq = 0; irq < SACCIC_LEN - 32; irq++)
    375   1.1       rjs 		if (sc->sc_intrhand[irq + 32])
    376   1.1       rjs 			sc->sc_imask.hi |= (1 << irq);
    377   1.1       rjs 
    378   1.1       rjs 
    379   1.1       rjs 	/* XXX this should not be done here */
    380   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN0,
    381   1.1       rjs 			  sc->sc_imask.lo);
    382   1.1       rjs 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN1,
    383   1.1       rjs 			  sc->sc_imask.hi);
    384   1.1       rjs 	DPRINTF(("sacc_intr_calculatemasks: %x %x\n", sc->sc_imask.lo,
    385   1.1       rjs 	    sc->sc_imask.hi));
    386   1.1       rjs }
    387