1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * OMAP USB PHY Support 4 * 5 * (C) Copyright 2013 6 * Texas Instruments, <www.ti.com> 7 * 8 * Author: Dan Murphy <dmurphy@ti.com> 9 */ 10 11 #include <common.h> 12 #include <usb.h> 13 #include <linux/errno.h> 14 #include <asm/omap_common.h> 15 #include <asm/arch/cpu.h> 16 #include <asm/arch/sys_proto.h> 17 18 #include <linux/compat.h> 19 #include <linux/usb/dwc3.h> 20 #include <linux/usb/xhci-omap.h> 21 22 #include "../host/xhci.h" 23 24 #ifdef CONFIG_OMAP_USB3PHY1_HOST 25 struct usb3_dpll_params { 26 u16 m; 27 u8 n; 28 u8 freq:3; 29 u8 sd; 30 u32 mf; 31 }; 32 33 struct usb3_dpll_map { 34 unsigned long rate; 35 struct usb3_dpll_params params; 36 struct usb3_dpll_map *dpll_map; 37 }; 38 39 static struct usb3_dpll_map dpll_map_usb[] = { 40 {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ 41 {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ 42 {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ 43 {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ 44 {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ 45 {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ 46 { }, /* Terminator */ 47 }; 48 49 static struct usb3_dpll_params *omap_usb3_get_dpll_params(void) 50 { 51 unsigned long rate; 52 struct usb3_dpll_map *dpll_map = dpll_map_usb; 53 54 rate = get_sys_clk_freq(); 55 56 for (; dpll_map->rate; dpll_map++) { 57 if (rate == dpll_map->rate) 58 return &dpll_map->params; 59 } 60 61 dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate); 62 63 return NULL; 64 } 65 66 static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) 67 { 68 u32 val; 69 70 writel(SET_PLL_GO, &phy_regs->pll_go); 71 do { 72 val = readl(&phy_regs->pll_status); 73 if (val & PLL_LOCK) 74 break; 75 } while (1); 76 } 77 78 static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) 79 { 80 struct usb3_dpll_params *dpll_params; 81 u32 val; 82 83 dpll_params = omap_usb3_get_dpll_params(); 84 if (!dpll_params) 85 return; 86 87 val = readl(&phy_regs->pll_config_1); 88 val &= ~PLL_REGN_MASK; 89 val |= dpll_params->n << PLL_REGN_SHIFT; 90 writel(val, &phy_regs->pll_config_1); 91 92 val = readl(&phy_regs->pll_config_2); 93 val &= ~PLL_SELFREQDCO_MASK; 94 val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; 95 writel(val, &phy_regs->pll_config_2); 96 97 val = readl(&phy_regs->pll_config_1); 98 val &= ~PLL_REGM_MASK; 99 val |= dpll_params->m << PLL_REGM_SHIFT; 100 writel(val, &phy_regs->pll_config_1); 101 102 val = readl(&phy_regs->pll_config_4); 103 val &= ~PLL_REGM_F_MASK; 104 val |= dpll_params->mf << PLL_REGM_F_SHIFT; 105 writel(val, &phy_regs->pll_config_4); 106 107 val = readl(&phy_regs->pll_config_3); 108 val &= ~PLL_SD_MASK; 109 val |= dpll_params->sd << PLL_SD_SHIFT; 110 writel(val, &phy_regs->pll_config_3); 111 112 omap_usb_dpll_relock(phy_regs); 113 } 114 115 static void usb3_phy_partial_powerup(struct omap_usb3_phy *phy_regs) 116 { 117 u32 rate = get_sys_clk_freq()/1000000; 118 u32 val; 119 120 val = readl((*ctrl)->control_phy_power_usb); 121 val &= ~(USB3_PWRCTL_CLK_CMD_MASK | USB3_PWRCTL_CLK_FREQ_MASK); 122 val |= (USB3_PHY_PARTIAL_RX_POWERON | USB3_PHY_TX_RX_POWERON); 123 val |= rate << USB3_PWRCTL_CLK_FREQ_SHIFT; 124 125 writel(val, (*ctrl)->control_phy_power_usb); 126 } 127 128 void usb_phy_power(int on) 129 { 130 u32 val; 131 132 val = readl((*ctrl)->control_phy_power_usb); 133 if (on) { 134 val &= ~USB3_PWRCTL_CLK_CMD_MASK; 135 val |= USB3_PHY_TX_RX_POWERON; 136 } else { 137 val &= (~USB3_PWRCTL_CLK_CMD_MASK & ~USB3_PHY_TX_RX_POWERON); 138 } 139 140 writel(val, (*ctrl)->control_phy_power_usb); 141 } 142 143 void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) 144 { 145 omap_usb_dpll_lock(phy_regs); 146 usb3_phy_partial_powerup(phy_regs); 147 /* 148 * Give enough time for the PHY to partially power-up before 149 * powering it up completely. delay value suggested by the HW 150 * team. 151 */ 152 mdelay(100); 153 } 154 155 static void omap_enable_usb3_phy(struct omap_xhci *omap) 156 { 157 u32 val; 158 159 val = (USBOTGSS_DMADISABLE | 160 USBOTGSS_STANDBYMODE_SMRT_WKUP | 161 USBOTGSS_IDLEMODE_NOIDLE); 162 writel(val, &omap->otg_wrapper->sysconfig); 163 164 /* Clear the utmi OTG status */ 165 val = readl(&omap->otg_wrapper->utmi_otg_status); 166 writel(val, &omap->otg_wrapper->utmi_otg_status); 167 168 /* Enable interrupts */ 169 writel(USBOTGSS_COREIRQ_EN, &omap->otg_wrapper->irqenable_set_0); 170 val = (USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN | 171 USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN | 172 USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN | 173 USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN | 174 USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN | 175 USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN | 176 USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN | 177 USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN | 178 USBOTGSS_IRQ_SET_1_OEVT_EN); 179 writel(val, &omap->otg_wrapper->irqenable_set_1); 180 181 /* Clear the IRQ status */ 182 val = readl(&omap->otg_wrapper->irqstatus_1); 183 writel(val, &omap->otg_wrapper->irqstatus_1); 184 val = readl(&omap->otg_wrapper->irqstatus_0); 185 writel(val, &omap->otg_wrapper->irqstatus_0); 186 }; 187 #endif /* CONFIG_OMAP_USB3PHY1_HOST */ 188 189 #ifdef CONFIG_OMAP_USB2PHY2_HOST 190 static void omap_enable_usb2_phy2(struct omap_xhci *omap) 191 { 192 u32 reg, val; 193 194 val = (~USB2PHY_AUTORESUME_EN & USB2PHY_DISCHGDET); 195 writel(val, (*ctrl)->control_srcomp_north_side); 196 197 setbits_le32((*prcm)->cm_coreaon_usb_phy2_core_clkctrl, 198 USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); 199 200 setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, 201 (USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K | 202 OTG_SS_CLKCTRL_MODULEMODE_HW)); 203 204 /* This is an undocumented Reserved register */ 205 reg = 0x4a0086c0; 206 val = readl(reg); 207 val |= 0x100; 208 setbits_le32(reg, val); 209 } 210 211 void usb_phy_power(int on) 212 { 213 return; 214 } 215 #endif /* CONFIG_OMAP_USB2PHY2_HOST */ 216 217 #ifdef CONFIG_AM437X_USB2PHY2_HOST 218 static void am437x_enable_usb2_phy2(struct omap_xhci *omap) 219 { 220 const u32 usb_otg_ss_clk_val = (USBOTGSSX_CLKCTRL_MODULE_EN | 221 USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960); 222 223 writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS0_CLKCTRL); 224 writel(usb_otg_ss_clk_val, PRM_PER_USB_OTG_SS1_CLKCTRL); 225 226 writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP0_CLKCTRL); 227 writel(USBPHYOCPSCP_MODULE_EN, PRM_PER_USBPHYOCP2SCP1_CLKCTRL); 228 } 229 230 void usb_phy_power(int on) 231 { 232 u32 val; 233 234 /* USB1_CTRL */ 235 val = readl(USB1_CTRL); 236 if (on) { 237 /* 238 * these bits are re-used on AM437x to power up/down the USB 239 * CM and OTG PHYs, if we don't toggle them, USB will not be 240 * functional on newer silicon revisions 241 */ 242 val &= ~(USB1_CTRL_CM_PWRDN | USB1_CTRL_OTG_PWRDN); 243 } else { 244 val |= USB1_CTRL_CM_PWRDN | USB1_CTRL_OTG_PWRDN; 245 } 246 247 writel(val, USB1_CTRL); 248 } 249 #endif /* CONFIG_AM437X_USB2PHY2_HOST */ 250 251 void omap_enable_phy(struct omap_xhci *omap) 252 { 253 #ifdef CONFIG_OMAP_USB2PHY2_HOST 254 omap_enable_usb2_phy2(omap); 255 #endif 256 257 #ifdef CONFIG_AM437X_USB2PHY2_HOST 258 am437x_enable_usb2_phy2(omap); 259 #endif 260 261 #ifdef CONFIG_OMAP_USB3PHY1_HOST 262 omap_enable_usb3_phy(omap); 263 omap_usb3_phy_init(omap->usb3_phy); 264 #endif 265 } 266