1 /* $OpenBSD: imxahci.c,v 1.3 2014/04/14 04:42:22 dlg Exp $ */ 2 /* 3 * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/buf.h> 21 #include <sys/kernel.h> 22 #include <sys/malloc.h> 23 #include <sys/device.h> 24 #include <sys/queue.h> 25 26 #include <machine/bus.h> 27 28 #include <dev/ic/ahcireg.h> 29 #include <dev/ic/ahcivar.h> 30 31 #include <armv7/armv7/armv7var.h> 32 #include <armv7/imx/imxccmvar.h> 33 #include <armv7/imx/imxiomuxcvar.h> 34 35 /* registers */ 36 #define SATA_CAP 0x000 37 #define SATA_GHC 0x004 38 #define SATA_IS 0x008 39 #define SATA_PI 0x00C 40 #define SATA_VS 0x010 41 #define SATA_CCC_CTL 0x014 42 #define SATA_CCC_PORTS 0x018 43 #define SATA_CAP2 0x024 44 #define SATA_BISTAFR 0x0A0 45 #define SATA_BISTCR 0x0A4 46 #define SATA_BISTFCTR 0x0A8 47 #define SATA_BSTSR 0x0AC 48 #define SATA_OOBR 0x0BC 49 #define SATA_GPCR 0x0D0 50 #define SATA_GPSR 0x0D4 51 #define SATA_TIMER1MS 0x0E0 52 #define SATA_TESTR 0x0F4 53 #define SATA_VERSIONR 0x0F8 54 #define SATA_P0CLB 0x100 55 #define SATA_P0FB 0x108 56 #define SATA_P0IS 0x110 57 #define SATA_P0IE 0x114 58 #define SATA_P0CMD 0x118 59 #define SATA_P0TFD 0x120 60 #define SATA_P0SIG 0x124 61 #define SATA_P0SSTS 0x128 62 #define SATA_P0SCTL 0x12C 63 #define SATA_P0SERR 0x130 64 #define SATA_P0SACT 0x134 65 #define SATA_P0CI 0x138 66 #define SATA_P0SNTF 0x13C 67 #define SATA_P0DMACR 0x170 68 #define SATA_P0PHYCR 0x178 69 #define SATA_P0PHYSR 0x17C 70 71 #define SATA_CAP_SSS (1 << 27) 72 #define SATA_GHC_HR (1 << 0) 73 #define SATA_P0PHYCR_TEST_PDDQ (1 << 20) 74 75 void imxahci_attach(struct device *, struct device *, void *); 76 int imxahci_detach(struct device *, int); 77 int imxahci_activate(struct device *, int); 78 79 extern int ahci_intr(void *); 80 81 struct imxahci_softc { 82 struct ahci_softc sc; 83 }; 84 85 struct cfattach imxahci_ca = { 86 sizeof(struct imxahci_softc), 87 NULL, 88 imxahci_attach, 89 imxahci_detach, 90 imxahci_activate 91 }; 92 93 struct cfdriver imxahci_cd = { 94 NULL, "ahci", DV_DULL 95 }; 96 97 void 98 imxahci_attach(struct device *parent, struct device *self, void *args) 99 { 100 struct armv7_attach_args *aa = args; 101 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 102 struct ahci_softc *sc = &imxsc->sc; 103 uint32_t timeout = 0x100000; 104 105 sc->sc_iot = aa->aa_iot; 106 sc->sc_ios = aa->aa_dev->mem[0].size; 107 sc->sc_dmat = aa->aa_dmat; 108 109 if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, 110 aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) 111 panic("imxahci_attach: bus_space_map failed!"); 112 113 sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO, 114 ahci_intr, sc, sc->sc_dev.dv_xname); 115 if (sc->sc_ih == NULL) { 116 printf(": unable to establish interrupt\n"); 117 goto unmap; 118 } 119 120 /* power it up */ 121 imxccm_enable_sata(); 122 delay(100); 123 124 /* power phy up */ 125 imxiomuxc_enable_sata(); 126 127 /* setup */ 128 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, 129 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR) & ~SATA_P0PHYCR_TEST_PDDQ); 130 131 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_GHC, SATA_GHC_HR); 132 133 while (!bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_VERSIONR)); 134 135 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, 136 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP) | SATA_CAP_SSS); 137 138 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, 1); 139 140 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS, imxccm_get_ahbclk()); 141 142 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0SSTS) & 0xF) && timeout--); 143 144 if (ahci_attach(sc) != 0) { 145 /* error printed by ahci_attach */ 146 goto irq; 147 } 148 149 return; 150 irq: 151 arm_intr_disestablish(sc->sc_ih); 152 unmap: 153 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 154 } 155 156 int 157 imxahci_detach(struct device *self, int flags) 158 { 159 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 160 struct ahci_softc *sc = &imxsc->sc; 161 162 ahci_detach(sc, flags); 163 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 164 return 0; 165 } 166 167 int 168 imxahci_activate(struct device *self, int act) 169 { 170 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 171 struct ahci_softc *sc = &imxsc->sc; 172 173 return ahci_activate((struct device *)sc, act); 174 } 175