1*ba55453cSDan Murphy /* 2*ba55453cSDan Murphy * OMAP USB PHY Support 3*ba55453cSDan Murphy * 4*ba55453cSDan Murphy * (C) Copyright 2013 5*ba55453cSDan Murphy * Texas Instruments, <www.ti.com> 6*ba55453cSDan Murphy * 7*ba55453cSDan Murphy * Author: Dan Murphy <dmurphy@ti.com> 8*ba55453cSDan Murphy * 9*ba55453cSDan Murphy * SPDX-License-Identifier: GPL-2.0+ 10*ba55453cSDan Murphy */ 11*ba55453cSDan Murphy 12*ba55453cSDan Murphy #include <common.h> 13*ba55453cSDan Murphy #include <usb.h> 14*ba55453cSDan Murphy #include <asm-generic/errno.h> 15*ba55453cSDan Murphy #include <asm/omap_common.h> 16*ba55453cSDan Murphy #include <asm/arch/cpu.h> 17*ba55453cSDan Murphy #include <asm/arch/sys_proto.h> 18*ba55453cSDan Murphy 19*ba55453cSDan Murphy #include <linux/compat.h> 20*ba55453cSDan Murphy #include <linux/usb/dwc3.h> 21*ba55453cSDan Murphy #include <linux/usb/xhci-omap.h> 22*ba55453cSDan Murphy 23*ba55453cSDan Murphy #include "../host/xhci.h" 24*ba55453cSDan Murphy 25*ba55453cSDan Murphy struct usb_dpll_params { 26*ba55453cSDan Murphy u16 m; 27*ba55453cSDan Murphy u8 n; 28*ba55453cSDan Murphy u8 freq:3; 29*ba55453cSDan Murphy u8 sd; 30*ba55453cSDan Murphy u32 mf; 31*ba55453cSDan Murphy }; 32*ba55453cSDan Murphy 33*ba55453cSDan Murphy #define NUM_USB_CLKS 6 34*ba55453cSDan Murphy 35*ba55453cSDan Murphy static struct usb_dpll_params omap_usb3_dpll_params[NUM_USB_CLKS] = { 36*ba55453cSDan Murphy {1250, 5, 4, 20, 0}, /* 12 MHz */ 37*ba55453cSDan Murphy {3125, 20, 4, 20, 0}, /* 16.8 MHz */ 38*ba55453cSDan Murphy {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ 39*ba55453cSDan Murphy {1250, 12, 4, 20, 0}, /* 26 MHz */ 40*ba55453cSDan Murphy {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ 41*ba55453cSDan Murphy {1000, 7, 4, 10, 0}, /* 20 MHz */ 42*ba55453cSDan Murphy }; 43*ba55453cSDan Murphy 44*ba55453cSDan Murphy static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) 45*ba55453cSDan Murphy { 46*ba55453cSDan Murphy u32 val; 47*ba55453cSDan Murphy 48*ba55453cSDan Murphy writel(SET_PLL_GO, &phy_regs->pll_go); 49*ba55453cSDan Murphy do { 50*ba55453cSDan Murphy val = readl(&phy_regs->pll_status); 51*ba55453cSDan Murphy if (val & PLL_LOCK) 52*ba55453cSDan Murphy break; 53*ba55453cSDan Murphy } while (1); 54*ba55453cSDan Murphy } 55*ba55453cSDan Murphy 56*ba55453cSDan Murphy static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) 57*ba55453cSDan Murphy { 58*ba55453cSDan Murphy u32 clk_index = get_sys_clk_index(); 59*ba55453cSDan Murphy u32 val; 60*ba55453cSDan Murphy 61*ba55453cSDan Murphy val = readl(&phy_regs->pll_config_1); 62*ba55453cSDan Murphy val &= ~PLL_REGN_MASK; 63*ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; 64*ba55453cSDan Murphy writel(val, &phy_regs->pll_config_1); 65*ba55453cSDan Murphy 66*ba55453cSDan Murphy val = readl(&phy_regs->pll_config_2); 67*ba55453cSDan Murphy val &= ~PLL_SELFREQDCO_MASK; 68*ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; 69*ba55453cSDan Murphy writel(val, &phy_regs->pll_config_2); 70*ba55453cSDan Murphy 71*ba55453cSDan Murphy val = readl(&phy_regs->pll_config_1); 72*ba55453cSDan Murphy val &= ~PLL_REGM_MASK; 73*ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; 74*ba55453cSDan Murphy writel(val, &phy_regs->pll_config_1); 75*ba55453cSDan Murphy 76*ba55453cSDan Murphy val = readl(&phy_regs->pll_config_4); 77*ba55453cSDan Murphy val &= ~PLL_REGM_F_MASK; 78*ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; 79*ba55453cSDan Murphy writel(val, &phy_regs->pll_config_4); 80*ba55453cSDan Murphy 81*ba55453cSDan Murphy val = readl(&phy_regs->pll_config_3); 82*ba55453cSDan Murphy val &= ~PLL_SD_MASK; 83*ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; 84*ba55453cSDan Murphy writel(val, &phy_regs->pll_config_3); 85*ba55453cSDan Murphy 86*ba55453cSDan Murphy omap_usb_dpll_relock(phy_regs); 87*ba55453cSDan Murphy } 88*ba55453cSDan Murphy 89*ba55453cSDan Murphy static void usb3_phy_partial_powerup(struct omap_usb3_phy *phy_regs) 90*ba55453cSDan Murphy { 91*ba55453cSDan Murphy u32 rate = get_sys_clk_freq()/1000000; 92*ba55453cSDan Murphy u32 val; 93*ba55453cSDan Murphy 94*ba55453cSDan Murphy val = readl((*ctrl)->control_phy_power_usb); 95*ba55453cSDan Murphy val &= ~(USB3_PWRCTL_CLK_CMD_MASK | USB3_PWRCTL_CLK_FREQ_MASK); 96*ba55453cSDan Murphy val |= (USB3_PHY_PARTIAL_RX_POWERON | USB3_PHY_TX_RX_POWERON); 97*ba55453cSDan Murphy val |= rate << USB3_PWRCTL_CLK_FREQ_SHIFT; 98*ba55453cSDan Murphy 99*ba55453cSDan Murphy writel(val, (*ctrl)->control_phy_power_usb); 100*ba55453cSDan Murphy } 101*ba55453cSDan Murphy 102*ba55453cSDan Murphy void usb3_phy_power(int on) 103*ba55453cSDan Murphy { 104*ba55453cSDan Murphy u32 val; 105*ba55453cSDan Murphy 106*ba55453cSDan Murphy val = readl((*ctrl)->control_phy_power_usb); 107*ba55453cSDan Murphy if (on) { 108*ba55453cSDan Murphy val &= ~USB3_PWRCTL_CLK_CMD_MASK; 109*ba55453cSDan Murphy val |= USB3_PHY_TX_RX_POWERON; 110*ba55453cSDan Murphy } else { 111*ba55453cSDan Murphy val &= (~USB3_PWRCTL_CLK_CMD_MASK & ~USB3_PHY_TX_RX_POWERON); 112*ba55453cSDan Murphy } 113*ba55453cSDan Murphy 114*ba55453cSDan Murphy writel(val, (*ctrl)->control_phy_power_usb); 115*ba55453cSDan Murphy } 116*ba55453cSDan Murphy 117*ba55453cSDan Murphy void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) 118*ba55453cSDan Murphy { 119*ba55453cSDan Murphy omap_usb_dpll_lock(phy_regs); 120*ba55453cSDan Murphy 121*ba55453cSDan Murphy usb3_phy_partial_powerup(phy_regs); 122*ba55453cSDan Murphy /* 123*ba55453cSDan Murphy * Give enough time for the PHY to partially power-up before 124*ba55453cSDan Murphy * powering it up completely. delay value suggested by the HW 125*ba55453cSDan Murphy * team. 126*ba55453cSDan Murphy */ 127*ba55453cSDan Murphy mdelay(100); 128*ba55453cSDan Murphy usb3_phy_power(1); 129*ba55453cSDan Murphy } 130*ba55453cSDan Murphy 131*ba55453cSDan Murphy void omap_enable_phy_clocks(struct omap_xhci *omap) 132*ba55453cSDan Murphy { 133*ba55453cSDan Murphy u32 val; 134*ba55453cSDan Murphy 135*ba55453cSDan Murphy /* Setting OCP2SCP1 register */ 136*ba55453cSDan Murphy setbits_le32((*prcm)->cm_l3init_ocp2scp1_clkctrl, 137*ba55453cSDan Murphy OCP2SCP1_CLKCTRL_MODULEMODE_HW); 138*ba55453cSDan Murphy 139*ba55453cSDan Murphy /* Turn on 32K AON clk */ 140*ba55453cSDan Murphy setbits_le32((*prcm)->cm_coreaon_usb_phy_core_clkctrl, 141*ba55453cSDan Murphy USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); 142*ba55453cSDan Murphy 143*ba55453cSDan Murphy /* Setting CM_L3INIT_CLKSTCTRL to 0x0 i.e NO sleep */ 144*ba55453cSDan Murphy writel(0x0, (*prcm)->cm_l3init_clkstctrl); 145*ba55453cSDan Murphy 146*ba55453cSDan Murphy val = (USBOTGSS_DMADISABLE | 147*ba55453cSDan Murphy USBOTGSS_STANDBYMODE_SMRT_WKUP | 148*ba55453cSDan Murphy USBOTGSS_IDLEMODE_NOIDLE); 149*ba55453cSDan Murphy writel(val, &omap->otg_wrapper->sysconfig); 150*ba55453cSDan Murphy 151*ba55453cSDan Murphy /* Clear the utmi OTG status */ 152*ba55453cSDan Murphy val = readl(&omap->otg_wrapper->utmi_otg_status); 153*ba55453cSDan Murphy writel(val, &omap->otg_wrapper->utmi_otg_status); 154*ba55453cSDan Murphy 155*ba55453cSDan Murphy /* Enable interrupts */ 156*ba55453cSDan Murphy writel(USBOTGSS_COREIRQ_EN, &omap->otg_wrapper->irqenable_set_0); 157*ba55453cSDan Murphy val = (USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN | 158*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN | 159*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN | 160*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN | 161*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN | 162*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN | 163*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN | 164*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN | 165*ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_OEVT_EN); 166*ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqenable_set_1); 167*ba55453cSDan Murphy 168*ba55453cSDan Murphy /* Clear the IRQ status */ 169*ba55453cSDan Murphy val = readl(&omap->otg_wrapper->irqstatus_1); 170*ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqstatus_1); 171*ba55453cSDan Murphy val = readl(&omap->otg_wrapper->irqstatus_0); 172*ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqstatus_0); 173*ba55453cSDan Murphy 174*ba55453cSDan Murphy /* Enable the USB OTG Super speed clocks */ 175*ba55453cSDan Murphy val = (OPTFCLKEN_REFCLK960M | OTG_SS_CLKCTRL_MODULEMODE_HW); 176*ba55453cSDan Murphy setbits_le32((*prcm)->cm_l3init_usb_otg_ss_clkctrl, val); 177*ba55453cSDan Murphy 178*ba55453cSDan Murphy }; 179*ba55453cSDan Murphy 180*ba55453cSDan Murphy void omap_reset_usb_phy(struct dwc3 *dwc3_reg) 181*ba55453cSDan Murphy { 182*ba55453cSDan Murphy /* Assert USB3 PHY reset */ 183*ba55453cSDan Murphy setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 184*ba55453cSDan Murphy 185*ba55453cSDan Murphy /* Assert USB2 PHY reset */ 186*ba55453cSDan Murphy setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 187*ba55453cSDan Murphy 188*ba55453cSDan Murphy mdelay(100); 189*ba55453cSDan Murphy 190*ba55453cSDan Murphy /* Clear USB3 PHY reset */ 191*ba55453cSDan Murphy clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 192*ba55453cSDan Murphy 193*ba55453cSDan Murphy /* Clear USB2 PHY reset */ 194*ba55453cSDan Murphy clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 195*ba55453cSDan Murphy 196*ba55453cSDan Murphy } 197*ba55453cSDan Murphy 198