Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.9-rc1 635 lines 19 kB view raw
1/* 2 * Copyright (c) 2015 MediaTek Inc. 3 * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> 4 * 5 * This software is licensed under the terms of the GNU General Public 6 * License version 2, as published by the Free Software Foundation, and 7 * may be copied, distributed, and modified under those terms. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16#include <dt-bindings/phy/phy.h> 17#include <linux/clk.h> 18#include <linux/delay.h> 19#include <linux/io.h> 20#include <linux/iopoll.h> 21#include <linux/module.h> 22#include <linux/of_address.h> 23#include <linux/phy/phy.h> 24#include <linux/platform_device.h> 25 26/* 27 * for sifslv2 register, but exclude port's; 28 * relative to USB3_SIF2_BASE base address 29 */ 30#define SSUSB_SIFSLV_SPLLC 0x0000 31#define SSUSB_SIFSLV_U2FREQ 0x0100 32 33/* offsets of sub-segment in each port registers */ 34#define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 35#define SSUSB_SIFSLV_U3PHYD_BASE 0x0100 36#define SSUSB_USB30_PHYA_SIV_B_BASE 0x0300 37#define SSUSB_SIFSLV_U3PHYA_DA_BASE 0x0400 38 39#define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000) 40#define PA0_RG_U2PLL_FORCE_ON BIT(15) 41 42#define U3P_USBPHYACR2 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0008) 43#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) 44 45#define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) 46#define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) 47#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) 48#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) 49#define PA5_RG_U2_HS_100U_U3_EN BIT(11) 50 51#define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018) 52#define PA6_RG_U2_ISO_EN BIT(31) 53#define PA6_RG_U2_BC11_SW_EN BIT(23) 54#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) 55#define PA6_RG_U2_SQTH GENMASK(3, 0) 56#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) 57 58#define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020) 59#define P2C_RG_USB20_GPIO_CTL BIT(9) 60#define P2C_USB20_GPIO_MODE BIT(8) 61#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE) 62 63#define U3D_U2PHYDCR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0060) 64#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24) 65 66#define U3P_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0068) 67#define P2C_FORCE_UART_EN BIT(26) 68#define P2C_FORCE_DATAIN BIT(23) 69#define P2C_FORCE_DM_PULLDOWN BIT(21) 70#define P2C_FORCE_DP_PULLDOWN BIT(20) 71#define P2C_FORCE_XCVRSEL BIT(19) 72#define P2C_FORCE_SUSPENDM BIT(18) 73#define P2C_FORCE_TERMSEL BIT(17) 74#define P2C_RG_DATAIN GENMASK(13, 10) 75#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10) 76#define P2C_RG_DMPULLDOWN BIT(7) 77#define P2C_RG_DPPULLDOWN BIT(6) 78#define P2C_RG_XCVRSEL GENMASK(5, 4) 79#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4) 80#define P2C_RG_SUSPENDM BIT(3) 81#define P2C_RG_TERMSEL BIT(2) 82#define P2C_DTM0_PART_MASK \ 83 (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \ 84 P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \ 85 P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \ 86 P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL) 87 88#define U3P_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x006C) 89#define P2C_RG_UART_EN BIT(16) 90#define P2C_RG_VBUSVALID BIT(5) 91#define P2C_RG_SESSEND BIT(4) 92#define P2C_RG_AVALID BIT(2) 93 94#define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000) 95#define P3A_RG_U3_VUSB10_ON BIT(5) 96 97#define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018) 98#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) 99#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) 100 101#define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024) 102#define P3A_RG_RX_DAC_MUX GENMASK(5, 1) 103#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) 104 105#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000) 106#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10) 107#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10) 108 109#define U3P_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE + 0x005c) 110#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) 111#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) 112#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8) 113#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8) 114 115#define U3P_XTALCTL3 (SSUSB_SIFSLV_SPLLC + 0x0018) 116#define XC3_RG_U3_XTAL_RX_PWD BIT(9) 117#define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) 118 119#define U3P_U2FREQ_FMCR0 (SSUSB_SIFSLV_U2FREQ + 0x00) 120#define P2F_RG_MONCLK_SEL GENMASK(27, 26) 121#define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) 122#define P2F_RG_FREQDET_EN BIT(24) 123#define P2F_RG_CYCLECNT GENMASK(23, 0) 124#define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) 125 126#define U3P_U2FREQ_VALUE (SSUSB_SIFSLV_U2FREQ + 0x0c) 127 128#define U3P_U2FREQ_FMMONR1 (SSUSB_SIFSLV_U2FREQ + 0x10) 129#define P2F_USB_FM_VALID BIT(0) 130#define P2F_RG_FRCK_EN BIT(8) 131 132#define U3P_REF_CLK 26 /* MHZ */ 133#define U3P_SLEW_RATE_COEF 28 134#define U3P_SR_COEF_DIVISOR 1000 135#define U3P_FM_DET_CYCLE_CNT 1024 136 137struct mt65xx_phy_pdata { 138 /* avoid RX sensitivity level degradation only for mt8173 */ 139 bool avoid_rx_sen_degradation; 140}; 141 142struct mt65xx_phy_instance { 143 struct phy *phy; 144 void __iomem *port_base; 145 u32 index; 146 u8 type; 147}; 148 149struct mt65xx_u3phy { 150 struct device *dev; 151 void __iomem *sif_base; /* include sif2, but exclude port's */ 152 struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ 153 const struct mt65xx_phy_pdata *pdata; 154 struct mt65xx_phy_instance **phys; 155 int nphys; 156}; 157 158static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, 159 struct mt65xx_phy_instance *instance) 160{ 161 void __iomem *sif_base = u3phy->sif_base; 162 int calibration_val; 163 int fm_out; 164 u32 tmp; 165 166 /* enable USB ring oscillator */ 167 tmp = readl(instance->port_base + U3P_USBPHYACR5); 168 tmp |= PA5_RG_U2_HSTX_SRCAL_EN; 169 writel(tmp, instance->port_base + U3P_USBPHYACR5); 170 udelay(1); 171 172 /*enable free run clock */ 173 tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); 174 tmp |= P2F_RG_FRCK_EN; 175 writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); 176 177 /* set cycle count as 1024, and select u2 channel */ 178 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 179 tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); 180 tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); 181 tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index); 182 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 183 184 /* enable frequency meter */ 185 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 186 tmp |= P2F_RG_FREQDET_EN; 187 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 188 189 /* ignore return value */ 190 readl_poll_timeout(sif_base + U3P_U2FREQ_FMMONR1, tmp, 191 (tmp & P2F_USB_FM_VALID), 10, 200); 192 193 fm_out = readl(sif_base + U3P_U2FREQ_VALUE); 194 195 /* disable frequency meter */ 196 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 197 tmp &= ~P2F_RG_FREQDET_EN; 198 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 199 200 /*disable free run clock */ 201 tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); 202 tmp &= ~P2F_RG_FRCK_EN; 203 writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); 204 205 if (fm_out) { 206 /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ 207 tmp = U3P_FM_DET_CYCLE_CNT * U3P_REF_CLK * U3P_SLEW_RATE_COEF; 208 tmp /= fm_out; 209 calibration_val = DIV_ROUND_CLOSEST(tmp, U3P_SR_COEF_DIVISOR); 210 } else { 211 /* if FM detection fail, set default value */ 212 calibration_val = 4; 213 } 214 dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n", 215 instance->index, fm_out, calibration_val); 216 217 /* set HS slew rate */ 218 tmp = readl(instance->port_base + U3P_USBPHYACR5); 219 tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 220 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); 221 writel(tmp, instance->port_base + U3P_USBPHYACR5); 222 223 /* disable USB ring oscillator */ 224 tmp = readl(instance->port_base + U3P_USBPHYACR5); 225 tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; 226 writel(tmp, instance->port_base + U3P_USBPHYACR5); 227} 228 229static void phy_instance_init(struct mt65xx_u3phy *u3phy, 230 struct mt65xx_phy_instance *instance) 231{ 232 void __iomem *port_base = instance->port_base; 233 u32 index = instance->index; 234 u32 tmp; 235 236 /* switch to USB function. (system register, force ip into usb mode) */ 237 tmp = readl(port_base + U3P_U2PHYDTM0); 238 tmp &= ~P2C_FORCE_UART_EN; 239 tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); 240 writel(tmp, port_base + U3P_U2PHYDTM0); 241 242 tmp = readl(port_base + U3P_U2PHYDTM1); 243 tmp &= ~P2C_RG_UART_EN; 244 writel(tmp, port_base + U3P_U2PHYDTM1); 245 246 if (!index) { 247 tmp = readl(port_base + U3P_U2PHYACR4); 248 tmp &= ~P2C_U2_GPIO_CTR_MSK; 249 writel(tmp, port_base + U3P_U2PHYACR4); 250 } 251 252 if (u3phy->pdata->avoid_rx_sen_degradation) { 253 if (!index) { 254 tmp = readl(port_base + U3P_USBPHYACR2); 255 tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; 256 writel(tmp, port_base + U3P_USBPHYACR2); 257 258 tmp = readl(port_base + U3D_U2PHYDCR0); 259 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 260 writel(tmp, port_base + U3D_U2PHYDCR0); 261 } else { 262 tmp = readl(port_base + U3D_U2PHYDCR0); 263 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 264 writel(tmp, port_base + U3D_U2PHYDCR0); 265 266 tmp = readl(port_base + U3P_U2PHYDTM0); 267 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 268 writel(tmp, port_base + U3P_U2PHYDTM0); 269 } 270 } 271 272 tmp = readl(port_base + U3P_USBPHYACR6); 273 tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ 274 tmp &= ~PA6_RG_U2_SQTH; 275 tmp |= PA6_RG_U2_SQTH_VAL(2); 276 writel(tmp, port_base + U3P_USBPHYACR6); 277 278 tmp = readl(port_base + U3P_U3PHYA_DA_REG0); 279 tmp &= ~P3A_RG_XTAL_EXT_EN_U3; 280 tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2); 281 writel(tmp, port_base + U3P_U3PHYA_DA_REG0); 282 283 tmp = readl(port_base + U3P_U3_PHYA_REG9); 284 tmp &= ~P3A_RG_RX_DAC_MUX; 285 tmp |= P3A_RG_RX_DAC_MUX_VAL(4); 286 writel(tmp, port_base + U3P_U3_PHYA_REG9); 287 288 tmp = readl(port_base + U3P_U3_PHYA_REG6); 289 tmp &= ~P3A_RG_TX_EIDLE_CM; 290 tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe); 291 writel(tmp, port_base + U3P_U3_PHYA_REG6); 292 293 tmp = readl(port_base + U3P_PHYD_CDR1); 294 tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1); 295 tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3); 296 writel(tmp, port_base + U3P_PHYD_CDR1); 297 298 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 299} 300 301static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, 302 struct mt65xx_phy_instance *instance) 303{ 304 void __iomem *port_base = instance->port_base; 305 u32 index = instance->index; 306 u32 tmp; 307 308 if (!index) { 309 /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ 310 tmp = readl(port_base + U3P_U3_PHYA_REG0); 311 tmp |= P3A_RG_U3_VUSB10_ON; 312 writel(tmp, port_base + U3P_U3_PHYA_REG0); 313 } 314 315 /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ 316 tmp = readl(port_base + U3P_U2PHYDTM0); 317 tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); 318 tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); 319 writel(tmp, port_base + U3P_U2PHYDTM0); 320 321 /* OTG Enable */ 322 tmp = readl(port_base + U3P_USBPHYACR6); 323 tmp |= PA6_RG_U2_OTG_VBUSCMP_EN; 324 writel(tmp, port_base + U3P_USBPHYACR6); 325 326 if (!index) { 327 tmp = readl(u3phy->sif_base + U3P_XTALCTL3); 328 tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; 329 writel(tmp, u3phy->sif_base + U3P_XTALCTL3); 330 331 /* switch 100uA current to SSUSB */ 332 tmp = readl(port_base + U3P_USBPHYACR5); 333 tmp |= PA5_RG_U2_HS_100U_U3_EN; 334 writel(tmp, port_base + U3P_USBPHYACR5); 335 } 336 337 tmp = readl(port_base + U3P_U2PHYDTM1); 338 tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID; 339 tmp &= ~P2C_RG_SESSEND; 340 writel(tmp, port_base + U3P_U2PHYDTM1); 341 342 /* USB 2.0 slew rate calibration */ 343 tmp = readl(port_base + U3P_USBPHYACR5); 344 tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 345 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4); 346 writel(tmp, port_base + U3P_USBPHYACR5); 347 348 if (u3phy->pdata->avoid_rx_sen_degradation && index) { 349 tmp = readl(port_base + U3D_U2PHYDCR0); 350 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 351 writel(tmp, port_base + U3D_U2PHYDCR0); 352 353 tmp = readl(port_base + U3P_U2PHYDTM0); 354 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 355 writel(tmp, port_base + U3P_U2PHYDTM0); 356 } 357 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 358} 359 360static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, 361 struct mt65xx_phy_instance *instance) 362{ 363 void __iomem *port_base = instance->port_base; 364 u32 index = instance->index; 365 u32 tmp; 366 367 tmp = readl(port_base + U3P_U2PHYDTM0); 368 tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); 369 tmp |= P2C_FORCE_SUSPENDM; 370 writel(tmp, port_base + U3P_U2PHYDTM0); 371 372 /* OTG Disable */ 373 tmp = readl(port_base + U3P_USBPHYACR6); 374 tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; 375 writel(tmp, port_base + U3P_USBPHYACR6); 376 377 if (!index) { 378 /* switch 100uA current back to USB2.0 */ 379 tmp = readl(port_base + U3P_USBPHYACR5); 380 tmp &= ~PA5_RG_U2_HS_100U_U3_EN; 381 writel(tmp, port_base + U3P_USBPHYACR5); 382 } 383 384 /* let suspendm=0, set utmi into analog power down */ 385 tmp = readl(port_base + U3P_U2PHYDTM0); 386 tmp &= ~P2C_RG_SUSPENDM; 387 writel(tmp, port_base + U3P_U2PHYDTM0); 388 udelay(1); 389 390 tmp = readl(port_base + U3P_U2PHYDTM1); 391 tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); 392 tmp |= P2C_RG_SESSEND; 393 writel(tmp, port_base + U3P_U2PHYDTM1); 394 395 if (!index) { 396 tmp = readl(port_base + U3P_U3_PHYA_REG0); 397 tmp &= ~P3A_RG_U3_VUSB10_ON; 398 writel(tmp, port_base + U3P_U3_PHYA_REG0); 399 } 400 401 if (u3phy->pdata->avoid_rx_sen_degradation && index) { 402 tmp = readl(port_base + U3D_U2PHYDCR0); 403 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 404 writel(tmp, port_base + U3D_U2PHYDCR0); 405 } 406 407 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 408} 409 410static void phy_instance_exit(struct mt65xx_u3phy *u3phy, 411 struct mt65xx_phy_instance *instance) 412{ 413 void __iomem *port_base = instance->port_base; 414 u32 index = instance->index; 415 u32 tmp; 416 417 if (u3phy->pdata->avoid_rx_sen_degradation && index) { 418 tmp = readl(port_base + U3D_U2PHYDCR0); 419 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 420 writel(tmp, port_base + U3D_U2PHYDCR0); 421 422 tmp = readl(port_base + U3P_U2PHYDTM0); 423 tmp &= ~P2C_FORCE_SUSPENDM; 424 writel(tmp, port_base + U3P_U2PHYDTM0); 425 } 426} 427 428static int mt65xx_phy_init(struct phy *phy) 429{ 430 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 431 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 432 int ret; 433 434 ret = clk_prepare_enable(u3phy->u3phya_ref); 435 if (ret) { 436 dev_err(u3phy->dev, "failed to enable u3phya_ref\n"); 437 return ret; 438 } 439 440 phy_instance_init(u3phy, instance); 441 return 0; 442} 443 444static int mt65xx_phy_power_on(struct phy *phy) 445{ 446 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 447 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 448 449 phy_instance_power_on(u3phy, instance); 450 hs_slew_rate_calibrate(u3phy, instance); 451 return 0; 452} 453 454static int mt65xx_phy_power_off(struct phy *phy) 455{ 456 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 457 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 458 459 phy_instance_power_off(u3phy, instance); 460 return 0; 461} 462 463static int mt65xx_phy_exit(struct phy *phy) 464{ 465 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 466 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 467 468 phy_instance_exit(u3phy, instance); 469 clk_disable_unprepare(u3phy->u3phya_ref); 470 return 0; 471} 472 473static struct phy *mt65xx_phy_xlate(struct device *dev, 474 struct of_phandle_args *args) 475{ 476 struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev); 477 struct mt65xx_phy_instance *instance = NULL; 478 struct device_node *phy_np = args->np; 479 int index; 480 481 482 if (args->args_count != 1) { 483 dev_err(dev, "invalid number of cells in 'phy' property\n"); 484 return ERR_PTR(-EINVAL); 485 } 486 487 for (index = 0; index < u3phy->nphys; index++) 488 if (phy_np == u3phy->phys[index]->phy->dev.of_node) { 489 instance = u3phy->phys[index]; 490 break; 491 } 492 493 if (!instance) { 494 dev_err(dev, "failed to find appropriate phy\n"); 495 return ERR_PTR(-EINVAL); 496 } 497 498 instance->type = args->args[0]; 499 500 if (!(instance->type == PHY_TYPE_USB2 || 501 instance->type == PHY_TYPE_USB3)) { 502 dev_err(dev, "unsupported device type: %d\n", instance->type); 503 return ERR_PTR(-EINVAL); 504 } 505 506 return instance->phy; 507} 508 509static struct phy_ops mt65xx_u3phy_ops = { 510 .init = mt65xx_phy_init, 511 .exit = mt65xx_phy_exit, 512 .power_on = mt65xx_phy_power_on, 513 .power_off = mt65xx_phy_power_off, 514 .owner = THIS_MODULE, 515}; 516 517static const struct mt65xx_phy_pdata mt2701_pdata = { 518 .avoid_rx_sen_degradation = false, 519}; 520 521static const struct mt65xx_phy_pdata mt8173_pdata = { 522 .avoid_rx_sen_degradation = true, 523}; 524 525static const struct of_device_id mt65xx_u3phy_id_table[] = { 526 { .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata }, 527 { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, 528 { }, 529}; 530MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table); 531 532static int mt65xx_u3phy_probe(struct platform_device *pdev) 533{ 534 const struct of_device_id *match; 535 struct device *dev = &pdev->dev; 536 struct device_node *np = dev->of_node; 537 struct device_node *child_np; 538 struct phy_provider *provider; 539 struct resource *sif_res; 540 struct mt65xx_u3phy *u3phy; 541 struct resource res; 542 int port, retval; 543 544 match = of_match_node(mt65xx_u3phy_id_table, pdev->dev.of_node); 545 if (!match) 546 return -EINVAL; 547 548 u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL); 549 if (!u3phy) 550 return -ENOMEM; 551 552 u3phy->pdata = match->data; 553 u3phy->nphys = of_get_child_count(np); 554 u3phy->phys = devm_kcalloc(dev, u3phy->nphys, 555 sizeof(*u3phy->phys), GFP_KERNEL); 556 if (!u3phy->phys) 557 return -ENOMEM; 558 559 u3phy->dev = dev; 560 platform_set_drvdata(pdev, u3phy); 561 562 sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 563 u3phy->sif_base = devm_ioremap_resource(dev, sif_res); 564 if (IS_ERR(u3phy->sif_base)) { 565 dev_err(dev, "failed to remap sif regs\n"); 566 return PTR_ERR(u3phy->sif_base); 567 } 568 569 u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref"); 570 if (IS_ERR(u3phy->u3phya_ref)) { 571 dev_err(dev, "error to get u3phya_ref\n"); 572 return PTR_ERR(u3phy->u3phya_ref); 573 } 574 575 port = 0; 576 for_each_child_of_node(np, child_np) { 577 struct mt65xx_phy_instance *instance; 578 struct phy *phy; 579 580 instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); 581 if (!instance) { 582 retval = -ENOMEM; 583 goto put_child; 584 } 585 586 u3phy->phys[port] = instance; 587 588 phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops); 589 if (IS_ERR(phy)) { 590 dev_err(dev, "failed to create phy\n"); 591 retval = PTR_ERR(phy); 592 goto put_child; 593 } 594 595 retval = of_address_to_resource(child_np, 0, &res); 596 if (retval) { 597 dev_err(dev, "failed to get address resource(id-%d)\n", 598 port); 599 goto put_child; 600 } 601 602 instance->port_base = devm_ioremap_resource(&phy->dev, &res); 603 if (IS_ERR(instance->port_base)) { 604 dev_err(dev, "failed to remap phy regs\n"); 605 retval = PTR_ERR(instance->port_base); 606 goto put_child; 607 } 608 609 instance->phy = phy; 610 instance->index = port; 611 phy_set_drvdata(phy, instance); 612 port++; 613 } 614 615 provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate); 616 617 return PTR_ERR_OR_ZERO(provider); 618put_child: 619 of_node_put(child_np); 620 return retval; 621} 622 623static struct platform_driver mt65xx_u3phy_driver = { 624 .probe = mt65xx_u3phy_probe, 625 .driver = { 626 .name = "mt65xx-u3phy", 627 .of_match_table = mt65xx_u3phy_id_table, 628 }, 629}; 630 631module_platform_driver(mt65xx_u3phy_driver); 632 633MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); 634MODULE_DESCRIPTION("mt65xx USB PHY driver"); 635MODULE_LICENSE("GPL v2");