1ba55453cSDan Murphy /* 2ba55453cSDan Murphy * OMAP USB PHY Support 3ba55453cSDan Murphy * 4ba55453cSDan Murphy * (C) Copyright 2013 5ba55453cSDan Murphy * Texas Instruments, <www.ti.com> 6ba55453cSDan Murphy * 7ba55453cSDan Murphy * Author: Dan Murphy <dmurphy@ti.com> 8ba55453cSDan Murphy * 9ba55453cSDan Murphy * SPDX-License-Identifier: GPL-2.0+ 10ba55453cSDan Murphy */ 11ba55453cSDan Murphy 12ba55453cSDan Murphy #include <common.h> 13ba55453cSDan Murphy #include <usb.h> 14ba55453cSDan Murphy #include <asm-generic/errno.h> 15ba55453cSDan Murphy #include <asm/omap_common.h> 16ba55453cSDan Murphy #include <asm/arch/cpu.h> 17ba55453cSDan Murphy #include <asm/arch/sys_proto.h> 18ba55453cSDan Murphy 19ba55453cSDan Murphy #include <linux/compat.h> 20ba55453cSDan Murphy #include <linux/usb/dwc3.h> 21ba55453cSDan Murphy #include <linux/usb/xhci-omap.h> 22ba55453cSDan Murphy 23ba55453cSDan Murphy #include "../host/xhci.h" 24ba55453cSDan Murphy 25834e91afSDan Murphy #ifdef CONFIG_OMAP_USB3PHY1_HOST 26ba55453cSDan Murphy struct usb_dpll_params { 27ba55453cSDan Murphy u16 m; 28ba55453cSDan Murphy u8 n; 29ba55453cSDan Murphy u8 freq:3; 30ba55453cSDan Murphy u8 sd; 31ba55453cSDan Murphy u32 mf; 32ba55453cSDan Murphy }; 33ba55453cSDan Murphy 34ba55453cSDan Murphy #define NUM_USB_CLKS 6 35ba55453cSDan Murphy 36ba55453cSDan Murphy static struct usb_dpll_params omap_usb3_dpll_params[NUM_USB_CLKS] = { 37ba55453cSDan Murphy {1250, 5, 4, 20, 0}, /* 12 MHz */ 38ba55453cSDan Murphy {3125, 20, 4, 20, 0}, /* 16.8 MHz */ 39ba55453cSDan Murphy {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ 40ba55453cSDan Murphy {1250, 12, 4, 20, 0}, /* 26 MHz */ 41ba55453cSDan Murphy {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ 42ba55453cSDan Murphy {1000, 7, 4, 10, 0}, /* 20 MHz */ 43ba55453cSDan Murphy }; 44ba55453cSDan Murphy 45ba55453cSDan Murphy static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) 46ba55453cSDan Murphy { 47ba55453cSDan Murphy u32 val; 48ba55453cSDan Murphy 49ba55453cSDan Murphy writel(SET_PLL_GO, &phy_regs->pll_go); 50ba55453cSDan Murphy do { 51ba55453cSDan Murphy val = readl(&phy_regs->pll_status); 52ba55453cSDan Murphy if (val & PLL_LOCK) 53ba55453cSDan Murphy break; 54ba55453cSDan Murphy } while (1); 55ba55453cSDan Murphy } 56ba55453cSDan Murphy 57ba55453cSDan Murphy static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) 58ba55453cSDan Murphy { 59ba55453cSDan Murphy u32 clk_index = get_sys_clk_index(); 60ba55453cSDan Murphy u32 val; 61ba55453cSDan Murphy 62ba55453cSDan Murphy val = readl(&phy_regs->pll_config_1); 63ba55453cSDan Murphy val &= ~PLL_REGN_MASK; 64ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; 65ba55453cSDan Murphy writel(val, &phy_regs->pll_config_1); 66ba55453cSDan Murphy 67ba55453cSDan Murphy val = readl(&phy_regs->pll_config_2); 68ba55453cSDan Murphy val &= ~PLL_SELFREQDCO_MASK; 69ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; 70ba55453cSDan Murphy writel(val, &phy_regs->pll_config_2); 71ba55453cSDan Murphy 72ba55453cSDan Murphy val = readl(&phy_regs->pll_config_1); 73ba55453cSDan Murphy val &= ~PLL_REGM_MASK; 74ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; 75ba55453cSDan Murphy writel(val, &phy_regs->pll_config_1); 76ba55453cSDan Murphy 77ba55453cSDan Murphy val = readl(&phy_regs->pll_config_4); 78ba55453cSDan Murphy val &= ~PLL_REGM_F_MASK; 79ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; 80ba55453cSDan Murphy writel(val, &phy_regs->pll_config_4); 81ba55453cSDan Murphy 82ba55453cSDan Murphy val = readl(&phy_regs->pll_config_3); 83ba55453cSDan Murphy val &= ~PLL_SD_MASK; 84ba55453cSDan Murphy val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; 85ba55453cSDan Murphy writel(val, &phy_regs->pll_config_3); 86ba55453cSDan Murphy 87ba55453cSDan Murphy omap_usb_dpll_relock(phy_regs); 88ba55453cSDan Murphy } 89ba55453cSDan Murphy 90ba55453cSDan Murphy static void usb3_phy_partial_powerup(struct omap_usb3_phy *phy_regs) 91ba55453cSDan Murphy { 92ba55453cSDan Murphy u32 rate = get_sys_clk_freq()/1000000; 93ba55453cSDan Murphy u32 val; 94ba55453cSDan Murphy 95ba55453cSDan Murphy val = readl((*ctrl)->control_phy_power_usb); 96ba55453cSDan Murphy val &= ~(USB3_PWRCTL_CLK_CMD_MASK | USB3_PWRCTL_CLK_FREQ_MASK); 97ba55453cSDan Murphy val |= (USB3_PHY_PARTIAL_RX_POWERON | USB3_PHY_TX_RX_POWERON); 98ba55453cSDan Murphy val |= rate << USB3_PWRCTL_CLK_FREQ_SHIFT; 99ba55453cSDan Murphy 100ba55453cSDan Murphy writel(val, (*ctrl)->control_phy_power_usb); 101ba55453cSDan Murphy } 102ba55453cSDan Murphy 103834e91afSDan Murphy void usb_phy_power(int on) 104ba55453cSDan Murphy { 105ba55453cSDan Murphy u32 val; 106ba55453cSDan Murphy 107ba55453cSDan Murphy val = readl((*ctrl)->control_phy_power_usb); 108ba55453cSDan Murphy if (on) { 109ba55453cSDan Murphy val &= ~USB3_PWRCTL_CLK_CMD_MASK; 110ba55453cSDan Murphy val |= USB3_PHY_TX_RX_POWERON; 111ba55453cSDan Murphy } else { 112ba55453cSDan Murphy val &= (~USB3_PWRCTL_CLK_CMD_MASK & ~USB3_PHY_TX_RX_POWERON); 113ba55453cSDan Murphy } 114ba55453cSDan Murphy 115ba55453cSDan Murphy writel(val, (*ctrl)->control_phy_power_usb); 116ba55453cSDan Murphy } 117ba55453cSDan Murphy 118ba55453cSDan Murphy void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) 119ba55453cSDan Murphy { 120ba55453cSDan Murphy omap_usb_dpll_lock(phy_regs); 121ba55453cSDan Murphy 122ba55453cSDan Murphy usb3_phy_partial_powerup(phy_regs); 123ba55453cSDan Murphy /* 124ba55453cSDan Murphy * Give enough time for the PHY to partially power-up before 125ba55453cSDan Murphy * powering it up completely. delay value suggested by the HW 126ba55453cSDan Murphy * team. 127ba55453cSDan Murphy */ 128ba55453cSDan Murphy mdelay(100); 129ba55453cSDan Murphy usb3_phy_power(1); 130ba55453cSDan Murphy } 131ba55453cSDan Murphy 132834e91afSDan Murphy static void omap_enable_usb3_phy(struct omap_xhci *omap) 133ba55453cSDan Murphy { 134ba55453cSDan Murphy u32 val; 135ba55453cSDan Murphy 136ba55453cSDan Murphy /* Setting OCP2SCP1 register */ 137ba55453cSDan Murphy setbits_le32((*prcm)->cm_l3init_ocp2scp1_clkctrl, 138ba55453cSDan Murphy OCP2SCP1_CLKCTRL_MODULEMODE_HW); 139ba55453cSDan Murphy 140ba55453cSDan Murphy /* Turn on 32K AON clk */ 141ba55453cSDan Murphy setbits_le32((*prcm)->cm_coreaon_usb_phy_core_clkctrl, 142ba55453cSDan Murphy USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); 143ba55453cSDan Murphy 144ba55453cSDan Murphy /* Setting CM_L3INIT_CLKSTCTRL to 0x0 i.e NO sleep */ 145ba55453cSDan Murphy writel(0x0, (*prcm)->cm_l3init_clkstctrl); 146ba55453cSDan Murphy 147ba55453cSDan Murphy val = (USBOTGSS_DMADISABLE | 148ba55453cSDan Murphy USBOTGSS_STANDBYMODE_SMRT_WKUP | 149ba55453cSDan Murphy USBOTGSS_IDLEMODE_NOIDLE); 150ba55453cSDan Murphy writel(val, &omap->otg_wrapper->sysconfig); 151ba55453cSDan Murphy 152ba55453cSDan Murphy /* Clear the utmi OTG status */ 153ba55453cSDan Murphy val = readl(&omap->otg_wrapper->utmi_otg_status); 154ba55453cSDan Murphy writel(val, &omap->otg_wrapper->utmi_otg_status); 155ba55453cSDan Murphy 156ba55453cSDan Murphy /* Enable interrupts */ 157ba55453cSDan Murphy writel(USBOTGSS_COREIRQ_EN, &omap->otg_wrapper->irqenable_set_0); 158ba55453cSDan Murphy val = (USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN | 159ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN | 160ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN | 161ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN | 162ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN | 163ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN | 164ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN | 165ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN | 166ba55453cSDan Murphy USBOTGSS_IRQ_SET_1_OEVT_EN); 167ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqenable_set_1); 168ba55453cSDan Murphy 169ba55453cSDan Murphy /* Clear the IRQ status */ 170ba55453cSDan Murphy val = readl(&omap->otg_wrapper->irqstatus_1); 171ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqstatus_1); 172ba55453cSDan Murphy val = readl(&omap->otg_wrapper->irqstatus_0); 173ba55453cSDan Murphy writel(val, &omap->otg_wrapper->irqstatus_0); 174ba55453cSDan Murphy 175ba55453cSDan Murphy /* Enable the USB OTG Super speed clocks */ 176ba55453cSDan Murphy val = (OPTFCLKEN_REFCLK960M | OTG_SS_CLKCTRL_MODULEMODE_HW); 177ba55453cSDan Murphy setbits_le32((*prcm)->cm_l3init_usb_otg_ss_clkctrl, val); 178ba55453cSDan Murphy 179ba55453cSDan Murphy }; 180834e91afSDan Murphy #endif /* CONFIG_OMAP_USB3PHY1_HOST */ 181834e91afSDan Murphy 182834e91afSDan Murphy #ifdef CONFIG_OMAP_USB2PHY2_HOST 183834e91afSDan Murphy static void omap_enable_usb2_phy2(struct omap_xhci *omap) 184834e91afSDan Murphy { 185834e91afSDan Murphy u32 reg, val; 186834e91afSDan Murphy 187834e91afSDan Murphy val = (~USB2PHY_AUTORESUME_EN & USB2PHY_DISCHGDET); 188834e91afSDan Murphy writel(val, (*ctrl)->control_srcomp_north_side); 189834e91afSDan Murphy 190834e91afSDan Murphy setbits_le32((*prcm)->cm_coreaon_usb_phy2_core_clkctrl, 191834e91afSDan Murphy USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); 192834e91afSDan Murphy 193834e91afSDan Murphy setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, 194834e91afSDan Murphy (USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K | 195834e91afSDan Murphy OTG_SS_CLKCTRL_MODULEMODE_HW)); 196834e91afSDan Murphy 197834e91afSDan Murphy /* This is an undocumented Reserved register */ 198834e91afSDan Murphy reg = 0x4a0086c0; 199834e91afSDan Murphy val = readl(reg); 200834e91afSDan Murphy val |= 0x100; 201834e91afSDan Murphy setbits_le32(reg, val); 202834e91afSDan Murphy } 203834e91afSDan Murphy 204834e91afSDan Murphy void usb_phy_power(int on) 205834e91afSDan Murphy { 206834e91afSDan Murphy return; 207834e91afSDan Murphy } 208834e91afSDan Murphy #endif /* CONFIG_OMAP_USB2PHY2_HOST */ 209ba55453cSDan Murphy 2103d799c7fSDan Murphy #ifdef CONFIG_AM437X_USB2PHY2_HOST 2113d799c7fSDan Murphy static void am437x_enable_usb2_phy2(struct omap_xhci *omap) 2123d799c7fSDan Murphy { 2133d799c7fSDan Murphy const u32 usb_otg_ss_clk_val = (USBOTGSSX_CLKCTRL_MODULE_EN | 2143d799c7fSDan Murphy USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960); 2153d799c7fSDan Murphy 2163d799c7fSDan Murphy writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS0_CLKCTRL); 2173d799c7fSDan Murphy writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS1_CLKCTRL); 2183d799c7fSDan Murphy 2193d799c7fSDan Murphy writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP0_CLKCTRL); 2203d799c7fSDan Murphy writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP1_CLKCTRL); 2213d799c7fSDan Murphy } 2223d799c7fSDan Murphy 2233d799c7fSDan Murphy void usb_phy_power(int on) 2243d799c7fSDan Murphy { 225*5ba95541SFelipe Balbi u32 val; 226*5ba95541SFelipe Balbi 227*5ba95541SFelipe Balbi /* USB1_CTRL */ 228*5ba95541SFelipe Balbi val = readl(USB1_CTRL); 229*5ba95541SFelipe Balbi if (on) { 230*5ba95541SFelipe Balbi /* 231*5ba95541SFelipe Balbi * these bits are re-used on AM437x to power up/down the USB 232*5ba95541SFelipe Balbi * CM and OTG PHYs, if we don't toggle them, USB will not be 233*5ba95541SFelipe Balbi * functional on newer silicon revisions 234*5ba95541SFelipe Balbi */ 235*5ba95541SFelipe Balbi val &= ~(USB1_CTRL_CM_PWRDN | USB1_CTRL_OTG_PWRDN); 236*5ba95541SFelipe Balbi } else { 237*5ba95541SFelipe Balbi val |= USB1_CTRL_CM_PWRDN | USB1_CTRL_OTG_PWRDN; 238*5ba95541SFelipe Balbi } 239*5ba95541SFelipe Balbi 240*5ba95541SFelipe Balbi writel(val, USB1_CTRL); 2413d799c7fSDan Murphy } 2423d799c7fSDan Murphy #endif /* CONFIG_AM437X_USB2PHY2_HOST */ 2433d799c7fSDan Murphy 244ba55453cSDan Murphy void omap_reset_usb_phy(struct dwc3 *dwc3_reg) 245ba55453cSDan Murphy { 246ba55453cSDan Murphy /* Assert USB3 PHY reset */ 247ba55453cSDan Murphy setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 248ba55453cSDan Murphy 249ba55453cSDan Murphy /* Assert USB2 PHY reset */ 250ba55453cSDan Murphy setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 251ba55453cSDan Murphy 252ba55453cSDan Murphy mdelay(100); 253ba55453cSDan Murphy 254ba55453cSDan Murphy /* Clear USB3 PHY reset */ 255ba55453cSDan Murphy clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 256ba55453cSDan Murphy 257ba55453cSDan Murphy /* Clear USB2 PHY reset */ 258ba55453cSDan Murphy clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 259ba55453cSDan Murphy 260ba55453cSDan Murphy } 261ba55453cSDan Murphy 262834e91afSDan Murphy void omap_enable_phy(struct omap_xhci *omap) 263834e91afSDan Murphy { 264834e91afSDan Murphy #ifdef CONFIG_OMAP_USB2PHY2_HOST 265834e91afSDan Murphy omap_enable_usb2_phy2(omap); 266834e91afSDan Murphy #endif 267834e91afSDan Murphy 2683d799c7fSDan Murphy #ifdef CONFIG_AM437X_USB2PHY2_HOST 2693d799c7fSDan Murphy am437x_enable_usb2_phy2(omap); 2703d799c7fSDan Murphy #endif 2713d799c7fSDan Murphy 272834e91afSDan Murphy #ifdef CONFIG_OMAP_USB3PHY1_HOST 273834e91afSDan Murphy omap_enable_usb3_phy(omap); 274834e91afSDan Murphy omap_usb3_phy_init(omap->usb3_phy); 275834e91afSDan Murphy #endif 276834e91afSDan Murphy } 277