1/*- 2 * Copyright (c) 2014-2015 M. Warner Losh <imp@freebsd.org> 3 * Copyright (c) 2015 Luiz Otavio O Souza <loos@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * The magic-bit-bang sequence used in this code may be based on a linux 28 * platform driver in the Allwinner SDK from Allwinner Technology Co., Ltd. 29 * www.allwinnertech.com, by Daniel Wang <danielwang@allwinnertech.com> 30 * though none of the original code was copied. 31 */ 32 33#include "opt_bus.h" 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD$"); 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/bus.h> 41#include <sys/rman.h> 42#include <sys/kernel.h> 43#include <sys/module.h> 44 45#include <machine/bus.h> 46#include <dev/ofw/ofw_bus.h> 47#include <dev/ofw/ofw_bus_subr.h> 48 49#include <dev/ahci/ahci.h> 50#include <dev/extres/clk/clk.h> 51#include <dev/extres/regulator/regulator.h> 52 53/* 54 * Allwinner a1x/a2x/a8x SATA attachment. This is just the AHCI register 55 * set with a few extra implementation-specific registers that need to 56 * be accounted for. There's only one PHY in the system, and it needs 57 * to be trained to bring the link up. In addition, there's some DMA 58 * specific things that need to be done as well. These things are also 59 * just about completely undocumented, except in ugly code in the Linux 60 * SDK Allwinner releases. 61 */ 62 63/* BITx -- Unknown bit that needs to be set/cleared at position x */ 64/* UFx -- Uknown multi-bit field frobbed during init */ 65#define AHCI_BISTAFR 0x00A0 66#define AHCI_BISTCR 0x00A4 67#define AHCI_BISTFCTR 0x00A8 68#define AHCI_BISTSR 0x00AC 69#define AHCI_BISTDECR 0x00B0 70#define AHCI_DIAGNR 0x00B4 71#define AHCI_DIAGNR1 0x00B8 72#define AHCI_OOBR 0x00BC 73#define AHCI_PHYCS0R 0x00C0 74/* Bits 0..17 are a mystery */ 75#define PHYCS0R_BIT18 (1 << 18) 76#define PHYCS0R_POWER_ENABLE (1 << 19) 77#define PHYCS0R_UF1_MASK (7 << 20) /* Unknown Field 1 */ 78#define PHYCS0R_UF1_INIT (3 << 20) 79#define PHYCS0R_BIT23 (1 << 23) 80#define PHYCS0R_UF2_MASK (7 << 24) /* Uknown Field 2 */ 81#define PHYCS0R_UF2_INIT (5 << 24) 82/* Bit 27 mystery */ 83#define PHYCS0R_POWER_STATUS_MASK (7 << 28) 84#define PHYCS0R_PS_GOOD (2 << 28) 85/* Bit 31 mystery */ 86#define AHCI_PHYCS1R 0x00C4 87/* Bits 0..5 are a mystery */ 88#define PHYCS1R_UF1_MASK (3 << 6) 89#define PHYCS1R_UF1_INIT (2 << 6) 90#define PHYCS1R_UF2_MASK (0x1f << 8) 91#define PHYCS1R_UF2_INIT (6 << 8) 92/* Bits 13..14 are a mystery */ 93#define PHYCS1R_BIT15 (1 << 15) 94#define PHYCS1R_UF3_MASK (3 << 16) 95#define PHYCS1R_UF3_INIT (2 << 16) 96/* Bit 18 mystery */ 97#define PHYCS1R_HIGHZ (1 << 19) 98/* Bits 20..27 mystery */ 99#define PHYCS1R_BIT28 (1 << 28) 100/* Bits 29..31 mystery */ 101#define AHCI_PHYCS2R 0x00C8 102/* bits 0..4 mystery */ 103#define PHYCS2R_UF1_MASK (0x1f << 5) 104#define PHYCS2R_UF1_INIT (0x19 << 5) 105/* Bits 10..23 mystery */ 106#define PHYCS2R_CALIBRATE (1 << 24) 107/* Bits 25..31 mystery */ 108#define AHCI_TIMER1MS 0x00E0 109#define AHCI_GPARAM1R 0x00E8 110#define AHCI_GPARAM2R 0x00EC 111#define AHCI_PPARAMR 0x00F0 112#define AHCI_TESTR 0x00F4 113#define AHCI_VERSIONR 0x00F8 114#define AHCI_IDR 0x00FC 115#define AHCI_RWCR 0x00FC 116 117#define AHCI_P0DMACR 0x0070 118#define AHCI_P0PHYCR 0x0078 119#define AHCI_P0PHYSR 0x007C 120 121#define PLL_FREQ 100000000 122 123struct ahci_a10_softc { 124 struct ahci_controller ahci_ctlr; 125 regulator_t ahci_reg; 126 clk_t clk_pll; 127 clk_t clk_gate; 128}; 129 130static void inline 131ahci_set(struct resource *m, bus_size_t off, uint32_t set) 132{ 133 uint32_t val = ATA_INL(m, off); 134 135 val |= set; 136 ATA_OUTL(m, off, val); 137} 138 139static void inline 140ahci_clr(struct resource *m, bus_size_t off, uint32_t clr) 141{ 142 uint32_t val = ATA_INL(m, off); 143 144 val &= ~clr; 145 ATA_OUTL(m, off, val); 146} 147 148static void inline 149ahci_mask_set(struct resource *m, bus_size_t off, uint32_t mask, uint32_t set) 150{ 151 uint32_t val = ATA_INL(m, off); 152 153 val &= mask; 154 val |= set; 155 ATA_OUTL(m, off, val); 156} 157 158/* 159 * Should this be phy_reset or phy_init 160 */ 161#define PHY_RESET_TIMEOUT 1000 162static void 163ahci_a10_phy_reset(device_t dev) 164{ 165 uint32_t to, val; 166 struct ahci_controller *ctlr = device_get_softc(dev); 167 168 /* 169 * Here starts the magic -- most of the comments are based 170 * on guesswork, names of routines and printf error 171 * messages. The code works, but it will do that even if the 172 * comments are 100% BS. 173 */ 174 175 /* 176 * Lock out other access while we initialize. Or at least that 177 * seems to be the case based on Linux SDK #defines. Maybe this 178 * put things into reset? 179 */ 180 ATA_OUTL(ctlr->r_mem, AHCI_RWCR, 0); 181 DELAY(100); 182 183 /* 184 * Set bit 19 in PHYCS1R. Guessing this disables driving the PHY 185 * port for a bit while we reset things. 186 */ 187 ahci_set(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_HIGHZ); 188 189 /* 190 * Frob PHYCS0R... 191 */ 192 ahci_mask_set(ctlr->r_mem, AHCI_PHYCS0R, 193 ~PHYCS0R_UF2_MASK, 194 PHYCS0R_UF2_INIT | PHYCS0R_BIT23 | PHYCS0R_BIT18); 195 196 /* 197 * Set three fields in PHYCS1R 198 */ 199 ahci_mask_set(ctlr->r_mem, AHCI_PHYCS1R, 200 ~(PHYCS1R_UF1_MASK | PHYCS1R_UF2_MASK | PHYCS1R_UF3_MASK), 201 PHYCS1R_UF1_INIT | PHYCS1R_UF2_INIT | PHYCS1R_UF3_INIT); 202 203 /* 204 * Two more mystery bits in PHYCS1R. -- can these be combined above? 205 */ 206 ahci_set(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_BIT15 | PHYCS1R_BIT28); 207 208 /* 209 * Now clear that first mysery bit. Perhaps this starts 210 * driving the PHY again so we can power it up and start 211 * talking to the SATA drive, if any below. 212 */ 213 ahci_clr(ctlr->r_mem, AHCI_PHYCS1R, PHYCS1R_HIGHZ); 214 215 /* 216 * Frob PHYCS0R again... 217 */ 218 ahci_mask_set(ctlr->r_mem, AHCI_PHYCS0R, 219 ~PHYCS0R_UF1_MASK, PHYCS0R_UF1_INIT); 220 221 /* 222 * Frob PHYCS2R, because 25 means something? 223 */ 224 ahci_mask_set(ctlr->r_mem, AHCI_PHYCS2R, ~PHYCS2R_UF1_MASK, 225 PHYCS2R_UF1_INIT); 226 227 DELAY(100); /* WAG */ 228 229 /* 230 * Turn on the power to the PHY and wait for it to report back 231 * good? 232 */ 233 ahci_set(ctlr->r_mem, AHCI_PHYCS0R, PHYCS0R_POWER_ENABLE); 234 for (to = PHY_RESET_TIMEOUT; to > 0; to--) { 235 val = ATA_INL(ctlr->r_mem, AHCI_PHYCS0R); 236 if ((val & PHYCS0R_POWER_STATUS_MASK) == PHYCS0R_PS_GOOD) 237 break; 238 DELAY(10); 239 } 240 if (to == 0 && bootverbose) 241 device_printf(dev, "PHY Power Failed PHYCS0R = %#x\n", val); 242 243 /* 244 * Calibrate the clocks between the device and the host. This appears 245 * to be an automated process that clears the bit when it is done. 246 */ 247 ahci_set(ctlr->r_mem, AHCI_PHYCS2R, PHYCS2R_CALIBRATE); 248 for (to = PHY_RESET_TIMEOUT; to > 0; to--) { 249 val = ATA_INL(ctlr->r_mem, AHCI_PHYCS2R); 250 if ((val & PHYCS2R_CALIBRATE) == 0) 251 break; 252 DELAY(10); 253 } 254 if (to == 0 && bootverbose) 255 device_printf(dev, "PHY Cal Failed PHYCS2R %#x\n", val); 256 257 /* 258 * OK, let things settle down a bit. 259 */ 260 DELAY(1000); 261 262 /* 263 * Go back into normal mode now that we've calibrated the PHY. 264 */ 265 ATA_OUTL(ctlr->r_mem, AHCI_RWCR, 7); 266} 267 268static void 269ahci_a10_ch_start(struct ahci_channel *ch) 270{ 271 uint32_t reg; 272 273 /* 274 * Magical values from Allwinner SDK, setup the DMA before start 275 * operations on this channel. 276 */ 277 reg = ATA_INL(ch->r_mem, AHCI_P0DMACR); 278 reg &= ~0xff00; 279 reg |= 0x4400; 280 ATA_OUTL(ch->r_mem, AHCI_P0DMACR, reg); 281} 282 283static int 284ahci_a10_ctlr_reset(device_t dev) 285{ 286 287 ahci_a10_phy_reset(dev); 288 289 return (ahci_ctlr_reset(dev)); 290} 291 292static int 293ahci_a10_probe(device_t dev) 294{ 295 296 if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-ahci")) 297 return (ENXIO); 298 device_set_desc(dev, "Allwinner Integrated AHCI controller"); 299 300 return (BUS_PROBE_DEFAULT); 301} 302 303static int 304ahci_a10_attach(device_t dev) 305{ 306 int error; 307 struct ahci_a10_softc *sc; 308 struct ahci_controller *ctlr; 309 310 sc = device_get_softc(dev); 311 ctlr = &sc->ahci_ctlr; 312 313 ctlr->quirks = AHCI_Q_NOPMP; 314 ctlr->vendorid = 0; 315 ctlr->deviceid = 0; 316 ctlr->subvendorid = 0; 317 ctlr->subdeviceid = 0; 318 ctlr->r_rid = 0; 319 if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 320 &ctlr->r_rid, RF_ACTIVE))) 321 return (ENXIO); 322 323 /* Enable the (optional) regulator */ 324 if (regulator_get_by_ofw_property(dev, 0, "target-supply", 325 &sc->ahci_reg) == 0) { 326 error = regulator_enable(sc->ahci_reg); 327 if (error != 0) { 328 device_printf(dev, "Could not enable regulator\n"); 329 goto fail; 330 } 331 } 332 333 /* Enable clocks */ 334 error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_gate); 335 if (error != 0) { 336 device_printf(dev, "Cannot get gate clock\n"); 337 goto fail; 338 } 339 error = clk_get_by_ofw_index(dev, 0, 1, &sc->clk_pll); 340 if (error != 0) { 341 device_printf(dev, "Cannot get PLL clock\n"); 342 goto fail; 343 } 344 error = clk_set_freq(sc->clk_pll, PLL_FREQ, CLK_SET_ROUND_DOWN); 345 if (error != 0) { 346 device_printf(dev, "Cannot set PLL frequency\n"); 347 goto fail; 348 } 349 error = clk_enable(sc->clk_pll); 350 if (error != 0) { 351 device_printf(dev, "Cannot enable PLL\n"); 352 goto fail; 353 } 354 error = clk_enable(sc->clk_gate); 355 if (error != 0) { 356 device_printf(dev, "Cannot enable clk gate\n"); 357 goto fail; 358 } 359 360 /* Reset controller */ 361 if ((error = ahci_a10_ctlr_reset(dev)) != 0) 362 goto fail; 363 364 /* 365 * No MSI registers on this platform. 366 */ 367 ctlr->msi = 0; 368 ctlr->numirqs = 1; 369 370 /* Channel start callback(). */ 371 ctlr->ch_start = ahci_a10_ch_start; 372 373 /* 374 * Note: ahci_attach will release ctlr->r_mem on errors automatically 375 */ 376 return (ahci_attach(dev)); 377 378fail: 379 if (sc->ahci_reg != NULL) 380 regulator_disable(sc->ahci_reg); 381 if (sc->clk_gate != NULL) 382 clk_release(sc->clk_gate); 383 if (sc->clk_pll != NULL) 384 clk_release(sc->clk_pll); 385 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); 386 return (error); 387} 388 389static int 390ahci_a10_detach(device_t dev) 391{ 392 struct ahci_a10_softc *sc; 393 struct ahci_controller *ctlr; 394 395 sc = device_get_softc(dev); 396 ctlr = &sc->ahci_ctlr; 397 398 if (sc->ahci_reg != NULL) 399 regulator_disable(sc->ahci_reg); 400 if (sc->clk_gate != NULL) 401 clk_release(sc->clk_gate); 402 if (sc->clk_pll != NULL) 403 clk_release(sc->clk_pll); 404 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); 405 return (ahci_detach(dev)); 406} 407 408static device_method_t ahci_ata_methods[] = { 409 DEVMETHOD(device_probe, ahci_a10_probe), 410 DEVMETHOD(device_attach, ahci_a10_attach), 411 DEVMETHOD(device_detach, ahci_a10_detach), 412 DEVMETHOD(bus_print_child, ahci_print_child), 413 DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), 414 DEVMETHOD(bus_release_resource, ahci_release_resource), 415 DEVMETHOD(bus_setup_intr, ahci_setup_intr), 416 DEVMETHOD(bus_teardown_intr,ahci_teardown_intr), 417 DEVMETHOD(bus_child_location_str, ahci_child_location_str), 418 DEVMETHOD_END 419}; 420 421static driver_t ahci_ata_driver = { 422 "ahci", 423 ahci_ata_methods, 424 sizeof(struct ahci_a10_softc) 425}; 426 427DRIVER_MODULE(a10_ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0); 428