18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This file configures the internal USB PHY in OMAP4430. Used 48c2ecf20Sopenharmony_ci * with TWL6030 transceiver and MUSB on OMAP4430. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com 78c2ecf20Sopenharmony_ci * Author: Hema HK <hemahk@ti.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/usb.h> 188c2ecf20Sopenharmony_ci#include <linux/usb/musb.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "soc.h" 218c2ecf20Sopenharmony_ci#include "control.h" 228c2ecf20Sopenharmony_ci#include "usb.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define CONTROL_DEV_CONF 0x300 258c2ecf20Sopenharmony_ci#define PHY_PD 0x1 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/** 288c2ecf20Sopenharmony_ci * omap4430_phy_power_down: disable MUSB PHY during early init 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * OMAP4 MUSB PHY module is enabled by default on reset, but this will 318c2ecf20Sopenharmony_ci * prevent core retention if not disabled by SW. USB driver will 328c2ecf20Sopenharmony_ci * later on enable this, once and if the driver needs it. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_cistatic int __init omap4430_phy_power_down(void) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci void __iomem *ctrl_base; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (!cpu_is_omap44xx()) 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); 428c2ecf20Sopenharmony_ci if (!ctrl_base) { 438c2ecf20Sopenharmony_ci pr_err("control module ioremap failed\n"); 448c2ecf20Sopenharmony_ci return -ENOMEM; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* Power down the phy */ 488c2ecf20Sopenharmony_ci writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci iounmap(ctrl_base); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return 0; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ciomap_early_initcall(omap4430_phy_power_down); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_civoid am35x_musb_reset(void) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci u32 regval; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Reset the musb interface */ 618c2ecf20Sopenharmony_ci regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci regval |= AM35XX_USBOTGSS_SW_RST; 648c2ecf20Sopenharmony_ci omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci regval &= ~AM35XX_USBOTGSS_SW_RST; 678c2ecf20Sopenharmony_ci omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_civoid am35x_musb_phy_power(u8 on) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci unsigned long timeout = jiffies + msecs_to_jiffies(100); 758c2ecf20Sopenharmony_ci u32 devconf2; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (on) { 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * Start the on-chip PHY and its PLL. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); 848c2ecf20Sopenharmony_ci devconf2 |= CONF2_PHY_PLLON; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci pr_info("Waiting for PHY clock good...\n"); 898c2ecf20Sopenharmony_ci while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) 908c2ecf20Sopenharmony_ci & CONF2_PHYCLKGD)) { 918c2ecf20Sopenharmony_ci cpu_relax(); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (time_after(jiffies, timeout)) { 948c2ecf20Sopenharmony_ci pr_err("musb PHY clock good timed out\n"); 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci } else { 998c2ecf20Sopenharmony_ci /* 1008c2ecf20Sopenharmony_ci * Power down the on-chip PHY. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci devconf2 &= ~CONF2_PHY_PLLON; 1058c2ecf20Sopenharmony_ci devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; 1068c2ecf20Sopenharmony_ci omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_civoid am35x_musb_clear_irq(void) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci u32 regval; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 1158c2ecf20Sopenharmony_ci regval |= AM35XX_USBOTGSS_INT_CLR; 1168c2ecf20Sopenharmony_ci omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR); 1178c2ecf20Sopenharmony_ci regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_civoid am35x_set_mode(u8 musb_mode) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci devconf2 &= ~CONF2_OTGMODE; 1258c2ecf20Sopenharmony_ci switch (musb_mode) { 1268c2ecf20Sopenharmony_ci case MUSB_HOST: /* Force VBUS valid, ID = 0 */ 1278c2ecf20Sopenharmony_ci devconf2 |= CONF2_FORCE_HOST; 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ 1308c2ecf20Sopenharmony_ci devconf2 |= CONF2_FORCE_DEVICE; 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci case MUSB_OTG: /* Don't override the VBUS/ID comparators */ 1338c2ecf20Sopenharmony_ci devconf2 |= CONF2_NO_OVERRIDE; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci default: 1368c2ecf20Sopenharmony_ci pr_info("Unsupported mode %u\n", musb_mode); 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 1408c2ecf20Sopenharmony_ci} 141