1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Allwinner SUNXI "glue layer" 4 * 5 * Copyright © 2015 Hans de Goede <hdegoede@redhat.com> 6 * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> 7 * 8 * Based on the sw_usb "Allwinner OTG Dual Role Controller" code. 9 * Copyright 2007-2012 (C) Allwinner Technology Co., Ltd. 10 * javen <javen@allwinnertech.com> 11 * 12 * Based on the DA8xx "glue layer" code. 13 * Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com> 14 * Copyright (C) 2005-2006 by Texas Instruments 15 * 16 * This file is part of the Inventra Controller Driver for Linux. 17 */ 18 #include <common.h> 19 #include <clk.h> 20 #include <dm.h> 21 #include <generic-phy.h> 22 #include <phy-sun4i-usb.h> 23 #include <reset.h> 24 #include <asm/arch/cpu.h> 25 #include <asm/arch/clock.h> 26 #include <asm/arch/gpio.h> 27 #include <asm-generic/gpio.h> 28 #include <dm/lists.h> 29 #include <dm/root.h> 30 #include <linux/usb/musb.h> 31 #include "linux-compat.h" 32 #include "musb_core.h" 33 #include "musb_uboot.h" 34 35 /****************************************************************************** 36 ****************************************************************************** 37 * From the Allwinner driver 38 ****************************************************************************** 39 ******************************************************************************/ 40 41 /****************************************************************************** 42 * From include/sunxi_usb_bsp.h 43 ******************************************************************************/ 44 45 /* reg offsets */ 46 #define USBC_REG_o_ISCR 0x0400 47 #define USBC_REG_o_PHYCTL 0x0404 48 #define USBC_REG_o_PHYBIST 0x0408 49 #define USBC_REG_o_PHYTUNE 0x040c 50 51 #define USBC_REG_o_VEND0 0x0043 52 53 /* Interface Status and Control */ 54 #define USBC_BP_ISCR_VBUS_VALID_FROM_DATA 30 55 #define USBC_BP_ISCR_VBUS_VALID_FROM_VBUS 29 56 #define USBC_BP_ISCR_EXT_ID_STATUS 28 57 #define USBC_BP_ISCR_EXT_DM_STATUS 27 58 #define USBC_BP_ISCR_EXT_DP_STATUS 26 59 #define USBC_BP_ISCR_MERGED_VBUS_STATUS 25 60 #define USBC_BP_ISCR_MERGED_ID_STATUS 24 61 62 #define USBC_BP_ISCR_ID_PULLUP_EN 17 63 #define USBC_BP_ISCR_DPDM_PULLUP_EN 16 64 #define USBC_BP_ISCR_FORCE_ID 14 65 #define USBC_BP_ISCR_FORCE_VBUS_VALID 12 66 #define USBC_BP_ISCR_VBUS_VALID_SRC 10 67 68 #define USBC_BP_ISCR_HOSC_EN 7 69 #define USBC_BP_ISCR_VBUS_CHANGE_DETECT 6 70 #define USBC_BP_ISCR_ID_CHANGE_DETECT 5 71 #define USBC_BP_ISCR_DPDM_CHANGE_DETECT 4 72 #define USBC_BP_ISCR_IRQ_ENABLE 3 73 #define USBC_BP_ISCR_VBUS_CHANGE_DETECT_EN 2 74 #define USBC_BP_ISCR_ID_CHANGE_DETECT_EN 1 75 #define USBC_BP_ISCR_DPDM_CHANGE_DETECT_EN 0 76 77 /****************************************************************************** 78 * From usbc/usbc.c 79 ******************************************************************************/ 80 81 #define OFF_SUN6I_AHB_RESET0 0x2c0 82 83 struct sunxi_musb_config { 84 struct musb_hdrc_config *config; 85 }; 86 87 struct sunxi_glue { 88 struct musb_host_data mdata; 89 struct clk clk; 90 struct reset_ctl rst; 91 struct sunxi_musb_config *cfg; 92 struct device dev; 93 struct phy phy; 94 }; 95 #define to_sunxi_glue(d) container_of(d, struct sunxi_glue, dev) 96 97 static u32 USBC_WakeUp_ClearChangeDetect(u32 reg_val) 98 { 99 u32 temp = reg_val; 100 101 temp &= ~BIT(USBC_BP_ISCR_VBUS_CHANGE_DETECT); 102 temp &= ~BIT(USBC_BP_ISCR_ID_CHANGE_DETECT); 103 temp &= ~BIT(USBC_BP_ISCR_DPDM_CHANGE_DETECT); 104 105 return temp; 106 } 107 108 static void USBC_EnableIdPullUp(__iomem void *base) 109 { 110 u32 reg_val; 111 112 reg_val = musb_readl(base, USBC_REG_o_ISCR); 113 reg_val |= BIT(USBC_BP_ISCR_ID_PULLUP_EN); 114 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 115 musb_writel(base, USBC_REG_o_ISCR, reg_val); 116 } 117 118 static void USBC_EnableDpDmPullUp(__iomem void *base) 119 { 120 u32 reg_val; 121 122 reg_val = musb_readl(base, USBC_REG_o_ISCR); 123 reg_val |= BIT(USBC_BP_ISCR_DPDM_PULLUP_EN); 124 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 125 musb_writel(base, USBC_REG_o_ISCR, reg_val); 126 } 127 128 static void USBC_ForceIdToLow(__iomem void *base) 129 { 130 u32 reg_val; 131 132 reg_val = musb_readl(base, USBC_REG_o_ISCR); 133 reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID); 134 reg_val |= (0x02 << USBC_BP_ISCR_FORCE_ID); 135 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 136 musb_writel(base, USBC_REG_o_ISCR, reg_val); 137 } 138 139 static void USBC_ForceIdToHigh(__iomem void *base) 140 { 141 u32 reg_val; 142 143 reg_val = musb_readl(base, USBC_REG_o_ISCR); 144 reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID); 145 reg_val |= (0x03 << USBC_BP_ISCR_FORCE_ID); 146 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 147 musb_writel(base, USBC_REG_o_ISCR, reg_val); 148 } 149 150 static void USBC_ForceVbusValidToLow(__iomem void *base) 151 { 152 u32 reg_val; 153 154 reg_val = musb_readl(base, USBC_REG_o_ISCR); 155 reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID); 156 reg_val |= (0x02 << USBC_BP_ISCR_FORCE_VBUS_VALID); 157 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 158 musb_writel(base, USBC_REG_o_ISCR, reg_val); 159 } 160 161 static void USBC_ForceVbusValidToHigh(__iomem void *base) 162 { 163 u32 reg_val; 164 165 reg_val = musb_readl(base, USBC_REG_o_ISCR); 166 reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID); 167 reg_val |= (0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID); 168 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); 169 musb_writel(base, USBC_REG_o_ISCR, reg_val); 170 } 171 172 static void USBC_ConfigFIFO_Base(void) 173 { 174 u32 reg_value; 175 176 /* config usb fifo, 8kb mode */ 177 reg_value = readl(SUNXI_SRAMC_BASE + 0x04); 178 reg_value &= ~(0x03 << 0); 179 reg_value |= BIT(0); 180 writel(reg_value, SUNXI_SRAMC_BASE + 0x04); 181 } 182 183 /****************************************************************************** 184 * Needed for the DFU polling magic 185 ******************************************************************************/ 186 187 static u8 last_int_usb; 188 189 bool dfu_usb_get_reset(void) 190 { 191 return !!(last_int_usb & MUSB_INTR_RESET); 192 } 193 194 /****************************************************************************** 195 * MUSB Glue code 196 ******************************************************************************/ 197 198 static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci) 199 { 200 struct musb *musb = __hci; 201 irqreturn_t retval = IRQ_NONE; 202 203 /* read and flush interrupts */ 204 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); 205 last_int_usb = musb->int_usb; 206 if (musb->int_usb) 207 musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); 208 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); 209 if (musb->int_tx) 210 musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); 211 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); 212 if (musb->int_rx) 213 musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); 214 215 if (musb->int_usb || musb->int_tx || musb->int_rx) 216 retval |= musb_interrupt(musb); 217 218 return retval; 219 } 220 221 /* musb_core does not call enable / disable in a balanced manner <sigh> */ 222 static bool enabled = false; 223 224 static int sunxi_musb_enable(struct musb *musb) 225 { 226 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 227 int ret; 228 229 pr_debug("%s():\n", __func__); 230 231 musb_ep_select(musb->mregs, 0); 232 musb_writeb(musb->mregs, MUSB_FADDR, 0); 233 234 if (enabled) 235 return 0; 236 237 /* select PIO mode */ 238 musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); 239 240 if (is_host_enabled(musb)) { 241 ret = sun4i_usb_phy_vbus_detect(&glue->phy); 242 if (ret == 1) { 243 printf("A charger is plugged into the OTG: "); 244 return -ENODEV; 245 } 246 247 ret = sun4i_usb_phy_id_detect(&glue->phy); 248 if (ret == 1) { 249 printf("No host cable detected: "); 250 return -ENODEV; 251 } 252 253 ret = generic_phy_power_on(&glue->phy); 254 if (ret) { 255 pr_err("failed to power on USB PHY\n"); 256 return ret; 257 } 258 } 259 260 USBC_ForceVbusValidToHigh(musb->mregs); 261 262 enabled = true; 263 return 0; 264 } 265 266 static void sunxi_musb_disable(struct musb *musb) 267 { 268 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 269 int ret; 270 271 pr_debug("%s():\n", __func__); 272 273 if (!enabled) 274 return; 275 276 if (is_host_enabled(musb)) { 277 ret = generic_phy_power_off(&glue->phy); 278 if (ret) { 279 pr_err("failed to power off USB PHY\n"); 280 return; 281 } 282 } 283 284 USBC_ForceVbusValidToLow(musb->mregs); 285 mdelay(200); /* Wait for the current session to timeout */ 286 287 enabled = false; 288 } 289 290 static int sunxi_musb_init(struct musb *musb) 291 { 292 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 293 int ret; 294 295 pr_debug("%s():\n", __func__); 296 297 ret = clk_enable(&glue->clk); 298 if (ret) { 299 dev_err(dev, "failed to enable clock\n"); 300 return ret; 301 } 302 303 if (reset_valid(&glue->rst)) { 304 ret = reset_deassert(&glue->rst); 305 if (ret) { 306 dev_err(dev, "failed to deassert reset\n"); 307 goto err_clk; 308 } 309 } 310 311 ret = generic_phy_init(&glue->phy); 312 if (ret) { 313 dev_err(dev, "failed to init USB PHY\n"); 314 goto err_rst; 315 } 316 317 musb->isr = sunxi_musb_interrupt; 318 319 USBC_ConfigFIFO_Base(); 320 USBC_EnableDpDmPullUp(musb->mregs); 321 USBC_EnableIdPullUp(musb->mregs); 322 323 if (is_host_enabled(musb)) { 324 /* Host mode */ 325 USBC_ForceIdToLow(musb->mregs); 326 } else { 327 /* Peripheral mode */ 328 USBC_ForceIdToHigh(musb->mregs); 329 } 330 USBC_ForceVbusValidToHigh(musb->mregs); 331 332 return 0; 333 334 err_rst: 335 if (reset_valid(&glue->rst)) 336 reset_assert(&glue->rst); 337 err_clk: 338 clk_disable(&glue->clk); 339 return ret; 340 } 341 342 static int sunxi_musb_exit(struct musb *musb) 343 { 344 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 345 int ret = 0; 346 347 if (generic_phy_valid(&glue->phy)) { 348 ret = generic_phy_exit(&glue->phy); 349 if (ret) { 350 dev_err(dev, "failed to power off usb phy\n"); 351 return ret; 352 } 353 } 354 355 if (reset_valid(&glue->rst)) 356 reset_assert(&glue->rst); 357 clk_disable(&glue->clk); 358 359 return 0; 360 } 361 362 static void sunxi_musb_pre_root_reset_end(struct musb *musb) 363 { 364 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 365 366 sun4i_usb_phy_set_squelch_detect(&glue->phy, false); 367 } 368 369 static void sunxi_musb_post_root_reset_end(struct musb *musb) 370 { 371 struct sunxi_glue *glue = to_sunxi_glue(musb->controller); 372 373 sun4i_usb_phy_set_squelch_detect(&glue->phy, true); 374 } 375 376 static const struct musb_platform_ops sunxi_musb_ops = { 377 .init = sunxi_musb_init, 378 .exit = sunxi_musb_exit, 379 .enable = sunxi_musb_enable, 380 .disable = sunxi_musb_disable, 381 .pre_root_reset_end = sunxi_musb_pre_root_reset_end, 382 .post_root_reset_end = sunxi_musb_post_root_reset_end, 383 }; 384 385 /* Allwinner OTG supports up to 5 endpoints */ 386 #define SUNXI_MUSB_MAX_EP_NUM 6 387 #define SUNXI_MUSB_RAM_BITS 11 388 389 static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = { 390 MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), 391 MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), 392 MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), 393 MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), 394 MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), 395 MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), 396 MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), 397 MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), 398 MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512), 399 MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512), 400 }; 401 402 /* H3/V3s OTG supports only 4 endpoints */ 403 #define SUNXI_MUSB_MAX_EP_NUM_H3 5 404 405 static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = { 406 MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), 407 MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), 408 MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), 409 MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), 410 MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), 411 MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), 412 MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), 413 MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), 414 }; 415 416 static struct musb_hdrc_config musb_config = { 417 .fifo_cfg = sunxi_musb_mode_cfg, 418 .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), 419 .multipoint = true, 420 .dyn_fifo = true, 421 .num_eps = SUNXI_MUSB_MAX_EP_NUM, 422 .ram_bits = SUNXI_MUSB_RAM_BITS, 423 }; 424 425 static struct musb_hdrc_config musb_config_h3 = { 426 .fifo_cfg = sunxi_musb_mode_cfg_h3, 427 .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), 428 .multipoint = true, 429 .dyn_fifo = true, 430 .soft_con = true, 431 .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, 432 .ram_bits = SUNXI_MUSB_RAM_BITS, 433 }; 434 435 static int musb_usb_probe(struct udevice *dev) 436 { 437 struct sunxi_glue *glue = dev_get_priv(dev); 438 struct musb_host_data *host = &glue->mdata; 439 struct musb_hdrc_platform_data pdata; 440 void *base = dev_read_addr_ptr(dev); 441 int ret; 442 443 #ifdef CONFIG_USB_MUSB_HOST 444 struct usb_bus_priv *priv = dev_get_uclass_priv(dev); 445 #endif 446 447 if (!base) 448 return -EINVAL; 449 450 glue->cfg = (struct sunxi_musb_config *)dev_get_driver_data(dev); 451 if (!glue->cfg) 452 return -EINVAL; 453 454 ret = clk_get_by_index(dev, 0, &glue->clk); 455 if (ret) { 456 dev_err(dev, "failed to get clock\n"); 457 return ret; 458 } 459 460 ret = reset_get_by_index(dev, 0, &glue->rst); 461 if (ret && ret != -ENOENT) { 462 dev_err(dev, "failed to get reset\n"); 463 return ret; 464 } 465 466 ret = generic_phy_get_by_name(dev, "usb", &glue->phy); 467 if (ret) { 468 pr_err("failed to get usb PHY\n"); 469 return ret; 470 } 471 472 memset(&pdata, 0, sizeof(pdata)); 473 pdata.power = 250; 474 pdata.platform_ops = &sunxi_musb_ops; 475 pdata.config = glue->cfg->config; 476 477 #ifdef CONFIG_USB_MUSB_HOST 478 priv->desc_before_addr = true; 479 480 pdata.mode = MUSB_HOST; 481 host->host = musb_init_controller(&pdata, &glue->dev, base); 482 if (!host->host) 483 return -EIO; 484 485 ret = musb_lowlevel_init(host); 486 if (!ret) 487 printf("Allwinner mUSB OTG (Host)\n"); 488 #else 489 pdata.mode = MUSB_PERIPHERAL; 490 host->host = musb_register(&pdata, &glue->dev, base); 491 if (!host->host) 492 return -EIO; 493 494 printf("Allwinner mUSB OTG (Peripheral)\n"); 495 #endif 496 497 return ret; 498 } 499 500 static int musb_usb_remove(struct udevice *dev) 501 { 502 struct sunxi_glue *glue = dev_get_priv(dev); 503 struct musb_host_data *host = &glue->mdata; 504 505 musb_stop(host->host); 506 free(host->host); 507 host->host = NULL; 508 509 return 0; 510 } 511 512 static const struct sunxi_musb_config sun4i_a10_cfg = { 513 .config = &musb_config, 514 }; 515 516 static const struct sunxi_musb_config sun6i_a31_cfg = { 517 .config = &musb_config, 518 }; 519 520 static const struct sunxi_musb_config sun8i_h3_cfg = { 521 .config = &musb_config_h3, 522 }; 523 524 static const struct udevice_id sunxi_musb_ids[] = { 525 { .compatible = "allwinner,sun4i-a10-musb", 526 .data = (ulong)&sun4i_a10_cfg }, 527 { .compatible = "allwinner,sun6i-a31-musb", 528 .data = (ulong)&sun6i_a31_cfg }, 529 { .compatible = "allwinner,sun8i-a33-musb", 530 .data = (ulong)&sun6i_a31_cfg }, 531 { .compatible = "allwinner,sun8i-h3-musb", 532 .data = (ulong)&sun8i_h3_cfg }, 533 { } 534 }; 535 536 U_BOOT_DRIVER(usb_musb) = { 537 .name = "sunxi-musb", 538 #ifdef CONFIG_USB_MUSB_HOST 539 .id = UCLASS_USB, 540 #else 541 .id = UCLASS_USB_GADGET_GENERIC, 542 #endif 543 .of_match = sunxi_musb_ids, 544 .probe = musb_usb_probe, 545 .remove = musb_usb_remove, 546 #ifdef CONFIG_USB_MUSB_HOST 547 .ops = &musb_usb_ops, 548 #endif 549 .platdata_auto_alloc_size = sizeof(struct usb_platdata), 550 .priv_auto_alloc_size = sizeof(struct sunxi_glue), 551 }; 552