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