18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2015 MediaTek Inc. 48c2ecf20Sopenharmony_ci * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <dt-bindings/phy/phy.h> 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/of_address.h> 158c2ecf20Sopenharmony_ci#include <linux/of_device.h> 168c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* version V1 sub-banks offset base address */ 208c2ecf20Sopenharmony_ci/* banks shared by multiple phys */ 218c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */ 228c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */ 238c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_CHIP 0x300 /* shared by u3 phys */ 248c2ecf20Sopenharmony_ci/* u2 phy bank */ 258c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000 268c2ecf20Sopenharmony_ci/* u3/pcie/sata phy banks */ 278c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_U3PHYD 0x000 288c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V1_U3PHYA 0x200 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* version V2 sub-banks offset base address */ 318c2ecf20Sopenharmony_ci/* u2 phy banks */ 328c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_MISC 0x000 338c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_U2FREQ 0x100 348c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300 358c2ecf20Sopenharmony_ci/* u3/pcie/sata phy banks */ 368c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_SPLLC 0x000 378c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_CHIP 0x100 388c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_U3PHYD 0x200 398c2ecf20Sopenharmony_ci#define SSUSB_SIFSLV_V2_U3PHYA 0x400 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define U3P_USBPHYACR0 0x000 428c2ecf20Sopenharmony_ci#define PA0_RG_U2PLL_FORCE_ON BIT(15) 438c2ecf20Sopenharmony_ci#define PA0_RG_USB20_INTR_EN BIT(5) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define U3P_USBPHYACR1 0x004 468c2ecf20Sopenharmony_ci#define PA1_RG_INTR_CAL GENMASK(23, 19) 478c2ecf20Sopenharmony_ci#define PA1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19) 488c2ecf20Sopenharmony_ci#define PA1_RG_VRT_SEL GENMASK(14, 12) 498c2ecf20Sopenharmony_ci#define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12) 508c2ecf20Sopenharmony_ci#define PA1_RG_TERM_SEL GENMASK(10, 8) 518c2ecf20Sopenharmony_ci#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define U3P_USBPHYACR2 0x008 548c2ecf20Sopenharmony_ci#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define U3P_USBPHYACR5 0x014 578c2ecf20Sopenharmony_ci#define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) 588c2ecf20Sopenharmony_ci#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) 598c2ecf20Sopenharmony_ci#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) 608c2ecf20Sopenharmony_ci#define PA5_RG_U2_HS_100U_U3_EN BIT(11) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define U3P_USBPHYACR6 0x018 638c2ecf20Sopenharmony_ci#define PA6_RG_U2_BC11_SW_EN BIT(23) 648c2ecf20Sopenharmony_ci#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) 658c2ecf20Sopenharmony_ci#define PA6_RG_U2_DISCTH GENMASK(7, 4) 668c2ecf20Sopenharmony_ci#define PA6_RG_U2_DISCTH_VAL(x) ((0xf & (x)) << 4) 678c2ecf20Sopenharmony_ci#define PA6_RG_U2_SQTH GENMASK(3, 0) 688c2ecf20Sopenharmony_ci#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define U3P_U2PHYACR4 0x020 718c2ecf20Sopenharmony_ci#define P2C_RG_USB20_GPIO_CTL BIT(9) 728c2ecf20Sopenharmony_ci#define P2C_USB20_GPIO_MODE BIT(8) 738c2ecf20Sopenharmony_ci#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define U3D_U2PHYDCR0 0x060 768c2ecf20Sopenharmony_ci#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24) 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define U3P_U2PHYDTM0 0x068 798c2ecf20Sopenharmony_ci#define P2C_FORCE_UART_EN BIT(26) 808c2ecf20Sopenharmony_ci#define P2C_FORCE_DATAIN BIT(23) 818c2ecf20Sopenharmony_ci#define P2C_FORCE_DM_PULLDOWN BIT(21) 828c2ecf20Sopenharmony_ci#define P2C_FORCE_DP_PULLDOWN BIT(20) 838c2ecf20Sopenharmony_ci#define P2C_FORCE_XCVRSEL BIT(19) 848c2ecf20Sopenharmony_ci#define P2C_FORCE_SUSPENDM BIT(18) 858c2ecf20Sopenharmony_ci#define P2C_FORCE_TERMSEL BIT(17) 868c2ecf20Sopenharmony_ci#define P2C_RG_DATAIN GENMASK(13, 10) 878c2ecf20Sopenharmony_ci#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10) 888c2ecf20Sopenharmony_ci#define P2C_RG_DMPULLDOWN BIT(7) 898c2ecf20Sopenharmony_ci#define P2C_RG_DPPULLDOWN BIT(6) 908c2ecf20Sopenharmony_ci#define P2C_RG_XCVRSEL GENMASK(5, 4) 918c2ecf20Sopenharmony_ci#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4) 928c2ecf20Sopenharmony_ci#define P2C_RG_SUSPENDM BIT(3) 938c2ecf20Sopenharmony_ci#define P2C_RG_TERMSEL BIT(2) 948c2ecf20Sopenharmony_ci#define P2C_DTM0_PART_MASK \ 958c2ecf20Sopenharmony_ci (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \ 968c2ecf20Sopenharmony_ci P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \ 978c2ecf20Sopenharmony_ci P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \ 988c2ecf20Sopenharmony_ci P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define U3P_U2PHYDTM1 0x06C 1018c2ecf20Sopenharmony_ci#define P2C_RG_UART_EN BIT(16) 1028c2ecf20Sopenharmony_ci#define P2C_FORCE_IDDIG BIT(9) 1038c2ecf20Sopenharmony_ci#define P2C_RG_VBUSVALID BIT(5) 1048c2ecf20Sopenharmony_ci#define P2C_RG_SESSEND BIT(4) 1058c2ecf20Sopenharmony_ci#define P2C_RG_AVALID BIT(2) 1068c2ecf20Sopenharmony_ci#define P2C_RG_IDDIG BIT(1) 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci#define U3P_U2PHYBC12C 0x080 1098c2ecf20Sopenharmony_ci#define P2C_RG_CHGDT_EN BIT(0) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#define U3P_U3_CHIP_GPIO_CTLD 0x0c 1128c2ecf20Sopenharmony_ci#define P3C_REG_IP_SW_RST BIT(31) 1138c2ecf20Sopenharmony_ci#define P3C_MCU_BUS_CK_GATE_EN BIT(30) 1148c2ecf20Sopenharmony_ci#define P3C_FORCE_IP_SW_RST BIT(29) 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define U3P_U3_CHIP_GPIO_CTLE 0x10 1178c2ecf20Sopenharmony_ci#define P3C_RG_SWRST_U3_PHYD BIT(25) 1188c2ecf20Sopenharmony_ci#define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_REG0 0x000 1218c2ecf20Sopenharmony_ci#define P3A_RG_CLKDRV_OFF GENMASK(3, 2) 1228c2ecf20Sopenharmony_ci#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2) 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_REG1 0x004 1258c2ecf20Sopenharmony_ci#define P3A_RG_CLKDRV_AMP GENMASK(31, 29) 1268c2ecf20Sopenharmony_ci#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_REG6 0x018 1298c2ecf20Sopenharmony_ci#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) 1308c2ecf20Sopenharmony_ci#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_REG9 0x024 1338c2ecf20Sopenharmony_ci#define P3A_RG_RX_DAC_MUX GENMASK(5, 1) 1348c2ecf20Sopenharmony_ci#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG0 0x100 1378c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16) 1388c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16) 1398c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12) 1408c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12) 1418c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10) 1428c2ecf20Sopenharmony_ci#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG4 0x108 1458c2ecf20Sopenharmony_ci#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19) 1468c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6) 1478c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG5 0x10c 1508c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28) 1518c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28) 1528c2ecf20Sopenharmony_ci#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12) 1538c2ecf20Sopenharmony_ci#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12) 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG6 0x110 1568c2ecf20Sopenharmony_ci#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16) 1578c2ecf20Sopenharmony_ci#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16) 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG7 0x114 1608c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16) 1618c2ecf20Sopenharmony_ci#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG20 0x13c 1648c2ecf20Sopenharmony_ci#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16) 1658c2ecf20Sopenharmony_ci#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16) 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#define U3P_U3_PHYA_DA_REG25 0x148 1688c2ecf20Sopenharmony_ci#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0) 1698c2ecf20Sopenharmony_ci#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x)) 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define U3P_U3_PHYD_LFPS1 0x00c 1728c2ecf20Sopenharmony_ci#define P3D_RG_FWAKE_TH GENMASK(21, 16) 1738c2ecf20Sopenharmony_ci#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16) 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci#define U3P_U3_PHYD_CDR1 0x05c 1768c2ecf20Sopenharmony_ci#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) 1778c2ecf20Sopenharmony_ci#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) 1788c2ecf20Sopenharmony_ci#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8) 1798c2ecf20Sopenharmony_ci#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#define U3P_U3_PHYD_RXDET1 0x128 1828c2ecf20Sopenharmony_ci#define P3D_RG_RXDET_STB2_SET GENMASK(17, 9) 1838c2ecf20Sopenharmony_ci#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9) 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci#define U3P_U3_PHYD_RXDET2 0x12c 1868c2ecf20Sopenharmony_ci#define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0) 1878c2ecf20Sopenharmony_ci#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x)) 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci#define U3P_SPLLC_XTALCTL3 0x018 1908c2ecf20Sopenharmony_ci#define XC3_RG_U3_XTAL_RX_PWD BIT(9) 1918c2ecf20Sopenharmony_ci#define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#define U3P_U2FREQ_FMCR0 0x00 1948c2ecf20Sopenharmony_ci#define P2F_RG_MONCLK_SEL GENMASK(27, 26) 1958c2ecf20Sopenharmony_ci#define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) 1968c2ecf20Sopenharmony_ci#define P2F_RG_FREQDET_EN BIT(24) 1978c2ecf20Sopenharmony_ci#define P2F_RG_CYCLECNT GENMASK(23, 0) 1988c2ecf20Sopenharmony_ci#define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci#define U3P_U2FREQ_VALUE 0x0c 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#define U3P_U2FREQ_FMMONR1 0x10 2038c2ecf20Sopenharmony_ci#define P2F_USB_FM_VALID BIT(0) 2048c2ecf20Sopenharmony_ci#define P2F_RG_FRCK_EN BIT(8) 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#define U3P_REF_CLK 26 /* MHZ */ 2078c2ecf20Sopenharmony_ci#define U3P_SLEW_RATE_COEF 28 2088c2ecf20Sopenharmony_ci#define U3P_SR_COEF_DIVISOR 1000 2098c2ecf20Sopenharmony_ci#define U3P_FM_DET_CYCLE_CNT 1024 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* SATA register setting */ 2128c2ecf20Sopenharmony_ci#define PHYD_CTRL_SIGNAL_MODE4 0x1c 2138c2ecf20Sopenharmony_ci/* CDR Charge Pump P-path current adjustment */ 2148c2ecf20Sopenharmony_ci#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20) 2158c2ecf20Sopenharmony_ci#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20) 2168c2ecf20Sopenharmony_ci#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8) 2178c2ecf20Sopenharmony_ci#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8) 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#define PHYD_DESIGN_OPTION2 0x24 2208c2ecf20Sopenharmony_ci/* Symbol lock count selection */ 2218c2ecf20Sopenharmony_ci#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4) 2228c2ecf20Sopenharmony_ci#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4) 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci#define PHYD_DESIGN_OPTION9 0x40 2258c2ecf20Sopenharmony_ci/* COMWAK GAP width window */ 2268c2ecf20Sopenharmony_ci#define RG_TG_MAX_MSK GENMASK(20, 16) 2278c2ecf20Sopenharmony_ci#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16) 2288c2ecf20Sopenharmony_ci/* COMINIT GAP width window */ 2298c2ecf20Sopenharmony_ci#define RG_T2_MAX_MSK GENMASK(13, 8) 2308c2ecf20Sopenharmony_ci#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8) 2318c2ecf20Sopenharmony_ci/* COMWAK GAP width window */ 2328c2ecf20Sopenharmony_ci#define RG_TG_MIN_MSK GENMASK(7, 5) 2338c2ecf20Sopenharmony_ci#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5) 2348c2ecf20Sopenharmony_ci/* COMINIT GAP width window */ 2358c2ecf20Sopenharmony_ci#define RG_T2_MIN_MSK GENMASK(4, 0) 2368c2ecf20Sopenharmony_ci#define RG_T2_MIN_VAL(x) (0x1f & (x)) 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci#define ANA_RG_CTRL_SIGNAL1 0x4c 2398c2ecf20Sopenharmony_ci/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */ 2408c2ecf20Sopenharmony_ci#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8) 2418c2ecf20Sopenharmony_ci#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8) 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci#define ANA_RG_CTRL_SIGNAL4 0x58 2448c2ecf20Sopenharmony_ci#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20) 2458c2ecf20Sopenharmony_ci#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20) 2468c2ecf20Sopenharmony_ci/* Loop filter R1 resistance adjustment for Gen1 speed */ 2478c2ecf20Sopenharmony_ci#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8) 2488c2ecf20Sopenharmony_ci#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8) 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci#define ANA_RG_CTRL_SIGNAL6 0x60 2518c2ecf20Sopenharmony_ci/* I-path capacitance adjustment for Gen1 */ 2528c2ecf20Sopenharmony_ci#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24) 2538c2ecf20Sopenharmony_ci#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24) 2548c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0) 2558c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x)) 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c 2588c2ecf20Sopenharmony_ci/* RX Gen1 LEQ tuning step */ 2598c2ecf20Sopenharmony_ci#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8) 2608c2ecf20Sopenharmony_ci#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8) 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8 2638c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16) 2648c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16) 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc 2678c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0) 2688c2ecf20Sopenharmony_ci#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x)) 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cienum mtk_phy_version { 2718c2ecf20Sopenharmony_ci MTK_PHY_V1 = 1, 2728c2ecf20Sopenharmony_ci MTK_PHY_V2, 2738c2ecf20Sopenharmony_ci}; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistruct mtk_phy_pdata { 2768c2ecf20Sopenharmony_ci /* avoid RX sensitivity level degradation only for mt8173 */ 2778c2ecf20Sopenharmony_ci bool avoid_rx_sen_degradation; 2788c2ecf20Sopenharmony_ci enum mtk_phy_version version; 2798c2ecf20Sopenharmony_ci}; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistruct u2phy_banks { 2828c2ecf20Sopenharmony_ci void __iomem *misc; 2838c2ecf20Sopenharmony_ci void __iomem *fmreg; 2848c2ecf20Sopenharmony_ci void __iomem *com; 2858c2ecf20Sopenharmony_ci}; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistruct u3phy_banks { 2888c2ecf20Sopenharmony_ci void __iomem *spllc; 2898c2ecf20Sopenharmony_ci void __iomem *chip; 2908c2ecf20Sopenharmony_ci void __iomem *phyd; /* include u3phyd_bank2 */ 2918c2ecf20Sopenharmony_ci void __iomem *phya; /* include u3phya_da */ 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistruct mtk_phy_instance { 2958c2ecf20Sopenharmony_ci struct phy *phy; 2968c2ecf20Sopenharmony_ci void __iomem *port_base; 2978c2ecf20Sopenharmony_ci union { 2988c2ecf20Sopenharmony_ci struct u2phy_banks u2_banks; 2998c2ecf20Sopenharmony_ci struct u3phy_banks u3_banks; 3008c2ecf20Sopenharmony_ci }; 3018c2ecf20Sopenharmony_ci struct clk *ref_clk; /* reference clock of (digital) phy */ 3028c2ecf20Sopenharmony_ci struct clk *da_ref_clk; /* reference clock of analog phy */ 3038c2ecf20Sopenharmony_ci u32 index; 3048c2ecf20Sopenharmony_ci u8 type; 3058c2ecf20Sopenharmony_ci int eye_src; 3068c2ecf20Sopenharmony_ci int eye_vrt; 3078c2ecf20Sopenharmony_ci int eye_term; 3088c2ecf20Sopenharmony_ci int intr; 3098c2ecf20Sopenharmony_ci int discth; 3108c2ecf20Sopenharmony_ci bool bc12_en; 3118c2ecf20Sopenharmony_ci}; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistruct mtk_tphy { 3148c2ecf20Sopenharmony_ci struct device *dev; 3158c2ecf20Sopenharmony_ci void __iomem *sif_base; /* only shared sif */ 3168c2ecf20Sopenharmony_ci const struct mtk_phy_pdata *pdata; 3178c2ecf20Sopenharmony_ci struct mtk_phy_instance **phys; 3188c2ecf20Sopenharmony_ci int nphys; 3198c2ecf20Sopenharmony_ci int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ 3208c2ecf20Sopenharmony_ci int src_coef; /* coefficient for slew rate calibrate */ 3218c2ecf20Sopenharmony_ci}; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic void hs_slew_rate_calibrate(struct mtk_tphy *tphy, 3248c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 3278c2ecf20Sopenharmony_ci void __iomem *fmreg = u2_banks->fmreg; 3288c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 3298c2ecf20Sopenharmony_ci int calibration_val; 3308c2ecf20Sopenharmony_ci int fm_out; 3318c2ecf20Sopenharmony_ci u32 tmp; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* use force value */ 3348c2ecf20Sopenharmony_ci if (instance->eye_src) 3358c2ecf20Sopenharmony_ci return; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* enable USB ring oscillator */ 3388c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR5); 3398c2ecf20Sopenharmony_ci tmp |= PA5_RG_U2_HSTX_SRCAL_EN; 3408c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR5); 3418c2ecf20Sopenharmony_ci udelay(1); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /*enable free run clock */ 3448c2ecf20Sopenharmony_ci tmp = readl(fmreg + U3P_U2FREQ_FMMONR1); 3458c2ecf20Sopenharmony_ci tmp |= P2F_RG_FRCK_EN; 3468c2ecf20Sopenharmony_ci writel(tmp, fmreg + U3P_U2FREQ_FMMONR1); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* set cycle count as 1024, and select u2 channel */ 3498c2ecf20Sopenharmony_ci tmp = readl(fmreg + U3P_U2FREQ_FMCR0); 3508c2ecf20Sopenharmony_ci tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); 3518c2ecf20Sopenharmony_ci tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); 3528c2ecf20Sopenharmony_ci if (tphy->pdata->version == MTK_PHY_V1) 3538c2ecf20Sopenharmony_ci tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci writel(tmp, fmreg + U3P_U2FREQ_FMCR0); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* enable frequency meter */ 3588c2ecf20Sopenharmony_ci tmp = readl(fmreg + U3P_U2FREQ_FMCR0); 3598c2ecf20Sopenharmony_ci tmp |= P2F_RG_FREQDET_EN; 3608c2ecf20Sopenharmony_ci writel(tmp, fmreg + U3P_U2FREQ_FMCR0); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* ignore return value */ 3638c2ecf20Sopenharmony_ci readl_poll_timeout(fmreg + U3P_U2FREQ_FMMONR1, tmp, 3648c2ecf20Sopenharmony_ci (tmp & P2F_USB_FM_VALID), 10, 200); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci fm_out = readl(fmreg + U3P_U2FREQ_VALUE); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* disable frequency meter */ 3698c2ecf20Sopenharmony_ci tmp = readl(fmreg + U3P_U2FREQ_FMCR0); 3708c2ecf20Sopenharmony_ci tmp &= ~P2F_RG_FREQDET_EN; 3718c2ecf20Sopenharmony_ci writel(tmp, fmreg + U3P_U2FREQ_FMCR0); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /*disable free run clock */ 3748c2ecf20Sopenharmony_ci tmp = readl(fmreg + U3P_U2FREQ_FMMONR1); 3758c2ecf20Sopenharmony_ci tmp &= ~P2F_RG_FRCK_EN; 3768c2ecf20Sopenharmony_ci writel(tmp, fmreg + U3P_U2FREQ_FMMONR1); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (fm_out) { 3798c2ecf20Sopenharmony_ci /* ( 1024 / FM_OUT ) x reference clock frequency x coef */ 3808c2ecf20Sopenharmony_ci tmp = tphy->src_ref_clk * tphy->src_coef; 3818c2ecf20Sopenharmony_ci tmp = (tmp * U3P_FM_DET_CYCLE_CNT) / fm_out; 3828c2ecf20Sopenharmony_ci calibration_val = DIV_ROUND_CLOSEST(tmp, U3P_SR_COEF_DIVISOR); 3838c2ecf20Sopenharmony_ci } else { 3848c2ecf20Sopenharmony_ci /* if FM detection fail, set default value */ 3858c2ecf20Sopenharmony_ci calibration_val = 4; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "phy:%d, fm_out:%d, calib:%d (clk:%d, coef:%d)\n", 3888c2ecf20Sopenharmony_ci instance->index, fm_out, calibration_val, 3898c2ecf20Sopenharmony_ci tphy->src_ref_clk, tphy->src_coef); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* set HS slew rate */ 3928c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR5); 3938c2ecf20Sopenharmony_ci tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 3948c2ecf20Sopenharmony_ci tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); 3958c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR5); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* disable USB ring oscillator */ 3988c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR5); 3998c2ecf20Sopenharmony_ci tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; 4008c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR5); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic void u3_phy_instance_init(struct mtk_tphy *tphy, 4048c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 4058c2ecf20Sopenharmony_ci{ 4068c2ecf20Sopenharmony_ci struct u3phy_banks *u3_banks = &instance->u3_banks; 4078c2ecf20Sopenharmony_ci u32 tmp; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci /* gating PCIe Analog XTAL clock */ 4108c2ecf20Sopenharmony_ci tmp = readl(u3_banks->spllc + U3P_SPLLC_XTALCTL3); 4118c2ecf20Sopenharmony_ci tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; 4128c2ecf20Sopenharmony_ci writel(tmp, u3_banks->spllc + U3P_SPLLC_XTALCTL3); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* gating XSQ */ 4158c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); 4168c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_XTAL_EXT_EN_U3; 4178c2ecf20Sopenharmony_ci tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2); 4188c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG0); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG9); 4218c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_RX_DAC_MUX; 4228c2ecf20Sopenharmony_ci tmp |= P3A_RG_RX_DAC_MUX_VAL(4); 4238c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG9); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG6); 4268c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_TX_EIDLE_CM; 4278c2ecf20Sopenharmony_ci tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe); 4288c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG6); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_CDR1); 4318c2ecf20Sopenharmony_ci tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1); 4328c2ecf20Sopenharmony_ci tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3); 4338c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_CDR1); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_LFPS1); 4368c2ecf20Sopenharmony_ci tmp &= ~P3D_RG_FWAKE_TH; 4378c2ecf20Sopenharmony_ci tmp |= P3D_RG_FWAKE_TH_VAL(0x34); 4388c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_LFPS1); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1); 4418c2ecf20Sopenharmony_ci tmp &= ~P3D_RG_RXDET_STB2_SET; 4428c2ecf20Sopenharmony_ci tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10); 4438c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET1); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2); 4468c2ecf20Sopenharmony_ci tmp &= ~P3D_RG_RXDET_STB2_SET_P3; 4478c2ecf20Sopenharmony_ci tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10); 4488c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2); 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic void u2_phy_instance_init(struct mtk_tphy *tphy, 4548c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 4578c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 4588c2ecf20Sopenharmony_ci u32 index = instance->index; 4598c2ecf20Sopenharmony_ci u32 tmp; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* switch to USB function, and enable usb pll */ 4628c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 4638c2ecf20Sopenharmony_ci tmp &= ~(P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM); 4648c2ecf20Sopenharmony_ci tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); 4658c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM1); 4688c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_UART_EN; 4698c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM1); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR0); 4728c2ecf20Sopenharmony_ci tmp |= PA0_RG_USB20_INTR_EN; 4738c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR0); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* disable switch 100uA current to SSUSB */ 4768c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR5); 4778c2ecf20Sopenharmony_ci tmp &= ~PA5_RG_U2_HS_100U_U3_EN; 4788c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR5); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (!index) { 4818c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYACR4); 4828c2ecf20Sopenharmony_ci tmp &= ~P2C_U2_GPIO_CTR_MSK; 4838c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYACR4); 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if (tphy->pdata->avoid_rx_sen_degradation) { 4878c2ecf20Sopenharmony_ci if (!index) { 4888c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR2); 4898c2ecf20Sopenharmony_ci tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; 4908c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR2); 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci tmp = readl(com + U3D_U2PHYDCR0); 4938c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 4948c2ecf20Sopenharmony_ci writel(tmp, com + U3D_U2PHYDCR0); 4958c2ecf20Sopenharmony_ci } else { 4968c2ecf20Sopenharmony_ci tmp = readl(com + U3D_U2PHYDCR0); 4978c2ecf20Sopenharmony_ci tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 4988c2ecf20Sopenharmony_ci writel(tmp, com + U3D_U2PHYDCR0); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5018c2ecf20Sopenharmony_ci tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 5028c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR6); 5078c2ecf20Sopenharmony_ci tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ 5088c2ecf20Sopenharmony_ci tmp &= ~PA6_RG_U2_SQTH; 5098c2ecf20Sopenharmony_ci tmp |= PA6_RG_U2_SQTH_VAL(2); 5108c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR6); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic void u2_phy_instance_power_on(struct mtk_tphy *tphy, 5168c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 5198c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 5208c2ecf20Sopenharmony_ci u32 index = instance->index; 5218c2ecf20Sopenharmony_ci u32 tmp; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5248c2ecf20Sopenharmony_ci tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK); 5258c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* OTG Enable */ 5288c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR6); 5298c2ecf20Sopenharmony_ci tmp |= PA6_RG_U2_OTG_VBUSCMP_EN; 5308c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR6); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM1); 5338c2ecf20Sopenharmony_ci tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID; 5348c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_SESSEND; 5358c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM1); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (tphy->pdata->avoid_rx_sen_degradation && index) { 5388c2ecf20Sopenharmony_ci tmp = readl(com + U3D_U2PHYDCR0); 5398c2ecf20Sopenharmony_ci tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 5408c2ecf20Sopenharmony_ci writel(tmp, com + U3D_U2PHYDCR0); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5438c2ecf20Sopenharmony_ci tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 5448c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); 5478c2ecf20Sopenharmony_ci} 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic void u2_phy_instance_power_off(struct mtk_tphy *tphy, 5508c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 5538c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 5548c2ecf20Sopenharmony_ci u32 index = instance->index; 5558c2ecf20Sopenharmony_ci u32 tmp; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5588c2ecf20Sopenharmony_ci tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); 5598c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* OTG Disable */ 5628c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR6); 5638c2ecf20Sopenharmony_ci tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; 5648c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR6); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM1); 5678c2ecf20Sopenharmony_ci tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); 5688c2ecf20Sopenharmony_ci tmp |= P2C_RG_SESSEND; 5698c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM1); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if (tphy->pdata->avoid_rx_sen_degradation && index) { 5728c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5738c2ecf20Sopenharmony_ci tmp &= ~(P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM); 5748c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci tmp = readl(com + U3D_U2PHYDCR0); 5778c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 5788c2ecf20Sopenharmony_ci writel(tmp, com + U3D_U2PHYDCR0); 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic void u2_phy_instance_exit(struct mtk_tphy *tphy, 5858c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 5888c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 5898c2ecf20Sopenharmony_ci u32 index = instance->index; 5908c2ecf20Sopenharmony_ci u32 tmp; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (tphy->pdata->avoid_rx_sen_degradation && index) { 5938c2ecf20Sopenharmony_ci tmp = readl(com + U3D_U2PHYDCR0); 5948c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 5958c2ecf20Sopenharmony_ci writel(tmp, com + U3D_U2PHYDCR0); 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYDTM0); 5988c2ecf20Sopenharmony_ci tmp &= ~P2C_FORCE_SUSPENDM; 5998c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYDTM0); 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_cistatic void u2_phy_instance_set_mode(struct mtk_tphy *tphy, 6048c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance, 6058c2ecf20Sopenharmony_ci enum phy_mode mode) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 6088c2ecf20Sopenharmony_ci u32 tmp; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci tmp = readl(u2_banks->com + U3P_U2PHYDTM1); 6118c2ecf20Sopenharmony_ci switch (mode) { 6128c2ecf20Sopenharmony_ci case PHY_MODE_USB_DEVICE: 6138c2ecf20Sopenharmony_ci tmp |= P2C_FORCE_IDDIG | P2C_RG_IDDIG; 6148c2ecf20Sopenharmony_ci break; 6158c2ecf20Sopenharmony_ci case PHY_MODE_USB_HOST: 6168c2ecf20Sopenharmony_ci tmp |= P2C_FORCE_IDDIG; 6178c2ecf20Sopenharmony_ci tmp &= ~P2C_RG_IDDIG; 6188c2ecf20Sopenharmony_ci break; 6198c2ecf20Sopenharmony_ci case PHY_MODE_USB_OTG: 6208c2ecf20Sopenharmony_ci tmp &= ~(P2C_FORCE_IDDIG | P2C_RG_IDDIG); 6218c2ecf20Sopenharmony_ci break; 6228c2ecf20Sopenharmony_ci default: 6238c2ecf20Sopenharmony_ci return; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci writel(tmp, u2_banks->com + U3P_U2PHYDTM1); 6268c2ecf20Sopenharmony_ci} 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_cistatic void pcie_phy_instance_init(struct mtk_tphy *tphy, 6298c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 6308c2ecf20Sopenharmony_ci{ 6318c2ecf20Sopenharmony_ci struct u3phy_banks *u3_banks = &instance->u3_banks; 6328c2ecf20Sopenharmony_ci u32 tmp; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (tphy->pdata->version != MTK_PHY_V1) 6358c2ecf20Sopenharmony_ci return; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); 6388c2ecf20Sopenharmony_ci tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H); 6398c2ecf20Sopenharmony_ci tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2); 6408c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG0); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* ref clk drive */ 6438c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG1); 6448c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_CLKDRV_AMP; 6458c2ecf20Sopenharmony_ci tmp |= P3A_RG_CLKDRV_AMP_VAL(0x4); 6468c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG1); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); 6498c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_CLKDRV_OFF; 6508c2ecf20Sopenharmony_ci tmp |= P3A_RG_CLKDRV_OFF_VAL(0x1); 6518c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci /* SSC delta -5000ppm */ 6548c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG20); 6558c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_PLL_DELTA1_PE2H; 6568c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c); 6578c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG20); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG25); 6608c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_PLL_DELTA_PE2H; 6618c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_DELTA_PE2H_VAL(0x36); 6628c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG25); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci /* change pll BW 0.6M */ 6658c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG5); 6668c2ecf20Sopenharmony_ci tmp &= ~(P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H); 6678c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_BR_PE2H_VAL(0x1) | P3A_RG_PLL_IC_PE2H_VAL(0x1); 6688c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG5); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG4); 6718c2ecf20Sopenharmony_ci tmp &= ~(P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H); 6728c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_BC_PE2H_VAL(0x3); 6738c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG4); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG6); 6768c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_PLL_IR_PE2H; 6778c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_IR_PE2H_VAL(0x2); 6788c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG6); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG7); 6818c2ecf20Sopenharmony_ci tmp &= ~P3A_RG_PLL_BP_PE2H; 6828c2ecf20Sopenharmony_ci tmp |= P3A_RG_PLL_BP_PE2H_VAL(0xa); 6838c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG7); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* Tx Detect Rx Timing: 10us -> 5us */ 6868c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1); 6878c2ecf20Sopenharmony_ci tmp &= ~P3D_RG_RXDET_STB2_SET; 6888c2ecf20Sopenharmony_ci tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10); 6898c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET1); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2); 6928c2ecf20Sopenharmony_ci tmp &= ~P3D_RG_RXDET_STB2_SET_P3; 6938c2ecf20Sopenharmony_ci tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10); 6948c2ecf20Sopenharmony_ci writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* wait for PCIe subsys register to active */ 6978c2ecf20Sopenharmony_ci usleep_range(2500, 3000); 6988c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic void pcie_phy_instance_power_on(struct mtk_tphy *tphy, 7028c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 7038c2ecf20Sopenharmony_ci{ 7048c2ecf20Sopenharmony_ci struct u3phy_banks *bank = &instance->u3_banks; 7058c2ecf20Sopenharmony_ci u32 tmp; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD); 7088c2ecf20Sopenharmony_ci tmp &= ~(P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST); 7098c2ecf20Sopenharmony_ci writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE); 7128c2ecf20Sopenharmony_ci tmp &= ~(P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD); 7138c2ecf20Sopenharmony_ci writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE); 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic void pcie_phy_instance_power_off(struct mtk_tphy *tphy, 7178c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct u3phy_banks *bank = &instance->u3_banks; 7218c2ecf20Sopenharmony_ci u32 tmp; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD); 7248c2ecf20Sopenharmony_ci tmp |= P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST; 7258c2ecf20Sopenharmony_ci writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE); 7288c2ecf20Sopenharmony_ci tmp |= P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD; 7298c2ecf20Sopenharmony_ci writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE); 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistatic void sata_phy_instance_init(struct mtk_tphy *tphy, 7338c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci struct u3phy_banks *u3_banks = &instance->u3_banks; 7368c2ecf20Sopenharmony_ci void __iomem *phyd = u3_banks->phyd; 7378c2ecf20Sopenharmony_ci u32 tmp; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* charge current adjustment */ 7408c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_RG_CTRL_SIGNAL6); 7418c2ecf20Sopenharmony_ci tmp &= ~(RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK); 7428c2ecf20Sopenharmony_ci tmp |= RG_CDR_BIRLTR_GEN1_VAL(0x6) | RG_CDR_BC_GEN1_VAL(0x1a); 7438c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_RG_CTRL_SIGNAL6); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL4); 7468c2ecf20Sopenharmony_ci tmp &= ~RG_CDR_BIRLTD0_GEN1_MSK; 7478c2ecf20Sopenharmony_ci tmp |= RG_CDR_BIRLTD0_GEN1_VAL(0x18); 7488c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL4); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL5); 7518c2ecf20Sopenharmony_ci tmp &= ~RG_CDR_BIRLTD0_GEN3_MSK; 7528c2ecf20Sopenharmony_ci tmp |= RG_CDR_BIRLTD0_GEN3_VAL(0x06); 7538c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL5); 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_RG_CTRL_SIGNAL4); 7568c2ecf20Sopenharmony_ci tmp &= ~(RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK); 7578c2ecf20Sopenharmony_ci tmp |= RG_CDR_BICLTR_GEN1_VAL(0x0c) | RG_CDR_BR_GEN2_VAL(0x07); 7588c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_RG_CTRL_SIGNAL4); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci tmp = readl(phyd + PHYD_CTRL_SIGNAL_MODE4); 7618c2ecf20Sopenharmony_ci tmp &= ~(RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK); 7628c2ecf20Sopenharmony_ci tmp |= RG_CDR_BICLTD0_GEN1_VAL(0x08) | RG_CDR_BICLTD1_GEN1_VAL(0x02); 7638c2ecf20Sopenharmony_ci writel(tmp, phyd + PHYD_CTRL_SIGNAL_MODE4); 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci tmp = readl(phyd + PHYD_DESIGN_OPTION2); 7668c2ecf20Sopenharmony_ci tmp &= ~RG_LOCK_CNT_SEL_MSK; 7678c2ecf20Sopenharmony_ci tmp |= RG_LOCK_CNT_SEL_VAL(0x02); 7688c2ecf20Sopenharmony_ci writel(tmp, phyd + PHYD_DESIGN_OPTION2); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci tmp = readl(phyd + PHYD_DESIGN_OPTION9); 7718c2ecf20Sopenharmony_ci tmp &= ~(RG_T2_MIN_MSK | RG_TG_MIN_MSK | 7728c2ecf20Sopenharmony_ci RG_T2_MAX_MSK | RG_TG_MAX_MSK); 7738c2ecf20Sopenharmony_ci tmp |= RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04) | 7748c2ecf20Sopenharmony_ci RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e); 7758c2ecf20Sopenharmony_ci writel(tmp, phyd + PHYD_DESIGN_OPTION9); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_RG_CTRL_SIGNAL1); 7788c2ecf20Sopenharmony_ci tmp &= ~RG_IDRV_0DB_GEN1_MSK; 7798c2ecf20Sopenharmony_ci tmp |= RG_IDRV_0DB_GEN1_VAL(0x20); 7808c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_RG_CTRL_SIGNAL1); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL1); 7838c2ecf20Sopenharmony_ci tmp &= ~RG_EQ_DLEQ_LFI_GEN1_MSK; 7848c2ecf20Sopenharmony_ci tmp |= RG_EQ_DLEQ_LFI_GEN1_VAL(0x03); 7858c2ecf20Sopenharmony_ci writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL1); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cistatic void phy_v1_banks_init(struct mtk_tphy *tphy, 7918c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 7948c2ecf20Sopenharmony_ci struct u3phy_banks *u3_banks = &instance->u3_banks; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci switch (instance->type) { 7978c2ecf20Sopenharmony_ci case PHY_TYPE_USB2: 7988c2ecf20Sopenharmony_ci u2_banks->misc = NULL; 7998c2ecf20Sopenharmony_ci u2_banks->fmreg = tphy->sif_base + SSUSB_SIFSLV_V1_U2FREQ; 8008c2ecf20Sopenharmony_ci u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM; 8018c2ecf20Sopenharmony_ci break; 8028c2ecf20Sopenharmony_ci case PHY_TYPE_USB3: 8038c2ecf20Sopenharmony_ci case PHY_TYPE_PCIE: 8048c2ecf20Sopenharmony_ci u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC; 8058c2ecf20Sopenharmony_ci u3_banks->chip = tphy->sif_base + SSUSB_SIFSLV_V1_CHIP; 8068c2ecf20Sopenharmony_ci u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; 8078c2ecf20Sopenharmony_ci u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA; 8088c2ecf20Sopenharmony_ci break; 8098c2ecf20Sopenharmony_ci case PHY_TYPE_SATA: 8108c2ecf20Sopenharmony_ci u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; 8118c2ecf20Sopenharmony_ci break; 8128c2ecf20Sopenharmony_ci default: 8138c2ecf20Sopenharmony_ci dev_err(tphy->dev, "incompatible PHY type\n"); 8148c2ecf20Sopenharmony_ci return; 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic void phy_v2_banks_init(struct mtk_tphy *tphy, 8198c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 8228c2ecf20Sopenharmony_ci struct u3phy_banks *u3_banks = &instance->u3_banks; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci switch (instance->type) { 8258c2ecf20Sopenharmony_ci case PHY_TYPE_USB2: 8268c2ecf20Sopenharmony_ci u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC; 8278c2ecf20Sopenharmony_ci u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ; 8288c2ecf20Sopenharmony_ci u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM; 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci case PHY_TYPE_USB3: 8318c2ecf20Sopenharmony_ci case PHY_TYPE_PCIE: 8328c2ecf20Sopenharmony_ci u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC; 8338c2ecf20Sopenharmony_ci u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP; 8348c2ecf20Sopenharmony_ci u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD; 8358c2ecf20Sopenharmony_ci u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA; 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci default: 8388c2ecf20Sopenharmony_ci dev_err(tphy->dev, "incompatible PHY type\n"); 8398c2ecf20Sopenharmony_ci return; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci} 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_cistatic void phy_parse_property(struct mtk_tphy *tphy, 8448c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 8458c2ecf20Sopenharmony_ci{ 8468c2ecf20Sopenharmony_ci struct device *dev = &instance->phy->dev; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci if (instance->type != PHY_TYPE_USB2) 8498c2ecf20Sopenharmony_ci return; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci instance->bc12_en = device_property_read_bool(dev, "mediatek,bc12"); 8528c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,eye-src", 8538c2ecf20Sopenharmony_ci &instance->eye_src); 8548c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,eye-vrt", 8558c2ecf20Sopenharmony_ci &instance->eye_vrt); 8568c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,eye-term", 8578c2ecf20Sopenharmony_ci &instance->eye_term); 8588c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,intr", 8598c2ecf20Sopenharmony_ci &instance->intr); 8608c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,discth", 8618c2ecf20Sopenharmony_ci &instance->discth); 8628c2ecf20Sopenharmony_ci dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d, intr:%d, disc:%d\n", 8638c2ecf20Sopenharmony_ci instance->bc12_en, instance->eye_src, 8648c2ecf20Sopenharmony_ci instance->eye_vrt, instance->eye_term, 8658c2ecf20Sopenharmony_ci instance->intr, instance->discth); 8668c2ecf20Sopenharmony_ci} 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic void u2_phy_props_set(struct mtk_tphy *tphy, 8698c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct u2phy_banks *u2_banks = &instance->u2_banks; 8728c2ecf20Sopenharmony_ci void __iomem *com = u2_banks->com; 8738c2ecf20Sopenharmony_ci u32 tmp; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci if (instance->bc12_en) { 8768c2ecf20Sopenharmony_ci tmp = readl(com + U3P_U2PHYBC12C); 8778c2ecf20Sopenharmony_ci tmp |= P2C_RG_CHGDT_EN; /* BC1.2 path Enable */ 8788c2ecf20Sopenharmony_ci writel(tmp, com + U3P_U2PHYBC12C); 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if (instance->eye_src) { 8828c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR5); 8838c2ecf20Sopenharmony_ci tmp &= ~PA5_RG_U2_HSTX_SRCTRL; 8848c2ecf20Sopenharmony_ci tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src); 8858c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR5); 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (instance->eye_vrt) { 8898c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR1); 8908c2ecf20Sopenharmony_ci tmp &= ~PA1_RG_VRT_SEL; 8918c2ecf20Sopenharmony_ci tmp |= PA1_RG_VRT_SEL_VAL(instance->eye_vrt); 8928c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR1); 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (instance->eye_term) { 8968c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR1); 8978c2ecf20Sopenharmony_ci tmp &= ~PA1_RG_TERM_SEL; 8988c2ecf20Sopenharmony_ci tmp |= PA1_RG_TERM_SEL_VAL(instance->eye_term); 8998c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR1); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci if (instance->intr) { 9038c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR1); 9048c2ecf20Sopenharmony_ci tmp &= ~PA1_RG_INTR_CAL; 9058c2ecf20Sopenharmony_ci tmp |= PA1_RG_INTR_CAL_VAL(instance->intr); 9068c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR1); 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (instance->discth) { 9108c2ecf20Sopenharmony_ci tmp = readl(com + U3P_USBPHYACR6); 9118c2ecf20Sopenharmony_ci tmp &= ~PA6_RG_U2_DISCTH; 9128c2ecf20Sopenharmony_ci tmp |= PA6_RG_U2_DISCTH_VAL(instance->discth); 9138c2ecf20Sopenharmony_ci writel(tmp, com + U3P_USBPHYACR6); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci} 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_cistatic int mtk_phy_init(struct phy *phy) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = phy_get_drvdata(phy); 9208c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); 9218c2ecf20Sopenharmony_ci int ret; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci ret = clk_prepare_enable(instance->ref_clk); 9248c2ecf20Sopenharmony_ci if (ret) { 9258c2ecf20Sopenharmony_ci dev_err(tphy->dev, "failed to enable ref_clk\n"); 9268c2ecf20Sopenharmony_ci return ret; 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci ret = clk_prepare_enable(instance->da_ref_clk); 9308c2ecf20Sopenharmony_ci if (ret) { 9318c2ecf20Sopenharmony_ci dev_err(tphy->dev, "failed to enable da_ref\n"); 9328c2ecf20Sopenharmony_ci clk_disable_unprepare(instance->ref_clk); 9338c2ecf20Sopenharmony_ci return ret; 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci switch (instance->type) { 9378c2ecf20Sopenharmony_ci case PHY_TYPE_USB2: 9388c2ecf20Sopenharmony_ci u2_phy_instance_init(tphy, instance); 9398c2ecf20Sopenharmony_ci u2_phy_props_set(tphy, instance); 9408c2ecf20Sopenharmony_ci break; 9418c2ecf20Sopenharmony_ci case PHY_TYPE_USB3: 9428c2ecf20Sopenharmony_ci u3_phy_instance_init(tphy, instance); 9438c2ecf20Sopenharmony_ci break; 9448c2ecf20Sopenharmony_ci case PHY_TYPE_PCIE: 9458c2ecf20Sopenharmony_ci pcie_phy_instance_init(tphy, instance); 9468c2ecf20Sopenharmony_ci break; 9478c2ecf20Sopenharmony_ci case PHY_TYPE_SATA: 9488c2ecf20Sopenharmony_ci sata_phy_instance_init(tphy, instance); 9498c2ecf20Sopenharmony_ci break; 9508c2ecf20Sopenharmony_ci default: 9518c2ecf20Sopenharmony_ci dev_err(tphy->dev, "incompatible PHY type\n"); 9528c2ecf20Sopenharmony_ci clk_disable_unprepare(instance->ref_clk); 9538c2ecf20Sopenharmony_ci clk_disable_unprepare(instance->da_ref_clk); 9548c2ecf20Sopenharmony_ci return -EINVAL; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic int mtk_phy_power_on(struct phy *phy) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = phy_get_drvdata(phy); 9638c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (instance->type == PHY_TYPE_USB2) { 9668c2ecf20Sopenharmony_ci u2_phy_instance_power_on(tphy, instance); 9678c2ecf20Sopenharmony_ci hs_slew_rate_calibrate(tphy, instance); 9688c2ecf20Sopenharmony_ci } else if (instance->type == PHY_TYPE_PCIE) { 9698c2ecf20Sopenharmony_ci pcie_phy_instance_power_on(tphy, instance); 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci return 0; 9738c2ecf20Sopenharmony_ci} 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_cistatic int mtk_phy_power_off(struct phy *phy) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = phy_get_drvdata(phy); 9788c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (instance->type == PHY_TYPE_USB2) 9818c2ecf20Sopenharmony_ci u2_phy_instance_power_off(tphy, instance); 9828c2ecf20Sopenharmony_ci else if (instance->type == PHY_TYPE_PCIE) 9838c2ecf20Sopenharmony_ci pcie_phy_instance_power_off(tphy, instance); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci return 0; 9868c2ecf20Sopenharmony_ci} 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_cistatic int mtk_phy_exit(struct phy *phy) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = phy_get_drvdata(phy); 9918c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (instance->type == PHY_TYPE_USB2) 9948c2ecf20Sopenharmony_ci u2_phy_instance_exit(tphy, instance); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci clk_disable_unprepare(instance->ref_clk); 9978c2ecf20Sopenharmony_ci clk_disable_unprepare(instance->da_ref_clk); 9988c2ecf20Sopenharmony_ci return 0; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_cistatic int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = phy_get_drvdata(phy); 10048c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (instance->type == PHY_TYPE_USB2) 10078c2ecf20Sopenharmony_ci u2_phy_instance_set_mode(tphy, instance, mode); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci return 0; 10108c2ecf20Sopenharmony_ci} 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_cistatic struct phy *mtk_phy_xlate(struct device *dev, 10138c2ecf20Sopenharmony_ci struct of_phandle_args *args) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci struct mtk_tphy *tphy = dev_get_drvdata(dev); 10168c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance = NULL; 10178c2ecf20Sopenharmony_ci struct device_node *phy_np = args->np; 10188c2ecf20Sopenharmony_ci int index; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci if (args->args_count != 1) { 10218c2ecf20Sopenharmony_ci dev_err(dev, "invalid number of cells in 'phy' property\n"); 10228c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci for (index = 0; index < tphy->nphys; index++) 10268c2ecf20Sopenharmony_ci if (phy_np == tphy->phys[index]->phy->dev.of_node) { 10278c2ecf20Sopenharmony_ci instance = tphy->phys[index]; 10288c2ecf20Sopenharmony_ci break; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci if (!instance) { 10328c2ecf20Sopenharmony_ci dev_err(dev, "failed to find appropriate phy\n"); 10338c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci instance->type = args->args[0]; 10378c2ecf20Sopenharmony_ci if (!(instance->type == PHY_TYPE_USB2 || 10388c2ecf20Sopenharmony_ci instance->type == PHY_TYPE_USB3 || 10398c2ecf20Sopenharmony_ci instance->type == PHY_TYPE_PCIE || 10408c2ecf20Sopenharmony_ci instance->type == PHY_TYPE_SATA)) { 10418c2ecf20Sopenharmony_ci dev_err(dev, "unsupported device type: %d\n", instance->type); 10428c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (tphy->pdata->version == MTK_PHY_V1) { 10468c2ecf20Sopenharmony_ci phy_v1_banks_init(tphy, instance); 10478c2ecf20Sopenharmony_ci } else if (tphy->pdata->version == MTK_PHY_V2) { 10488c2ecf20Sopenharmony_ci phy_v2_banks_init(tphy, instance); 10498c2ecf20Sopenharmony_ci } else { 10508c2ecf20Sopenharmony_ci dev_err(dev, "phy version is not supported\n"); 10518c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci phy_parse_property(tphy, instance); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci return instance->phy; 10578c2ecf20Sopenharmony_ci} 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_cistatic const struct phy_ops mtk_tphy_ops = { 10608c2ecf20Sopenharmony_ci .init = mtk_phy_init, 10618c2ecf20Sopenharmony_ci .exit = mtk_phy_exit, 10628c2ecf20Sopenharmony_ci .power_on = mtk_phy_power_on, 10638c2ecf20Sopenharmony_ci .power_off = mtk_phy_power_off, 10648c2ecf20Sopenharmony_ci .set_mode = mtk_phy_set_mode, 10658c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10668c2ecf20Sopenharmony_ci}; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic const struct mtk_phy_pdata tphy_v1_pdata = { 10698c2ecf20Sopenharmony_ci .avoid_rx_sen_degradation = false, 10708c2ecf20Sopenharmony_ci .version = MTK_PHY_V1, 10718c2ecf20Sopenharmony_ci}; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_cistatic const struct mtk_phy_pdata tphy_v2_pdata = { 10748c2ecf20Sopenharmony_ci .avoid_rx_sen_degradation = false, 10758c2ecf20Sopenharmony_ci .version = MTK_PHY_V2, 10768c2ecf20Sopenharmony_ci}; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_cistatic const struct mtk_phy_pdata mt8173_pdata = { 10798c2ecf20Sopenharmony_ci .avoid_rx_sen_degradation = true, 10808c2ecf20Sopenharmony_ci .version = MTK_PHY_V1, 10818c2ecf20Sopenharmony_ci}; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic const struct of_device_id mtk_tphy_id_table[] = { 10848c2ecf20Sopenharmony_ci { .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata }, 10858c2ecf20Sopenharmony_ci { .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata }, 10868c2ecf20Sopenharmony_ci { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, 10878c2ecf20Sopenharmony_ci { .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata }, 10888c2ecf20Sopenharmony_ci { .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata }, 10898c2ecf20Sopenharmony_ci { }, 10908c2ecf20Sopenharmony_ci}; 10918c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mtk_tphy_id_table); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic int mtk_tphy_probe(struct platform_device *pdev) 10948c2ecf20Sopenharmony_ci{ 10958c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 10968c2ecf20Sopenharmony_ci struct device_node *np = dev->of_node; 10978c2ecf20Sopenharmony_ci struct device_node *child_np; 10988c2ecf20Sopenharmony_ci struct phy_provider *provider; 10998c2ecf20Sopenharmony_ci struct resource *sif_res; 11008c2ecf20Sopenharmony_ci struct mtk_tphy *tphy; 11018c2ecf20Sopenharmony_ci struct resource res; 11028c2ecf20Sopenharmony_ci int port, retval; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL); 11058c2ecf20Sopenharmony_ci if (!tphy) 11068c2ecf20Sopenharmony_ci return -ENOMEM; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci tphy->pdata = of_device_get_match_data(dev); 11098c2ecf20Sopenharmony_ci if (!tphy->pdata) 11108c2ecf20Sopenharmony_ci return -EINVAL; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci tphy->nphys = of_get_child_count(np); 11138c2ecf20Sopenharmony_ci tphy->phys = devm_kcalloc(dev, tphy->nphys, 11148c2ecf20Sopenharmony_ci sizeof(*tphy->phys), GFP_KERNEL); 11158c2ecf20Sopenharmony_ci if (!tphy->phys) 11168c2ecf20Sopenharmony_ci return -ENOMEM; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci tphy->dev = dev; 11198c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, tphy); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 11228c2ecf20Sopenharmony_ci /* SATA phy of V1 needn't it if not shared with PCIe or USB */ 11238c2ecf20Sopenharmony_ci if (sif_res && tphy->pdata->version == MTK_PHY_V1) { 11248c2ecf20Sopenharmony_ci /* get banks shared by multiple phys */ 11258c2ecf20Sopenharmony_ci tphy->sif_base = devm_ioremap_resource(dev, sif_res); 11268c2ecf20Sopenharmony_ci if (IS_ERR(tphy->sif_base)) { 11278c2ecf20Sopenharmony_ci dev_err(dev, "failed to remap sif regs\n"); 11288c2ecf20Sopenharmony_ci return PTR_ERR(tphy->sif_base); 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci tphy->src_ref_clk = U3P_REF_CLK; 11338c2ecf20Sopenharmony_ci tphy->src_coef = U3P_SLEW_RATE_COEF; 11348c2ecf20Sopenharmony_ci /* update parameters of slew rate calibrate if exist */ 11358c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", 11368c2ecf20Sopenharmony_ci &tphy->src_ref_clk); 11378c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci port = 0; 11408c2ecf20Sopenharmony_ci for_each_child_of_node(np, child_np) { 11418c2ecf20Sopenharmony_ci struct mtk_phy_instance *instance; 11428c2ecf20Sopenharmony_ci struct phy *phy; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); 11458c2ecf20Sopenharmony_ci if (!instance) { 11468c2ecf20Sopenharmony_ci retval = -ENOMEM; 11478c2ecf20Sopenharmony_ci goto put_child; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci tphy->phys[port] = instance; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci phy = devm_phy_create(dev, child_np, &mtk_tphy_ops); 11538c2ecf20Sopenharmony_ci if (IS_ERR(phy)) { 11548c2ecf20Sopenharmony_ci dev_err(dev, "failed to create phy\n"); 11558c2ecf20Sopenharmony_ci retval = PTR_ERR(phy); 11568c2ecf20Sopenharmony_ci goto put_child; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci retval = of_address_to_resource(child_np, 0, &res); 11608c2ecf20Sopenharmony_ci if (retval) { 11618c2ecf20Sopenharmony_ci dev_err(dev, "failed to get address resource(id-%d)\n", 11628c2ecf20Sopenharmony_ci port); 11638c2ecf20Sopenharmony_ci goto put_child; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci instance->port_base = devm_ioremap_resource(&phy->dev, &res); 11678c2ecf20Sopenharmony_ci if (IS_ERR(instance->port_base)) { 11688c2ecf20Sopenharmony_ci dev_err(dev, "failed to remap phy regs\n"); 11698c2ecf20Sopenharmony_ci retval = PTR_ERR(instance->port_base); 11708c2ecf20Sopenharmony_ci goto put_child; 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci instance->phy = phy; 11748c2ecf20Sopenharmony_ci instance->index = port; 11758c2ecf20Sopenharmony_ci phy_set_drvdata(phy, instance); 11768c2ecf20Sopenharmony_ci port++; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci instance->ref_clk = devm_clk_get_optional(&phy->dev, "ref"); 11798c2ecf20Sopenharmony_ci if (IS_ERR(instance->ref_clk)) { 11808c2ecf20Sopenharmony_ci dev_err(dev, "failed to get ref_clk(id-%d)\n", port); 11818c2ecf20Sopenharmony_ci retval = PTR_ERR(instance->ref_clk); 11828c2ecf20Sopenharmony_ci goto put_child; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci instance->da_ref_clk = 11868c2ecf20Sopenharmony_ci devm_clk_get_optional(&phy->dev, "da_ref"); 11878c2ecf20Sopenharmony_ci if (IS_ERR(instance->da_ref_clk)) { 11888c2ecf20Sopenharmony_ci dev_err(dev, "failed to get da_ref_clk(id-%d)\n", port); 11898c2ecf20Sopenharmony_ci retval = PTR_ERR(instance->da_ref_clk); 11908c2ecf20Sopenharmony_ci goto put_child; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci } 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(provider); 11978c2ecf20Sopenharmony_ciput_child: 11988c2ecf20Sopenharmony_ci of_node_put(child_np); 11998c2ecf20Sopenharmony_ci return retval; 12008c2ecf20Sopenharmony_ci} 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_cistatic struct platform_driver mtk_tphy_driver = { 12038c2ecf20Sopenharmony_ci .probe = mtk_tphy_probe, 12048c2ecf20Sopenharmony_ci .driver = { 12058c2ecf20Sopenharmony_ci .name = "mtk-tphy", 12068c2ecf20Sopenharmony_ci .of_match_table = mtk_tphy_id_table, 12078c2ecf20Sopenharmony_ci }, 12088c2ecf20Sopenharmony_ci}; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_cimodule_platform_driver(mtk_tphy_driver); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ciMODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); 12138c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MediaTek T-PHY driver"); 12148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1215