omap_phy_internal.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * This file configures the internal USB PHY in OMAP4430. Used
  4. * with TWL6030 transceiver and MUSB on OMAP4430.
  5. *
  6. * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com
  7. * Author: Hema HK <[email protected]>
  8. */
  9. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10. #include <linux/types.h>
  11. #include <linux/delay.h>
  12. #include <linux/clk.h>
  13. #include <linux/io.h>
  14. #include <linux/err.h>
  15. #include <linux/usb.h>
  16. #include <linux/usb/musb.h>
  17. #include "soc.h"
  18. #include "control.h"
  19. #include "usb.h"
  20. #define CONTROL_DEV_CONF 0x300
  21. #define PHY_PD 0x1
  22. /**
  23. * omap4430_phy_power_down: disable MUSB PHY during early init
  24. *
  25. * OMAP4 MUSB PHY module is enabled by default on reset, but this will
  26. * prevent core retention if not disabled by SW. USB driver will
  27. * later on enable this, once and if the driver needs it.
  28. */
  29. static int __init omap4430_phy_power_down(void)
  30. {
  31. void __iomem *ctrl_base;
  32. if (!cpu_is_omap44xx())
  33. return 0;
  34. ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
  35. if (!ctrl_base) {
  36. pr_err("control module ioremap failed\n");
  37. return -ENOMEM;
  38. }
  39. /* Power down the phy */
  40. writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
  41. iounmap(ctrl_base);
  42. return 0;
  43. }
  44. omap_early_initcall(omap4430_phy_power_down);
  45. void am35x_musb_reset(void)
  46. {
  47. u32 regval;
  48. /* Reset the musb interface */
  49. regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
  50. regval |= AM35XX_USBOTGSS_SW_RST;
  51. omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
  52. regval &= ~AM35XX_USBOTGSS_SW_RST;
  53. omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
  54. regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
  55. }
  56. void am35x_musb_phy_power(u8 on)
  57. {
  58. unsigned long timeout = jiffies + msecs_to_jiffies(100);
  59. u32 devconf2;
  60. if (on) {
  61. /*
  62. * Start the on-chip PHY and its PLL.
  63. */
  64. devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  65. devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
  66. devconf2 |= CONF2_PHY_PLLON;
  67. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  68. pr_info("Waiting for PHY clock good...\n");
  69. while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
  70. & CONF2_PHYCLKGD)) {
  71. cpu_relax();
  72. if (time_after(jiffies, timeout)) {
  73. pr_err("musb PHY clock good timed out\n");
  74. break;
  75. }
  76. }
  77. } else {
  78. /*
  79. * Power down the on-chip PHY.
  80. */
  81. devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  82. devconf2 &= ~CONF2_PHY_PLLON;
  83. devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
  84. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  85. }
  86. }
  87. void am35x_musb_clear_irq(void)
  88. {
  89. u32 regval;
  90. regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
  91. regval |= AM35XX_USBOTGSS_INT_CLR;
  92. omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
  93. regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
  94. }
  95. void am35x_set_mode(u8 musb_mode)
  96. {
  97. u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  98. devconf2 &= ~CONF2_OTGMODE;
  99. switch (musb_mode) {
  100. case MUSB_HOST: /* Force VBUS valid, ID = 0 */
  101. devconf2 |= CONF2_FORCE_HOST;
  102. break;
  103. case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
  104. devconf2 |= CONF2_FORCE_DEVICE;
  105. break;
  106. case MUSB_OTG: /* Don't override the VBUS/ID comparators */
  107. devconf2 |= CONF2_NO_OVERRIDE;
  108. break;
  109. default:
  110. pr_info("Unsupported mode %u\n", musb_mode);
  111. }
  112. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  113. }