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 ixm6_ahcisata_init(struct imx_ahci_softc *sc) { uint32_t v; int timeout; /* AHCISATA clock enable */ v = imx6_ccm_read(CCM_CCGR5); imx6_ccm_write(CCM_CCGR5, v | CCM_CCGR5_100M_CLK_ENABLE(3)); /* PLL power up */ if (imx6_pll_power(CCM_ANALOG_PLL_ENET, 1) != 0) { aprint_error_dev(sc->sc_dev, "couldn't enable CCM_ANALOG_PLL_ENET\n"); return -1; } v = imx6_ccm_read(CCM_ANALOG_PLL_ENET); v |= CCM_ANALOG_PLL_ENET_ENABLE_100M; imx6_ccm_write(CCM_ANALOG_PLL_ENET, v); v = iomux_read(IOMUX_GPR13); /* clear */ 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 */ iomux_write(IOMUX_GPR13, v); /* phy reset */ if (imx6_ahcisata_phy_write(sc, SATA_PHY_CLOCK_RESET, SATA_PHY_CLOCK_RESET_RST) < 0) { aprint_error_dev(sc->sc_dev, "cannot reset PHY\n"); return -1; } for (timeout = 50; timeout > 0; --timeout) { delay(100); v = imx6_ahcisata_phy_read(sc, SATA_PHY_LANE0_OUT_STAT); if (v < 0) { aprint_error_dev(sc->sc_dev, "cannot read LANE0 status\n"); break; } if (v & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) break; } if (timeout <= 0) return -1; /* Support Staggered Spin-up */ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, v | SATA_CAP_SSS); /* Ports Implmented. must set 1 */ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_PI); bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, v | SATA_PI_PI); /* set 1ms-timer = AHB clock / 1000 */ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS, imx6_get_clock(IMX6CLK_AHB) / 1000); return 0; }