Home | History | Annotate | Line # | Download | only in g42xxeb
      1   1.1      bsh /*
      2   1.1      bsh  * Copyright (c) 2002, 2003, 2005  Genetec corp.  All rights reserved.
      3   1.1      bsh  *
      4   1.1      bsh  * PCMCIA/CF support for TWINTAIL (G4255EB)
      5   1.1      bsh  * Written by Hiroyuki Bessho for Genetec corp.
      6   1.1      bsh  *
      7   1.1      bsh  * Redistribution and use in source and binary forms, with or without
      8   1.1      bsh  * modification, are permitted provided that the following conditions
      9   1.1      bsh  * are met:
     10   1.1      bsh  * 1. Redistributions of source code must retain the above copyright
     11   1.1      bsh  *    notice, this list of conditions and the following disclaimer.
     12   1.1      bsh  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      bsh  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      bsh  *    documentation and/or other materials provided with the distribution.
     15   1.1      bsh  * 3. The name of Genetec corp. may not be used to endorse
     16   1.1      bsh  *    or promote products derived from this software without specific prior
     17   1.1      bsh  *    written permission.
     18   1.1      bsh  *
     19   1.1      bsh  * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
     20   1.1      bsh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1      bsh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1      bsh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORP.
     23   1.1      bsh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1      bsh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1      bsh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1      bsh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1      bsh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1      bsh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1      bsh  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1      bsh  */
     31   1.1      bsh 
     32   1.1      bsh #include <sys/types.h>
     33   1.1      bsh #include <sys/param.h>
     34   1.1      bsh #include <sys/systm.h>
     35   1.1      bsh #include <sys/device.h>
     36   1.1      bsh #include <sys/callout.h>
     37   1.1      bsh #include <sys/kernel.h>
     38   1.1      bsh #include <sys/kthread.h>
     39   1.1      bsh #include <uvm/uvm.h>
     40   1.1      bsh 
     41  1.11   dyoung #include <sys/bus.h>
     42   1.1      bsh #include <machine/intr.h>
     43   1.1      bsh 
     44   1.1      bsh #include <dev/pcmcia/pcmciareg.h>
     45   1.1      bsh #include <dev/pcmcia/pcmciavar.h>
     46   1.1      bsh #include <dev/pcmcia/pcmciachip.h>
     47   1.1      bsh 
     48   1.1      bsh #include <arch/arm/xscale/pxa2x0var.h>
     49   1.1      bsh #include <arch/arm/xscale/pxa2x0reg.h>
     50   1.1      bsh #include <arch/arm/sa11x0/sa11xx_pcicvar.h>
     51   1.1      bsh #include <arch/evbarm/g42xxeb/g42xxeb_reg.h>
     52   1.1      bsh #include <arch/evbarm/g42xxeb/g42xxeb_var.h>
     53   1.1      bsh #include <arch/evbarm/g42xxeb/gb225reg.h>
     54   1.1      bsh #include <arch/evbarm/g42xxeb/gb225var.h>
     55   1.1      bsh 
     56   1.1      bsh 
     57   1.1      bsh //#define DONT_USE_CARD_DETECT_INTR
     58   1.1      bsh 
     59   1.1      bsh #define PCMCIA_INT	G42XXEB_INT_EXT1
     60   1.1      bsh #define CF_INT     	G42XXEB_INT_EXT0
     61   1.1      bsh 
     62   1.1      bsh #ifdef DEBUG
     63   1.1      bsh #define DPRINTF(arg)	printf arg
     64   1.1      bsh #else
     65   1.1      bsh #define DPRINTF(arg)
     66   1.1      bsh #endif
     67   1.1      bsh 
     68   1.1      bsh struct opcic_softc;
     69   1.1      bsh 
     70   1.1      bsh struct opcic_socket {
     71   1.1      bsh 	struct sapcic_socket ss;	/* inherit socket for sa11x0 pcic */
     72   1.1      bsh 
     73   1.1      bsh #if 0
     74   1.1      bsh 	int voltage;			/* card power voltage selected by
     75   1.1      bsh 					   upper layer */
     76   1.1      bsh #endif
     77   1.1      bsh };
     78   1.1      bsh 
     79   1.1      bsh struct opcic_softc {
     80   1.1      bsh 	struct sapcic_softc sc_pc;	/* inherit SA11xx pcic */
     81   1.1      bsh 
     82   1.1      bsh 	struct opcic_socket sc_socket[2];
     83   1.1      bsh 	int sc_cards;
     84   1.1      bsh 	bus_space_handle_t sc_memctl_ioh;
     85   1.1      bsh };
     86   1.1      bsh 
     87  1.13      chs static int  	opcic_match(device_t, cfdata_t, void *);
     88  1.13      chs static void  	opcic_attach(device_t, device_t, void *);
     89   1.1      bsh static int 	opcic_print(void *, const char *);
     90   1.1      bsh 
     91   1.1      bsh static	int	opcic_read(struct sapcic_socket *, int);
     92   1.1      bsh static	void	opcic_write(struct sapcic_socket *, int, int);
     93   1.1      bsh static	void	opcic_set_power(struct sapcic_socket *, int);
     94   1.1      bsh static	void	opcic_clear_intr(int);
     95   1.1      bsh static	void	*opcic_intr_establish(struct sapcic_socket *, int,
     96   1.1      bsh 				       int (*)(void *), void *);
     97   1.1      bsh static	void	opcic_intr_disestablish(struct sapcic_socket *, void *);
     98   1.1      bsh #ifndef DONT_USE_CARD_DETECT_INTR
     99   1.1      bsh static	int	opcic_card_detect(void *, int);
    100   1.1      bsh #endif
    101   1.1      bsh 
    102  1.13      chs CFATTACH_DECL_NEW(opcic, sizeof(struct opcic_softc),
    103   1.1      bsh     opcic_match, opcic_attach, NULL, NULL);
    104   1.1      bsh 
    105   1.1      bsh static struct sapcic_tag opcic_tag = {
    106   1.1      bsh 	opcic_read,
    107   1.1      bsh 	opcic_write,
    108   1.1      bsh 	opcic_set_power,
    109   1.1      bsh 	opcic_clear_intr,
    110   1.1      bsh 	opcic_intr_establish,
    111   1.1      bsh 	opcic_intr_disestablish,
    112   1.1      bsh };
    113   1.1      bsh 
    114   1.1      bsh 
    115   1.1      bsh #define HAVE_CARD(r)	(((r)&CARDDET_DET)==0)
    116   1.1      bsh 
    117   1.3    perry static inline uint8_t
    118   1.1      bsh opcic_read_card_status(struct opcic_socket *so)
    119   1.1      bsh {
    120   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)(so->ss.sc);
    121   1.1      bsh 	struct opio_softc *osc =
    122   1.8       he 	    device_private(device_parent(sc->sc_pc.sc_dev));
    123   1.1      bsh 
    124   1.1      bsh 	return bus_space_read_1(osc->sc_iot, osc->sc_ioh,
    125   1.1      bsh 	    GB225_CFDET + 2 * so->ss.socket);
    126   1.1      bsh 
    127   1.1      bsh }
    128   1.1      bsh 
    129   1.1      bsh static int
    130  1.13      chs opcic_match(device_t parent, cfdata_t cf, void *aux)
    131   1.1      bsh {
    132   1.1      bsh 	return	1;
    133   1.1      bsh }
    134   1.1      bsh 
    135   1.1      bsh static void
    136  1.13      chs opcic_attach(device_t parent, device_t self, void *aux)
    137   1.1      bsh {
    138   1.1      bsh 	int i;
    139   1.1      bsh 	struct pcmciabus_attach_args paa;
    140  1.13      chs 	struct opcic_softc *sc = device_private(self);
    141  1.13      chs 	struct opio_softc *psc = device_private(parent);
    142  1.13      chs 	struct obio_softc *bsd = device_private(device_parent(parent));
    143   1.5       he 	bus_space_handle_t memctl_ioh = bsd->sc_memctl_ioh;
    144   1.1      bsh 	bus_space_tag_t iot =  psc->sc_iot;
    145   1.1      bsh 
    146   1.1      bsh 	printf("\n");
    147   1.1      bsh 
    148   1.1      bsh 	/* tell PXA2X0 that we have two sockets */
    149   1.1      bsh #if 0
    150   1.1      bsh 	bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR, MECR_NOS);
    151   1.1      bsh #else
    152   1.1      bsh 	bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR, MECR_CIT|MECR_NOS);
    153   1.1      bsh #endif
    154   1.1      bsh 	sc->sc_pc.sc_iot = psc->sc_iot;
    155   1.1      bsh 	sc->sc_memctl_ioh = memctl_ioh;
    156   1.1      bsh 
    157   1.1      bsh 	sc->sc_cards = 0;
    158   1.1      bsh 
    159   1.1      bsh 	for(i = 0; i < 2; i++) {
    160   1.1      bsh 		sc->sc_socket[i].ss.sc = &sc->sc_pc;
    161   1.1      bsh 		sc->sc_socket[i].ss.socket = i;
    162   1.1      bsh 		sc->sc_socket[i].ss.pcictag_cookie = NULL;
    163   1.1      bsh 		sc->sc_socket[i].ss.pcictag = &opcic_tag;
    164   1.1      bsh 		sc->sc_socket[i].ss.event_thread = NULL;
    165   1.1      bsh 		sc->sc_socket[i].ss.event = 0;
    166   1.1      bsh 		sc->sc_socket[i].ss.laststatus = CARDDET_NOCARD;
    167   1.1      bsh 		sc->sc_socket[i].ss.shutdown = 0;
    168   1.1      bsh 
    169   1.1      bsh 		sc->sc_socket[i].ss.power_capability =
    170   1.1      bsh 		    (SAPCIC_POWER_5V|SAPCIC_POWER_3V);
    171   1.1      bsh 
    172   1.1      bsh 		bus_space_write_4(iot, memctl_ioh, MEMCTL_MCIO(i),
    173   1.1      bsh 		    MC_TIMING_VAL(1,1,1));
    174   1.1      bsh #if 0
    175   1.1      bsh 		bus_space_write_4(iot, memctl_ioh, MEMCTL_MCATT(i),
    176   1.1      bsh 		    MC_TIMING_VAL(31,31,31));
    177   1.1      bsh #endif
    178   1.1      bsh 
    179   1.1      bsh 		paa.paa_busname = "pcmcia";
    180   1.1      bsh 		paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions;
    181   1.1      bsh 		paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i].ss;
    182   1.1      bsh 
    183   1.1      bsh 		sc->sc_socket[i].ss.pcmcia =
    184  1.14  thorpej 		    config_found(sc->sc_pc.sc_dev, &paa, opcic_print,
    185  1.15  thorpej 				 CFARGS_NONE);
    186   1.1      bsh 
    187   1.1      bsh #ifndef DONT_USE_CARD_DETECT_INTR
    188   1.1      bsh 		/* interrupt for card insertion/removal */
    189   1.1      bsh 		opio_intr_establish(psc,
    190   1.1      bsh 		    i==0 ? OPIO_INTR_CF_INSERT : OPIO_INTR_PCMCIA_INSERT,
    191   1.1      bsh 		    IPL_BIO, opcic_card_detect, &sc->sc_socket[i]);
    192   1.1      bsh #else
    193   1.1      bsh 		bus_space_write_4(iot, ioh, MEMCTL_MECR, MECR_NOS | MECR_CIT);
    194   1.1      bsh 
    195   1.1      bsh #endif
    196   1.1      bsh 
    197   1.1      bsh 		/* schedule kthread creation */
    198   1.6       ad 		sapcic_kthread_create(&sc->sc_socket[i].ss);
    199   1.1      bsh 	}
    200   1.1      bsh 
    201   1.1      bsh }
    202   1.1      bsh 
    203   1.1      bsh static int
    204   1.1      bsh opcic_print(void *aux, const char *name)
    205   1.1      bsh {
    206   1.1      bsh 	return (UNCONF);
    207   1.1      bsh }
    208   1.1      bsh 
    209   1.1      bsh #ifndef DONT_USE_CARD_DETECT_INTR
    210   1.1      bsh static int
    211   1.1      bsh opcic_card_detect(void *arg, int val)
    212   1.1      bsh {
    213   1.1      bsh 	struct opcic_socket *socket = arg;
    214   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)socket->ss.sc;
    215   1.1      bsh 	bus_space_tag_t iot = sc->sc_pc.sc_iot;
    216   1.1      bsh 	bus_space_handle_t memctl_ioh = sc->sc_memctl_ioh;
    217   1.1      bsh 	int sock_no = socket->ss.socket;
    218   1.1      bsh 	int last, s;
    219   1.1      bsh 
    220   1.1      bsh 	s = splbio();
    221   1.1      bsh 	last = sc->sc_cards;
    222   1.1      bsh 	if (HAVE_CARD(val)) {
    223   1.1      bsh 		sc->sc_cards |= 1<<sock_no;
    224   1.1      bsh 		/* if it is the first card, turn on expansion memory
    225   1.1      bsh 		 * control. */
    226   1.1      bsh 		if (last == 0)
    227   1.1      bsh 			bus_space_write_4(iot, memctl_ioh, MEMCTL_MECR,
    228   1.1      bsh 			    MECR_NOS | MECR_CIT);
    229   1.1      bsh 	}
    230   1.1      bsh 	else {
    231   1.1      bsh 		sc->sc_cards &= ~(1<<sock_no);
    232   1.1      bsh 		/* if we loast all cards, turn off expansion memory
    233   1.1      bsh 		 * control. */
    234   1.1      bsh #if 0
    235   1.1      bsh 		if (sc->sc_cards == 0)
    236   1.1      bsh 			bus_space_write_4(iot, memctl_ioh,
    237   1.1      bsh 			    MEMCTL_MECR, MECR_NOS);
    238   1.1      bsh #endif
    239   1.1      bsh 	}
    240   1.1      bsh 	splx(s);
    241   1.1      bsh 
    242  1.10      bsh 	DPRINTF(("%s: card %d %s\n", device_xname(sc->sc_pc.sc_dev), sock_no,
    243   1.1      bsh 	    HAVE_CARD(val) ? "inserted" : "removed"));
    244   1.1      bsh 
    245   1.1      bsh 	sapcic_intr(arg);
    246   1.1      bsh 
    247   1.1      bsh 	return 1;
    248   1.1      bsh }
    249   1.1      bsh #endif /* DONT_USE_CARD_DETECT_INTR */
    250   1.1      bsh 
    251   1.1      bsh static int
    252   1.1      bsh opcic_read(struct sapcic_socket *__so, int which)
    253   1.1      bsh {
    254   1.1      bsh 	struct opcic_socket *so = (struct opcic_socket *)__so;
    255   1.1      bsh 	uint8_t reg;
    256   1.1      bsh 
    257   1.1      bsh 	reg = opcic_read_card_status(so);
    258   1.1      bsh 
    259   1.1      bsh 	switch (which) {
    260   1.1      bsh 	case SAPCIC_STATUS_CARD:
    261   1.1      bsh 		return HAVE_CARD(reg) ?
    262   1.1      bsh 		    SAPCIC_CARD_VALID : SAPCIC_CARD_INVALID;
    263   1.1      bsh 
    264   1.1      bsh 	case SAPCIC_STATUS_VS1:
    265   1.1      bsh 		return (reg & CARDDET_NVS1) == 0;
    266   1.1      bsh 
    267   1.1      bsh 	case SAPCIC_STATUS_VS2:
    268   1.1      bsh 		return (reg & CARDDET_NVS2) == 0;
    269   1.1      bsh 
    270   1.1      bsh 	case SAPCIC_STATUS_READY:
    271   1.1      bsh 		return 1;
    272   1.1      bsh 
    273   1.1      bsh 	default:
    274   1.7    perry 		panic("%s: bogus register", __func__);
    275   1.1      bsh 	}
    276   1.1      bsh }
    277   1.1      bsh 
    278   1.1      bsh static void
    279   1.1      bsh opcic_write(struct sapcic_socket *__so, int which, int arg)
    280   1.1      bsh {
    281   1.1      bsh 	struct opcic_socket *so = (struct opcic_socket *)__so;
    282   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)so->ss.sc;
    283   1.1      bsh 	struct opio_softc *psc =
    284   1.8       he 	     device_private(device_parent(sc->sc_pc.sc_dev));
    285   1.1      bsh 	struct obio_softc *bsc =
    286   1.9      bsh 	     device_private(device_parent(psc->sc_dev));
    287   1.1      bsh 
    288   1.1      bsh 	switch (which) {
    289   1.1      bsh 	case SAPCIC_CONTROL_RESET:
    290   1.1      bsh 		obio_peripheral_reset(bsc, so->ss.socket, arg);
    291   1.1      bsh 		delay(500*1000);
    292   1.1      bsh 		break;
    293   1.1      bsh 
    294   1.1      bsh 	case SAPCIC_CONTROL_LINEENABLE:
    295   1.1      bsh 		break;
    296   1.1      bsh 
    297   1.1      bsh 	case SAPCIC_CONTROL_WAITENABLE:
    298   1.1      bsh 		break;
    299   1.1      bsh 
    300   1.1      bsh 	case SAPCIC_CONTROL_POWERSELECT:
    301   1.1      bsh #if 0
    302   1.1      bsh 		so->voltage = arg;
    303   1.1      bsh #endif
    304   1.1      bsh 		break;
    305   1.1      bsh 
    306   1.1      bsh 	default:
    307   1.7    perry 		panic("%s: bogus register", __func__);
    308   1.1      bsh 	}
    309   1.1      bsh }
    310   1.1      bsh 
    311   1.1      bsh static void
    312   1.1      bsh opcic_set_power(struct sapcic_socket *__so, int arg)
    313   1.1      bsh {
    314   1.1      bsh 	struct opcic_socket *so = (struct opcic_socket *)__so;
    315   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)so->ss.sc;
    316   1.1      bsh 	struct opio_softc *psc =
    317   1.8       he 	    device_private(device_parent(sc->sc_pc.sc_dev));
    318   1.1      bsh  	int shift, save;
    319   1.1      bsh 	volatile uint8_t *p;
    320   1.1      bsh 
    321   1.1      bsh 	if( arg < 0 || SAPCIC_POWER_5V < arg )
    322   1.1      bsh 		panic("sacpcic_set_power: bogus arg\n");
    323   1.1      bsh 
    324   1.1      bsh 	DPRINTF(("card %d: DET=%x\n",
    325   1.1      bsh 	    so->ss.socket,
    326   1.1      bsh 	    bus_space_read_1(psc->sc_iot, psc->sc_ioh,
    327   1.1      bsh 		GB225_CFDET + 2*so->ss.socket)));
    328   1.1      bsh 
    329   1.1      bsh 	p = (volatile uint8_t *)bus_space_vaddr(psc->sc_iot, psc->sc_ioh)
    330   1.1      bsh 	    + GB225_CARDPOW;
    331   1.1      bsh 
    332   1.1      bsh 	shift = 4 * !so->ss.socket;
    333   1.1      bsh 
    334   1.1      bsh 	save = disable_interrupts(I32_bit);
    335   1.1      bsh 	*p = (*p & ~(0x0f << shift)) | ((CARDPOW_VPPVCC | (arg<<2)) << shift);
    336   1.1      bsh 	restore_interrupts(save);
    337   1.1      bsh 
    338   1.1      bsh 	DPRINTF(("card %d power: %x\n", so->ss.socket, *p));
    339   1.1      bsh }
    340   1.1      bsh 
    341   1.1      bsh static void
    342   1.1      bsh opcic_clear_intr(int arg)
    343   1.1      bsh {
    344   1.1      bsh }
    345   1.1      bsh 
    346   1.1      bsh static void *
    347   1.1      bsh opcic_intr_establish(struct sapcic_socket *so, int level,
    348   1.1      bsh     int (* ih_fun)(void *), void *ih_arg)
    349   1.1      bsh {
    350   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)so->sc;
    351   1.1      bsh 	struct opio_softc *psc =
    352   1.8       he 	    device_private(device_parent(sc->sc_pc.sc_dev));
    353   1.1      bsh 	struct obio_softc *bsc =
    354   1.9      bsh 	    device_private(device_parent(psc->sc_dev));
    355   1.1      bsh 	int irq;
    356   1.1      bsh 
    357   1.1      bsh 	DPRINTF(("opcic_intr_establish %d\n", so->socket));
    358   1.1      bsh 
    359   1.1      bsh 	irq = so->socket ? PCMCIA_INT : CF_INT;
    360   1.1      bsh 	return obio_intr_establish(bsc, irq, level, IST_EDGE_FALLING,
    361   1.1      bsh 	    ih_fun, ih_arg);
    362   1.1      bsh }
    363   1.1      bsh 
    364   1.1      bsh static void
    365   1.1      bsh opcic_intr_disestablish(struct sapcic_socket *so, void *ih)
    366   1.1      bsh {
    367   1.1      bsh 	struct opcic_softc *sc = (struct opcic_softc *)so->sc;
    368   1.1      bsh 	struct opio_softc *psc =
    369   1.8       he 	    device_private(device_parent(sc->sc_pc.sc_dev));
    370   1.1      bsh 	struct obio_softc *bsc =
    371  1.13      chs 	    device_private(device_parent(psc->sc_dev));
    372   1.1      bsh 	int (* func)(void *) = ((struct obio_handler *)ih)->func;
    373   1.1      bsh 
    374   1.1      bsh 	int irq = so->socket ? PCMCIA_INT : CF_INT;
    375   1.1      bsh 
    376   1.1      bsh 	obio_intr_disestablish(bsc, irq, func);
    377   1.1      bsh }
    378