#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <loongson/dev/bonitoreg.h>
#include <loongson/dev/bonitovar.h>
#include <loongson/dev/bonito_irq.h>
int gdium_revision = 0;
void gdium_attach_hook(pci_chipset_tag_t);
void gdium_device_register(struct device *, void *);
int gdium_intr_map(int, int, int);
void gdium_powerdown(void);
void gdium_reset(void);
void gdium_setup(void);
const struct bonito_config gdium_bonito = {
.bc_adbase = 11,
.bc_gpioIE = LOONGSON_INTRMASK_GPIO,
.bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
LOONGSON_INTRMASK_PCI_PARERR,
.bc_intSteer = 0,
.bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
.bc_attach_hook = gdium_attach_hook,
.bc_intr_map = gdium_intr_map
};
const struct platform gdium_platform = {
.system_type = LOONGSON_GDIUM,
.vendor = "EMTEC",
.product = "Gdium",
.bonito_config = &gdium_bonito,
.isa_chipset = NULL,
.legacy_io_ranges = NULL,
.setup = gdium_setup,
.device_register = gdium_device_register,
.powerdown = gdium_powerdown,
.reset = gdium_reset
};
void
gdium_attach_hook(pci_chipset_tag_t pc)
{
pcireg_t id;
pcitag_t tag;
#ifdef notyet
int bar;
#endif
#if 0
pcireg_t reg;
int dev, func;
#endif
#ifdef notyet
tag = pci_make_tag(pc, 0, 13, 0);
for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4)
pci_conf_write(pc, tag, bar, 0);
#else
tag = pci_make_tag(pc, 0, 13, 0);
pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000);
#endif
tag = pci_make_tag(pc, 0, 17, 0);
id = pci_conf_read(pc, tag, PCI_ID_REG);
if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
gdium_revision = 1;
#if 0
for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
tag = pci_make_tag(pc, 0, dev, 0);
id = pci_conf_read(pc, tag, PCI_ID_REG);
if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
continue;
if (gdium_revision != 0) {
reg = pci_conf_read(pc, tag, 0xe0);
reg |= 0x00000003;
pci_conf_write(pc, tag, 0xe0, reg);
} else {
for (func = 0; func < 2; func++) {
tag = pci_make_tag(pc, 0, dev, func);
id = pci_conf_read(pc, tag, PCI_ID_REG);
if (PCI_VENDOR(id) != PCI_VENDOR_NEC)
continue;
if (PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB &&
PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2)
continue;
reg = pci_conf_read(pc, tag, 0xe0);
reg &= ~0x00000007;
reg |= 0x00000005;
pci_conf_write(pc, tag, 0xe0, reg);
pci_conf_write(pc, tag, 0xe4, 0x00000020);
}
}
}
#endif
}
int
gdium_intr_map(int dev, int fn, int pin)
{
switch (dev) {
case 13:
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4);
case 14:
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA);
case 15:
if (gdium_revision == 0)
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
(pin - 1));
else
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB);
case 16:
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID);
case 17:
if (gdium_revision != 0)
return BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC);
else
break;
default:
break;
}
return -1;
}
extern struct cfdriver bonito_cd;
extern struct cfdriver pci_cd;
extern struct cfdriver ehci_cd;
extern struct cfdriver usb_cd;
extern struct cfdriver uhub_cd;
extern struct cfdriver umass_cd;
extern struct cfdriver scsibus_cd;
extern struct cfdriver sd_cd;
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
void
gdium_device_register(struct device *dev, void *aux)
{
struct cfdriver *cf = dev->dv_cfdata->cf_driver;
static int gkey_chain_pos = 0;
static struct device *lastparent = NULL;
if (dev->dv_parent != lastparent && gkey_chain_pos != 0)
return;
switch (gkey_chain_pos) {
case 0:
if (cf == &bonito_cd)
goto advance;
break;
case 1:
if (cf == &pci_cd)
goto advance;
break;
case 2:
if (cf == &ehci_cd) {
struct pci_attach_args *paa = aux;
if (paa->pa_device == 15)
goto advance;
}
break;
case 3:
if (cf == &usb_cd)
goto advance;
break;
case 4:
if (cf == &uhub_cd)
goto advance;
break;
case 5:
if (cf == &umass_cd) {
struct usb_attach_arg *uaa = aux;
if (uaa->port == 3)
goto advance;
}
break;
case 6:
if (cf == &scsibus_cd)
goto advance;
break;
case 7:
bootdv = dev;
break;
}
return;
advance:
gkey_chain_pos++;
lastparent = dev;
}
void
gdium_powerdown()
{
REGVAL(BONITO_GPIODATA) |= 0x00000002;
REGVAL(BONITO_GPIOIE) &= ~0x00000002;
}
void
gdium_reset()
{
REGVAL(BONITO_GPIODATA) &= ~0x00000002;
REGVAL(BONITO_GPIOIE) &= ~0x00000002;
}
void
gdium_setup()
{
bonito_early_setup();
}