bool spi_hw_attach(sdioh_info_t *sd) { osl_t *osh; spih_info_t *si; sd_trace(("%s: enter\n", __FUNCTION__)); osh = sd->osh; if ((si = (spih_info_t *)MALLOC(osh, sizeof(spih_info_t))) == NULL) { sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); return FALSE; } bzero(si, sizeof(spih_info_t)); sd->controller = si; si->osh = sd->osh; si->rev = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_REV, 4) & 0xFF; if (si->rev < 3) { sd_err(("Host controller %d not supported, please upgrade to rev >= 3\n", si->rev)); MFREE(osh, si, sizeof(spih_info_t)); return (FALSE); } sd_err(("Attaching to Generic PCI SPI Host Controller Rev %d\n", si->rev)); ASSERT(si->rev >= 3); si->bar0 = sd->bar0; if (si->rev < 10) { si->pciregs = (spih_pciregs_t *)spi_reg_map(osh, (uintptr)si->bar0, sizeof(spih_pciregs_t)); sd_err(("Mapped PCI Core regs to BAR0 at %p\n", si->pciregs)); si->bar1 = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR1, 4); si->regs = (spih_regs_t *)spi_reg_map(osh, (uintptr)si->bar1, sizeof(spih_regs_t)); sd_err(("Mapped SPI Controller regs to BAR1 at %p\n", si->regs)); } else { si->regs = (spih_regs_t *)spi_reg_map(osh, (uintptr)si->bar0, sizeof(spih_regs_t)); sd_err(("Mapped SPI Controller regs to BAR0 at %p\n", si->regs)); si->pciregs = NULL; } SPIPCI_WREG(osh, &si->regs->spih_ctrl, 0x000000d1); SPIPCI_WREG(osh, &si->regs->spih_ext, 0x00000000); SPIPCI_WREG(osh, &si->regs->spih_gpio_data, SPIH_CS); SPIPCI_WREG(osh, &si->regs->spih_gpio_ctrl, (SPIH_CS | SPIH_SLOT_POWER)); while ((SPIPCI_RREG(osh, &si->regs->spih_stat) & SPIH_RFEMPTY) == 0) { SPIPCI_RREG(osh, &si->regs->spih_data); } OSL_DELAY(250000); if (si->rev >= 4) { if (SPIPCI_RREG(osh, &si->regs->spih_gpio_data) & SPIH_CARD_DETECT) { sd_err(("%s: no card detected in SD slot\n", __FUNCTION__)); spi_reg_unmap(osh, (uintptr)si->regs, sizeof(spih_regs_t)); if (si->pciregs) { spi_reg_unmap(osh, (uintptr)si->pciregs, sizeof(spih_pciregs_t)); } MFREE(osh, si, sizeof(spih_info_t)); return FALSE; } } SPIPCI_WREG(osh, &si->regs->spih_int_edge, 0x80000000); SPIPCI_WREG(osh, &si->regs->spih_int_pol, 0x40000004); if (si->pciregs) { SPIPCI_WREG(osh, &si->pciregs->ICR, PCI_INT_PROP_EN); } sd_trace(("%s: exit\n", __FUNCTION__)); return TRUE; }
/* Attach to PCI-SPI Host Controller Hardware */ bool spi_hw_attach(sdioh_info_t *sd) { osl_t *osh; spih_info_t *si; sd_trace(("%s: enter\n", __FUNCTION__)); osh = sd->osh; if ((si = (spih_info_t *)MALLOC(osh, sizeof(spih_info_t))) == NULL) { sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); return FALSE; } bzero(si, sizeof(spih_info_t)); sd->controller = si; si->osh = sd->osh; si->rev = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_REV, 4) & 0xFF; if (si->rev < 3) { sd_err(("Host controller %d not supported, please upgrade to rev >= 3\n", si->rev)); MFREE(osh, si, sizeof(spih_info_t)); return (FALSE); } sd_err(("Attaching to Generic PCI SPI Host Controller Rev %d\n", si->rev)); /* FPGA Revision < 3 not supported by driver anymore. */ ASSERT(si->rev >= 3); si->bar0 = sd->bar0; /* Rev < 10 PciSpiHost has 2 BARs: * BAR0 = PCI Core Registers * BAR1 = PciSpiHost Registers (all other cores on backplane) * * Rev 10 and up use a different PCI core which only has a single * BAR0 which contains the PciSpiHost Registers. */ if (si->rev < 10) { si->pciregs = (spih_pciregs_t *)spi_reg_map(osh, (uintptr)si->bar0, sizeof(spih_pciregs_t)); sd_err(("Mapped PCI Core regs to BAR0 at %p\n", si->pciregs)); si->bar1 = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR1, 4); si->regs = (spih_regs_t *)spi_reg_map(osh, (uintptr)si->bar1, sizeof(spih_regs_t)); sd_err(("Mapped SPI Controller regs to BAR1 at %p\n", si->regs)); } else { si->regs = (spih_regs_t *)spi_reg_map(osh, (uintptr)si->bar0, sizeof(spih_regs_t)); sd_err(("Mapped SPI Controller regs to BAR0 at %p\n", si->regs)); si->pciregs = NULL; } /* Enable SPI Controller, 16.67MHz SPI Clock */ SPIPCI_WREG(osh, &si->regs->spih_ctrl, 0x000000d1); /* Set extended feature register to defaults */ SPIPCI_WREG(osh, &si->regs->spih_ext, 0x00000000); /* Set GPIO CS# High (de-asserted) */ SPIPCI_WREG(osh, &si->regs->spih_gpio_data, SPIH_CS); /* set GPIO[0] to output for CS# */ /* set GPIO[1] to output for power control */ /* set GPIO[2] to input for card detect */ SPIPCI_WREG(osh, &si->regs->spih_gpio_ctrl, (SPIH_CS | SPIH_SLOT_POWER)); /* Clear out the Read FIFO in case there is any stuff left in there from a previous run. */ while ((SPIPCI_RREG(osh, &si->regs->spih_stat) & SPIH_RFEMPTY) == 0) { SPIPCI_RREG(osh, &si->regs->spih_data); } /* Wait for power to stabilize to the SDIO Card (100msec was insufficient) */ OSL_DELAY(250000); /* Check card detect on FPGA Revision >= 4 */ if (si->rev >= 4) { if (SPIPCI_RREG(osh, &si->regs->spih_gpio_data) & SPIH_CARD_DETECT) { sd_err(("%s: no card detected in SD slot\n", __FUNCTION__)); spi_reg_unmap(osh, (uintptr)si->regs, sizeof(spih_regs_t)); if (si->pciregs) { spi_reg_unmap(osh, (uintptr)si->pciregs, sizeof(spih_pciregs_t)); } MFREE(osh, si, sizeof(spih_info_t)); return FALSE; } } /* Interrupts are level sensitive */ SPIPCI_WREG(osh, &si->regs->spih_int_edge, 0x80000000); /* Interrupts are active low. */ SPIPCI_WREG(osh, &si->regs->spih_int_pol, 0x40000004); /* Enable interrupts through PCI Core. */ if (si->pciregs) { SPIPCI_WREG(osh, &si->pciregs->ICR, PCI_INT_PROP_EN); } sd_trace(("%s: exit\n", __FUNCTION__)); return TRUE; }