static void jmahci_attach(device_t parent, device_t self, void *aux) { struct jmahci_attach_args *jma = aux; const struct pci_attach_args *pa = jma->jma_pa; struct ahci_softc *sc = device_private(self); uint32_t ahci_cap; aprint_naive(": AHCI disk controller\n"); aprint_normal("\n"); sc->sc_atac.atac_dev = self; sc->sc_ahcit = jma->jma_ahcit; sc->sc_ahcih = jma->jma_ahcih; ahci_cap = AHCI_READ(sc, AHCI_CAP); if (pci_dma64_available(jma->jma_pa) && (ahci_cap & AHCI_CAP_64BIT)) sc->sc_dmat = jma->jma_pa->pa_dmat64; else sc->sc_dmat = jma->jma_pa->pa_dmat; if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID) sc->sc_atac_capflags = ATAC_CAP_RAID; ahci_attach(sc); if (!pmf_device_register(self, NULL, jmahci_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static int ahci_gen_attach(device_t dev) { struct ahci_controller *ctlr = device_get_softc(dev); int error; ctlr->r_rid = 0; ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_rid, RF_ACTIVE); if (ctlr->r_mem == NULL) return (ENXIO); /* Setup controller defaults. */ ctlr->numirqs = 1; /* Reset controller */ if ((error = ahci_gen_ctlr_reset(dev)) == 0) error = ahci_attach(dev); if (error != 0) { if (ctlr->r_mem != NULL) bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); } return error; }
void imxahci_attach(struct device *parent, struct device *self, void *args) { struct armv7_attach_args *aa = args; struct imxahci_softc *imxsc = (struct imxahci_softc *) self; struct ahci_softc *sc = &imxsc->sc; uint32_t timeout = 0x100000; sc->sc_iot = aa->aa_iot; sc->sc_ios = aa->aa_dev->mem[0].size; sc->sc_dmat = aa->aa_dmat; if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) panic("imxahci_attach: bus_space_map failed!"); sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO, ahci_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); goto unmap; } /* power it up */ imxccm_enable_sata(); delay(100); /* power phy up */ imxiomuxc_enable_sata(); /* setup */ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR) & ~SATA_P0PHYCR_TEST_PDDQ); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_GHC, SATA_GHC_HR); while (!bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_VERSIONR)); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP) | SATA_CAP_SSS); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, 1); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS, imxccm_get_ahbclk()); while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0SSTS) & 0xF) && timeout--); if (ahci_attach(sc) != 0) { /* error printed by ahci_attach */ goto irq; } return; irq: arm_intr_disestablish(sc->sc_ih); unmap: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); }
static void ahci_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct ahci_pci_softc *psc = device_private(self); struct ahci_softc *sc = &psc->ah_sc; bus_size_t size; char devinfo[256]; const char *intrstr; pci_intr_handle_t intrhandle; void *ih; sc->sc_atac.atac_dev = self; if (pci_mapreg_map(pa, AHCI_PCI_ABAR, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_ahcit, &sc->sc_ahcih, NULL, &size) != 0) { aprint_error_dev(self, "can't map ahci registers\n"); return; } psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); aprint_naive(": AHCI disk controller\n"); aprint_normal(": %s\n", devinfo); if (pci_intr_map(pa, &intrhandle) != 0) { aprint_error("%s: couldn't map interrupt\n", AHCINAME(sc)); return; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, ahci_intr, sc); if (ih == NULL) { aprint_error("%s: couldn't establish interrupt", AHCINAME(sc)); return; } aprint_normal("%s: interrupting at %s\n", AHCINAME(sc), intrstr ? intrstr : "unknown interrupt"); sc->sc_dmat = pa->pa_dmat; if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID) { AHCIDEBUG_PRINT(("%s: RAID mode\n", AHCINAME(sc)), DEBUG_PROBE); sc->sc_atac_capflags = ATAC_CAP_RAID; } else { AHCIDEBUG_PRINT(("%s: SATA mode\n", AHCINAME(sc)), DEBUG_PROBE); } ahci_attach(sc); if (!pmf_device_register(self, NULL, ahci_pci_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void ahci_pci_attach(struct device *parent, struct device *self, void *aux) { struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self; struct ahci_softc *sc = &psc->psc_ahci; struct pci_attach_args *pa = aux; const struct ahci_device *ad; pci_intr_handle_t ih; int mapped = 0; psc->psc_pc = pa->pa_pc; psc->psc_tag = pa->pa_tag; sc->sc_dmat = pa->pa_dmat; ad = ahci_lookup_device(pa); if (ad != NULL && ad->ad_attach != NULL) { if (ad->ad_attach(sc, pa) != 0) { /* error should be printed by ad_attach */ return; } } if (!(sc->sc_flags & AHCI_F_NO_MSI)) mapped = pci_intr_map_msi(pa, &ih) != 0 ? 0 : 1; if (!mapped && pci_intr_map(pa, &ih) != 0) { printf(": unable to map interrupt\n"); return; } printf(": %s,", pci_intr_string(pa->pa_pc, ih)); if (ahci_map_regs(psc, pa) != 0) { /* error already printed by ahci_map_regs */ return; } if (ahci_map_intr(psc, pa, ih) != 0) { /* error already printed by ahci_map_intr */ goto unmap; } if (ahci_attach(sc) != 0) { /* error printed by ahci_attach */ goto unmap; } return; unmap: ahci_unmap_regs(psc); return; }
static void tegra_ahcisata_attach(device_t parent, device_t self, void *aux) { struct tegra_ahcisata_softc * const sc = device_private(self); struct tegraio_attach_args * const tio = aux; const struct tegra_locators * const loc = &tio->tio_loc; prop_dictionary_t prop = device_properties(self); const char *pin; sc->sc_bst = tio->tio_bst; bus_space_subregion(tio->tio_bst, tio->tio_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); sc->sc.sc_atac.atac_dev = self; sc->sc.sc_dmat = tio->tio_dmat; sc->sc.sc_ahcit = tio->tio_bst; sc->sc.sc_ahcis = loc->loc_size - TEGRA_AHCISATA_OFFSET; bus_space_subregion(tio->tio_bst, tio->tio_bsh, loc->loc_offset + TEGRA_AHCISATA_OFFSET, loc->loc_size - TEGRA_AHCISATA_OFFSET, &sc->sc.sc_ahcih); sc->sc.sc_ahci_quirks = AHCI_QUIRK_SKIP_RESET; aprint_naive("\n"); aprint_normal(": SATA\n"); if (prop_dictionary_get_cstring_nocopy(prop, "power-gpio", &pin)) { sc->sc_pin_power = tegra_gpio_acquire(pin, GPIO_PIN_OUTPUT); if (sc->sc_pin_power) tegra_gpio_write(sc->sc_pin_power, 1); } tegra_car_periph_sata_enable(); tegra_xusbpad_sata_enable(); tegra_ahcisata_init(sc); sc->sc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL, ahci_intr, &sc->sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); ahci_attach(&sc->sc); }
static void imx6_ahcisata_attach(device_t parent, device_t self, void *aux) { struct imx_ahci_softc *sc; struct ahci_softc *ahci_sc; struct axi_attach_args *aa; aa = aux; sc = device_private(self); sc->sc_dev = self; sc->sc_iot = aa->aa_iot; if (aa->aa_size == AXICF_SIZE_DEFAULT) aa->aa_size = IMX6_SATA_SIZE; aprint_naive("\n"); aprint_normal(": AHCI Controller\n"); if (bus_space_map(aa->aa_iot, aa->aa_addr, aa->aa_size, 0, &sc->sc_ioh)) { aprint_error_dev(self, "cannot map registers\n"); return; } if (ixm6_ahcisata_init(sc) != 0) { aprint_error_dev(self, "couldn't init ahci\n"); return; } ahci_sc = &sc->sc_ahcisc; ahci_sc->sc_atac.atac_dev = sc->sc_dev; ahci_sc->sc_ahci_ports = 1; ahci_sc->sc_dmat = aa->aa_dmat; ahci_sc->sc_ahcis = aa->aa_size; ahci_sc->sc_ahcit = sc->sc_iot; ahci_sc->sc_ahcih = sc->sc_ioh; sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL, ahci_intr, ahci_sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "unable to establish interrupt\n"); return; } ahci_attach(ahci_sc); }
static int ahci_a10_attach(device_t dev) { int error; struct ahci_controller *ctlr; ctlr = device_get_softc(dev); ctlr->quirks = AHCI_Q_NOPMP; ctlr->vendorid = 0; ctlr->deviceid = 0; ctlr->subvendorid = 0; ctlr->subdeviceid = 0; ctlr->r_rid = 0; if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_rid, RF_ACTIVE))) return (ENXIO); /* Turn on the PLL for SATA */ a10_clk_ahci_activate(); /* Reset controller */ if ((error = ahci_a10_ctlr_reset(dev)) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (error); }; /* * No MSI registers on this platform. */ ctlr->msi = 0; ctlr->numirqs = 1; /* Channel start callback(). */ ctlr->ch_start = ahci_a10_ch_start; /* * Note: ahci_attach will release ctlr->r_mem on errors automatically */ return (ahci_attach(dev)); }
static void ahci_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct ahci_pci_softc *psc = device_private(self); struct ahci_softc *sc = &psc->ah_sc; const char *intrstr; bool ahci_cap_64bit; bool ahci_bad_64bit; pci_intr_handle_t intrhandle; sc->sc_atac.atac_dev = self; if (pci_mapreg_map(pa, AHCI_PCI_ABAR, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_ahcit, &sc->sc_ahcih, NULL, &sc->sc_ahcis) != 0) { aprint_error_dev(self, "can't map ahci registers\n"); return; } psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; pci_aprint_devinfo(pa, "AHCI disk controller"); if (pci_intr_map(pa, &intrhandle) != 0) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); psc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, ahci_intr, sc); if (psc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr ? intrstr : "unknown interrupt"); sc->sc_dmat = pa->pa_dmat; sc->sc_ahci_quirks = ahci_pci_has_quirk(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); ahci_cap_64bit = (AHCI_READ(sc, AHCI_CAP) & AHCI_CAP_64BIT) != 0; ahci_bad_64bit = ((sc->sc_ahci_quirks & AHCI_PCI_QUIRK_BAD64) != 0); if (pci_dma64_available(pa) && ahci_cap_64bit) { if (!ahci_bad_64bit) sc->sc_dmat = pa->pa_dmat64; aprint_verbose_dev(self, "64-bit DMA%s\n", (sc->sc_dmat == pa->pa_dmat) ? " unavailable" : ""); } if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID) { AHCIDEBUG_PRINT(("%s: RAID mode\n", AHCINAME(sc)), DEBUG_PROBE); sc->sc_atac_capflags = ATAC_CAP_RAID; } else { AHCIDEBUG_PRINT(("%s: SATA mode\n", AHCINAME(sc)), DEBUG_PROBE); } ahci_attach(sc); if (!pmf_device_register(self, NULL, ahci_pci_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static int imx6_ahci_attach(device_t dev) { struct ahci_controller* ctlr; uint16_t pllstat; uint32_t v; int error, timeout; ctlr = device_get_softc(dev); /* Power up the controller and phy. */ error = imx6_ccm_sata_enable(); if (error != 0) { device_printf(dev, "error enabling controller and phy\n"); return (error); } ctlr->vendorid = 0; ctlr->deviceid = 0; ctlr->subvendorid = 0; ctlr->subdeviceid = 0; ctlr->numirqs = 1; ctlr->r_rid = 0; if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_rid, RF_ACTIVE)) == NULL) { return (ENXIO); } v = imx_iomux_gpr_get(IOMUX_GPR13); /* Clear out existing values; these numbers are bitmasks. */ v &= ~(IOMUX_GPR13_SATA_PHY_8(7) | IOMUX_GPR13_SATA_PHY_7(0x1f) | IOMUX_GPR13_SATA_PHY_6(7) | IOMUX_GPR13_SATA_SPEED(1) | IOMUX_GPR13_SATA_PHY_5(1) | IOMUX_GPR13_SATA_PHY_4(7) | IOMUX_GPR13_SATA_PHY_3(0xf) | IOMUX_GPR13_SATA_PHY_2(0x1f) | IOMUX_GPR13_SATA_PHY_1(1) | IOMUX_GPR13_SATA_PHY_0(1)); /* setting */ v |= IOMUX_GPR13_SATA_PHY_8(5) | /* Rx 3.0db */ IOMUX_GPR13_SATA_PHY_7(0x12) | /* Rx SATA2m */ IOMUX_GPR13_SATA_PHY_6(3) | /* Rx DPLL mode */ IOMUX_GPR13_SATA_SPEED(1) | /* 3.0GHz */ IOMUX_GPR13_SATA_PHY_5(0) | /* SpreadSpectram */ IOMUX_GPR13_SATA_PHY_4(4) | /* Tx Attenuation 9/16 */ IOMUX_GPR13_SATA_PHY_3(0) | /* Tx Boost 0db */ IOMUX_GPR13_SATA_PHY_2(0x11) | /* Tx Level 1.104V */ IOMUX_GPR13_SATA_PHY_1(1); /* PLL clock enable */ imx_iomux_gpr_set(IOMUX_GPR13, v); /* phy reset */ error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET, SATA_PHY_CLOCK_RESET_RST); if (error != 0) { device_printf(dev, "cannot reset PHY\n"); goto fail; } for (timeout = 50; timeout > 0; --timeout) { DELAY(100); error = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT, &pllstat); if (error != 0) { device_printf(dev, "cannot read LANE0 status\n"); goto fail; } if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) { break; } } if (timeout <= 0) { device_printf(dev, "time out reading LANE0 status\n"); error = ETIMEDOUT; goto fail; } /* Support Staggered Spin-up */ v = ATA_INL(ctlr->r_mem, AHCI_CAP); ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS); /* Ports Implemented. must set 1 */ v = ATA_INL(ctlr->r_mem, AHCI_PI); ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0)); /* set 1ms-timer = AHB clock / 1000 */ ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS, imx_ccm_ahb_hz() / 1000); /* * Note: ahci_attach will release ctlr->r_mem on errors automatically */ return (ahci_attach(dev)); fail: bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (error); }
static int tegra_ahci_attach(device_t dev) { struct tegra_ahci_sc *sc; struct ahci_controller *ctlr; phandle_t node; int rv, rid; sc = device_get_softc(dev); sc->dev = dev; ctlr = &sc->ctlr; node = ofw_bus_get_node(dev); ctlr->r_rid = 0; ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_rid, RF_ACTIVE); if (ctlr->r_mem == NULL) return (ENXIO); rid = 1; sc->sata_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sata_mem == NULL) { rv = ENXIO; goto fail; } rv = get_fdt_resources(sc, node); if (rv != 0) { device_printf(sc->dev, "Failed to allocate FDT resource(s)\n"); goto fail; } rv = enable_fdt_resources(sc); if (rv != 0) { device_printf(sc->dev, "Failed to enable FDT resource(s)\n"); goto fail; } rv = tegra_ahci_ctrl_init(sc); if (rv != 0) { device_printf(sc->dev, "Failed to initialize controller)\n"); goto fail; } /* Setup controller defaults. */ ctlr->msi = 0; ctlr->numirqs = 1; ctlr->ccc = 0; /* Reset controller. */ rv = tegra_ahci_ctlr_reset(dev); if (rv != 0) goto fail; rv = ahci_attach(dev); return (rv); fail: /* XXX FDT stuff */ if (sc->sata_mem != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->sata_mem); if (ctlr->r_mem != NULL) bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (rv); }
static void awin_ahci_attach(device_t parent, device_t self, void *aux) { struct awin_ahci_softc * const asc = device_private(self); struct ahci_softc * const sc = &asc->asc_sc; struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; awin_ahci_enable(aio->aio_core_bst, aio->aio_ccm_bsh); sc->sc_atac.atac_dev = self; sc->sc_dmat = aio->aio_dmat; sc->sc_ahcit = aio->aio_core_bst; sc->sc_ahcis = loc->loc_size; sc->sc_ahci_ports = 1; sc->sc_ahci_quirks = AHCI_QUIRK_BADPMP; sc->sc_save_init_data = true; sc->sc_channel_start = awin_ahci_channel_start; bus_space_subregion(aio->aio_core_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_ahcih); aprint_naive(": AHCI SATA controller\n"); aprint_normal(": AHCI SATA controller\n"); /* * Bring up the PHY. */ awin_ahci_phy_init(asc); /* * If there is a GPIO to turn on power, do it now. */ const char *pin_name; prop_dictionary_t dict = device_properties(self); if (prop_dictionary_get_cstring_nocopy(dict, "power-gpio", &pin_name)) { if (awin_gpio_pin_reserve(pin_name, &asc->asc_gpio_pin)) { awin_gpio_pindata_write(&asc->asc_gpio_pin, 1); } else { aprint_error_dev(self, "failed to reserve GPIO \"%s\"\n", pin_name); } } /* * Establish the interrupt */ asc->asc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL, ahci_intr, sc); if (asc->asc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", loc->loc_intr); goto fail; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); ahci_attach(sc); return; fail: if (asc->asc_ih) { intr_disestablish(asc->asc_ih); asc->asc_ih = NULL; } }