1/*- 2 * Copyright (c) 2016 Stanislav Galabov. 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 ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD$"); 28 29#include <sys/stddef.h> 30#include <sys/param.h> 31#include <sys/types.h> 32#include <sys/kernel.h> 33#include <sys/bus.h> 34#include <sys/module.h> 35 36#include <machine/bus.h> 37 38#include <dev/fdt/fdt_common.h> 39#include <dev/fdt/fdt_clock.h> 40#include <mips/mediatek/fdt_reset.h> 41#include <dev/ofw/ofw_bus.h> 42#include <dev/ofw/ofw_bus_subr.h> 43 44#include <mips/mediatek/mtk_sysctl.h> 45#include <mips/mediatek/mtk_soc.h> 46#include <mips/mediatek/mtk_usb_phy.h> 47 48#define RESET_ASSERT_DELAY 1000 49#define RESET_DEASSERT_DELAY 10000 50 51struct mtk_usb_phy_softc { 52 device_t dev; 53 struct resource * res; 54 uint32_t fm_base; 55 uint32_t u2_base; 56 uint32_t sr_coef; 57 uint32_t socid; 58}; 59 60#define USB_PHY_READ(_sc, _off) bus_read_4((_sc)->res, (_off)) 61#define USB_PHY_WRITE(_sc, _off, _val) bus_write_4((_sc)->res, (_off), (_val)) 62#define USB_PHY_CLR_SET(_sc, _off, _clr, _set) \ 63 USB_PHY_WRITE(_sc, _off, ((USB_PHY_READ(_sc, _off) & ~(_clr)) | (_set))) 64 65#define USB_PHY_READ_U2(_sc, _off) \ 66 USB_PHY_READ((_sc), ((_sc)->u2_base + (_off))) 67#define USB_PHY_WRITE_U2(_sc, _off, _val) \ 68 USB_PHY_WRITE((_sc), ((_sc)->u2_base + (_off)), (_val)) 69#define USB_PHY_CLR_SET_U2(_sc, _off, _clr, _set) \ 70 USB_PHY_WRITE_U2((_sc), (_off), ((USB_PHY_READ_U2((_sc), (_off)) & \ 71 ~(_clr)) | (_set))) 72#define USB_PHY_BARRIER(_sc) bus_barrier((_sc)->res, 0, 0, \ 73 BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ) 74 75#define USB_PHY_READ_FM(_sc, _off) \ 76 USB_PHY_READ((_sc), ((_sc)->fm_base + (_off))) 77#define USB_PHY_WRITE_FM(_sc, _off) \ 78 USB_PHY_WRITE((_sc), ((_sc)->fm_base + (_off)), (_val)) 79#define USB_PHY_CLR_SET_FM(_sc, _off, _clr, _set) \ 80 USB_PHY_WRITE_U2((_sc), (_off), ((USB_PHY_READ_U2((_sc), (_off)) & \ 81 ~(_clr)) | (_set))) 82 83static void mtk_usb_phy_mt7621_init(device_t); 84static void mtk_usb_phy_mt7628_init(device_t); 85 86static struct ofw_compat_data compat_data[] = { 87 { "ralink,mt7620-usbphy", MTK_SOC_MT7620A }, 88 { "mediatek,mt7620-usbphy", MTK_SOC_MT7620A }, 89 { "ralink,mt7628an-usbphy", MTK_SOC_MT7628 }, 90 { "ralink,rt3352-usbphy", MTK_SOC_RT3352 }, 91 { "ralink,rt3050-usbphy", MTK_SOC_RT3050 }, 92 { NULL, MTK_SOC_UNKNOWN } 93}; 94 95static int 96mtk_usb_phy_probe(device_t dev) 97{ 98 struct mtk_usb_phy_softc *sc = device_get_softc(dev); 99 100 if (!ofw_bus_status_okay(dev)) 101 return (ENXIO); 102 if ((sc->socid = 103 ofw_bus_search_compatible(dev, compat_data)->ocd_data) == 104 MTK_SOC_UNKNOWN) 105 return (ENXIO); 106 107 device_set_desc(dev, "MTK USB PHY"); 108 109 return (0); 110} 111 112static int 113mtk_usb_phy_attach(device_t dev) 114{ 115 struct mtk_usb_phy_softc * sc = device_get_softc(dev); 116 phandle_t node; 117 uint32_t val; 118 int rid; 119 120 sc->dev = dev; 121 122 /* Get our FDT node and SoC id */ 123 node = ofw_bus_get_node(dev); 124 125 /* Now let's see about setting USB to host or device mode */ 126 /* XXX: is it the same for all SoCs? */ 127 val = mtk_sysctl_get(SYSCTL_SYSCFG1); 128 if (OF_hasprop(node, "mtk,usb-device")) 129 val &= ~SYSCFG1_USB_HOST_MODE; 130 else 131 val |= SYSCFG1_USB_HOST_MODE; 132 mtk_sysctl_set(SYSCTL_SYSCFG1, val); 133 134 /* If we have clocks defined - enable them */ 135 if (OF_hasprop(node, "clocks")) 136 fdt_clock_enable_all(dev); 137 138 /* If we have resets defined - perform a reset sequence */ 139 if (OF_hasprop(node, "resets")) { 140 fdt_reset_assert_all(dev); 141 DELAY(RESET_ASSERT_DELAY); 142 fdt_reset_deassert_all(dev); 143 DELAY(RESET_DEASSERT_DELAY); 144 } 145 146 /* Careful, some devices actually require resources */ 147 if (OF_hasprop(node, "reg")) { 148 rid = 0; 149 sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 150 RF_ACTIVE); 151 if (sc->res == NULL) { 152 device_printf(dev, "could not map memory\n"); 153 return (ENXIO); 154 } 155 } else { 156 sc->res = NULL; 157 } 158 159 /* Some SoCs require specific USB PHY init... handle these */ 160 switch (sc->socid) { 161 case MTK_SOC_MT7628: /* Fallthrough */ 162 case MTK_SOC_MT7688: 163 if (sc->res == NULL) 164 return (ENXIO); 165 sc->fm_base = MT7628_FM_FEG_BASE; 166 sc->u2_base = MT7628_U2_BASE; 167 sc->sr_coef = MT7628_SR_COEF; 168 mtk_usb_phy_mt7628_init(dev); 169 break; 170 case MTK_SOC_MT7621: 171 if (sc->res == NULL) 172 return (ENXIO); 173 sc->fm_base = MT7621_FM_FEG_BASE; 174 sc->u2_base = MT7621_U2_BASE; 175 sc->sr_coef = MT7621_SR_COEF; 176 mtk_usb_phy_mt7621_init(dev); 177 break; 178 } 179 180 /* We no longer need the resources, release them */ 181 if (sc->res != NULL) 182 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res); 183 184 return (0); 185} 186 187static int 188mtk_usb_phy_detach(device_t dev) 189{ 190 struct mtk_usb_phy_softc *sc = device_get_softc(dev); 191 phandle_t node; 192 193 /* Get our FDT node */ 194 node = ofw_bus_get_node(dev); 195 196 /* If we have resets defined - assert them */ 197 if (OF_hasprop(node, "resets")) 198 fdt_reset_assert_all(dev); 199 200 /* If we have clocks defined - disable them */ 201 if (OF_hasprop(node, "clocks")) 202 fdt_clock_disable_all(dev); 203 204 /* Finally, release resources, if any were allocated */ 205 if (sc->res != NULL) 206 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res); 207 208 return (0); 209} 210 211/* 212 * Things currently seem to work a lot better without slew rate calibration 213 * both on MT7621 and MT7688, so we leave it out for now. 214 */ 215#ifdef notyet 216static void 217mtk_usb_phy_slew_rate_calibration(struct mtk_usb_phy_softc *sc) 218{ 219 uint32_t val; 220 int i; 221 222 USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, 0, SRCAL_EN); 223 USB_PHY_BARRIER(sc); 224 DELAY(1000); 225 226 USB_PHY_CLR_SET_FM(sc, U2_PHY_FMMONR1, 0, FRCK_EN); 227 USB_PHY_BARRIER(sc); 228 USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, CYCLECNT, 0x400); 229 USB_PHY_BARRIER(sc); 230 USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, 0, FDET_EN); 231 USB_PHY_BARRIER(sc); 232 233 for (i = 0; i < 1000; i++) { 234 if ((val = USB_PHY_READ_FM(sc, U2_PHY_FMMONR0)) != 0) { 235 device_printf(sc->dev, "DONE with FDET\n"); 236 break; 237 } 238 DELAY(10000); 239 } 240 device_printf(sc->dev, "After FDET\n"); 241 242 USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, FDET_EN, 0); 243 USB_PHY_BARRIER(sc); 244 USB_PHY_CLR_SET_FM(sc, U2_PHY_FMMONR1, FRCK_EN, 0); 245 USB_PHY_BARRIER(sc); 246 USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCAL_EN, 0); 247 USB_PHY_BARRIER(sc); 248 DELAY(1000); 249 250 if (val == 0) { 251 USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCTRL, 0x4 << SRCTRL_OFF); 252 USB_PHY_BARRIER(sc); 253 } else { 254 val = ((((1024 * 25 * sc->sr_coef) / val) + 500) / 1000) & 255 SRCTRL_MSK; 256 USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCTRL, val << SRCTRL_OFF); 257 USB_PHY_BARRIER(sc); 258 } 259} 260#endif 261 262static void 263mtk_usb_phy_mt7621_init(device_t dev) 264{ 265#ifdef notyet 266 struct mtk_usb_phy_softc *sc = device_get_softc(dev); 267 268 /* Slew rate calibration only, but for 2 ports */ 269 mtk_usb_phy_slew_rate_calibration(sc); 270 271 sc->u2_base = MT7621_U2_BASE_P1; 272 mtk_usb_phy_slew_rate_calibration(sc); 273#endif 274} 275 276static void 277mtk_usb_phy_mt7628_init(device_t dev) 278{ 279 struct mtk_usb_phy_softc *sc = device_get_softc(dev); 280 281 /* XXX: possibly add barriers between the next writes? */ 282 USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00ffff02); 283 USB_PHY_BARRIER(sc); 284 USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00555502); 285 USB_PHY_BARRIER(sc); 286 USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00aaaa02); 287 USB_PHY_BARRIER(sc); 288 USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00000402); 289 USB_PHY_BARRIER(sc); 290 USB_PHY_WRITE_U2(sc, U2_PHY_AC0, 0x0048086a); 291 USB_PHY_BARRIER(sc); 292 USB_PHY_WRITE_U2(sc, U2_PHY_AC1, 0x4400001c); 293 USB_PHY_BARRIER(sc); 294 USB_PHY_WRITE_U2(sc, U2_PHY_ACR3, 0xc0200000); 295 USB_PHY_BARRIER(sc); 296 USB_PHY_WRITE_U2(sc, U2_PHY_DTM0, 0x02000000); 297 USB_PHY_BARRIER(sc); 298 299#ifdef notyet 300 /* Slew rate calibration */ 301 mtk_usb_phy_slew_rate_calibration(sc); 302#endif 303} 304 305static device_method_t mtk_usb_phy_methods[] = { 306 /* Device interface */ 307 DEVMETHOD(device_probe, mtk_usb_phy_probe), 308 DEVMETHOD(device_attach, mtk_usb_phy_attach), 309 DEVMETHOD(device_detach, mtk_usb_phy_detach), 310 DEVMETHOD(device_suspend, bus_generic_suspend), 311 DEVMETHOD(device_resume, bus_generic_resume), 312 DEVMETHOD(device_shutdown, bus_generic_shutdown), 313 314 DEVMETHOD_END 315}; 316 317static driver_t mtk_usb_phy_driver = { 318 .name = "usbphy", 319 .methods = mtk_usb_phy_methods, 320 .size = sizeof(struct mtk_usb_phy_softc), 321}; 322 323static devclass_t mtk_usb_phy_devclass; 324 325DRIVER_MODULE(usbphy, simplebus, mtk_usb_phy_driver, mtk_usb_phy_devclass, 0, 326 0); 327