Home | History | Annotate | Line # | Download | only in pci
      1 /*	$NetBSD: pci_machdep.c,v 1.38 2015/10/02 05:22:50 msaitoh Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2000 Soren S. Jorvang.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions, and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     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 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.38 2015/10/02 05:22:50 msaitoh Exp $");
     30 
     31 #define _MIPS_BUS_DMA_PRIVATE
     32 
     33 #include <sys/param.h>
     34 #include <sys/bus.h>
     35 #include <sys/cpu.h>
     36 #include <sys/device.h>
     37 #include <sys/errno.h>
     38 #include <sys/extent.h>
     39 #include <sys/intr.h>
     40 #include <sys/systm.h>
     41 #include <sys/time.h>
     42 
     43 #include <dev/pci/pcivar.h>
     44 #include <dev/pci/pcireg.h>
     45 #include <dev/pci/pcidevs.h>
     46 #include <dev/pci/pciconf.h>
     47 #include <dev/pci/pciide_apollo_reg.h>
     48 
     49 #include <cobalt/dev/gtreg.h>
     50 
     51 /*
     52  * PCI doesn't have any special needs; just use
     53  * the generic versions of these functions.
     54  */
     55 struct mips_bus_dma_tag pci_bus_dma_tag = {
     56 	._dmamap_ops = _BUS_DMAMAP_OPS_INITIALIZER,
     57 	._dmamem_ops = _BUS_DMAMEM_OPS_INITIALIZER,
     58 	._dmatag_ops = _BUS_DMATAG_OPS_INITIALIZER,
     59 };
     60 
     61 void
     62 pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
     63 {
     64 	/* XXX */
     65 
     66 	return;
     67 }
     68 
     69 int
     70 pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
     71 {
     72 
     73 	return 32;
     74 }
     75 
     76 pcitag_t
     77 pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
     78 {
     79 
     80 	return (bus << 16) | (device << 11) | (function << 8);
     81 }
     82 
     83 void
     84 pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
     85 {
     86 
     87 	if (bp != NULL)
     88 		*bp = (tag >> 16) & 0xff;
     89 	if (dp != NULL)
     90 		*dp = (tag >> 11) & 0x1f;
     91 	if (fp != NULL)
     92 		*fp = (tag >> 8) & 0x07;
     93 }
     94 
     95 pcireg_t
     96 pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
     97 {
     98 	pcireg_t data;
     99 	int bus, dev, func;
    100 
    101 	KASSERT(pc != NULL);
    102 
    103 	if ((unsigned int)reg >= PCI_CONF_SIZE)
    104 		return (pcireg_t) -1;
    105 
    106 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
    107 
    108 	/*
    109 	 * 2700 hardware wedges on accesses to device 6.
    110 	 */
    111 	if (bus == 0 && dev == 6)
    112 		return 0;
    113 	/*
    114 	 * 2800 hardware wedges on accesses to device 31.
    115 	 */
    116 	if (bus == 0 && dev == 31)
    117 		return 0;
    118 
    119 	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR,
    120 	    PCICFG_ENABLE | tag | reg);
    121 	data = bus_space_read_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_DATA);
    122 	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR, 0);
    123 
    124 	return data;
    125 }
    126 
    127 void
    128 pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
    129 {
    130 
    131 	if ((unsigned int)reg >= PCI_CONF_SIZE)
    132 		return;
    133 
    134 	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR,
    135 	    PCICFG_ENABLE | tag | reg);
    136 	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_DATA, data);
    137 	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR, 0);
    138 }
    139 
    140 int
    141 pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
    142 {
    143 	pci_chipset_tag_t pc = pa->pa_pc;
    144 	pcitag_t intrtag = pa->pa_intrtag;
    145 	int pin = pa->pa_intrpin;
    146 	int line = pa->pa_intrline;
    147 	int bus, dev, func;
    148 
    149 	pci_decompose_tag(pc, intrtag, &bus, &dev, &func);
    150 
    151 	/*
    152 	 * The interrupt lines of the internal Tulips are connected
    153 	 * directly to the CPU.
    154 	 */
    155 	if (cobalt_id == COBALT_ID_QUBE2700) {
    156 		if (bus == 0 && dev == 7 && pin == PCI_INTERRUPT_PIN_A) {
    157 			/* tulip is connected to CPU INT2 on Qube2700 */
    158 			*ihp = NICU_INT + 2;
    159 			return 0;
    160 		}
    161 	} else {
    162 		if (bus == 0 && dev == 7 && pin == PCI_INTERRUPT_PIN_A) {
    163 			/* the primary tulip is connected to CPU INT1 */
    164 			*ihp = NICU_INT + 1;
    165 			return 0;
    166 		}
    167 		if (bus == 0 && dev == 12 && pin == PCI_INTERRUPT_PIN_A) {
    168 			/* the secondary tulip is connected to CPU INT2 */
    169 			*ihp = NICU_INT + 2;
    170 			return 0;
    171 		}
    172 	}
    173 
    174 	/* sanity check */
    175 	if (line == 0 || line >= NICU_INT)
    176 		return -1;
    177 
    178 	*ihp = line;
    179 	return 0;
    180 }
    181 
    182 const char *
    183 pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char *buf, size_t len)
    184 {
    185 	if (ih >= NICU_INT)
    186 		snprintf(buf, len, "level %d", ih - NICU_INT);
    187 	else
    188 		snprintf(buf, len, "irq %d", ih);
    189 
    190 	return buf;
    191 }
    192 
    193 const struct evcnt *
    194 pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
    195 {
    196 
    197 	/* XXX for now, no evcnt parent reported */
    198 	return NULL;
    199 }
    200 
    201 int
    202 pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
    203 		 int attr, uint64_t data)
    204 {
    205 
    206 	switch (attr) {
    207 	case PCI_INTR_MPSAFE:
    208 		return 0;
    209 	default:
    210 		return ENODEV;
    211 	}
    212 }
    213 
    214 void *
    215 pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
    216     int (*func)(void *), void *arg)
    217 {
    218 
    219 	if (ih >= NICU_INT)
    220 		return cpu_intr_establish(ih - NICU_INT, level, func, arg);
    221 	else
    222 		return icu_intr_establish(ih, IST_LEVEL, level, func, arg);
    223 }
    224 
    225 void
    226 pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
    227 {
    228 
    229 	/* Try both, only the valid one will disestablish. */
    230 	cpu_intr_disestablish(cookie);
    231 	icu_intr_disestablish(cookie);
    232 }
    233 
    234 void
    235 pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin, int swiz,
    236     int *iline)
    237 {
    238 
    239 	/*
    240 	 * Use irq 9 on all devices on the Qube's PCI slot.
    241 	 * XXX doesn't handle devices over PCI-PCI bridges
    242 	 */
    243 	if (bus == 0 && dev == 10 && pin != PCI_INTERRUPT_PIN_NONE)
    244 		*iline = 9;
    245 }
    246 
    247 int
    248 pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func, pcireg_t id)
    249 {
    250 
    251 	/* ignore bogus IDs */
    252 	if (PCI_VENDOR(id) == 0)
    253 		return 0;
    254 
    255 	/* 2700 hardware wedges on accesses to device 6. */
    256 	if (bus == 0 && dev == 6)
    257 		return 0;
    258 
    259 	/* 2800 hardware wedges on accesses to device 31. */
    260 	if (bus == 0 && dev == 31)
    261 		return 0;
    262 
    263 	/* Don't configure the bridge and PCI probe. */
    264 	if (PCI_VENDOR(id) == PCI_VENDOR_MARVELL &&
    265 	    PCI_PRODUCT(id) == PCI_PRODUCT_MARVELL_GT64011)
    266 	        return 0;
    267 
    268 	/* Don't configure on-board VIA VT82C586 (pcib, uhci) */
    269 	if (bus == 0 && dev == 9 && (func == 0 || func == 2))
    270 		return 0;
    271 
    272 	/* Enable viaide secondary port. Some firmware doesn't enable it. */
    273 	if (bus == 0 && dev == 9 && func == 1) {
    274 		pcitag_t tag;
    275 		pcireg_t csr;
    276 
    277 #define	APO_VIAIDECONF	(APO_VIA_REGBASE + 0x00)
    278 
    279 		tag = pci_make_tag(pc, bus, dev, func);
    280 		csr = pci_conf_read(pc, tag, APO_VIAIDECONF);
    281 		pci_conf_write(pc, tag, APO_VIAIDECONF,
    282 		    csr | APO_IDECONF_EN(1));
    283 	}
    284 	return PCI_CONF_DEFAULT & ~(PCI_COMMAND_SERR_ENABLE |
    285 	    PCI_COMMAND_PARITY_ENABLE);
    286 }
    287