Home | History | Annotate | Line # | Download | only in s3c2xx0
s3c2800_pci.c revision 1.26
      1  1.26  jmcneill /*	$NetBSD: s3c2800_pci.c,v 1.26 2018/11/26 12:21:51 jmcneill Exp $	*/
      2   1.1       bsh 
      3   1.1       bsh /*
      4   1.1       bsh  * Copyright (c) 2002 Fujitsu Component Limited
      5   1.1       bsh  * Copyright (c) 2002 Genetec Corporation
      6   1.1       bsh  * All rights reserved.
      7   1.1       bsh  *
      8   1.1       bsh  * Redistribution and use in source and binary forms, with or without
      9   1.1       bsh  * modification, are permitted provided that the following conditions
     10   1.1       bsh  * are met:
     11   1.1       bsh  * 1. Redistributions of source code must retain the above copyright
     12   1.1       bsh  *    notice, this list of conditions and the following disclaimer.
     13   1.1       bsh  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1       bsh  *    notice, this list of conditions and the following disclaimer in the
     15   1.1       bsh  *    documentation and/or other materials provided with the distribution.
     16   1.1       bsh  * 3. Neither the name of The Fujitsu Component Limited nor the name of
     17   1.1       bsh  *    Genetec corporation may not be used to endorse or promote products
     18   1.1       bsh  *    derived from this software without specific prior written permission.
     19   1.1       bsh  *
     20   1.1       bsh  * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
     21   1.1       bsh  * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     22   1.1       bsh  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     23   1.1       bsh  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24   1.1       bsh  * DISCLAIMED.  IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
     25   1.1       bsh  * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26   1.1       bsh  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27   1.1       bsh  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
     28   1.1       bsh  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     29   1.1       bsh  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     30   1.1       bsh  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     31   1.1       bsh  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1       bsh  * SUCH DAMAGE.
     33   1.1       bsh  *
     34   1.1       bsh  * derived from evbarm/ifpga/ifpga_pci.c
     35   1.1       bsh  */
     36   1.1       bsh 
     37   1.1       bsh /*
     38   1.1       bsh  * Copyright (c) 2001 ARM Ltd
     39   1.1       bsh  * All rights reserved.
     40   1.1       bsh  *
     41   1.1       bsh  * Redistribution and use in source and binary forms, with or without
     42   1.1       bsh  * modification, are permitted provided that the following conditions
     43   1.1       bsh  * are met:
     44   1.1       bsh  * 1. Redistributions of source code must retain the above copyright
     45   1.1       bsh  *    notice, this list of conditions and the following disclaimer.
     46   1.1       bsh  * 2. Redistributions in binary form must reproduce the above copyright
     47   1.1       bsh  *    notice, this list of conditions and the following disclaimer in the
     48   1.1       bsh  *    documentation and/or other materials provided with the distribution.
     49   1.1       bsh  * 3. The name of the company may not be used to endorse or promote
     50   1.1       bsh  *    products derived from this software without specific prior written
     51   1.1       bsh  *    permission.
     52   1.1       bsh  *
     53   1.1       bsh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     54   1.1       bsh  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     55   1.1       bsh  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     56   1.1       bsh  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     57   1.1       bsh  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     58   1.1       bsh  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     59   1.1       bsh  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     60   1.1       bsh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     61   1.1       bsh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     62   1.1       bsh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     63   1.1       bsh  * SUCH DAMAGE.
     64   1.1       bsh  *
     65   1.1       bsh  * Copyright (c) 1997,1998 Mark Brinicombe.
     66   1.1       bsh  * Copyright (c) 1997,1998 Causality Limited
     67   1.1       bsh  * All rights reserved.
     68   1.1       bsh  *
     69   1.1       bsh  * Redistribution and use in source and binary forms, with or without
     70   1.1       bsh  * modification, are permitted provided that the following conditions
     71   1.1       bsh  * are met:
     72   1.1       bsh  * 1. Redistributions of source code must retain the above copyright
     73   1.1       bsh  *    notice, this list of conditions and the following disclaimer.
     74   1.1       bsh  * 2. Redistributions in binary form must reproduce the above copyright
     75   1.1       bsh  *    notice, this list of conditions and the following disclaimer in the
     76   1.1       bsh  *    documentation and/or other materials provided with the distribution.
     77   1.1       bsh  * 3. All advertising materials mentioning features or use of this software
     78   1.1       bsh  *    must display the following acknowledgement:
     79   1.1       bsh  *	This product includes software developed by Mark Brinicombe
     80   1.1       bsh  *	for the NetBSD Project.
     81   1.1       bsh  * 4. The name of the company nor the name of the author may be used to
     82   1.1       bsh  *    endorse or promote products derived from this software without specific
     83   1.1       bsh  *    prior written permission.
     84   1.1       bsh  *
     85   1.1       bsh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     86   1.1       bsh  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     87   1.1       bsh  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     88   1.1       bsh  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     89   1.1       bsh  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     90   1.1       bsh  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     91   1.1       bsh  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     92   1.1       bsh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     93   1.1       bsh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     94   1.1       bsh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     95   1.1       bsh  * SUCH DAMAGE.
     96   1.1       bsh  */
     97   1.1       bsh 
     98   1.1       bsh /*
     99   1.1       bsh  * PCI configuration support for Samsung s3c2800.
    100   1.1       bsh  */
    101   1.7     lukem 
    102   1.7     lukem #include <sys/cdefs.h>
    103  1.26  jmcneill __KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.26 2018/11/26 12:21:51 jmcneill Exp $");
    104  1.20      matt 
    105  1.20      matt #include "opt_pci.h"
    106  1.20      matt #include "pci.h"
    107   1.1       bsh 
    108   1.1       bsh #include <sys/param.h>
    109   1.1       bsh #include <sys/systm.h>
    110   1.1       bsh #include <sys/kernel.h>
    111   1.1       bsh #include <sys/device.h>
    112   1.1       bsh #include <sys/extent.h>
    113   1.1       bsh #include <sys/malloc.h>
    114   1.1       bsh 
    115   1.1       bsh #include <uvm/uvm_extern.h>
    116   1.1       bsh 
    117  1.16    dyoung #include <sys/bus.h>
    118   1.1       bsh 
    119   1.1       bsh #include <dev/pci/pcireg.h>
    120  1.20      matt #include <dev/pci/pcivar.h>
    121   1.1       bsh #include <dev/pci/pciconf.h>
    122   1.1       bsh 
    123  1.20      matt #include <arm/locore.h>
    124  1.20      matt 
    125  1.20      matt #include <arm/s3c2xx0/s3c2800reg.h>
    126  1.20      matt #include <arm/s3c2xx0/s3c2800var.h>
    127   1.1       bsh 
    128   1.1       bsh /*
    129   1.1       bsh  * pci tag encoding.
    130   1.1       bsh  * also useful for configuration type 0 address
    131   1.1       bsh  */
    132   1.1       bsh #define BUSNO_SHIFT	16
    133   1.1       bsh #define BUSNO_MASK	(0xff<<BUSNO_SHIFT)
    134   1.1       bsh #define DEVNO_SHIFT	11
    135   1.1       bsh #define DEVNO_MASK	(0x1f<<DEVNO_SHIFT)
    136   1.1       bsh #define tag_to_devno(tag)	(((tag)&DEVNO_MASK)>>DEVNO_SHIFT)
    137   1.1       bsh #define FUNNO_SHIFT	8
    138   1.1       bsh #define FUNNO_MASK	(0x07<<FUNNO_SHIFT)
    139   1.1       bsh 
    140   1.1       bsh #define BUS0_DEV_MIN	1
    141   1.1       bsh #define BUS0_DEV_MAX	21
    142   1.1       bsh 
    143  1.19       chs void	s3c2800_pci_attach_hook(device_t, device_t, struct pcibus_attach_args *);
    144   1.1       bsh int	s3c2800_pci_bus_maxdevs(void *, int);
    145   1.1       bsh pcitag_t s3c2800_pci_make_tag(void *, int, int, int);
    146   1.1       bsh void	s3c2800_pci_decompose_tag(void *, pcitag_t, int *, int *, int *);
    147   1.1       bsh pcireg_t s3c2800_pci_conf_read(void *, pcitag_t, int);
    148   1.1       bsh void	s3c2800_pci_conf_write(void *, pcitag_t, int, pcireg_t);
    149  1.18      matt void	s3c2800_pci_conf_interrupt(void *, int, int, int, int, int *);
    150  1.14    dyoung int	s3c2800_pci_intr_map(const struct pci_attach_args *,
    151  1.14    dyoung 	    pci_intr_handle_t *);
    152  1.21  christos const char *s3c2800_pci_intr_string(void *, pci_intr_handle_t, char *, size_t);
    153   1.1       bsh const struct evcnt *s3c2800_pci_intr_evcnt(void *, pci_intr_handle_t);
    154  1.12  christos void *s3c2800_pci_intr_establish(void *, pci_intr_handle_t, int,
    155  1.25  jmcneill 				  int (*) (void *), void *, const char *);
    156   1.1       bsh void	s3c2800_pci_intr_disestablish(void *, void *);
    157   1.1       bsh 
    158   1.1       bsh #define	PCI_CONF_LOCK(s)	(s) = disable_interrupts(I32_bit)
    159   1.1       bsh #define	PCI_CONF_UNLOCK(s)	restore_interrupts((s))
    160   1.1       bsh 
    161   1.1       bsh struct sspci_irq_handler {
    162   1.1       bsh 	int (*func) (void *);
    163   1.1       bsh 	void *arg;
    164   1.1       bsh 	int level;
    165   1.1       bsh 	SLIST_ENTRY(sspci_irq_handler) link;
    166   1.1       bsh };
    167   1.1       bsh 
    168   1.1       bsh struct sspci_softc {
    169  1.19       chs 	device_t sc_dev;
    170   1.1       bsh 
    171   1.1       bsh 	bus_space_tag_t sc_iot;
    172   1.1       bsh 	bus_space_handle_t sc_reg_ioh;
    173   1.1       bsh 	bus_space_handle_t sc_conf0_ioh;	/* config type0 space */
    174   1.1       bsh 	bus_space_handle_t sc_conf1_ioh;	/* config type1 space */
    175   1.1       bsh 
    176   1.1       bsh 	uint32_t sc_pciinten;	/* copy of PCIINTEN register */
    177   1.1       bsh 
    178   1.1       bsh 	/* list of interrupt handlers. SLIST is not good for removing
    179   1.1       bsh 	 * element from it, but intr_disestablish is rarely called */
    180   1.1       bsh 	SLIST_HEAD(, sspci_irq_handler) sc_irq_handlers;
    181   1.1       bsh 
    182   1.1       bsh 	void *sc_softinterrupt;
    183   1.1       bsh };
    184   1.1       bsh 
    185  1.19       chs static int sspci_match(device_t, cfdata_t, void *aux);
    186  1.19       chs static void sspci_attach(device_t, device_t, void *);
    187   1.1       bsh 
    188   1.1       bsh static int sspci_bs_map(void *, bus_addr_t, bus_size_t, int,
    189   1.1       bsh 			     bus_space_handle_t *);
    190   1.1       bsh static int sspci_init_controller(struct sspci_softc *);
    191   1.1       bsh static int sspci_intr(void *);
    192   1.1       bsh static void sspci_softintr(void *);
    193   1.1       bsh 
    194   1.1       bsh /* attach structures */
    195  1.19       chs CFATTACH_DECL_NEW(sspci, sizeof(struct sspci_softc), sspci_match, sspci_attach,
    196   1.1       bsh     NULL, NULL);
    197   1.1       bsh 
    198   1.1       bsh 
    199   1.1       bsh struct arm32_pci_chipset sspci_chipset = {
    200  1.26  jmcneill 	.pc_attach_hook = s3c2800_pci_attach_hook,
    201  1.26  jmcneill 	.pc_bus_maxdevs = s3c2800_pci_bus_maxdevs,
    202  1.26  jmcneill 	.pc_make_tag = s3c2800_pci_make_tag,
    203  1.26  jmcneill 	.pc_decompose_tag = s3c2800_pci_decompose_tag,
    204  1.26  jmcneill 	.pc_conf_read = s3c2800_pci_conf_read,
    205  1.26  jmcneill 	.pc_conf_write = s3c2800_pci_conf_write,
    206  1.26  jmcneill 	.pc_intr_map = s3c2800_pci_intr_map,
    207  1.26  jmcneill 	.pc_intr_string = s3c2800_pci_intr_string,
    208  1.26  jmcneill 	.pc_intr_evcnt = s3c2800_pci_intr_evcnt,
    209  1.26  jmcneill 	.pc_intr_establish = s3c2800_pci_intr_establish,
    210  1.26  jmcneill 	.pc_intr_disestablish = s3c2800_pci_intr_disestablish,
    211  1.26  jmcneill 	.pc_conf_interrupt = s3c2800_pci_conf_interrupt,
    212   1.1       bsh };
    213   1.1       bsh 
    214   1.1       bsh 
    215   1.1       bsh /*
    216   1.1       bsh  * bus space tag for PCI IO/Memory access space.
    217   1.1       bsh  * filled in by sspci_attach()
    218   1.1       bsh  */
    219   1.1       bsh struct bus_space sspci_io_tag, sspci_mem_tag;
    220   1.1       bsh 
    221   1.1       bsh static int
    222  1.19       chs sspci_match(device_t parent, cfdata_t match, void *aux)
    223   1.1       bsh {
    224   1.1       bsh 	return 1;
    225   1.1       bsh }
    226   1.1       bsh 
    227   1.1       bsh static void
    228  1.19       chs sspci_attach(device_t parent, device_t self, void *aux)
    229   1.1       bsh {
    230  1.19       chs 	struct sspci_softc *sc = device_private(self);
    231   1.1       bsh 	struct s3c2xx0_attach_args *aa = aux;
    232   1.1       bsh 	bus_space_tag_t iot;
    233   1.1       bsh 	bus_dma_tag_t pci_dma_tag;
    234   1.1       bsh 	const char *error_on;	/* for panic message */
    235   1.1       bsh #if defined(PCI_NETBSD_CONFIGURE)
    236   1.1       bsh 	struct extent *ioext, *memext;
    237   1.1       bsh 	struct pcibus_attach_args pci_pba;
    238   1.1       bsh #endif
    239   1.1       bsh 
    240   1.1       bsh #define FAIL(which)  do { \
    241   1.1       bsh 	error_on=(which); goto abort; }while(/*CONSTCOND*/0)
    242   1.1       bsh 
    243  1.19       chs 	sc->sc_dev = self;
    244   1.1       bsh 	iot = sc->sc_iot = aa->sa_iot;
    245   1.1       bsh 	if (bus_space_map(iot, S3C2800_PCICTL_BASE,
    246   1.1       bsh 		S3C2800_PCICTL_SIZE, 0, &sc->sc_reg_ioh))
    247   1.1       bsh 		FAIL("control regs");
    248   1.1       bsh 
    249   1.1       bsh 	if (bus_space_map(iot, S3C2800_PCI_CONF0_BASE,
    250   1.1       bsh 		S3C2800_PCI_CONF0_SIZE, 0, &sc->sc_conf0_ioh))
    251   1.1       bsh 		FAIL("config type 0 area");
    252   1.1       bsh 
    253   1.1       bsh #if 0
    254   1.1       bsh 	if (bus_space_map(iot, S3C2800_PCI_CONF1_BASE,
    255   1.1       bsh 		S3C2800_PCI_CONF1_SIZE, 0, &sc->sc_conf1_ioh))
    256   1.1       bsh 		FAIL("config type 1 area");
    257   1.1       bsh #endif
    258   1.1       bsh 	printf("\n");
    259   1.1       bsh 
    260   1.1       bsh 	SLIST_INIT(&sc->sc_irq_handlers);
    261   1.4       bsh 	if (!s3c2800_intr_establish(S3C2800_INT_PCI, IPL_AUDIO, IST_LEVEL,
    262   1.1       bsh 		sspci_intr, sc))
    263   1.1       bsh 		FAIL("intr_establish");
    264   1.1       bsh 
    265  1.13      matt 	sc->sc_softinterrupt = softint_establish(SOFTINT_SERIAL,
    266   1.1       bsh 	    sspci_softintr, sc);
    267   1.1       bsh 	if (sc->sc_softinterrupt == NULL)
    268  1.13      matt 		FAIL("softint_establish");
    269   1.1       bsh 
    270   1.1       bsh #if defined(PCI_NETBSD_CONFIGURE)
    271   1.1       bsh 	if (sspci_init_controller(sc)) {
    272  1.19       chs 		printf("%s: failed to initialize controller\n", device_xname(self));
    273   1.1       bsh 		return;
    274   1.1       bsh 	}
    275   1.1       bsh #endif
    276   1.1       bsh 
    277   1.1       bsh 	sc->sc_pciinten =
    278   1.1       bsh 	    PCIINT_INA | PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
    279   1.1       bsh 	    PCIINT_MFE | PCIINT_PRA | PCIINT_PRD;
    280   1.1       bsh 
    281   1.1       bsh 	bus_space_write_4(iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
    282   1.1       bsh 	    sc->sc_pciinten);
    283   1.1       bsh 
    284   1.1       bsh 	{
    285   1.1       bsh 		pcireg_t id_reg, class_reg;
    286   1.1       bsh 		char buf[1000];
    287   1.1       bsh 
    288   1.1       bsh 		id_reg = bus_space_read_4(iot, sc->sc_reg_ioh,
    289   1.1       bsh 		    PCI_ID_REG);
    290   1.1       bsh 		class_reg = bus_space_read_4(iot,
    291   1.1       bsh 		    sc->sc_reg_ioh, PCI_CLASS_REG);
    292   1.1       bsh 
    293   1.8    kleink 		pci_devinfo(id_reg, class_reg, 1, buf, sizeof(buf));
    294  1.19       chs 		printf("%s: %s\n", device_xname(self), buf);
    295   1.1       bsh 	}
    296   1.1       bsh 
    297   1.1       bsh #if defined(PCI_NETBSD_CONFIGURE)
    298   1.6       bsh 	ioext = extent_create("pciio", 0x100, S3C2800_PCI_IOSPACE_SIZE - 0x100,
    299  1.17      para 	    NULL, 0, EX_NOWAIT);
    300   1.1       bsh 
    301   1.1       bsh 	memext = extent_create("pcimem", 0, S3C2800_PCI_MEMSPACE_SIZE,
    302  1.17      para 	    NULL, 0, EX_NOWAIT);
    303   1.1       bsh 
    304   1.1       bsh 	sspci_chipset.pc_conf_v = (void *) sc;
    305   1.1       bsh 	sspci_chipset.pc_intr_v = (void *) sc;
    306   1.1       bsh 
    307   1.1       bsh 	pci_configure_bus(&sspci_chipset, ioext, memext, NULL, 0,
    308   1.1       bsh 	    arm_dcache_align);
    309   1.1       bsh 
    310   1.1       bsh 	extent_destroy(memext);
    311   1.1       bsh 	extent_destroy(ioext);
    312   1.1       bsh #endif				/* PCI_NETBSD_CONFIGURE */
    313   1.1       bsh 
    314   1.1       bsh 	/* initialize bus space tag */
    315   1.1       bsh 	sspci_io_tag = *iot;
    316   1.1       bsh 	sspci_io_tag.bs_cookie = (void *) S3C2800_PCI_IOSPACE_BASE;
    317   1.1       bsh 	sspci_io_tag.bs_map = sspci_bs_map;
    318   1.1       bsh 	sspci_mem_tag = *iot;
    319   1.1       bsh 	sspci_mem_tag.bs_cookie = (void *) S3C2800_PCI_MEMSPACE_BASE;
    320   1.1       bsh 	sspci_mem_tag.bs_map = sspci_bs_map;
    321   1.1       bsh 
    322   1.1       bsh 
    323   1.1       bsh 	/* Platform provides PCI DMA tag */
    324   1.1       bsh 	pci_dma_tag = s3c2800_pci_dma_init();
    325   1.1       bsh 
    326   1.1       bsh 	pci_pba.pba_pc = &sspci_chipset;
    327   1.1       bsh 	pci_pba.pba_iot = &sspci_io_tag;
    328   1.1       bsh 	pci_pba.pba_memt = &sspci_mem_tag;
    329   1.1       bsh 	pci_pba.pba_dmat = pci_dma_tag;
    330   1.5      fvdl 	pci_pba.pba_dmat64 = NULL;
    331  1.15    dyoung 	pci_pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
    332   1.1       bsh 	pci_pba.pba_bus = 0;
    333   1.1       bsh 	pci_pba.pba_bridgetag = NULL;
    334   1.1       bsh 
    335   1.9  drochner 	config_found_ia(self, "pcibus", &pci_pba, pcibusprint);
    336   1.1       bsh 
    337   1.1       bsh 	return;
    338   1.1       bsh 
    339   1.1       bsh #undef FAIL
    340   1.1       bsh abort:
    341   1.1       bsh 	panic("%s: map failed (%s)",
    342  1.19       chs 	    device_xname(self), error_on);
    343   1.1       bsh }
    344   1.1       bsh 
    345   1.1       bsh 
    346   1.1       bsh static int
    347   1.1       bsh sspci_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag,
    348   1.1       bsh 	     bus_space_handle_t * bshp)
    349   1.1       bsh {
    350   1.1       bsh 	bus_addr_t startpa, endpa;
    351   1.1       bsh 	vaddr_t va;
    352   1.1       bsh 
    353   1.1       bsh #ifdef PCI_DEBUG
    354   1.1       bsh 	printf("sspci_bs_map: t=%p, addr=%lx, size=%lx, flag=%d\n",
    355   1.1       bsh 	    t, bpa, size, flag);
    356   1.1       bsh #endif
    357   1.1       bsh 
    358   1.1       bsh 	/* Round the allocation to page boundries */
    359   1.1       bsh 	startpa = trunc_page(bpa);
    360   1.1       bsh 	endpa = round_page(bpa + size);
    361   1.1       bsh 
    362   1.1       bsh 	/* Get some VM.  */
    363  1.11      yamt 	va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
    364  1.11      yamt 	    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
    365   1.1       bsh 	if (va == 0)
    366   1.1       bsh 		return ENOMEM;
    367   1.1       bsh 
    368   1.1       bsh 	/* Store the bus space handle */
    369   1.1       bsh 	*bshp = va + (bpa & PGOFSET);
    370   1.1       bsh 
    371   1.1       bsh 	/* Now map the pages */
    372   1.1       bsh 	/* The cookie is the physical base address for PCI I/O or memory area */
    373   1.1       bsh 	while (startpa < endpa) {
    374   1.1       bsh 		/* XXX pmap_kenter_pa maps pages cacheable -- not what we
    375   1.1       bsh 		 * want.  */
    376   1.1       bsh 		pmap_enter(pmap_kernel(), va, (bus_addr_t) t + startpa,
    377   1.1       bsh 		    VM_PROT_READ | VM_PROT_WRITE, 0);
    378   1.3   thorpej 		va += PAGE_SIZE;
    379   1.3   thorpej 		startpa += PAGE_SIZE;
    380   1.1       bsh 	}
    381   1.1       bsh 	pmap_update(pmap_kernel());
    382   1.1       bsh 
    383   1.1       bsh 	return 0;
    384   1.1       bsh }
    385   1.1       bsh 
    386   1.1       bsh 
    387   1.1       bsh 
    388   1.1       bsh void
    389  1.18      matt s3c2800_pci_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, int *iline)
    390   1.1       bsh {
    391   1.1       bsh #ifdef PCI_DEBUG
    392  1.18      matt 	printf("pci_conf_interrupt(v(%p), bus(%d), dev(%d), ipin(%d), swiz(%d), *iline(%p)\n", v, bus, dev, ipin, swiz, iline);
    393   1.1       bsh #endif
    394   1.1       bsh 	if (bus == 0) {
    395   1.1       bsh 		*iline = dev;
    396   1.1       bsh 	} else {
    397   1.1       bsh 		panic("pci_conf_interrupt: bus=%d: not yet implemented", bus);
    398   1.1       bsh 	}
    399   1.1       bsh }
    400   1.1       bsh 
    401   1.1       bsh void
    402  1.19       chs s3c2800_pci_attach_hook(device_t parent, device_t self,
    403   1.1       bsh 			struct pcibus_attach_args * pba)
    404   1.1       bsh {
    405   1.1       bsh 
    406   1.1       bsh 	/* Nothing to do. */
    407   1.1       bsh #ifdef PCI_DEBUG
    408   1.1       bsh 	printf("s3c2800_pci_attach_hook()\n");
    409   1.1       bsh #endif
    410   1.1       bsh }
    411   1.1       bsh 
    412   1.1       bsh int
    413   1.1       bsh s3c2800_pci_bus_maxdevs(void *v, int busno)
    414   1.1       bsh {
    415   1.1       bsh 
    416   1.1       bsh #ifdef PCI_DEBUG
    417   1.1       bsh 	printf("s3c2800_pci_bus_maxdevs(v=%p, busno=%d)\n", v, busno);
    418   1.1       bsh #endif
    419   1.1       bsh 	return (32);
    420   1.1       bsh }
    421   1.1       bsh pcitag_t
    422   1.1       bsh s3c2800_pci_make_tag(void *v, int bus, int device, int function)
    423   1.1       bsh {
    424   1.1       bsh 
    425   1.1       bsh 	return ((bus << BUSNO_SHIFT) | (device << DEVNO_SHIFT) |
    426   1.1       bsh 	    (function << FUNNO_SHIFT));
    427   1.1       bsh }
    428   1.1       bsh 
    429   1.1       bsh void
    430   1.1       bsh s3c2800_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
    431   1.1       bsh {
    432   1.1       bsh 	if (bp != NULL)
    433   1.1       bsh 		*bp = (tag >> BUSNO_SHIFT) & 0xff;
    434   1.1       bsh 	if (dp != NULL)
    435   1.1       bsh 		*dp = (tag >> DEVNO_SHIFT) & 0x1f;
    436   1.1       bsh 	if (fp != NULL)
    437   1.1       bsh 		*fp = (tag >> FUNNO_SHIFT) & 0x7;
    438   1.1       bsh }
    439   1.1       bsh 
    440   1.1       bsh static vaddr_t
    441   1.1       bsh make_pci_conf_va(struct sspci_softc * sc, pcitag_t tag, int offset)
    442   1.1       bsh {
    443  1.22   msaitoh 
    444  1.22   msaitoh 	if ((unsigned int)offset >= PCI_CONF_SIZE)
    445  1.22   msaitoh 		return (vaddr_t) -1;
    446  1.22   msaitoh 
    447   1.1       bsh 	if ((tag & BUSNO_MASK) == 0) {
    448   1.1       bsh 		/* configuration type 0 */
    449   1.1       bsh 		int devno = tag_to_devno(tag);
    450   1.1       bsh 
    451   1.1       bsh 		if (devno < BUS0_DEV_MIN || BUS0_DEV_MAX < devno)
    452   1.1       bsh 			return 0;
    453   1.1       bsh 
    454   1.1       bsh 		return (vaddr_t) bus_space_vaddr(sc->sc_iot, sc->sc_conf0_ioh) +
    455   1.1       bsh 		    (tag & (DEVNO_MASK | FUNNO_MASK)) + offset;
    456   1.1       bsh 	} else {
    457   1.1       bsh 		/* XXX */
    458   1.1       bsh 		return (vaddr_t) - 1;	/* cause fault */
    459   1.1       bsh 	}
    460   1.1       bsh }
    461   1.1       bsh 
    462   1.1       bsh 
    463   1.1       bsh pcireg_t
    464   1.1       bsh s3c2800_pci_conf_read(void *v, pcitag_t tag, int offset)
    465   1.1       bsh {
    466   1.1       bsh 	struct sspci_softc *sc = v;
    467   1.1       bsh 	vaddr_t va = make_pci_conf_va(sc, tag, offset);
    468   1.1       bsh 	int s;
    469   1.1       bsh 	pcireg_t rv;
    470   1.1       bsh 
    471   1.1       bsh #ifdef PCI_DEBUG
    472   1.1       bsh 	printf("s3c2800_pci_conf_read: base=%lx tag=%lx offset=%x\n",
    473   1.1       bsh 	    sc->sc_conf0_ioh, tag, offset);
    474   1.1       bsh #endif
    475   1.1       bsh 	if (va == 0)
    476   1.1       bsh 		return -1;
    477   1.1       bsh 
    478   1.1       bsh 	PCI_CONF_LOCK(s);
    479   1.1       bsh 
    480   1.1       bsh 	if (badaddr_read((void *) va, sizeof(rv), &rv)) {
    481   1.1       bsh #if PCI_DEBUG
    482   1.1       bsh 		printf("conf_read: %lx bad address\n", va);
    483   1.1       bsh #endif
    484   1.1       bsh 		rv = (pcireg_t) - 1;
    485   1.1       bsh 	}
    486   1.1       bsh 	PCI_CONF_UNLOCK(s);
    487   1.1       bsh 
    488   1.1       bsh 	return rv;
    489   1.1       bsh }
    490   1.1       bsh 
    491   1.1       bsh void
    492   1.1       bsh s3c2800_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
    493   1.1       bsh {
    494   1.1       bsh 	struct sspci_softc *sc = v;
    495   1.1       bsh 	vaddr_t va = make_pci_conf_va(sc, tag, offset);
    496   1.1       bsh 	u_int s;
    497   1.1       bsh 
    498   1.1       bsh #ifdef PCI_DEBUG
    499   1.1       bsh 	printf("s3c2800_pci_conf_write: tag=%lx offset=%x -> va=%lx\n", tag, offset, va);
    500   1.1       bsh #endif
    501   1.1       bsh 
    502   1.1       bsh 	PCI_CONF_LOCK(s);
    503   1.1       bsh 
    504   1.1       bsh 	*(pcireg_t *) va = val;
    505   1.1       bsh 
    506   1.1       bsh 	PCI_CONF_UNLOCK(s);
    507   1.1       bsh }
    508   1.1       bsh 
    509   1.1       bsh void *
    510   1.1       bsh s3c2800_pci_intr_establish(void *pcv, pci_intr_handle_t ih, int level,
    511  1.25  jmcneill 			   int (*func) (void *), void *arg, const char *xname)
    512   1.1       bsh {
    513   1.1       bsh 	struct sspci_softc *sc = pcv;
    514   1.1       bsh 	struct sspci_irq_handler *handler;
    515   1.1       bsh 	int s;
    516   1.1       bsh 
    517   1.1       bsh #ifdef PCI_DEBUG
    518   1.1       bsh 	printf("s3c2800_pci_intr_establish(pcv=%p, ih=0x%lx, level=%d, "
    519  1.25  jmcneill 	    "func=%p, arg=%p, xname=%s)\n", pcv, ih, level, func, arg, xname);
    520   1.1       bsh #endif
    521   1.1       bsh 
    522   1.1       bsh 	handler = malloc(sizeof *handler, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    523   1.1       bsh 	if (handler == NULL)
    524   1.1       bsh 		panic("sspci_intr_establish: can't malloc handler info");
    525   1.1       bsh 
    526   1.1       bsh 	handler->func = func;
    527   1.1       bsh 	handler->arg = arg;
    528   1.1       bsh 	handler->level = level;
    529   1.1       bsh 
    530   1.1       bsh 	s = splhigh();
    531   1.1       bsh 	SLIST_INSERT_HEAD(&sc->sc_irq_handlers, handler, link);
    532   1.1       bsh 	splx(s);
    533   1.1       bsh 
    534   1.1       bsh 	return (handler);
    535   1.1       bsh }
    536   1.1       bsh 
    537   1.1       bsh void
    538   1.1       bsh s3c2800_pci_intr_disestablish(void *pcv, void *cookie)
    539   1.1       bsh {
    540   1.1       bsh 	struct sspci_softc *sc = pcv;
    541   1.1       bsh 	struct sspci_irq_handler *ih = cookie;
    542   1.1       bsh 	int s;
    543   1.1       bsh 
    544   1.1       bsh #ifdef PCI_DEBUG
    545   1.1       bsh 	printf("s3c2800_pci_intr_disestablish(pcv=%p, cookie=%p)\n",
    546   1.1       bsh 	    pcv, cookie);
    547   1.1       bsh #endif
    548   1.1       bsh 
    549   1.1       bsh 	s = splhigh();
    550   1.1       bsh 	SLIST_REMOVE(&sc->sc_irq_handlers, ih, sspci_irq_handler, link);
    551   1.1       bsh 	splx(s);
    552   1.1       bsh }
    553   1.1       bsh 
    554   1.1       bsh int
    555  1.14    dyoung s3c2800_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
    556   1.1       bsh {
    557   1.1       bsh #ifdef PCI_DEBUG
    558   1.1       bsh 	int pin = pa->pa_intrpin;
    559   1.1       bsh 	void *pcv = pa->pa_pc;
    560   1.1       bsh 	pcitag_t intrtag = pa->pa_intrtag;
    561   1.1       bsh 	int bus, device, function;
    562   1.1       bsh 
    563   1.1       bsh 	s3c2800_pci_decompose_tag(pcv, intrtag, &bus, &device, &function);
    564   1.1       bsh 	printf("s3c2800_pci_intr_map: pcv=%p, tag=%08lx pin=%d dev=%d\n",
    565   1.1       bsh 	    pcv, intrtag, pin, device);
    566   1.1       bsh #endif
    567   1.1       bsh 
    568   1.1       bsh 
    569   1.1       bsh 	/* S3C2800 has only one interrupt line for PCI */
    570   1.1       bsh 	*ihp = 0;
    571   1.1       bsh 	return 0;
    572   1.1       bsh }
    573   1.1       bsh 
    574   1.1       bsh const char *
    575  1.21  christos s3c2800_pci_intr_string(void *pcv, pci_intr_handle_t ih, char *buf, size_t len)
    576   1.1       bsh {
    577   1.1       bsh 	/* We have only one interrupt source from PCI */
    578  1.21  christos 	strlcpy(buf, "pciint", len);
    579  1.21  christos 	return buf;
    580   1.1       bsh }
    581   1.1       bsh 
    582   1.1       bsh const struct evcnt *
    583   1.1       bsh s3c2800_pci_intr_evcnt(void *pcv, pci_intr_handle_t ih)
    584   1.1       bsh {
    585   1.1       bsh 
    586   1.1       bsh 	/* XXX for now, no evcnt parent reported */
    587   1.1       bsh 	return NULL;
    588   1.1       bsh }
    589   1.1       bsh /*
    590   1.1       bsh  * Initialize PCI controller
    591   1.1       bsh  */
    592   1.1       bsh int
    593   1.1       bsh sspci_init_controller(struct sspci_softc * sc)
    594   1.1       bsh {
    595   1.1       bsh 	bus_space_tag_t iot = sc->sc_iot;
    596   1.1       bsh 	bus_space_handle_t ioh = sc->sc_reg_ioh;
    597   1.1       bsh 
    598   1.1       bsh 	/* disable PCI command */
    599   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
    600   1.1       bsh 	    0xffff0000);
    601   1.1       bsh 
    602   1.1       bsh 	/* latency=0x10, cacheline=8 */
    603   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_BHLC_REG,
    604   1.1       bsh 	    PCI_BHLC_CODE(0, 0, 0, 0x10, 8));
    605   1.1       bsh 
    606   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_INTERRUPT_REG,
    607   1.1       bsh 	    PCI_INTERRUPT_CODE(0, 0, 0, 0));
    608   1.1       bsh 
    609   1.1       bsh 
    610   1.1       bsh 
    611   1.1       bsh #if 1
    612   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_MAPREG_START,
    613   1.1       bsh 	    PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
    614   1.1       bsh 	/* Cover all DBANKs with BAR0 */
    615   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xf8000000);
    616   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, S3C2800_DBANK0_START);
    617   1.1       bsh #else
    618   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_MAPREG_START,
    619   1.1       bsh 	    PCI_MAPREG_MEM_TYPE_32BIT | 0xf0000000);
    620   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_MAPREG_START + 4,
    621   1.1       bsh 	    PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
    622   1.1       bsh 
    623   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xffff0000);
    624   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, 0xffff0000);
    625   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBAM1, 0xf1000000);
    626   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIBATPA1, S3C2800_DBANK0_START);
    627   1.1       bsh #endif
    628   1.1       bsh 
    629   1.1       bsh 	bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
    630   1.1       bsh 	    PCI_STATUS_PARITY_DETECT |
    631   1.1       bsh 	    PCI_STATUS_SPECIAL_ERROR |
    632   1.1       bsh 	    PCI_STATUS_MASTER_ABORT |
    633   1.1       bsh 	    PCI_STATUS_MASTER_TARGET_ABORT |
    634   1.1       bsh 	    PCI_STATUS_TARGET_TARGET_ABORT |
    635   1.1       bsh 	    PCI_STATUS_DEVSEL_MEDIUM |
    636   1.1       bsh 	    PCI_STATUS_PARITY_ERROR |
    637   1.1       bsh 	    PCI_STATUS_BACKTOBACK_SUPPORT |
    638   1.1       bsh 	    PCI_STATUS_CAPLIST_SUPPORT |
    639   1.1       bsh 	    PCI_COMMAND_MASTER_ENABLE |
    640   1.1       bsh 	    PCI_COMMAND_MEM_ENABLE |
    641   1.1       bsh 	    PCI_COMMAND_IO_ENABLE);
    642   1.1       bsh 
    643   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCICON,
    644   1.1       bsh 	    PCICON_ARB | PCICON_HST);
    645   1.1       bsh 
    646   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCISET, 0);
    647   1.1       bsh 	/* clear all interrupts */
    648   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIINTST, 0xffffffff);
    649   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCIINTEN, 0);
    650   1.1       bsh 
    651   1.1       bsh 	bus_space_write_4(iot, ioh, PCICTL_PCICON,
    652   1.1       bsh 	    PCICON_RDY | PCICON_CFD | PCICON_ATS |
    653   1.1       bsh 	    PCICON_ARB | PCICON_HST);
    654   1.1       bsh 
    655   1.1       bsh 
    656   1.1       bsh #ifdef PCI_DEBUG
    657   1.1       bsh 	{
    658   1.1       bsh 		pcireg_t reg;
    659   1.1       bsh 		int i;
    660   1.1       bsh 
    661   1.1       bsh 		for (i = 0; i <= 0x40; i += sizeof(pcireg_t)) {
    662   1.1       bsh 			reg = bus_space_read_4(iot, ioh, i);
    663   1.1       bsh 			printf("%03x: %08x\n", i, reg);
    664   1.1       bsh 		}
    665   1.1       bsh 		for (i = 0x100; i <= 0x154; i += sizeof(pcireg_t)) {
    666   1.1       bsh 			reg = bus_space_read_4(iot, ioh, i);
    667   1.1       bsh 			printf("%03x: %08x\n", i, reg);
    668   1.1       bsh 		}
    669   1.1       bsh 	}
    670   1.1       bsh #endif
    671   1.1       bsh 	return 0;
    672   1.1       bsh }
    673   1.1       bsh 
    674   1.1       bsh 
    675   1.1       bsh static const char *pci_abnormal_error_name[] = {
    676   1.1       bsh 	"PCI reset deasserted",
    677   1.1       bsh 	"PCI reset asserted",
    678   1.1       bsh 	"PCI master detected fatal error",
    679   1.1       bsh 	"PCI master detected parity error",
    680   1.1       bsh 	"PCI target detected parity error",
    681   1.1       bsh 	"PCI SERR# asserted",
    682   1.1       bsh };
    683   1.1       bsh 
    684   1.1       bsh static int
    685   1.1       bsh sspci_intr(void *arg)
    686   1.1       bsh {
    687   1.1       bsh 	struct sspci_softc *sc = arg;
    688   1.1       bsh 	int s;
    689   1.1       bsh 	bus_space_tag_t iot = sc->sc_iot;
    690   1.1       bsh 	bus_space_handle_t ioh = sc->sc_reg_ioh;
    691   1.1       bsh 	uint32_t interrupts, errors;
    692   1.1       bsh 
    693   1.1       bsh 	interrupts = bus_space_read_4(iot, ioh, PCICTL_PCIINTST);
    694   1.1       bsh 
    695   1.1       bsh 	if (interrupts & PCIINT_INA) {
    696   1.1       bsh 		s = splhigh();
    697  1.13      matt 		softint_schedule(sc->sc_softinterrupt);
    698   1.1       bsh 
    699   1.1       bsh 		/* mask INTA itnerrupt until softinterrupt is handled */
    700   1.1       bsh 		sc->sc_pciinten &= ~PCIINT_INA;
    701   1.1       bsh 		bus_space_write_4(iot, ioh, PCICTL_PCIINTEN,
    702   1.1       bsh 		    sc->sc_pciinten);
    703   1.1       bsh 
    704   1.1       bsh 		/* acknowledge INTA interrupt */
    705   1.1       bsh 		bus_space_write_4(iot, ioh, PCICTL_PCIINTST, PCIINT_INA);
    706   1.1       bsh 
    707   1.1       bsh 		splx(s);
    708   1.1       bsh 
    709   1.1       bsh 		interrupts &= ~PCIINT_INA;
    710   1.1       bsh 
    711   1.1       bsh 	}
    712   1.1       bsh 	errors = interrupts & (PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
    713   1.1       bsh 	    PCIINT_MFE | PCIINT_PRA | PCIINT_PRD);
    714   1.1       bsh 	if (errors) {
    715   1.1       bsh 		int i;
    716   1.1       bsh 
    717   1.1       bsh 		for (i = 0; errors; ++i) {
    718   1.1       bsh 			if ((errors & (1 << i)) == 0)
    719   1.1       bsh 				continue;
    720   1.1       bsh 
    721  1.19       chs 			printf("%s: %s\n", device_xname(sc->sc_dev),
    722   1.1       bsh 			    pci_abnormal_error_name[i > 4 ? 5 : i]);
    723   1.1       bsh 
    724   1.1       bsh 			errors &= ~(1 << i);
    725   1.1       bsh 		}
    726   1.1       bsh 		/* acknowledge interrupts */
    727   1.1       bsh 		bus_space_write_4(iot, ioh, PCICTL_PCIINTST, interrupts);
    728   1.1       bsh 	}
    729   1.1       bsh 	return 0;
    730   1.1       bsh }
    731   1.1       bsh 
    732   1.1       bsh static void
    733   1.1       bsh sspci_softintr(void *arg)
    734   1.1       bsh {
    735   1.1       bsh 	struct sspci_softc *sc = arg;
    736   1.1       bsh 	struct sspci_irq_handler *ih;
    737   1.1       bsh 	int s;
    738   1.1       bsh 
    739   1.1       bsh 
    740   1.1       bsh 	SLIST_FOREACH(ih, &(sc->sc_irq_handlers), link) {
    741   1.1       bsh 		s = _splraise(ih->level);
    742   1.1       bsh 		ih->func(ih->arg);
    743   1.1       bsh 		splx(s);
    744   1.1       bsh 	}
    745   1.1       bsh 
    746   1.1       bsh 	/* unmask INTA interrupt */
    747   1.1       bsh 	s = splhigh();
    748   1.1       bsh 	sc->sc_pciinten |= PCIINT_INA;
    749   1.1       bsh 	bus_space_write_4(sc->sc_iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
    750   1.1       bsh 	    sc->sc_pciinten);
    751   1.1       bsh 	splx(s);
    752   1.1       bsh }
    753