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