1 /*- 2 * Copyright (c) 2017 Rogiel Sulzbach <rogiel@allogica.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/rman.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 38 #include <machine/bus.h> 39 #include <dev/ofw/ofw_bus.h> 40 #include <dev/ofw/ofw_bus_subr.h> 41 42 #include <dev/ahci/ahci.h> 43 #include <arm/freescale/imx/imx_iomuxreg.h> 44 #include <arm/freescale/imx/imx_iomuxvar.h> 45 #include <arm/freescale/imx/imx_ccmvar.h> 46 47 #define SATA_TIMER1MS 0x000000e0 48 49 #define SATA_P0PHYCR 0x00000178 50 #define SATA_P0PHYCR_CR_READ (1 << 19) 51 #define SATA_P0PHYCR_CR_WRITE (1 << 18) 52 #define SATA_P0PHYCR_CR_CAP_DATA (1 << 17) 53 #define SATA_P0PHYCR_CR_CAP_ADDR (1 << 16) 54 #define SATA_P0PHYCR_CR_DATA_IN(v) ((v) & 0xffff) 55 56 #define SATA_P0PHYSR 0x0000017c 57 #define SATA_P0PHYSR_CR_ACK (1 << 18) 58 #define SATA_P0PHYSR_CR_DATA_OUT(v) ((v) & 0xffff) 59 60 /* phy registers */ 61 #define SATA_PHY_CLOCK_RESET 0x7f3f 62 #define SATA_PHY_CLOCK_RESET_RST (1 << 0) 63 64 #define SATA_PHY_LANE0_OUT_STAT 0x2003 65 #define SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE (1 << 1) 66 67 static struct ofw_compat_data compat_data[] = { 68 {"fsl,imx6q-ahci", true}, 69 {NULL, false} 70 }; 71 72 static int 73 imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, bool on) 74 { 75 uint32_t v; 76 int timeout; 77 bool state; 78 79 v = ATA_INL(sc->r_mem, SATA_P0PHYCR); 80 if (on) { 81 v |= bitmask; 82 } else { 83 v &= ~bitmask; 84 } 85 ATA_OUTL(sc->r_mem, SATA_P0PHYCR, v); 86 87 for (timeout = 5000; timeout > 0; --timeout) { 88 v = ATA_INL(sc->r_mem, SATA_P0PHYSR); 89 state = (v & SATA_P0PHYSR_CR_ACK) == SATA_P0PHYSR_CR_ACK; 90 if(state == on) { 91 break; 92 } 93 DELAY(100); 94 } 95 96 if (timeout > 0) { 97 return (0); 98 } 99 100 return (ETIMEDOUT); 101 } 102 103 static int 104 imx6_ahci_phy_addr(struct ahci_controller* sc, uint32_t addr) 105 { 106 int error; 107 108 DELAY(100); 109 110 ATA_OUTL(sc->r_mem, SATA_P0PHYCR, addr); 111 112 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, true); 113 if (error != 0) { 114 device_printf(sc->dev, 115 "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=1\n", 116 __FUNCTION__); 117 return (error); 118 } 119 120 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, false); 121 if (error != 0) { 122 device_printf(sc->dev, 123 "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=0\n", 124 __FUNCTION__); 125 return (error); 126 } 127 128 return (0); 129 } 130 131 static int 132 imx6_ahci_phy_write(struct ahci_controller* sc, uint32_t addr, 133 uint16_t data) 134 { 135 int error; 136 137 error = imx6_ahci_phy_addr(sc, addr); 138 if (error != 0) { 139 device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", 140 __FUNCTION__); 141 return (error); 142 } 143 144 ATA_OUTL(sc->r_mem, SATA_P0PHYCR, data); 145 146 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, true); 147 if (error != 0) { 148 device_printf(sc->dev, 149 "%s: error on SATA_P0PHYCR_CR_CAP_DATA=1\n", __FUNCTION__); 150 return (error); 151 } 152 if (imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, false) != 0) { 153 device_printf(sc->dev, 154 "%s: error on SATA_P0PHYCR_CR_CAP_DATA=0\n", __FUNCTION__); 155 return (error); 156 } 157 158 if ((addr == SATA_PHY_CLOCK_RESET) && data) { 159 /* we can't check ACK after RESET */ 160 ATA_OUTL(sc->r_mem, SATA_P0PHYCR, 161 SATA_P0PHYCR_CR_DATA_IN(data) | SATA_P0PHYCR_CR_WRITE); 162 return (0); 163 } 164 165 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, true); 166 if (error != 0) { 167 device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=1\n", 168 __FUNCTION__); 169 return (error); 170 } 171 172 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, false); 173 if (error != 0) { 174 device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=0\n", 175 __FUNCTION__); 176 return (error); 177 } 178 179 return (0); 180 } 181 182 static int 183 imx6_ahci_phy_read(struct ahci_controller* sc, uint32_t addr, uint16_t* val) 184 { 185 int error; 186 uint32_t v; 187 188 error = imx6_ahci_phy_addr(sc, addr); 189 if (error != 0) { 190 device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", 191 __FUNCTION__); 192 return (error); 193 } 194 195 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, true); 196 if (error != 0) { 197 device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=1\n", 198 __FUNCTION__); 199 return (error); 200 } 201 202 v = ATA_INL(sc->r_mem, SATA_P0PHYSR); 203 204 error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, false); 205 if (error != 0) { 206 device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=0\n", 207 __FUNCTION__); 208 return (error); 209 } 210 211 *val = SATA_P0PHYSR_CR_DATA_OUT(v); 212 return (0); 213 } 214 215 static int 216 imx6_ahci_probe(device_t dev) 217 { 218 219 if (!ofw_bus_status_okay(dev)) { 220 return (ENXIO); 221 } 222 223 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) { 224 return (ENXIO); 225 } 226 device_set_desc(dev, "i.MX6 Integrated AHCI controller"); 227 228 return (BUS_PROBE_DEFAULT); 229 } 230 231 static int 232 imx6_ahci_attach(device_t dev) 233 { 234 struct ahci_controller* ctlr; 235 uint16_t pllstat; 236 uint32_t v; 237 int error, timeout; 238 239 ctlr = device_get_softc(dev); 240 241 /* Power up the controller and phy. */ 242 error = imx6_ccm_sata_enable(); 243 if (error != 0) { 244 device_printf(dev, "error enabling controller and phy\n"); 245 return (error); 246 } 247 248 ctlr->vendorid = 0; 249 ctlr->deviceid = 0; 250 ctlr->subvendorid = 0; 251 ctlr->subdeviceid = 0; 252 ctlr->numirqs = 1; 253 ctlr->r_rid = 0; 254 if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 255 &ctlr->r_rid, RF_ACTIVE)) == NULL) { 256 return (ENXIO); 257 } 258 259 v = imx_iomux_gpr_get(IOMUX_GPR13); 260 /* Clear out existing values; these numbers are bitmasks. */ 261 v &= ~(IOMUX_GPR13_SATA_PHY_8(7) | 262 IOMUX_GPR13_SATA_PHY_7(0x1f) | 263 IOMUX_GPR13_SATA_PHY_6(7) | 264 IOMUX_GPR13_SATA_SPEED(1) | 265 IOMUX_GPR13_SATA_PHY_5(1) | 266 IOMUX_GPR13_SATA_PHY_4(7) | 267 IOMUX_GPR13_SATA_PHY_3(0xf) | 268 IOMUX_GPR13_SATA_PHY_2(0x1f) | 269 IOMUX_GPR13_SATA_PHY_1(1) | 270 IOMUX_GPR13_SATA_PHY_0(1)); 271 /* setting */ 272 v |= IOMUX_GPR13_SATA_PHY_8(5) | /* Rx 3.0db */ 273 IOMUX_GPR13_SATA_PHY_7(0x12) | /* Rx SATA2m */ 274 IOMUX_GPR13_SATA_PHY_6(3) | /* Rx DPLL mode */ 275 IOMUX_GPR13_SATA_SPEED(1) | /* 3.0GHz */ 276 IOMUX_GPR13_SATA_PHY_5(0) | /* SpreadSpectram */ 277 IOMUX_GPR13_SATA_PHY_4(4) | /* Tx Attenuation 9/16 */ 278 IOMUX_GPR13_SATA_PHY_3(0) | /* Tx Boost 0db */ 279 IOMUX_GPR13_SATA_PHY_2(0x11) | /* Tx Level 1.104V */ 280 IOMUX_GPR13_SATA_PHY_1(1); /* PLL clock enable */ 281 imx_iomux_gpr_set(IOMUX_GPR13, v); 282 283 /* phy reset */ 284 error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET, 285 SATA_PHY_CLOCK_RESET_RST); 286 if (error != 0) { 287 device_printf(dev, "cannot reset PHY\n"); 288 goto fail; 289 } 290 291 for (timeout = 50; timeout > 0; --timeout) { 292 DELAY(100); 293 error = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT, 294 &pllstat); 295 if (error != 0) { 296 device_printf(dev, "cannot read LANE0 status\n"); 297 goto fail; 298 } 299 if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) { 300 break; 301 } 302 } 303 if (timeout <= 0) { 304 device_printf(dev, "time out reading LANE0 status\n"); 305 error = ETIMEDOUT; 306 goto fail; 307 } 308 309 /* Support Staggered Spin-up */ 310 v = ATA_INL(ctlr->r_mem, AHCI_CAP); 311 ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS); 312 313 /* Ports Implemented. must set 1 */ 314 v = ATA_INL(ctlr->r_mem, AHCI_PI); 315 ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0)); 316 317 /* set 1ms-timer = AHB clock / 1000 */ 318 ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS, 319 imx_ccm_ahb_hz() / 1000); 320 321 /* 322 * Note: ahci_attach will release ctlr->r_mem on errors automatically 323 */ 324 return (ahci_attach(dev)); 325 326 fail: 327 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); 328 return (error); 329 } 330 331 static int 332 imx6_ahci_detach(device_t dev) 333 { 334 335 return (ahci_detach(dev)); 336 } 337 338 static device_method_t imx6_ahci_ata_methods[] = { 339 /* device probe, attach and detach methods */ 340 DEVMETHOD(device_probe, imx6_ahci_probe), 341 DEVMETHOD(device_attach, imx6_ahci_attach), 342 DEVMETHOD(device_detach, imx6_ahci_detach), 343 344 /* ahci bus methods */ 345 DEVMETHOD(bus_print_child, ahci_print_child), 346 DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), 347 DEVMETHOD(bus_release_resource, ahci_release_resource), 348 DEVMETHOD(bus_setup_intr, ahci_setup_intr), 349 DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), 350 DEVMETHOD(bus_child_location_str, ahci_child_location_str), 351 352 DEVMETHOD_END 353 }; 354 355 static driver_t ahci_ata_driver = { 356 "ahci", 357 imx6_ahci_ata_methods, 358 sizeof(struct ahci_controller) 359 }; 360 361 DRIVER_MODULE(imx6_ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0); 362 MODULE_DEPEND(imx6_ahci, ahci, 1, 1, 1); 363 SIMPLEBUS_PNP_INFO(compat_data) 364