1 /* $NetBSD: octeon_dwctwo.c,v 1.9 2016/07/12 03:34:25 matt Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Masao Uebayashi <uebayasi@tombiinc.com> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Copyright (c) 2015 Internet Initiative Japan, Inc. 21 * All rights reserved. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: octeon_dwctwo.c,v 1.9 2016/07/12 03:34:25 matt Exp $"); 47 48 #include "opt_octeon.h" 49 #include "opt_usb.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/device.h> 54 #include <sys/bus.h> 55 #include <sys/cpu.h> 56 #include <sys/workqueue.h> 57 58 #include <dev/usb/usb.h> 59 #include <dev/usb/usbdi.h> 60 #include <dev/usb/usbdivar.h> 61 #include <dev/usb/usb_mem.h> 62 63 #include <mips/cavium/include/iobusvar.h> 64 #include <mips/cavium/dev/octeon_ciureg.h> 65 #include <mips/cavium/dev/octeon_usbnreg.h> 66 #include <mips/cavium/dev/octeon_usbnvar.h> 67 #include <mips/cavium/dev/octeon_usbcreg.h> 68 #include <mips/cavium/dev/octeon_usbcvar.h> 69 #include <mips/cavium/octeonvar.h> 70 71 #include <dwc2/dwc2var.h> 72 #include <dwc2/dwc2.h> 73 #include "dwc2_core.h" 74 75 struct octeon_dwc2_softc { 76 struct dwc2_softc sc_dwc2; 77 /* USBC bus space tag */ 78 struct mips_bus_space sc_dwc2_bust; 79 80 /* USBN bus space */ 81 bus_space_tag_t sc_bust; 82 bus_space_handle_t sc_regh; 83 bus_space_handle_t sc_reg2h; 84 85 void *sc_ih; 86 }; 87 88 static int octeon_dwc2_match(device_t, struct cfdata *, void *); 89 static void octeon_dwc2_attach(device_t, device_t, void *); 90 static uint32_t octeon_dwc2_rd_4(void *, bus_space_handle_t, 91 bus_size_t); 92 static void octeon_dwc2_wr_4(void *, bus_space_handle_t, 93 bus_size_t, uint32_t); 94 int octeon_dwc2_set_dma_addr(device_t, bus_addr_t, int); 95 static inline void octeon_dwc2_reg_assert(struct octeon_dwc2_softc *, 96 bus_size_t, uint64_t); 97 static inline void octeon_dwc2_reg_deassert(struct octeon_dwc2_softc *, 98 bus_size_t, uint64_t); 99 static inline uint64_t octeon_dwc2_reg_rd(struct octeon_dwc2_softc *, 100 bus_size_t); 101 static inline void octeon_dwc2_reg_wr(struct octeon_dwc2_softc *, 102 bus_size_t, uint64_t); 103 static inline void octeon_dwc2_reg2_assert(struct octeon_dwc2_softc *, 104 bus_size_t, uint64_t); 105 static inline void octeon_dwc2_reg2_deassert(struct octeon_dwc2_softc *, 106 bus_size_t, uint64_t); 107 static inline uint64_t octeon_dwc2_reg2_rd(struct octeon_dwc2_softc *, 108 bus_size_t); 109 static inline void octeon_dwc2_reg2_wr(struct octeon_dwc2_softc *, 110 bus_size_t, uint64_t); 111 112 static struct dwc2_core_params octeon_dwc2_params = { 113 .otg_cap = 2, /* 2 - No HNP/SRP capable */ 114 .otg_ver = 0, 115 .dma_enable = 1, 116 .dma_desc_enable = 0, 117 .speed = 0, /* 0 - High Speed */ 118 .enable_dynamic_fifo = 1, 119 .en_multiple_tx_fifo = 0, 120 .host_rx_fifo_size = 456, 121 .host_nperio_tx_fifo_size = 912, 122 .host_perio_tx_fifo_size = 256, 123 .max_transfer_size = 65535, 124 .max_packet_count = 511, 125 .host_channels = 8, 126 .phy_type = 1, /* UTMI */ 127 .phy_utmi_width = 16, /* 16 bits */ 128 .phy_ulpi_ddr = 0, 129 .phy_ulpi_ext_vbus = 0, 130 .i2c_enable = 0, 131 .ulpi_fs_ls = 0, 132 .host_support_fs_ls_low_power = 0, 133 .host_ls_low_power_phy_clk = 0, /* 48 MHz */ 134 .ts_dline = 0, 135 .reload_ctl = 0, 136 .ahbcfg = 0, /* XXX */ 137 .uframe_sched = 1, 138 .external_id_pin_ctl = -1, 139 .hibernation = -1, 140 }; 141 142 CFATTACH_DECL_NEW(octeon_dwctwo, sizeof(struct octeon_dwc2_softc), 143 octeon_dwc2_match, octeon_dwc2_attach, NULL, NULL); 144 145 static int 146 octeon_dwc2_match(device_t parent, struct cfdata *cf, void *aux) 147 { 148 struct iobus_attach_args *aa = aux; 149 150 if (strcmp(cf->cf_name, aa->aa_name) != 0) 151 return 0; 152 153 return 1; 154 } 155 156 static void 157 octeon_dwc2_attach(device_t parent, device_t self, void *aux) 158 { 159 struct octeon_dwc2_softc *sc = device_private(self); 160 struct iobus_attach_args *aa = aux; 161 uint64_t clk; 162 int status; 163 164 aprint_normal("\n"); 165 166 sc->sc_dwc2.sc_dev = self; 167 sc->sc_bust = aa->aa_bust; 168 169 sc->sc_dwc2_bust.bs_cookie = sc; 170 sc->sc_dwc2_bust.bs_map = aa->aa_bust->bs_map; 171 sc->sc_dwc2_bust.bs_unmap = aa->aa_bust->bs_unmap; 172 sc->sc_dwc2_bust.bs_r_4 = octeon_dwc2_rd_4; 173 sc->sc_dwc2_bust.bs_w_4 = octeon_dwc2_wr_4; 174 175 sc->sc_dwc2.sc_iot = &sc->sc_dwc2_bust; 176 sc->sc_dwc2.sc_bus.ub_dmatag = aa->aa_dmat; 177 sc->sc_dwc2.sc_params = &octeon_dwc2_params; 178 sc->sc_dwc2.sc_set_dma_addr = octeon_dwc2_set_dma_addr; 179 180 status = bus_space_map(sc->sc_dwc2.sc_iot, USBC_BASE, USBC_SIZE, 181 0, &sc->sc_dwc2.sc_ioh); 182 if (status != 0) 183 panic("can't map USBC space"); 184 185 status = bus_space_map(sc->sc_bust, USBN_BASE, USBN_SIZE, 186 0, &sc->sc_regh); 187 if (status != 0) 188 panic("can't map USBN space"); 189 190 status = bus_space_map(sc->sc_bust, USBN_2_BASE, USBN_2_SIZE, 191 0, &sc->sc_reg2h); 192 if (status != 0) 193 panic("can't map USBN_2 space"); 194 195 switch (MIPS_PRID_IMPL(mips_options.mips_cpu_id)) { 196 case MIPS_CN50XX: 197 /* 198 * 2. Configure the reference clock, PHY, and HCLK: 199 * a. Write USBN_CLK_CTL[POR] = 1 and 200 * USBN_CLK_CTL[HRST,PRST,HCLK_RST] = 0 201 */ 202 clk = octeon_dwc2_reg_rd(sc, USBN_CLK_CTL_OFFSET); 203 clk |= USBN_CLK_CTL_POR; 204 clk &= ~(USBN_CLK_CTL_HRST | USBN_CLK_CTL_PRST | 205 USBN_CLK_CTL_HCLK_RST | USBN_CLK_CTL_ENABLE); 206 /* 207 * b. Select the USB reference clock/crystal parameters by writing 208 * appropriate values to USBN_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON]. 209 */ 210 /* XXX board specific */ 211 clk &= ~(USBN_CLK_CTL_P_C_SEL | USBN_CLK_CTL_P_RTYPE | 212 USBN_CLK_CTL_P_COM_ON); 213 /* 214 * c. Select the HCLK via writing USBN_CLK_CTL[DIVIDE, DIVIDE2] and 215 * setting USBN_CLK_CTL[ENABLE] = 1. 216 */ 217 /* XXX board specific */ 218 clk &= ~(USBN_CLK_CTL_DIVIDE | USBN_CLK_CTL_DIVIDE2); 219 clk |= SET_USBN_CLK_CTL_DIVIDE(0x4ULL) 220 | SET_USBN_CLK_CTL_DIVIDE2(0x0ULL); 221 octeon_dwc2_reg_wr(sc, USBN_CLK_CTL_OFFSET, clk); 222 /* 223 * d. Write USBN_CLK_CTL[HCLK_RST] = 1. 224 */ 225 octeon_dwc2_reg_assert(sc, USBN_CLK_CTL_OFFSET, USBN_CLK_CTL_HCLK_RST); 226 /* 227 * e. Wait 64 core-clock cycles for HCLK to stabilize. 228 */ 229 delay(1); 230 break; 231 case MIPS_CN31XX: 232 case MIPS_CN30XX: 233 /* 234 * 2. If changing the HCLK divide value: 235 * a. write USBN_CLK_CTL[DIVIDE] with the new divide value. 236 */ 237 clk = octeon_dwc2_reg_rd(sc, USBN_CLK_CTL_OFFSET); 238 clk |= 0x4ULL & USBN_CLK_CTL_DIVIDE; 239 octeon_dwc2_reg_wr(sc, USBN_CLK_CTL_OFFSET, clk); 240 /* 241 * b. Wait 64 core-clock cycles for HCLK to stabilize. 242 */ 243 delay(1); 244 break; 245 default: 246 panic("unknown H/W type"); /* XXX */ 247 } 248 249 /* 250 * 3. Program the power-on reset field in the USBN clock-control register: 251 * USBN_CLK_CTL[POR] = 0 252 */ 253 octeon_dwc2_reg_deassert(sc, USBN_CLK_CTL_OFFSET, USBN_CLK_CTL_POR); 254 /* 255 * 4. Wait 40 us for PHY clock to start (CN3xxx) 256 * 4. Wait 1 ms for PHY clock to start (CN50xx) 257 */ 258 delay(1000); 259 260 /* 261 * 5. Program the Reset input from automatic test equipment field 262 * in the USBP control and status register: 263 * USBN_USBP_CTL_STATUS[ATE_RESET] = 1 264 */ 265 octeon_dwc2_reg_assert(sc, USBN_USBP_CTL_STATUS_OFFSET, 266 USBN_USBP_CTL_STATUS_ATE_RESET); 267 /* 268 * 6. Wait 10 cycles. 269 */ 270 delay(1); 271 /* 272 * 7. Clear ATE_RESET field in the USBN clock-control register: 273 * USBN_USBP_CTL_STATUS[ATE_RESET] = 0 274 */ 275 octeon_dwc2_reg_deassert(sc, USBN_USBP_CTL_STATUS_OFFSET, 276 USBN_USBP_CTL_STATUS_ATE_RESET); 277 /* 278 * 8. Program the PHY reset field in the USBN clock-control register: 279 * USBN_CLK_CTL[PRST] = 1 280 */ 281 octeon_dwc2_reg_assert(sc, USBN_CLK_CTL_OFFSET, USBN_CLK_CTL_PRST); 282 /* 283 * 9. Program the USBP control and status register to select host or device mode. 284 * USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for device 285 */ 286 octeon_dwc2_reg_deassert(sc, USBN_USBP_CTL_STATUS_OFFSET, 287 USBN_USBP_CTL_STATUS_HST_MODE); 288 /* 289 * 10. Wait 1 us. 290 */ 291 delay(1); 292 293 /* 294 * 11. Program the hreset_n field in the USBN clock-control register: 295 * USBN_CLK_CTL[HRST] = 1 296 */ 297 octeon_dwc2_reg_assert(sc, USBN_CLK_CTL_OFFSET, USBN_CLK_CTL_HRST); 298 299 delay(1); 300 301 /* Finally, enable clock */ 302 octeon_dwc2_reg_assert(sc, USBN_CLK_CTL_OFFSET, USBN_CLK_CTL_ENABLE); 303 304 delay(10); 305 306 status = dwc2_init(&sc->sc_dwc2); 307 if (status != 0) 308 panic("can't initialize dwc2, error=%d\n", status); 309 310 sc->sc_dwc2.sc_child = 311 config_found(sc->sc_dwc2.sc_dev, &sc->sc_dwc2.sc_bus, usbctlprint); 312 313 sc->sc_ih = octeon_intr_establish(ffs64(CIU_INTX_SUM0_USB) - 1, 314 IPL_VM, dwc2_intr, sc); 315 if (sc->sc_ih == NULL) 316 panic("can't establish common interrupt\n"); 317 } 318 319 static uint32_t 320 octeon_dwc2_rd_4(void *v, bus_space_handle_t h, bus_size_t off) 321 { 322 323 /* dwc2 uses little-endian addressing */ 324 return mips_lwu((h + off) ^ 4); 325 } 326 327 static void 328 octeon_dwc2_wr_4(void *v, bus_space_handle_t h, bus_size_t off, 329 uint32_t val) 330 { 331 332 /* dwc2 uses little-endian addressing */ 333 mips_sw((h + off) ^ 4, val); 334 } 335 336 int 337 octeon_dwc2_set_dma_addr(device_t self, dma_addr_t dma_addr, int ch) 338 { 339 struct octeon_dwc2_softc *sc = device_private(self); 340 341 octeon_dwc2_reg2_wr(sc, 342 USBN_DMA0_INB_CHN0_OFFSET + ch * 0x8, dma_addr); 343 octeon_dwc2_reg2_wr(sc, 344 USBN_DMA0_OUTB_CHN0_OFFSET + ch * 0x8, dma_addr); 345 return 0; 346 } 347 348 349 static inline void 350 octeon_dwc2_reg_assert(struct octeon_dwc2_softc *sc, bus_size_t offset, 351 uint64_t bits) 352 { 353 uint64_t value; 354 355 value = octeon_dwc2_reg_rd(sc, offset); 356 value |= bits; 357 octeon_dwc2_reg_wr(sc, offset, value); 358 } 359 360 static inline void 361 octeon_dwc2_reg_deassert(struct octeon_dwc2_softc *sc, bus_size_t offset, 362 uint64_t bits) 363 { 364 uint64_t value; 365 366 value = octeon_dwc2_reg_rd(sc, offset); 367 value &= ~bits; 368 octeon_dwc2_reg_wr(sc, offset, value); 369 } 370 371 static inline uint64_t 372 octeon_dwc2_reg_rd(struct octeon_dwc2_softc *sc, bus_size_t off) 373 { 374 return bus_space_read_8(sc->sc_bust, sc->sc_regh, off); 375 } 376 377 static inline void 378 octeon_dwc2_reg_wr(struct octeon_dwc2_softc *sc, bus_size_t off, uint64_t val) 379 { 380 bus_space_write_8(sc->sc_bust, sc->sc_regh, off, val); 381 /* guarantee completion of the store operation on RSL registers*/ 382 bus_space_read_8(sc->sc_bust, sc->sc_regh, off); 383 } 384 385 static inline void 386 octeon_dwc2_reg2_assert(struct octeon_dwc2_softc *sc, bus_size_t off, 387 uint64_t bits) 388 { 389 uint64_t val; 390 391 val = octeon_dwc2_reg2_rd(sc, off); 392 val |= bits; 393 octeon_dwc2_reg2_wr(sc, off, val); 394 } 395 396 static inline void 397 octeon_dwc2_reg2_deassert(struct octeon_dwc2_softc *sc, bus_size_t off, 398 uint64_t bits) 399 { 400 uint64_t val; 401 402 val = octeon_dwc2_reg2_rd(sc, off); 403 val &= ~bits; 404 octeon_dwc2_reg2_wr(sc, off, val); 405 } 406 407 static inline uint64_t 408 octeon_dwc2_reg2_rd(struct octeon_dwc2_softc *sc, bus_size_t off) 409 { 410 return bus_space_read_8(sc->sc_bust, sc->sc_reg2h, off); 411 } 412 413 static inline void 414 octeon_dwc2_reg2_wr(struct octeon_dwc2_softc *sc, bus_size_t off, uint64_t val) 415 { 416 bus_space_write_8(sc->sc_bust, sc->sc_reg2h, off, val); 417 /* guarantee completion of the store operation on RSL registers*/ 418 bus_space_read_8(sc->sc_bust, sc->sc_reg2h, off); 419 } 420