Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003   * This file configures the internal USB PHY in OMAP4430. Used
0004   * with TWL6030 transceiver and MUSB on OMAP4430.
0005   *
0006   * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com
0007   * Author: Hema HK <hemahk@ti.com>
0008   */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <linux/types.h>
0013 #include <linux/delay.h>
0014 #include <linux/clk.h>
0015 #include <linux/io.h>
0016 #include <linux/err.h>
0017 #include <linux/usb.h>
0018 #include <linux/usb/musb.h>
0019 
0020 #include "soc.h"
0021 #include "control.h"
0022 #include "usb.h"
0023 
0024 #define CONTROL_DEV_CONF        0x300
0025 #define PHY_PD              0x1
0026 
0027 /**
0028  * omap4430_phy_power_down: disable MUSB PHY during early init
0029  *
0030  * OMAP4 MUSB PHY module is enabled by default on reset, but this will
0031  * prevent core retention if not disabled by SW. USB driver will
0032  * later on enable this, once and if the driver needs it.
0033  */
0034 static int __init omap4430_phy_power_down(void)
0035 {
0036     void __iomem *ctrl_base;
0037 
0038     if (!cpu_is_omap44xx())
0039         return 0;
0040 
0041     ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
0042     if (!ctrl_base) {
0043         pr_err("control module ioremap failed\n");
0044         return -ENOMEM;
0045     }
0046 
0047     /* Power down the phy */
0048     writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
0049 
0050     iounmap(ctrl_base);
0051 
0052     return 0;
0053 }
0054 omap_early_initcall(omap4430_phy_power_down);
0055 
0056 void am35x_musb_reset(void)
0057 {
0058     u32 regval;
0059 
0060     /* Reset the musb interface */
0061     regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
0062 
0063     regval |= AM35XX_USBOTGSS_SW_RST;
0064     omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
0065 
0066     regval &= ~AM35XX_USBOTGSS_SW_RST;
0067     omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
0068 
0069     regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
0070 }
0071 
0072 void am35x_musb_phy_power(u8 on)
0073 {
0074     unsigned long timeout = jiffies + msecs_to_jiffies(100);
0075     u32 devconf2;
0076 
0077     if (on) {
0078         /*
0079          * Start the on-chip PHY and its PLL.
0080          */
0081         devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
0082 
0083         devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
0084         devconf2 |= CONF2_PHY_PLLON;
0085 
0086         omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
0087 
0088         pr_info("Waiting for PHY clock good...\n");
0089         while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
0090                 & CONF2_PHYCLKGD)) {
0091             cpu_relax();
0092 
0093             if (time_after(jiffies, timeout)) {
0094                 pr_err("musb PHY clock good timed out\n");
0095                 break;
0096             }
0097         }
0098     } else {
0099         /*
0100          * Power down the on-chip PHY.
0101          */
0102         devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
0103 
0104         devconf2 &= ~CONF2_PHY_PLLON;
0105         devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
0106         omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
0107     }
0108 }
0109 
0110 void am35x_musb_clear_irq(void)
0111 {
0112     u32 regval;
0113 
0114     regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
0115     regval |= AM35XX_USBOTGSS_INT_CLR;
0116     omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
0117     regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
0118 }
0119 
0120 void am35x_set_mode(u8 musb_mode)
0121 {
0122     u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
0123 
0124     devconf2 &= ~CONF2_OTGMODE;
0125     switch (musb_mode) {
0126     case MUSB_HOST:     /* Force VBUS valid, ID = 0 */
0127         devconf2 |= CONF2_FORCE_HOST;
0128         break;
0129     case MUSB_PERIPHERAL:   /* Force VBUS valid, ID = 1 */
0130         devconf2 |= CONF2_FORCE_DEVICE;
0131         break;
0132     case MUSB_OTG:      /* Don't override the VBUS/ID comparators */
0133         devconf2 |= CONF2_NO_OVERRIDE;
0134         break;
0135     default:
0136         pr_info("Unsupported mode %u\n", musb_mode);
0137     }
0138 
0139     omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
0140 }