1 /* $OpenBSD: imxahci.c,v 1.11 2018/04/02 17:43:08 patrick 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 #include <machine/fdt.h> 28 29 #include <dev/ic/ahcireg.h> 30 #include <dev/ic/ahcivar.h> 31 32 #include <dev/ofw/openfirm.h> 33 #include <dev/ofw/ofw_clock.h> 34 #include <dev/ofw/ofw_misc.h> 35 #include <dev/ofw/fdt.h> 36 37 /* registers */ 38 #define SATA_CAP 0x000 39 #define SATA_GHC 0x004 40 #define SATA_IS 0x008 41 #define SATA_PI 0x00C 42 #define SATA_VS 0x010 43 #define SATA_CCC_CTL 0x014 44 #define SATA_CCC_PORTS 0x018 45 #define SATA_CAP2 0x024 46 #define SATA_BISTAFR 0x0A0 47 #define SATA_BISTCR 0x0A4 48 #define SATA_BISTFCTR 0x0A8 49 #define SATA_BSTSR 0x0AC 50 #define SATA_OOBR 0x0BC 51 #define SATA_GPCR 0x0D0 52 #define SATA_GPSR 0x0D4 53 #define SATA_TIMER1MS 0x0E0 54 #define SATA_TESTR 0x0F4 55 #define SATA_VERSIONR 0x0F8 56 #define SATA_P0CLB 0x100 57 #define SATA_P0FB 0x108 58 #define SATA_P0IS 0x110 59 #define SATA_P0IE 0x114 60 #define SATA_P0CMD 0x118 61 #define SATA_P0TFD 0x120 62 #define SATA_P0SIG 0x124 63 #define SATA_P0SSTS 0x128 64 #define SATA_P0SCTL 0x12C 65 #define SATA_P0SERR 0x130 66 #define SATA_P0SACT 0x134 67 #define SATA_P0CI 0x138 68 #define SATA_P0SNTF 0x13C 69 #define SATA_P0DMACR 0x170 70 #define SATA_P0PHYCR 0x178 71 #define SATA_P0PHYSR 0x17C 72 73 #define SATA_CAP_SSS (1 << 27) 74 #define SATA_GHC_HR (1 << 0) 75 #define SATA_P0PHYCR_TEST_PDDQ (1 << 20) 76 77 /* iomuxc */ 78 #define IOMUXC_GPR13 0x034 79 #define IOMUXC_GPR13_SATA_PHY_1_TX_EDGE_RATE (1 << 0) 80 #define IOMUXC_GPR13_SATA_PHY_1_MPLL_CLK_EN (1 << 1) 81 #define IOMUXC_GPR13_SATA_PHY_2_1104V (0x11 << 2) 82 #define IOMUXC_GPR13_SATA_PHY_3_333DB (0x00 << 7) 83 #define IOMUXC_GPR13_SATA_PHY_4_9_16 (0x04 << 11) 84 #define IOMUXC_GPR13_SATA_PHY_5_SS (0x01 << 14) 85 #define IOMUXC_GPR13_SATA_SPEED_3G (0x01 << 15) 86 #define IOMUXC_GPR13_SATA_PHY_6 (0x03 << 16) 87 #define IOMUXC_GPR13_SATA_PHY_7_SATA2M (0x12 << 19) 88 #define IOMUXC_GPR13_SATA_PHY_8_30DB (0x05 << 24) 89 #define IOMUXC_GPR13_SATA_MASK 0x07FFFFFF 90 91 int imxahci_match(struct device *, void *, void *); 92 void imxahci_attach(struct device *, struct device *, void *); 93 int imxahci_detach(struct device *, int); 94 int imxahci_activate(struct device *, int); 95 96 extern int ahci_intr(void *); 97 98 struct imxahci_softc { 99 struct ahci_softc sc; 100 }; 101 102 struct cfattach imxahci_ca = { 103 sizeof(struct imxahci_softc), 104 imxahci_match, 105 imxahci_attach, 106 imxahci_detach, 107 imxahci_activate 108 }; 109 110 struct cfdriver imxahci_cd = { 111 NULL, "imxahci", DV_DULL 112 }; 113 114 int 115 imxahci_match(struct device *parent, void *match, void *aux) 116 { 117 struct fdt_attach_args *faa = aux; 118 119 return OF_is_compatible(faa->fa_node, "fsl,imx6q-ahci"); 120 } 121 122 void 123 imxahci_attach(struct device *parent, struct device *self, void *aux) 124 { 125 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 126 struct ahci_softc *sc = &imxsc->sc; 127 struct fdt_attach_args *faa = aux; 128 uint32_t timeout = 0x100000; 129 struct regmap *rm; 130 uint32_t reg; 131 132 if (faa->fa_nreg < 1) 133 return; 134 135 sc->sc_iot = faa->fa_iot; 136 sc->sc_ios = faa->fa_reg[0].size; 137 sc->sc_dmat = faa->fa_dmat; 138 139 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 140 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 141 panic("imxahci_attach: bus_space_map failed!"); 142 143 sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO, 144 ahci_intr, sc, sc->sc_dev.dv_xname); 145 if (sc->sc_ih == NULL) { 146 printf(": unable to establish interrupt\n"); 147 goto unmap; 148 } 149 150 /* power it up */ 151 clock_enable(faa->fa_node, "sata_ref"); 152 clock_enable(faa->fa_node, "sata"); 153 delay(100); 154 155 /* power phy up */ 156 rm = regmap_bycompatible("fsl,imx6q-iomuxc-gpr"); 157 if (rm != NULL) { 158 reg = regmap_read_4(rm, IOMUXC_GPR13); 159 reg &= ~IOMUXC_GPR13_SATA_MASK; 160 reg |= IOMUXC_GPR13_SATA_PHY_2_1104V | 161 IOMUXC_GPR13_SATA_PHY_3_333DB | 162 IOMUXC_GPR13_SATA_PHY_4_9_16 | 163 IOMUXC_GPR13_SATA_SPEED_3G | 164 IOMUXC_GPR13_SATA_PHY_6 | 165 IOMUXC_GPR13_SATA_PHY_7_SATA2M | 166 IOMUXC_GPR13_SATA_PHY_8_30DB; 167 regmap_write_4(rm, IOMUXC_GPR13, reg); 168 reg = regmap_read_4(rm, IOMUXC_GPR13); 169 reg |= IOMUXC_GPR13_SATA_PHY_1_MPLL_CLK_EN; 170 regmap_write_4(rm, IOMUXC_GPR13, reg); 171 } 172 173 /* setup */ 174 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, 175 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR) & ~SATA_P0PHYCR_TEST_PDDQ); 176 177 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_GHC, SATA_GHC_HR); 178 179 while (!bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_VERSIONR)); 180 181 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, 182 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP) | SATA_CAP_SSS); 183 184 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, 1); 185 186 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS, 187 clock_get_frequency(faa->fa_node, "ahb")); 188 189 while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0SSTS) & 0xF) && timeout--); 190 191 printf(":"); 192 193 if (ahci_attach(sc) != 0) { 194 /* error printed by ahci_attach */ 195 goto irq; 196 } 197 198 return; 199 irq: 200 arm_intr_disestablish(sc->sc_ih); 201 unmap: 202 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 203 } 204 205 int 206 imxahci_detach(struct device *self, int flags) 207 { 208 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 209 struct ahci_softc *sc = &imxsc->sc; 210 211 ahci_detach(sc, flags); 212 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 213 return 0; 214 } 215 216 int 217 imxahci_activate(struct device *self, int act) 218 { 219 struct imxahci_softc *imxsc = (struct imxahci_softc *) self; 220 struct ahci_softc *sc = &imxsc->sc; 221 222 return ahci_activate((struct device *)sc, act); 223 } 224