1 /* $NetBSD: rk_emmcphy.c,v 1.4 2021/01/27 03:10:19 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2019 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: rk_emmcphy.c,v 1.4 2021/01/27 03:10:19 thorpej Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/mutex.h> 38 #include <sys/kmem.h> 39 40 #include <dev/fdt/fdtvar.h> 41 #include <dev/fdt/syscon.h> 42 43 #define GRF_EMMCPHY_CON0 0x00 44 #define PHYCTRL_FRQSEL __BITS(13,12) 45 #define PHYCTRL_FRQSEL_200M 0 46 #define PHYCTRL_FRQSEL_50M 1 47 #define PHYCTRL_FRQSEL_100M 2 48 #define PHYCTRL_FRQSEL_150M 3 49 #define PHYCTRL_OTAPDLYENA __BIT(11) 50 #define PHYCTRL_OTAPDLYSEL __BITS(10,7) 51 #define PHYCTRL_ITAPCHGWIN __BIT(6) 52 #define PHYCTRL_ITAPDLYSEL __BITS(5,1) 53 #define PHYCTRL_ITAPDLYENA __BIT(0) 54 #define GRF_EMMCPHY_CON1 0x04 55 #define PHYCTRL_CLKBUFSEL __BITS(8,6) 56 #define PHYCTRL_SELDLYTXCLK __BIT(5) 57 #define PHYCTRL_SELDLYRXCLK __BIT(4) 58 #define PHYCTRL_STRBSEL __BITS(3,0) 59 #define GRF_EMMCPHY_CON2 0x08 60 #define PHYCTRL_REN_STRB __BIT(9) 61 #define PHYCTRL_REN_CMD __BIT(8) 62 #define PHYCTRL_REN_DAT __BITS(7,0) 63 #define GRF_EMMCPHY_CON3 0x0c 64 #define PHYCTRL_PU_STRB __BIT(9) 65 #define PHYCTRL_PU_CMD __BIT(8) 66 #define PHYCTRL_PU_DAT __BITS(7,0) 67 #define GRF_EMMCPHY_CON4 0x10 68 #define PHYCTRL_OD_RELEASE_CMD __BIT(9) 69 #define PHYCTRL_OD_RELEASE_STRB __BIT(8) 70 #define PHYCTRL_OD_RELEASE_DAT __BITS(7,0) 71 #define GRF_EMMCPHY_CON5 0x14 72 #define PHYCTRL_ODEN_STRB __BIT(9) 73 #define PHYCTRL_ODEN_CMD __BIT(8) 74 #define PHYCTRL_ODEN_DAT __BITS(7,0) 75 #define GRF_EMMCPHY_CON6 0x18 76 #define PHYCTRL_DLL_TRM_ICP __BITS(12,9) 77 #define PHYCTRL_EN_RTRIM __BIT(8) 78 #define PHYCTRL_RETRIM __BIT(7) 79 #define PHYCTRL_DR_TY __BITS(6,4) 80 #define PHYCTRL_RETENB __BIT(3) 81 #define PHYCTRL_RETEN __BIT(2) 82 #define PHYCTRL_ENDLL __BIT(1) 83 #define PHYCTRL_PDB __BIT(0) 84 #define GRF_EMMCPHY_STATUS 0x20 85 #define PHYCTRL_CALDONE __BIT(6) 86 #define PHYCTRL_DLLRDY __BIT(5) 87 #define PHYCTRL_RTRIM __BITS(4,1) 88 #define PHYCTRL_EXR_NINST __BIT(0) 89 90 static const struct device_compatible_entry compat_data[] = { 91 { .compat = "rockchip,rk3399-emmc-phy" }, 92 DEVICE_COMPAT_EOL 93 }; 94 95 struct rk_emmcphy_softc { 96 device_t sc_dev; 97 struct syscon *sc_syscon; 98 bus_addr_t sc_regbase; 99 int sc_phandle; 100 struct clk *sc_clk; 101 }; 102 103 #define RD4(sc, reg) \ 104 syscon_read_4((sc)->sc_syscon, (sc)->sc_regbase + (reg)) 105 #define WR4(sc, reg, val) \ 106 syscon_write_4((sc)->sc_syscon, (sc)->sc_regbase + (reg), (val)) 107 108 static int rk_emmcphy_match(device_t, cfdata_t, void *); 109 static void rk_emmcphy_attach(device_t, device_t, void *); 110 111 CFATTACH_DECL_NEW(rkemmcphy, sizeof(struct rk_emmcphy_softc), 112 rk_emmcphy_match, rk_emmcphy_attach, NULL, NULL); 113 114 static void * 115 rk_emmcphy_acquire(device_t dev, const void *data, size_t len) 116 { 117 struct rk_emmcphy_softc * const sc = device_private(dev); 118 119 if (len != 0) 120 return NULL; 121 122 if (sc->sc_clk == NULL) 123 sc->sc_clk = fdtbus_clock_get(sc->sc_phandle, "emmcclk"); 124 125 return sc; 126 } 127 128 static void 129 rk_emmcphy_release(device_t dev, void *priv) 130 { 131 } 132 133 static int 134 rk_emmcphy_enable(device_t dev, void *priv, bool enable) 135 { 136 struct rk_emmcphy_softc * const sc = device_private(dev); 137 uint32_t mask, val; 138 u_int rate, frqsel; 139 140 syscon_lock(sc->sc_syscon); 141 142 if (enable) { 143 /* Drive strength */ 144 mask = PHYCTRL_DR_TY; 145 val = __SHIFTIN(0, PHYCTRL_DR_TY); 146 WR4(sc, GRF_EMMCPHY_CON6, (mask << 16) | val); 147 148 /* Enable output tap delay */ 149 mask = PHYCTRL_OTAPDLYENA | PHYCTRL_OTAPDLYSEL; 150 val = PHYCTRL_OTAPDLYENA | __SHIFTIN(4, PHYCTRL_OTAPDLYSEL); 151 WR4(sc, GRF_EMMCPHY_CON0, (mask << 16) | val); 152 } 153 154 /* Power down PHY and disable DLL before making changes */ 155 mask = PHYCTRL_ENDLL | PHYCTRL_PDB; 156 val = 0; 157 WR4(sc, GRF_EMMCPHY_CON6, (mask << 16) | val); 158 159 if (enable == false) { 160 syscon_unlock(sc->sc_syscon); 161 return 0; 162 } 163 164 rate = sc->sc_clk ? clk_get_rate(sc->sc_clk) : 0; 165 166 if (rate != 0) { 167 if (rate < 75000000) 168 frqsel = PHYCTRL_FRQSEL_50M; 169 else if (rate < 125000000) 170 frqsel = PHYCTRL_FRQSEL_100M; 171 else if (rate < 175000000) 172 frqsel = PHYCTRL_FRQSEL_150M; 173 else 174 frqsel = PHYCTRL_FRQSEL_200M; 175 } else { 176 frqsel = PHYCTRL_FRQSEL_200M; 177 } 178 179 delay(3); 180 181 /* Power up PHY */ 182 mask = PHYCTRL_PDB; 183 val = PHYCTRL_PDB; 184 WR4(sc, GRF_EMMCPHY_CON6, (mask << 16) | val); 185 186 /* Wait for calibration */ 187 delay(10); 188 val = RD4(sc, GRF_EMMCPHY_STATUS); 189 if ((val & PHYCTRL_CALDONE) == 0) { 190 device_printf(dev, "PHY calibration did not complete\n"); 191 syscon_unlock(sc->sc_syscon); 192 return EIO; 193 } 194 195 /* Set DLL frequency */ 196 mask = PHYCTRL_FRQSEL; 197 val = __SHIFTIN(frqsel, PHYCTRL_FRQSEL); 198 WR4(sc, GRF_EMMCPHY_CON0, (mask << 16) | val); 199 200 /* Enable DLL */ 201 mask = PHYCTRL_ENDLL; 202 val = PHYCTRL_ENDLL; 203 WR4(sc, GRF_EMMCPHY_CON6, (mask << 16) | val); 204 205 if (rate != 0) { 206 /* Wait for DLL ready */ 207 delay(50000); 208 val = RD4(sc, GRF_EMMCPHY_STATUS); 209 if ((val & PHYCTRL_DLLRDY) == 0) { 210 device_printf(dev, "DLL loop failed to lock\n"); 211 syscon_unlock(sc->sc_syscon); 212 return EIO; 213 } 214 } 215 216 syscon_unlock(sc->sc_syscon); 217 218 return 0; 219 } 220 221 static const struct fdtbus_phy_controller_func rk_emmcphy_funcs = { 222 .acquire = rk_emmcphy_acquire, 223 .release = rk_emmcphy_release, 224 .enable = rk_emmcphy_enable, 225 }; 226 227 static int 228 rk_emmcphy_match(device_t parent, cfdata_t cf, void *aux) 229 { 230 struct fdt_attach_args * const faa = aux; 231 232 return of_compatible_match(faa->faa_phandle, compat_data); 233 } 234 235 static void 236 rk_emmcphy_attach(device_t parent, device_t self, void *aux) 237 { 238 struct rk_emmcphy_softc * const sc = device_private(self); 239 struct fdt_attach_args * const faa = aux; 240 const int phandle = faa->faa_phandle; 241 bus_addr_t addr; 242 bus_size_t size; 243 244 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 245 aprint_error(": couldn't get registers\n"); 246 return; 247 } 248 249 sc->sc_dev = self; 250 sc->sc_phandle = phandle; 251 sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(phandle)); 252 if (sc->sc_syscon == NULL) { 253 aprint_error(": couldn't get syscon\n"); 254 return; 255 } 256 sc->sc_regbase = addr; 257 258 aprint_naive("\n"); 259 aprint_normal(": eMMC PHY\n"); 260 261 fdtbus_register_phy_controller(self, phandle, &rk_emmcphy_funcs); 262 } 263