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.6-rc6 608 lines 18 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_instance { 138 struct phy *phy; 139 void __iomem *port_base; 140 u32 index; 141 u8 type; 142}; 143 144struct mt65xx_u3phy { 145 struct device *dev; 146 void __iomem *sif_base; /* include sif2, but exclude port's */ 147 struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ 148 struct mt65xx_phy_instance **phys; 149 int nphys; 150}; 151 152static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, 153 struct mt65xx_phy_instance *instance) 154{ 155 void __iomem *sif_base = u3phy->sif_base; 156 int calibration_val; 157 int fm_out; 158 u32 tmp; 159 160 /* enable USB ring oscillator */ 161 tmp = readl(instance->port_base + U3P_USBPHYACR5); 162 tmp |= PA5_RG_U2_HSTX_SRCAL_EN; 163 writel(tmp, instance->port_base + U3P_USBPHYACR5); 164 udelay(1); 165 166 /*enable free run clock */ 167 tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); 168 tmp |= P2F_RG_FRCK_EN; 169 writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); 170 171 /* set cycle count as 1024, and select u2 channel */ 172 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 173 tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); 174 tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); 175 tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index); 176 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 177 178 /* enable frequency meter */ 179 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 180 tmp |= P2F_RG_FREQDET_EN; 181 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 182 183 /* ignore return value */ 184 readl_poll_timeout(sif_base + U3P_U2FREQ_FMMONR1, tmp, 185 (tmp & P2F_USB_FM_VALID), 10, 200); 186 187 fm_out = readl(sif_base + U3P_U2FREQ_VALUE); 188 189 /* disable frequency meter */ 190 tmp = readl(sif_base + U3P_U2FREQ_FMCR0); 191 tmp &= ~P2F_RG_FREQDET_EN; 192 writel(tmp, sif_base + U3P_U2FREQ_FMCR0); 193 194 /*disable free run clock */ 195 tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); 196 tmp &= ~P2F_RG_FRCK_EN; 197 writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); 198 199 if (fm_out) { 200 /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ 201 tmp = U3P_FM_DET_CYCLE_CNT * U3P_REF_CLK * U3P_SLEW_RATE_COEF; 202 tmp /= fm_out; 203 calibration_val = DIV_ROUND_CLOSEST(tmp, U3P_SR_COEF_DIVISOR); 204 } else { 205 /* if FM detection fail, set default value */ 206 calibration_val = 4; 207 } 208 dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n", 209 instance->index, fm_out, calibration_val); 210 211 /* set HS slew rate */ 212 tmp = readl(instance->port_base + U3P_USBPHYACR5); 213 tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 214 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); 215 writel(tmp, instance->port_base + U3P_USBPHYACR5); 216 217 /* disable USB ring oscillator */ 218 tmp = readl(instance->port_base + U3P_USBPHYACR5); 219 tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; 220 writel(tmp, instance->port_base + U3P_USBPHYACR5); 221} 222 223static void phy_instance_init(struct mt65xx_u3phy *u3phy, 224 struct mt65xx_phy_instance *instance) 225{ 226 void __iomem *port_base = instance->port_base; 227 u32 index = instance->index; 228 u32 tmp; 229 230 /* switch to USB function. (system register, force ip into usb mode) */ 231 tmp = readl(port_base + U3P_U2PHYDTM0); 232 tmp &= ~P2C_FORCE_UART_EN; 233 tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); 234 writel(tmp, port_base + U3P_U2PHYDTM0); 235 236 tmp = readl(port_base + U3P_U2PHYDTM1); 237 tmp &= ~P2C_RG_UART_EN; 238 writel(tmp, port_base + U3P_U2PHYDTM1); 239 240 if (!index) { 241 tmp = readl(port_base + U3P_U2PHYACR4); 242 tmp &= ~P2C_U2_GPIO_CTR_MSK; 243 writel(tmp, port_base + U3P_U2PHYACR4); 244 245 tmp = readl(port_base + U3P_USBPHYACR2); 246 tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; 247 writel(tmp, port_base + U3P_USBPHYACR2); 248 249 tmp = readl(port_base + U3D_U2PHYDCR0); 250 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 251 writel(tmp, port_base + U3D_U2PHYDCR0); 252 } else { 253 tmp = readl(port_base + U3D_U2PHYDCR0); 254 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 255 writel(tmp, port_base + U3D_U2PHYDCR0); 256 257 tmp = readl(port_base + U3P_U2PHYDTM0); 258 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 259 writel(tmp, port_base + U3P_U2PHYDTM0); 260 } 261 262 tmp = readl(port_base + U3P_USBPHYACR6); 263 tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ 264 tmp &= ~PA6_RG_U2_SQTH; 265 tmp |= PA6_RG_U2_SQTH_VAL(2); 266 writel(tmp, port_base + U3P_USBPHYACR6); 267 268 tmp = readl(port_base + U3P_U3PHYA_DA_REG0); 269 tmp &= ~P3A_RG_XTAL_EXT_EN_U3; 270 tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2); 271 writel(tmp, port_base + U3P_U3PHYA_DA_REG0); 272 273 tmp = readl(port_base + U3P_U3_PHYA_REG9); 274 tmp &= ~P3A_RG_RX_DAC_MUX; 275 tmp |= P3A_RG_RX_DAC_MUX_VAL(4); 276 writel(tmp, port_base + U3P_U3_PHYA_REG9); 277 278 tmp = readl(port_base + U3P_U3_PHYA_REG6); 279 tmp &= ~P3A_RG_TX_EIDLE_CM; 280 tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe); 281 writel(tmp, port_base + U3P_U3_PHYA_REG6); 282 283 tmp = readl(port_base + U3P_PHYD_CDR1); 284 tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1); 285 tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3); 286 writel(tmp, port_base + U3P_PHYD_CDR1); 287 288 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 289} 290 291static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, 292 struct mt65xx_phy_instance *instance) 293{ 294 void __iomem *port_base = instance->port_base; 295 u32 index = instance->index; 296 u32 tmp; 297 298 if (!index) { 299 /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ 300 tmp = readl(port_base + U3P_U3_PHYA_REG0); 301 tmp |= P3A_RG_U3_VUSB10_ON; 302 writel(tmp, port_base + U3P_U3_PHYA_REG0); 303 } 304 305 /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ 306 tmp = readl(port_base + U3P_U2PHYDTM0); 307 tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); 308 tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); 309 writel(tmp, port_base + U3P_U2PHYDTM0); 310 311 /* OTG Enable */ 312 tmp = readl(port_base + U3P_USBPHYACR6); 313 tmp |= PA6_RG_U2_OTG_VBUSCMP_EN; 314 writel(tmp, port_base + U3P_USBPHYACR6); 315 316 if (!index) { 317 tmp = readl(u3phy->sif_base + U3P_XTALCTL3); 318 tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; 319 writel(tmp, u3phy->sif_base + U3P_XTALCTL3); 320 321 /* [mt8173]switch 100uA current to SSUSB */ 322 tmp = readl(port_base + U3P_USBPHYACR5); 323 tmp |= PA5_RG_U2_HS_100U_U3_EN; 324 writel(tmp, port_base + U3P_USBPHYACR5); 325 } 326 327 tmp = readl(port_base + U3P_U2PHYDTM1); 328 tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID; 329 tmp &= ~P2C_RG_SESSEND; 330 writel(tmp, port_base + U3P_U2PHYDTM1); 331 332 /* USB 2.0 slew rate calibration */ 333 tmp = readl(port_base + U3P_USBPHYACR5); 334 tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 335 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4); 336 writel(tmp, port_base + U3P_USBPHYACR5); 337 338 if (index) { 339 tmp = readl(port_base + U3D_U2PHYDCR0); 340 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 341 writel(tmp, port_base + U3D_U2PHYDCR0); 342 343 tmp = readl(port_base + U3P_U2PHYDTM0); 344 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 345 writel(tmp, port_base + U3P_U2PHYDTM0); 346 } 347 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 348} 349 350static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, 351 struct mt65xx_phy_instance *instance) 352{ 353 void __iomem *port_base = instance->port_base; 354 u32 index = instance->index; 355 u32 tmp; 356 357 tmp = readl(port_base + U3P_U2PHYDTM0); 358 tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); 359 tmp |= P2C_FORCE_SUSPENDM; 360 writel(tmp, port_base + U3P_U2PHYDTM0); 361 362 /* OTG Disable */ 363 tmp = readl(port_base + U3P_USBPHYACR6); 364 tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; 365 writel(tmp, port_base + U3P_USBPHYACR6); 366 367 if (!index) { 368 /* switch 100uA current back to USB2.0 */ 369 tmp = readl(port_base + U3P_USBPHYACR5); 370 tmp &= ~PA5_RG_U2_HS_100U_U3_EN; 371 writel(tmp, port_base + U3P_USBPHYACR5); 372 } 373 374 /* let suspendm=0, set utmi into analog power down */ 375 tmp = readl(port_base + U3P_U2PHYDTM0); 376 tmp &= ~P2C_RG_SUSPENDM; 377 writel(tmp, port_base + U3P_U2PHYDTM0); 378 udelay(1); 379 380 tmp = readl(port_base + U3P_U2PHYDTM1); 381 tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); 382 tmp |= P2C_RG_SESSEND; 383 writel(tmp, port_base + U3P_U2PHYDTM1); 384 385 if (!index) { 386 tmp = readl(port_base + U3P_U3_PHYA_REG0); 387 tmp &= ~P3A_RG_U3_VUSB10_ON; 388 writel(tmp, port_base + U3P_U3_PHYA_REG0); 389 } else { 390 tmp = readl(port_base + U3D_U2PHYDCR0); 391 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 392 writel(tmp, port_base + U3D_U2PHYDCR0); 393 } 394 395 dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); 396} 397 398static void phy_instance_exit(struct mt65xx_u3phy *u3phy, 399 struct mt65xx_phy_instance *instance) 400{ 401 void __iomem *port_base = instance->port_base; 402 u32 index = instance->index; 403 u32 tmp; 404 405 if (index) { 406 tmp = readl(port_base + U3D_U2PHYDCR0); 407 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 408 writel(tmp, port_base + U3D_U2PHYDCR0); 409 410 tmp = readl(port_base + U3P_U2PHYDTM0); 411 tmp &= ~P2C_FORCE_SUSPENDM; 412 writel(tmp, port_base + U3P_U2PHYDTM0); 413 } 414} 415 416static int mt65xx_phy_init(struct phy *phy) 417{ 418 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 419 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 420 int ret; 421 422 ret = clk_prepare_enable(u3phy->u3phya_ref); 423 if (ret) { 424 dev_err(u3phy->dev, "failed to enable u3phya_ref\n"); 425 return ret; 426 } 427 428 phy_instance_init(u3phy, instance); 429 return 0; 430} 431 432static int mt65xx_phy_power_on(struct phy *phy) 433{ 434 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 435 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 436 437 phy_instance_power_on(u3phy, instance); 438 hs_slew_rate_calibrate(u3phy, instance); 439 return 0; 440} 441 442static int mt65xx_phy_power_off(struct phy *phy) 443{ 444 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 445 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 446 447 phy_instance_power_off(u3phy, instance); 448 return 0; 449} 450 451static int mt65xx_phy_exit(struct phy *phy) 452{ 453 struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); 454 struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); 455 456 phy_instance_exit(u3phy, instance); 457 clk_disable_unprepare(u3phy->u3phya_ref); 458 return 0; 459} 460 461static struct phy *mt65xx_phy_xlate(struct device *dev, 462 struct of_phandle_args *args) 463{ 464 struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev); 465 struct mt65xx_phy_instance *instance = NULL; 466 struct device_node *phy_np = args->np; 467 int index; 468 469 470 if (args->args_count != 1) { 471 dev_err(dev, "invalid number of cells in 'phy' property\n"); 472 return ERR_PTR(-EINVAL); 473 } 474 475 for (index = 0; index < u3phy->nphys; index++) 476 if (phy_np == u3phy->phys[index]->phy->dev.of_node) { 477 instance = u3phy->phys[index]; 478 break; 479 } 480 481 if (!instance) { 482 dev_err(dev, "failed to find appropriate phy\n"); 483 return ERR_PTR(-EINVAL); 484 } 485 486 instance->type = args->args[0]; 487 488 if (!(instance->type == PHY_TYPE_USB2 || 489 instance->type == PHY_TYPE_USB3)) { 490 dev_err(dev, "unsupported device type: %d\n", instance->type); 491 return ERR_PTR(-EINVAL); 492 } 493 494 return instance->phy; 495} 496 497static struct phy_ops mt65xx_u3phy_ops = { 498 .init = mt65xx_phy_init, 499 .exit = mt65xx_phy_exit, 500 .power_on = mt65xx_phy_power_on, 501 .power_off = mt65xx_phy_power_off, 502 .owner = THIS_MODULE, 503}; 504 505static int mt65xx_u3phy_probe(struct platform_device *pdev) 506{ 507 struct device *dev = &pdev->dev; 508 struct device_node *np = dev->of_node; 509 struct device_node *child_np; 510 struct phy_provider *provider; 511 struct resource *sif_res; 512 struct mt65xx_u3phy *u3phy; 513 struct resource res; 514 int port, retval; 515 516 u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL); 517 if (!u3phy) 518 return -ENOMEM; 519 520 u3phy->nphys = of_get_child_count(np); 521 u3phy->phys = devm_kcalloc(dev, u3phy->nphys, 522 sizeof(*u3phy->phys), GFP_KERNEL); 523 if (!u3phy->phys) 524 return -ENOMEM; 525 526 u3phy->dev = dev; 527 platform_set_drvdata(pdev, u3phy); 528 529 sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 530 u3phy->sif_base = devm_ioremap_resource(dev, sif_res); 531 if (IS_ERR(u3phy->sif_base)) { 532 dev_err(dev, "failed to remap sif regs\n"); 533 return PTR_ERR(u3phy->sif_base); 534 } 535 536 u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref"); 537 if (IS_ERR(u3phy->u3phya_ref)) { 538 dev_err(dev, "error to get u3phya_ref\n"); 539 return PTR_ERR(u3phy->u3phya_ref); 540 } 541 542 port = 0; 543 for_each_child_of_node(np, child_np) { 544 struct mt65xx_phy_instance *instance; 545 struct phy *phy; 546 547 instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); 548 if (!instance) { 549 retval = -ENOMEM; 550 goto put_child; 551 } 552 553 u3phy->phys[port] = instance; 554 555 phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops); 556 if (IS_ERR(phy)) { 557 dev_err(dev, "failed to create phy\n"); 558 retval = PTR_ERR(phy); 559 goto put_child; 560 } 561 562 retval = of_address_to_resource(child_np, 0, &res); 563 if (retval) { 564 dev_err(dev, "failed to get address resource(id-%d)\n", 565 port); 566 goto put_child; 567 } 568 569 instance->port_base = devm_ioremap_resource(&phy->dev, &res); 570 if (IS_ERR(instance->port_base)) { 571 dev_err(dev, "failed to remap phy regs\n"); 572 retval = PTR_ERR(instance->port_base); 573 goto put_child; 574 } 575 576 instance->phy = phy; 577 instance->index = port; 578 phy_set_drvdata(phy, instance); 579 port++; 580 } 581 582 provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate); 583 584 return PTR_ERR_OR_ZERO(provider); 585put_child: 586 of_node_put(child_np); 587 return retval; 588} 589 590static const struct of_device_id mt65xx_u3phy_id_table[] = { 591 { .compatible = "mediatek,mt8173-u3phy", }, 592 { }, 593}; 594MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table); 595 596static struct platform_driver mt65xx_u3phy_driver = { 597 .probe = mt65xx_u3phy_probe, 598 .driver = { 599 .name = "mt65xx-u3phy", 600 .of_match_table = mt65xx_u3phy_id_table, 601 }, 602}; 603 604module_platform_driver(mt65xx_u3phy_driver); 605 606MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); 607MODULE_DESCRIPTION("mt65xx USB PHY driver"); 608MODULE_LICENSE("GPL v2");