#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.13 2022/10/15 04:47:37 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <sys/extent.h>
#include <sys/bus.h>
#include <sys/intr.h>
#include <uvm/uvm_extern.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>
#include <dev/pci/pciconf.h>
#include <powerpc/ibm4xx/ibm405gp.h>
#include <powerpc/ibm4xx/pci_machdep.h>
#include <powerpc/ibm4xx/dev/pcicreg.h>
#ifdef DHT_FIXUP_PDCIDE
#include <dev/pci/pciidereg.h>
#endif
static struct powerpc_bus_space pci_iot = {
_BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE,
0x00000000,
IBM405GP_PCIC0_BASE,
IBM405GP_PCIC0_BASE + 8,
};
static bus_space_handle_t pci_ioh;
void
ibm4xx_pci_machdep_init(void)
{
if (pci_ioh == 0 &&
(bus_space_init(&pci_iot, "pcicfg", NULL, 0) ||
bus_space_map(&pci_iot, IBM405GP_PCIC0_BASE, 8, 0, &pci_ioh)))
panic("Cannot map PCI registers");
}
void
ibm4xx_pci_attach_hook(device_t parent, device_t self,
struct pcibus_attach_args *pba)
{
#ifdef PCI_CONFIGURE_VERBOSE
printf("pci_attach_hook\n");
ibm4xx_show_pci_map();
#endif
ibm4xx_setup_pci();
#ifdef PCI_CONFIGURE_VERBOSE
ibm4xx_show_pci_map();
#endif
}
pcitag_t
ibm4xx_pci_make_tag(void *v, int bus, int device, int function)
{
pcitag_t tag;
if (bus >= 256 || device >= 32 || function >= 8)
panic("pci_make_tag: bad request");
tag = 0x80000000 | (bus << 16) | (device << 11) | (function << 8);
return tag;
}
void
ibm4xx_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
{
if (bp != NULL)
*bp = (tag >> 16) & 0xff;
if (dp != NULL)
*dp = (tag >> 11) & 0x1f;
if (fp != NULL)
*fp = (tag >> 8) & 0x07;
}
pcireg_t
ibm4xx_pci_conf_read(void *v, pcitag_t tag, int reg)
{
pcireg_t data;
if ((unsigned int)reg >= PCI_CONF_SIZE)
return (pcireg_t) -1;
bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, tag | reg);
data = bus_space_read_4(&pci_iot, pci_ioh, PCIC_CFGDATA);
bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, 0);
return data;
}
void
ibm4xx_pci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
{
if ((unsigned int)reg >= PCI_CONF_SIZE)
return;
bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, tag | reg);
bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGDATA, data);
bus_space_write_4(&pci_iot, pci_ioh, PCIC_CFGADDR, 0);
}
int
ibm4xx_pci_intr_setattr(void *v, pci_intr_handle_t *ihp, int attr,
uint64_t data)
{
switch (attr) {
case PCI_INTR_MPSAFE:
return 0;
default:
return ENODEV;
}
}
int
ibm4xx_pci_conf_hook(void *v, int bus, int dev, int func, pcireg_t id)
{
if ((PCI_VENDOR(id) == PCI_VENDOR_IBM && PCI_PRODUCT(id) == PCI_PRODUCT_IBM_405GP) ||
(PCI_VENDOR(id) == PCI_VENDOR_INTEL && PCI_PRODUCT(id) == PCI_PRODUCT_INTEL_80960_RP)) {
return 0;
}
#ifdef DHT_FIXUP_PDCIDE
if (PCI_VENDOR(id) == PCI_VENDOR_PROMISE &&
PCI_PRODUCT(id) == PCI_PRODUCT_PROMISE_PDC20265) {
pcitag_t tag;
pcireg_t csr;
tag = ibm4xx_pci_make_tag(v, bus, dev, func);
csr = ibm4xx_pci_conf_read(v, tag, PCI_CLASS_REG);
csr |= (PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1))
<< PCI_INTERFACE_SHIFT;
ibm4xx_pci_conf_write(v, tag, PCI_CLASS_REG, csr);
}
#endif
return PCI_CONF_DEFAULT;
}