blob: 5b453bc73492a1e248f36e2c6e42a745b9659a4b [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Zhanyong Wang <zhanyong.wang@mediatek.com>
*
*/
#include <dt-bindings/phy/phy.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/regmap.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/regulator/consumer.h>
#include "phy-mtk-tphy-debug.h"
/* version V1 sub-banks offset base address */
/* banks shared by multiple phys */
#define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
#define SSUSB_SIFSLV_V1_CHIP 0x300 /* shared by u3 phys */
/* u2 phy bank */
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
/* u3/pcie/sata phy banks */
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
/* version V2/V3 sub-banks offset base address */
/* V3: U2FREQ is not used anymore, but reserved */
/* u2 phy banks */
#define SSUSB_SIFSLV_V2_MISC 0x000
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300
/* u3/pcie/sata phy banks */
#define SSUSB_SIFSLV_V2_SPLLC 0x000
#define SSUSB_SIFSLV_V2_CHIP 0x100
#define SSUSB_SIFSLV_V2_U3PHYD 0x200
#define SSUSB_SIFSLV_V2_U3PHYA 0x400
#define U3P_MISC_REG1 0x04
#define MR1_EFUSE_AUTO_LOAD_DIS BIT(6)
#define MR1_EFUSE_AUTO_LOAD_DIS_P0 BIT(6)
#define MR1_EFUSE_AUTO_LOAD_DIS_P1 BIT(28)
#define MR1_EFUSE_AUTO_LOAD_DIS_P2 BIT(29)
#define U3P_USBPHYACR0 0x000
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
#define PA0_USB20_PLL_PREDIV GENMASK(7, 6)
#define PA0_USB20_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
#define PA0_RG_USB20_INTR_EN BIT(5)
#define U3P_USBPHYACR1 0x004
#define PA1_RG_INTR_CAL GENMASK(23, 19)
#define PA1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19)
#define PA1_RG_VRT_SEL GENMASK(14, 12)
#define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12)
#define PA1_RG_VRT_SEL_MASK (0x7)
#define PA1_RG_VRT_SEL_OFST (12)
#define PA1_RG_TERM_SEL GENMASK(10, 8)
#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
#define PA1_RG_TERM_SEL_MASK (0x7)
#define PA1_RG_TERM_SEL_OFST (8)
#define U3P_USBPHYACR2 0x008
#define PA2_RG_U2PLL_BW GENMASK(21, 19)
#define PA2_RG_U2PLL_BW_VAL(x) ((0x7 & (x)) << 19)
#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
#define U3P_USBPHYACR5 0x014
#define PA5_RG_U2_HSTX_SRCAL_EN BIT(15)
#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12)
#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
#define PA5_RG_U2_HS_100U_U3_EN BIT(11)
#define U3P_USBPHYACR6 0x018
#define PA6_RG_U2_PHY_REV6 GENMASK(31, 30)
#define PA6_RG_U2_PHY_REV6_VAL(x) ((0x3 & (x)) << 30)
#define PA6_RG_U2_PHY_REV6_MASK (0x3)
#define PA6_RG_U2_PHY_REV6_OFET (30)
#define PA6_RG_U2_PHY_REV1 BIT(25)
#define PA6_RG_U2_BC11_SW_EN BIT(23)
#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
#define PA6_RG_U2_DISCTH GENMASK(7, 4)
#define PA6_RG_U2_DISCTH_VAL(x) ((0xf & (x)) << 4)
#define PA6_RG_U2_DISCTH_MASK (0xf)
#define PA6_RG_U2_DISCTH_OFET (4)
#define PA6_RG_U2_SQTH GENMASK(3, 0)
#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x))
#define U3P_U2PHYACR4 0x020
#define P2C_RG_USB20_GPIO_CTL BIT(9)
#define P2C_USB20_GPIO_MODE BIT(8)
#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
#define U3P_U2PHYA_RESV 0x030
#define P2R_RG_U2PLL_FBDIV_26M 0x1bb13b
#define P2R_RG_U2PLL_FBDIV_48M 0x3c0000
#define U3P_U2PHYA_RESV1 0x044
#define P2R_RG_U2PLL_REFCLK_SEL BIT(5)
#define P2R_RG_U2PLL_FRA_EN BIT(3)
#define U3D_U2PHYDCR0 0x060
#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24)
#define U3P_U2PHYDTM0 0x068
#define P2C_FORCE_UART_EN BIT(26)
#define P2C_FORCE_DATAIN BIT(23)
#define P2C_FORCE_DM_PULLDOWN BIT(21)
#define P2C_FORCE_DP_PULLDOWN BIT(20)
#define P2C_FORCE_XCVRSEL BIT(19)
#define P2C_FORCE_SUSPENDM BIT(18)
#define P2C_FORCE_TERMSEL BIT(17)
#define P2C_RG_DATAIN GENMASK(13, 10)
#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
#define P2C_RG_DMPULLDOWN BIT(7)
#define P2C_RG_DPPULLDOWN BIT(6)
#define P2C_RG_XCVRSEL GENMASK(5, 4)
#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
#define P2C_RG_SUSPENDM BIT(3)
#define P2C_RG_TERMSEL BIT(2)
#define P2C_DTM0_PART_MASK \
(P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
P2C_FORCE_SUSPENDM | P2C_FORCE_TERMSEL | \
P2C_RG_DMPULLDOWN | P2C_RG_DPPULLDOWN | \
P2C_RG_TERMSEL)
#define P2C_DTM0_PART_MASK2 \
(P2C_FORCE_DM_PULLDOWN | P2C_FORCE_DP_PULLDOWN | \
P2C_FORCE_XCVRSEL | P2C_FORCE_SUSPENDM | \
P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL)
#define U3P_U2PHYDTM1 0x06C
#define P2C_RG_UART_EN BIT(16)
#define P2C_FORCE_VBUSVALID BIT(13)
#define P2C_FORCE_SESSEND BIT(12)
#define P2C_FORCE_BVALID BIT(11)
#define P2C_FORCE_AVALID BIT(10)
#define P2C_FORCE_IDDIG BIT(9)
#define P2C_FORCE_IDPULLUP BIT(8)
#define P2C_RG_VBUSVALID BIT(5)
#define P2C_RG_SESSEND BIT(4)
#define P2C_RG_BVALID BIT(3)
#define P2C_RG_AVALID BIT(2)
#define P2C_RG_IDDIG BIT(1)
#define U3P_U2PHYBC12C 0x080
#define P2C_RG_CHGDT_EN BIT(0)
#define U3P_U3_CHIP_GPIO_CTLD 0x0c
#define P3C_REG_IP_SW_RST BIT(31)
#define P3C_MCU_BUS_CK_GATE_EN BIT(30)
#define P3C_FORCE_IP_SW_RST BIT(29)
#define U3P_U3_CHIP_GPIO_CTLE 0x10
#define P3C_RG_SWRST_U3_PHYD BIT(25)
#define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
#define U3P_U3_PHYA_REG0 0x000
#define P3A_RG_IEXT_INTR GENMASK(15, 10)
#define P3A_RG_IEXT_INTR_VAL(x) ((0x3f & (x)) << 10)
#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
#define U3P_U3_PHYA_REG1 0x004
#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
#define RG_SSUSB_VA_ON BIT(29)
#define U3P_U3_PHYA_REG6 0x018
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
#define U3P_U3_PHYA_REG9 0x024
#define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
#define U3P_U3_PHYA_DA_REG0 0x100
#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
#define U3P_U3_PHYA_DA_REG4 0x108
#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
#define U3P_U3_PHYA_DA_REG5 0x10c
#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
#define U3P_U3_PHYA_DA_REG6 0x110
#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG7 0x114
#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG20 0x13c
#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
#define U3P_U3_PHYA_DA_REG25 0x148
#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
#define U3P_U3_PHYD_LFPS1 0x00c
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
#define U3P_U3_PHYD_IMPCAL0 0x010
#define P3D_RG_FORCE_TX_IMPEL BIT(31)
#define P3D_RG_TX_IMPEL GENMASK(28, 24)
#define P3D_RG_TX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
#define U3P_U3_PHYD_IMPCAL1 0x014
#define P3D_RG_FORCE_RX_IMPEL BIT(31)
#define P3D_RG_RX_IMPEL GENMASK(28, 24)
#define P3D_RG_RX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
#define U3P_U3_PHYD_RSV 0x054
#define P3D_RG_EFUSE_AUTO_LOAD_DIS BIT(12)
#define U3P_U3_PHYD_CDR1 0x05c
#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8)
#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
#define U3P_U3_PHYD_TOP1 0x100
#define P3D_RG_SSUSB_PHY_MODE GENMASK(2, 1)
#define P3D_RG_SSUSB_PHY_MODE_VAL(x) ((0x3 & (x)) << 1)
#define P3D_RG_SSUSB_FORCE_PHY_MODE BIT(0)
#define U3P_U3_PHYD_RXDET1 0x128
#define P3D_RG_RXDET_STB2_SET GENMASK(17, 9)
#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9)
#define U3P_U3_PHYD_RXDET2 0x12c
#define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0)
#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x))
#define U3P_SPLLC_XTALCTL3 0x018
#define XC3_RG_U3_XTAL_RX_PWD BIT(9)
#define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8)
#define U3P_U2FREQ_FMCR0 0x00
#define P2F_RG_MONCLK_SEL GENMASK(27, 26)
#define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26)
#define P2F_RG_FREQDET_EN BIT(24)
#define P2F_RG_CYCLECNT GENMASK(23, 0)
#define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x))
#define U3P_U2FREQ_VALUE 0x0c
#define U3P_U2FREQ_FMMONR1 0x10
#define P2F_USB_FM_VALID BIT(0)
#define P2F_RG_FRCK_EN BIT(8)
#define U3P_REF_CLK 26 /* MHZ */
#define U3P_SLEW_RATE_COEF 28
#define U3P_SR_COEF_DIVISOR 1000
#define U3P_FM_DET_CYCLE_CNT 1024
/* SATA register setting */
#define PHYD_CTRL_SIGNAL_MODE4 0x1c
/* CDR Charge Pump P-path current adjustment */
#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20)
#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20)
#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8)
#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8)
#define PHYD_DESIGN_OPTION2 0x24
/* Symbol lock count selection */
#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4)
#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4)
#define PHYD_DESIGN_OPTION9 0x40
/* COMWAK GAP width window */
#define RG_TG_MAX_MSK GENMASK(20, 16)
#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16)
/* COMINIT GAP width window */
#define RG_T2_MAX_MSK GENMASK(13, 8)
#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8)
/* COMWAK GAP width window */
#define RG_TG_MIN_MSK GENMASK(7, 5)
#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5)
/* COMINIT GAP width window */
#define RG_T2_MIN_MSK GENMASK(4, 0)
#define RG_T2_MIN_VAL(x) (0x1f & (x))
#define ANA_RG_CTRL_SIGNAL1 0x4c
/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */
#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8)
#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL4 0x58
#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20)
#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20)
/* Loop filter R1 resistance adjustment for Gen1 speed */
#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8)
#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL6 0x60
/* I-path capacitance adjustment for Gen1 */
#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24)
#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24)
#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0)
#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x))
#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c
/* RX Gen1 LEQ tuning step */
#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8)
#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8)
#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8
#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16)
#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16)
#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
#define PHY_MODE_BC11_SW_SET 1
#define PHY_MODE_BC11_SW_CLR 2
/* PHY switch between pcie/usb3/sgmii/sata */
#define USB_PHY_SWITCH_CTRL 0x0
#define RG_PHY_SW_TYPE GENMASK(3, 0)
#define RG_PHY_SW_PCIE 0x0
#define RG_PHY_SW_USB3 0x1
#define RG_PHY_SW_SGMII 0x2
#define RG_PHY_SW_SATA 0x3
#define TPHY_CLKS_CNT 2
#define RUN_ONCE_PHY_TYPE_SATA BIT(1)
#define RUN_ONCE_PHY_TYPE_PCIE BIT(2)
#define RUN_ONCE_PHY_TYPE_USB2 BIT(3)
#define RUN_ONCE_PHY_TYPE_USB3 BIT(4)
enum mtk_phy_version {
MTK_PHY_V1 = 1,
MTK_PHY_V2,
MTK_PHY_V3,
};
struct mtk_phy_pdata {
/* avoid RX sensitivity level degradation only for mt8173 */
bool avoid_rx_sen_degradation;
/*
* workaround only for mt8195, HW fix it for others of V3,
* u2phy should use integer mode instead of fractional mode of
* 48M PLL, fix it by switching PLL to 26M from default 48M
*/
bool sw_pll_48m_to_26m;
/*
* Some SoCs (e.g. mt8195) drop a bit when use auto load efuse,
* support sw way, also support it for v2/v3 optionally.
*/
bool sw_efuse_supported;
enum mtk_phy_version version;
};
struct u2phy_banks {
void __iomem *misc;
void __iomem *fmreg;
void __iomem *com;
};
struct u3phy_banks {
void __iomem *spllc;
void __iomem *chip;
void __iomem *phyd; /* include u3phyd_bank2 */
void __iomem *phya; /* include u3phya_da */
};
struct mtk_phy_instance {
struct phy *phy;
void __iomem *port_base;
union {
struct u2phy_banks u2_banks;
struct u3phy_banks u3_banks;
};
struct clk_bulk_data clks[TPHY_CLKS_CNT];
u32 index;
u32 type;
struct regmap *type_sw;
u32 type_sw_reg;
u32 type_sw_index;
bool efuse_alv_en;
u32 efuse_autoloadvalid;
u32 efuse_autoload_dis;
u32 efuse_sw_en;
u32 efuse_intr;
u32 efuse_tx_imp;
u32 efuse_rx_imp;
int eye_src;
int eye_vrt;
int eye_term;
int intr;
int discth;
int rev6;
bool bc12_en;
bool eye_src_en;
bool eye_vrt_en;
bool eye_term_en;
bool intr_en;
bool discth_en;
bool rev6_en;
};
struct mtk_tphy {
struct device *dev;
void __iomem *sif_base; /* only shared sif */
const struct mtk_phy_pdata *pdata;
struct mtk_phy_instance **phys;
int nphys;
int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */
int src_coef; /* coefficient for slew rate calibrate */
u32 run_once;
#ifdef CONFIG_DEBUG_FS
char cmd_buf[1024];
struct dentry *debugfs_root;
#endif
};
struct tphy_usbreg_set {
unsigned int offset;
const char *name;
unsigned int width;
const char *comment;
};
static struct tphy_usbreg_set mtk_usb20phy_v2[] = {
{ 0x0000, "MISC_REG0", 32, NULL }, /* SIFSLV Miscellaneous Control0 */
{ 0x0004, "MISC_REG1", 32, NULL }, /* SIFSLV Miscellaneous Control1 */
{ 0x0008, "MISC_REG2", 32, NULL }, /* SIFSLV Miscellaneous Control2 */
{ 0x000C, "MISC_REG3", 32, NULL }, /* SIFSLV Miscellaneous Control3 */
{ 0x0010, "MISC_REG4", 32, NULL }, /* SIFSLV Miscellaneous Control4 */
{ 0x0014, "MISC_REG5", 32, NULL }, /* SIFSLV Miscellaneous Control5 */
{ 0x0020, "MISC_RGS0", 32, NULL }, /* SIFSLV Miscellaneous Status0 */
{ 0x0024, "MISC_RGS1", 32, NULL }, /* SIFSLV Miscellaneous Status1 */
{ 0x0100, "FMCR0", 32, NULL }, /* Frequency Meter Control0 */
{ 0x0104, "FMCR1", 32, NULL }, /* Frequency Meter Control1 */
{ 0x0108, "FMCR2", 32, NULL }, /* Frequency Meter Control2 */
{ 0x010C, "FMMONR0", 32, NULL }, /* Frequency Meter Monitor0 */
{ 0x0110, "FMMONR1", 32, NULL }, /* Frequency Meter Monitor1 */
{ 0x0300, "USBPHYACR0", 32, NULL }, /* U2PHYA Common0 */
{ 0x0304, "USBPHYACR1", 32, NULL }, /* U2PHYA Common1 */
{ 0x0308, "USBPHYACR2", 32, NULL }, /* U2PHYA Common2 */
{ 0x0310, "USBPHYACR4", 32, NULL }, /* U2PHYA Common4 */
{ 0x0314, "USBPHYACR5", 32, NULL }, /* U2PHYA Common5 */
{ 0x0318, "USBPHYACR6", 32, NULL }, /* U2PHYA Common6 */
{ 0x031C, "U2PHYACR3", 32, NULL }, /* U2PHYA Control3 */
{ 0x0320, "U2PHYACR4", 32, NULL }, /* U2PHYA Control4 */
{ 0x0324, "U2PHYAMON0", 32, NULL }, /* U2PHYA Monitor0 */
{ 0x0360, "U2PHYDCR0", 32, NULL }, /* U2PHYD Control0 */
{ 0x0364, "U2PHYDCR1", 32, NULL }, /* U2PHYD Control1 */
{ 0x0368, "U2PHYDTM0", 32, NULL }, /* U2PHYD Control UTMI0 */
{ 0x036C, "U2PHYDTM1", 32, NULL }, /* U2PHYD Control UTMI1 */
{ 0x0370, "U2PHYDMON0", 32, NULL }, /* U2PHYD Monitor0 */
{ 0x0374, "U2PHYDMON1", 32, NULL }, /* U2PHYD Monitor1 */
{ 0x0378, "U2PHYDMON2", 32, NULL }, /* U2PHYD Monitor2 */
{ 0x037C, "U2PHYDMON3", 32, NULL }, /* U2PHYD Monitor3 */
{ 0x0380, "U2PHYBC12C", 32, NULL }, /* U2PHYD BC12 Control */
{ 0x0384, "U2PHYBC12C1", 32, NULL },/* U2PHYD BC12 Control1 */
{ 0x0388, "U2PHYDFUN", 32, NULL }, /* U2PHYD Function */
{ 0x03E0, "REGFPPC", 32, NULL }, /* USB Feature */
{ 0x03F0, "VERSIONC", 32, NULL }, /* USB Regfile version */
{ 0x03FC, "REGFCOM", 32, NULL }, /* USB Common */
{ 0, NULL, 0, NULL}
};
static struct tphy_usbreg_set mtk_usb30phy_v2[] = {
{ 0x0700, "SYSPLL_0", 32, NULL }, /* SYSPLL Control 0 */
{ 0x0704, "SYSPLL_1", 32, NULL }, /* SYSPLL Control 1 */
{ 0x0708, "SYSPLL_2", 32, NULL }, /* SYSPLL Control 2 */
{ 0x070C, "SYSPLL_SDM", 32, NULL },/* SYSPLL Control 3 for SDM */
{ 0x0710, "XTALCTL_1", 32, NULL }, /* XTALCTL Control 1 */
{ 0x0714, "XTALCTL_2", 32, NULL }, /* XTALCTL Control 2 */
{ 0x0718, "XTALCTL3", 32, NULL }, /* XTALCTL Control 2 */
{ 0x0800, "GPIO_CTLA", 32, NULL }, /* A60802 Chip PAD control */
{ 0x0804, "GPIO_CTLB", 32, NULL }, /* A60802 Chip PAD control */
{ 0x0808, "GPIO_CTLC", 32, NULL }, /* A60802 Chip PAD control */
{ 0x080C, "GPIO_CTLD", 32, NULL }, /* A60802 Chip Reserved */
{ 0x0810, "GPIO_CTLE", 32, NULL }, /* A60802 Chip Reserved */
{ 0x0900, "PHYD_MIX0", 32, NULL }, /* PHYD Mix 0 */
{ 0x0904, "PHYD_MIX1", 32, NULL }, /* PHYD Mix 1 */
{ 0x0908, "PHYD_LFPS0", 32, NULL },/* PHYD LFPS 0 */
{ 0x090C, "PHYD_LFPS1", 32, NULL },/* PHYD LFPS 1 */
{ 0x0910, "PHYD_IMPCAL0", 32, NULL }, /* PHYD Impedance Calibration0 */
{ 0x0914, "PHYD_IMPCAL1", 32, NULL }, /* PHYD Impedance Calibration1 */
{ 0x0918, "PHYD_TXPLL0", 32, NULL }, /* PHYD Tx PLL 0 */
{ 0x091C, "PHYD_TXPLL1", 32, NULL }, /* PHYD Tx PLL 1 */
{ 0x0920, "PHYD_TXPLL2", 32, NULL }, /* PHYD Tx PLL 2 */
{ 0x0924, "PHYD_FL0", 32, NULL }, /* PHYD Frequency Lock Detection*/
{ 0x0928, "PHYD_MIX2", 32, NULL }, /* PHYD Mix 2 */
{ 0x092C, "PHYD_RX0", 32, NULL }, /* PHYD Rx */
{ 0x0930, "PHYD_T2RLB", 32, NULL }, /* PHYD T2R Loopback */
{ 0x0934, "PHYD_CPPAT", 32, NULL }, /* PHYD CP pattern gen */
{ 0x0938, "PHYD_MIX3", 32, NULL }, /* PHYD Mix 3 */
{ 0x093C, "PHYD_EBUFCTL", 32, NULL },/* PHYD Ebuf control */
{ 0x0940, "PHYD_PIPE0", 32, NULL }, /* PHYD PIPE control 0 */
{ 0x0944, "PHYD_PIPE1", 32, NULL }, /* PHYD PIPE control 1 */
{ 0x0948, "PHYD_MIX4", 32, NULL }, /* PHYD Mix 4 */
{ 0x094C, "PHYD_CKGEN0", 32, NULL }, /* PHYD CKGEN control 0 */
{ 0x0950, "PHYD_MIX5", 32, NULL },
{ 0x0954, "PHYD_RESERVED", 32, NULL }, /* PHYD Reserved */
{ 0x0958, "PHYD_CDR0", 32, NULL }, /* PHYD CDR control 0 */
{ 0x095C, "PHYD_CDR1", 32, NULL }, /* PHYD CDR control 1 */
{ 0x0960, "PHYD_PLL_0", 32, NULL }, /* PHYD PLL control 0 */
{ 0x0964, "PHYD_PLL_1", 32, NULL }, /* PHYD PLL control 1 */
{ 0x0968, "PHYD_BCN_DET_1", 32, NULL }, /* PHYD BCN DET 1 */
{ 0x096C, "PHYD_BCN_DET_2", 32, NULL }, /* PHYD BCN DET 2 */
{ 0x0970, "EQ0", 32, NULL }, /* PHYA EQ 0 register */
{ 0x0974, "EQ1", 32, NULL }, /* PHYA EQ 1 register */
{ 0x0978, "EQ2", 32, NULL }, /* PHYA EQ 2 register */
{ 0x097C, "EQ3", 32, NULL }, /* PHYA EQ 3 register */
{ 0x0980, "EQ_EYE0", 32, NULL }, /* PHYA EYE 0 register */
{ 0x0984, "EQ_EYE1", 32, NULL }, /* PHYA EYE 1 register */
{ 0x0988, "EQ_EYE2", 32, NULL }, /* PHYA EYE 2 register */
{ 0x098C, "EQ_DFE0", 32, NULL },
{ 0x0990, "EQ_DFE1", 32, NULL },
{ 0x0994, "EQ_DFE2", 32, NULL },
{ 0x0998, "EQ_DFE3", 32, NULL },
{ 0x099C, "EQ_DFE4", 32, NULL },
{ 0x09A0, "PHYD_MON0", 32, NULL }, /* PHYD Monitor 0 */
{ 0x09A4, "PHYD_MON1", 32, NULL }, /* PHYD Monitor 1 */
{ 0x09A8, "PHYD_MON2", 32, NULL }, /* PHYD Monitor 2 */
{ 0x09AC, "PHYD_MON3", 32, NULL }, /* PHYD Monitor 3 */
{ 0x09B0, "PHYD_MON4", 32, NULL }, /* PHYD Monitor 4 */
{ 0x09B4, "PHYD_MON5", 32, NULL }, /* PHYD Monitor 5 */
{ 0x09B8, "PHYD_MON6", 32, NULL }, /* PHYD Monitor 6 */
{ 0x0A00, "B2_PHYD_TOP1", 32, NULL }, /* Bank2 PHYD TOP1 */
{ 0x0A04, "B2_PHYD_TOP2", 32, NULL }, /* Bank2 PHYD TOP2 */
{ 0x0A08, "B2_PHYD_TOP3", 32, NULL }, /* Bank2 PHYD TOP3 */
{ 0x0A0C, "B2_PHYD_TOP4", 32, NULL }, /* Bank2 PHYD TOP4 */
{ 0x0A10, "B2_PHYD_TOP5", 32, NULL }, /* Bank2 PHYD TOP5 */
{ 0x0A14, "B2_PHYD_TOP6", 32, NULL }, /* Bank2 PHYD TOP6 */
{ 0x0A18, "B2_PHYD_TOP7", 32, NULL }, /* Bank2 PHYD TOP7 */
{ 0x0A1C, "B2_PHYD_P_SIGDET1", 32, NULL }, /* PHYD_P_SIGDET1 */
{ 0x0A20, "B2_PHYD_P_SIGDET2", 32, NULL }, /* PHYD_P_SIGDET2 */
{ 0x0A24, "B2_PHYD_P_SIGDET_CAL1 ", 32, NULL }, /* PHYD_P_SIGDET_CAL1 */
{ 0x0A28, "B2_PHYD_RXDET1", 32, NULL }, /* Bank2 PHYD_RXDET1 */
{ 0x0A2C, "B2_PHYD_RXDET2", 32, NULL }, /* Bank2 PHYD_RXDET2 */
{ 0x0A30, "B2_PHYD_MISC0", 32, NULL }, /* B2_PHYD_MISC0 */
{ 0x0A34, "B2_PHYD_MISC2", 32, NULL }, /* B2_PHYD_MISC2 */
{ 0x0A38, "B2_PHYD_MISC3", 32, NULL }, /* B2_PHYD_MISC3 */
{ 0x0A3C, "B2_PHYD_L1SS", 32, NULL }, /* B2_PHYD_L1SS */
{ 0x0A40, "B2_ROSC_0", 32, NULL }, /* B2_ROSC_0 */
{ 0x0A44, "B2_ROSC_1", 32, NULL }, /* B2_ROSC_1 */
{ 0x0A48, "B2_ROSC_2", 32, NULL }, /* B2_ROSC_2 */
{ 0x0A4C, "B2_ROSC_3", 32, NULL }, /* B2_ROSC_3 */
{ 0x0A50, "B2_ROSC_4", 32, NULL }, /* B2_ROSC_4 */
{ 0x0A54, "B2_ROSC_5", 32, NULL }, /* B2_ROSC_5 */
{ 0x0A58, "B2_ROSC_6", 32, NULL }, /* B2_ROSC_6 */
{ 0x0A5C, "B2_ROSC_7", 32, NULL }, /* B2_ROSC_7 */
{ 0x0A60, "B2_ROSC_8", 32, NULL }, /* B2_ROSC_8 */
{ 0x0A64, "B2_ROSC_9", 32, NULL }, /* B2_ROSC_9 */
{ 0x0A68, "B2_ROSC_A", 32, NULL }, /* B2_ROSC_A */
{ 0x0A70, "B2_2step_sigdet", 32, NULL }, /* B2_2step_sigdet */
{ 0x0A74, "B2_2step_sigdet_1", 32, NULL }, /* B2_2step_sigdet_1 */
{ 0x0AE0, "PHYD_VERSION", 32, NULL }, /* PHYD_VERSION */
{ 0x0AE4, "PHYD_MODEL", 32, NULL }, /* PHYD_MODEL */
{ 0x0B00, "reg0", 32, NULL },
{ 0x0B04, "reg1", 32, NULL },
{ 0x0B08, "reg2", 32, NULL },
{ 0x0B0C, "reg3", 32, NULL },
{ 0x0B10, "reg4", 32, NULL },
{ 0x0B14, "reg5", 32, NULL },
{ 0x0B18, "reg6", 32, NULL },
{ 0x0B1C, "reg7", 32, NULL },
{ 0x0B20, "reg8", 32, NULL },
{ 0x0B24, "reg9", 32, NULL },
{ 0x0B28, "regA", 32, NULL },
{ 0x0B2C, "regB", 32, NULL },
{ 0x0B30, "regC", 32, NULL },
{ 0x0B34, "regD", 32, NULL },
{ 0x0B38, "regF", 32, NULL },
{ 0x0C00, "reg0", 32, NULL }, /* DA__CDR_REFCK_SEL */
{ 0x0C04, "reg1", 32, NULL }, /* DA_PCIE_MODE */
{ 0x0C08, "reg4", 32, NULL }, /* DA__PLL_KBAND_PREDIV */
{ 0x0C0C, "reg5", 32, NULL }, /* DA__PLL_IC */
{ 0x0C10, "reg6", 32, NULL }, /* DA__PLL_IR */
{ 0x0C14, "reg7", 32, NULL }, /* DA__PLL_BP */
{ 0x0C18, "reg8", 32, NULL }, /* DA__PLL_FBKSEL */
{ 0x0C1C, "reg9", 32, NULL }, /* DA__PLL_FBKDIV */
{ 0x0C20, "reg10", 32, NULL },
{ 0x0C38, "reg19", 32, NULL },/* DA__PLL_SSC_DELTA1 */
{ 0x0C3C, "reg20", 32, NULL },
{ 0x0C40, "reg21", 32, NULL },
{ 0x0C44, "reg23", 32, NULL },
{ 0x0C48, "reg25", 32, NULL },
{ 0x0C4C, "reg26", 32, NULL }, /* DA__PLL_REFCKDIV */
{ 0x0C50, "reg28", 32, NULL }, /* DA__CDR_BPA */
{ 0x0C54, "reg29", 32, NULL }, /* DA__CDR_BPB */
{ 0x0C58, "reg30", 32, NULL }, /* DA__CDR_BR */
{ 0x0C5C, "reg31", 32, NULL }, /* DA__CDR_FBDIV */
{ 0x0C60, "reg32", 32, NULL },
{ 0x0C64, "reg33", 32, NULL }, /* DA__EQ_RSTEP2 */
{ 0x0C68, "reg34", 32, NULL }, /* DA__PLL_BC */
{ 0x0C6C, "reg35", 32, NULL }, /* DA__PLL_BR */
{ 0x0C70, "reg36", 32, NULL }, /* DA__PLL_BP2 */
{ 0x0C74, "reg37", 32, NULL },
{ 0, NULL, 0, NULL}
};
static inline unsigned int uffs(unsigned int x)
{
unsigned int r = 1;
if (!x)
return 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
#define IO_SET_FIELD(reg, field, val) \
do { \
unsigned int sb = uffs((unsigned int)field); \
unsigned int tv = readl(reg); \
if (sb) { \
tv &= ~(field); \
tv |= ((val) << (sb - 1)); \
writel(tv, reg); \
} \
} while (0)
#define IO_GET_FIELD(reg, field, val) \
do { \
unsigned int sb = uffs((unsigned int)field); \
unsigned int tv = readl(reg); \
if (sb) { \
val = ((tv & (field)) >> (sb - 1)); \
} else \
val = tv; \
} while (0)
static void register_set_field(void __iomem *address, unsigned int start_bit,
unsigned int len, unsigned int value)
{
unsigned long field;
if (start_bit > 31 || len > 31 || (start_bit + len > 31))
pr_info("[debug] Invalid Register field range or length\n");
else {
field = ((1 << len) - 1) << start_bit;
value &= (1 << len) - 1;
pr_info("[debug]+0x%p (0x%x)\n", address, readl(address));
IO_SET_FIELD(address, field, value);
pr_info("[debug]-0x%p (0x%x)\n", address, readl(address));
}
}
static void register_get_field(void __iomem *address, unsigned int start_bit,
unsigned int len, unsigned int value)
{
unsigned long field;
if (start_bit > 31 || len > 31 || (start_bit + len > 31))
pr_info("[debug] Invalid reg field range or length\n");
else {
field = ((1 << len) - 1) << start_bit;
IO_GET_FIELD(address, field, value);
pr_info("[debug]0x%p start_bit(%d)len(%d)(0x%x)\n",
address, start_bit, len, value);
}
}
static void tphy_print_phy_regs(struct seq_file *s, int index)
{
int i;
unsigned int temp;
struct mtk_tphy *tphy = s->private;
struct mtk_phy_instance *instance = tphy->phys[index];
struct u2phy_banks *u2_banks = &instance->u2_banks;
struct u3phy_banks *u3_banks = &instance->u3_banks;
struct tphy_usbreg_set *usbxxreg;
void __iomem *pbase = instance->port_base;
void __iomem *misc;
void __iomem *fmreg;
void __iomem *com;
void __iomem *spllc;
void __iomem *chip;
void __iomem *phyd;
void __iomem *phya;
if (instance->type == PHY_TYPE_USB2) {
com = u2_banks->com;
fmreg = u2_banks->fmreg;
misc = u2_banks->misc;
seq_printf(s, "\nMTK USB2.0 PHY%i:MTK_PHY_%s\n", index,
(tphy->pdata->version == MTK_PHY_V1) ? "V1" : "V2");
seq_printf(s, " com : 0x%p\n", com);
seq_printf(s, " fmreg: 0x%p\n", fmreg);
seq_printf(s, " misc : 0x%p\n", misc);
if (PTR_ERR(com)) {
temp = readl(com + U3P_USBPHYACR0);
seq_printf(s, " 0x%p: U3P_USBPHYACR0 = 0x%08X\n",
com + U3P_USBPHYACR0, temp);
temp = readl(com + U3P_USBPHYACR2);
seq_printf(s, " 0x%p: U3P_USBPHYACR2 = 0x%08X\n",
com + U3P_USBPHYACR2, temp);
temp = readl(com + U3P_USBPHYACR5);
seq_printf(s, " 0x%p: U3P_USBPHYACR5 = 0x%08X\n",
com + U3P_USBPHYACR5, temp);
temp = readl(com + U3P_USBPHYACR6);
seq_printf(s, " 0x%p: U3P_USBPHYACR6 = 0x%08X\n",
com + U3P_USBPHYACR6, temp);
temp = readl(com + U3P_U2PHYACR4);
seq_printf(s, " 0x%p: U3P_U2PHYACR4 = 0x%08X\n",
com + U3P_U2PHYACR4, temp);
temp = readl(com + U3D_U2PHYDCR0);
seq_printf(s, " 0x%p: U3D_U2PHYDCR0 = 0x%08X\n",
com + U3D_U2PHYDCR0, temp);
temp = readl(com + U3P_U2PHYDTM0);
seq_printf(s, " 0x%p: U3P_U2PHYDTM0 = 0x%08X\n",
com + U3P_U2PHYDTM0, temp);
temp = readl(com + U3P_U2PHYDTM1);
seq_printf(s, " 0x%p: U3P_U2PHYDTM1 = 0x%08X\n",
com + U3P_U2PHYDTM1, temp);
temp = readl(com + U3P_U3_PHYA_REG0);
seq_printf(s, " 0x%p: U3P_U3_PHYA_REG0 = 0x%08X\n",
com + U3P_U3_PHYA_REG0, temp);
temp = readl(com + U3P_U3_PHYA_REG6);
seq_printf(s, " 0x%p: U3P_U3_PHYA_REG6 = 0x%08X\n",
com + U3P_U3_PHYA_REG6, temp);
temp = readl(com + U3P_U3_PHYA_REG9);
seq_printf(s, " 0x%p: U3P_U3_PHYA_REG9 = 0x%08X\n",
com + U3P_U3_PHYA_REG9, temp);
}
if (PTR_ERR(fmreg)) {
seq_printf(s, "\nMTK USB3.0 PHY%i[fmreg:0x%p]\n",
index, fmreg);
temp = readl(fmreg + U3P_U2FREQ_FMCR0);
seq_printf(s, " 0x%p: U3P_U2FREQ_FMCR0 = 0x%08X\n",
fmreg + U3P_U2FREQ_FMCR0, temp);
temp = readl(fmreg + U3P_U2FREQ_VALUE);
seq_printf(s, " 0x%p: U3P_U2FREQ_VALUE = 0x%08X\n",
fmreg + U3P_U2FREQ_VALUE, temp);
temp = readl(fmreg + U3P_U2FREQ_FMMONR1);
seq_printf(s, " 0x%p: U3P_U2FREQ_FMMONR1= 0x%08X\n",
fmreg + U3P_U2FREQ_FMMONR1, temp);
}
if (PTR_ERR(pbase) && (tphy->pdata->version == MTK_PHY_V2)) {
seq_printf(s, "\nMTK USB2.0 Port%i[port_base: %p]\n",
index, pbase);
for (i = 0; i < ARRAY_SIZE(mtk_usb20phy_v2); i++) {
usbxxreg = &mtk_usb20phy_v2[i];
switch (usbxxreg->width) {
case 8:
seq_printf(s, "%-12s(0x%p): 0x%02X\n",
usbxxreg->name, pbase + usbxxreg->offset,
readb(pbase + usbxxreg->offset));
break;
case 16:
seq_printf(s, "%-12s(0x%p): 0x%04X\n",
usbxxreg->name,
pbase + usbxxreg->offset,
readw(pbase + usbxxreg->offset));
break;
case 32:
seq_printf(s, "%-12s(0x%p): 0x%08X\n",
usbxxreg->name,
pbase + usbxxreg->offset,
readl(pbase + usbxxreg->offset));
break;
}
}
}
} else if (instance->type == PHY_TYPE_USB3) {
spllc = u3_banks->spllc;
chip = u3_banks->chip;
phyd = u3_banks->phyd;
phya = u3_banks->phya;
seq_printf(s, "\nMTK USB3.0 PHY%i:MTK_PHY_%s\n", index,
(tphy->pdata->version == MTK_PHY_V1) ? "V1" : "V2");
seq_printf(s, " spllc: 0x%p\n", spllc);
seq_printf(s, " chip : 0x%p\n", chip);
seq_printf(s, " phyd : 0x%p\n", phyd);
seq_printf(s, " phya : 0x%p\n", phya);
if (PTR_ERR(spllc)) {
/* gating PCIe Analog XTAL clock */
temp = readl(u3_banks->spllc + U3P_SPLLC_XTALCTL3);
seq_printf(s,
" 0x%p: U3P_SPLLC_XTALCTL3 = 0x%08X\n",
spllc + U3P_SPLLC_XTALCTL3, temp);
}
if (PTR_ERR(chip)) {
temp = readl(u3_banks->chip + U3P_U3_CHIP_GPIO_CTLD);
seq_printf(s,
" 0x%p: U3P_U3_CHIP_GPIO_CTLD = 0x%08X\n",
chip + U3P_U3_CHIP_GPIO_CTLD, temp);
temp = readl(u3_banks->chip + U3P_U3_CHIP_GPIO_CTLE);
seq_printf(s,
" 0x%p: U3P_U3_CHIP_GPIO_CTLE = 0x%08X\n",
chip + U3P_U3_CHIP_GPIO_CTLE, temp);
}
if (PTR_ERR(phyd)) {
/* switch to USB 3.0 phy */
temp = readl(u3_banks->phyd + U3P_U3_PHYD_TOP1);
seq_printf(s, " 0x%p: U3P_U3_PHYD_TOP1 = 0x%08X\n",
phyd + U3P_U3_PHYD_TOP1, temp);
temp = readl(u3_banks->phyd + U3P_U3_PHYD_CDR1);
seq_printf(s, " 0x%p: U3P_U3_PHYD_CDR1 = 0x%08X\n",
phyd + U3P_U3_PHYD_CDR1, temp);
temp = readl(u3_banks->phyd + U3P_U3_PHYD_LFPS1);
seq_printf(s, " 0x%p: U3P_U3_PHYD_LFPS1 = 0x%08X\n",
phyd + U3P_U3_CHIP_GPIO_CTLE, temp);
temp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1);
seq_printf(s, " 0x%p: U3P_U3_PHYD_RXDET1 = 0x%08X\n",
phyd + U3P_U3_PHYD_RXDET1, temp);
temp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2);
seq_printf(s, " 0x%p: U3P_U3_PHYD_RXDET2 = 0x%08X\n",
phyd + U3P_U3_PHYD_RXDET2, temp);
}
if (PTR_ERR(phya)) {
/* gating XSQ */
temp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0);
seq_printf(s, " 0x%p: U3P_U3_PHYA_DA_REG0 = 0x%08X\n",
phya + U3P_U3_PHYA_DA_REG0, temp);
temp = readl(u3_banks->phya + U3P_U3_PHYA_REG9);
seq_printf(s, " 0x%p: U3P_U3_PHYA_REG9 = 0x%08X\n",
phya + U3P_U3_PHYA_REG9, temp);
temp = readl(u3_banks->phya + U3P_U3_PHYA_REG6);
seq_printf(s, " 0x%p: U3P_U3_PHYA_REG6 = 0x%08X\n",
phya + U3P_U3_PHYA_REG6, temp);
}
if (PTR_ERR(pbase) && (tphy->pdata->version == MTK_PHY_V2)) {
seq_printf(s, "\nMTK USB3.0 Port%i[port_base: %p]\n",
index, pbase);
pbase -= 0x700;
for (i = 0; i < ARRAY_SIZE(mtk_usb30phy_v2); i++) {
usbxxreg = &mtk_usb30phy_v2[i];
switch (usbxxreg->width) {
case 8:
seq_printf(s, "%-12s(0x%p): 0x%02X\n",
usbxxreg->name,
pbase + usbxxreg->offset,
readb(pbase + usbxxreg->offset));
break;
case 16:
seq_printf(s, "%-12s(0x%p): 0x%04X\n",
usbxxreg->name,
pbase + usbxxreg->offset,
readw(pbase + usbxxreg->offset));
break;
case 32:
seq_printf(s, "%-12s(0x%p): 0x%08X\n",
usbxxreg->name,
pbase + usbxxreg->offset,
readl(pbase + usbxxreg->offset));
break;
}
}
}
}
}
static int tphy_phy_regdump_show(struct seq_file *m, void *unused)
{
int i = 0;
struct mtk_tphy *tphy = m->private;
seq_printf(m, "\n===tphy_print_phy_regs(%i) help===\n", tphy->nphys);
for (i = 0; i < tphy->nphys; i++)
tphy_print_phy_regs(m, i);
return 0;
}
static int tphy_phy_regdump(struct inode *inode, struct file *file)
{
return single_open(file, tphy_phy_regdump_show, inode->i_private);
}
static const struct file_operations mtk_tphy_regdump_fops = {
.open = tphy_phy_regdump,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int tphy_phy_debug_proc_show(struct seq_file *m, void *v)
{
seq_puts(m, "\n===tphy_phy_debug help===\n");
seq_puts(m, "\n REGISTER control usage:\n");
seq_puts(m, " write : echo 1 0 [addr] [value] >debug\n");
seq_puts(m, " read : echo 1 1 [addr] > debug\n");
seq_puts(m,
" write mask: echo 1 2 [addr] [bit] [len] [val] >debug\n");
seq_puts(m, " read mask: echo 1 3 [addr] [bit] [len] >debug\n");
seq_puts(m, " dump : echo 1 4 > debug\n");
seq_puts(m, "=========================================\n\n");
return 0;
}
static ssize_t tphy_phy_debug_proc_write(struct file *file,
const char *buf, size_t count, loff_t *data)
{
int ret;
int cmd, p1, p3, p4, p5;
unsigned int reg_value;
int sscanf_num;
struct seq_file *s = file->private_data;
struct mtk_tphy *tphy = s->private;
void __iomem *iomem = NULL;
struct mtk_phy_instance *instance;
#ifdef CONFIG_64BIT
u64 p2, memio;
#else
u32 p2, memio;
#endif
p1 = p2 = p3 = p4 = p5 = -1;
if (count == 0)
return -1;
if (count > 255)
count = 255;
ret = copy_from_user(tphy->cmd_buf, buf, count);
if (ret < 0)
return -1;
tphy->cmd_buf[count] = '\0';
pr_info("[debug]debug received:%s\n", tphy->cmd_buf);
#ifdef CONFIG_64BIT
sscanf_num = sscanf(tphy->cmd_buf, "%x %x %llx %x %x %x",
&cmd, &p1, &p2, &p3, &p4, &p5);
#else
sscanf_num = sscanf(tphy->cmd_buf, "%x %x %x %x %x %x",
&cmd, &p1, &p2, &p3, &p4, &p5);
#endif
if (sscanf_num < 1)
return count;
if (cmd == 0)
pr_info("[debug] zone <0x%.8x> is not exist yet\n", p1);
else if (cmd == 1) {
iomem += p2;
#ifdef CONFIG_64BIT
instance = tphy->phys[0];
memio = (u64)instance->port_base;
memio &= ~0x000003FFFULL;
memio ^= p2 & (~0x000003FFFULL);
if (memio) {
pr_debug("[debug] <0x%llx> is not valid range\n", p2);
return -1;
}
#else
instance = tphy->phys[0];
memio = (u32)instance->port_base;
memio &= ~0x000003FFFUL;
memio ^= p2 & (~0x000003FFFUL);
if (memio) {
pr_debug("[debug] <0x%x> is not valid range\n", p2);
return -1;
}
#endif
if (p1 == 0) {
reg_value = p3;
pr_info("[debug][Write]+0x%p (0x%08X)\n",
iomem, readl(iomem));
writel(reg_value, iomem);
pr_info("[debug][Write]-0x%p (0x%08X)\n",
iomem, readl(iomem));
} else if (p1 == 1)
pr_info("[debug][Read]0x%p (0x%08X)\n",
iomem, readl(iomem));
else if (p1 == 2)
register_set_field(iomem, p3, p4, p5);
else if (p1 == 3)
register_get_field(iomem, p3, p4, p5);
else
pr_info("[tphy debug] todo\n");
}
return count;
}
static int tphy_phy_debug_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, tphy_phy_debug_proc_show, inode->i_private);
}
static const struct file_operations mtk_tphy_debug_proc_fops = {
.open = tphy_phy_debug_proc_open,
.write = tphy_phy_debug_proc_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
int tphy_phy_init_debugfs(void *handle)
{
int ret;
struct dentry *file;
struct dentry *root;
struct mtk_tphy *tphy = (struct mtk_tphy *)handle;
root = debugfs_create_dir(dev_driver_string(tphy->dev), NULL);
if (!root) {
ret = -ENOMEM;
goto err0;
}
file = debugfs_create_file("regdump", 0444, root, tphy,
&mtk_tphy_regdump_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
file = debugfs_create_file("debug", 0644, root, tphy,
&mtk_tphy_debug_proc_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
tphy->debugfs_root = root;
return 0;
err1:
debugfs_remove_recursive(root);
err0:
return ret;
}
EXPORT_SYMBOL_GPL(tphy_phy_init_debugfs);
void tphy_phy_exit_debugfs(void *handle)
{
struct mtk_tphy *tphy = (struct mtk_tphy *)handle;
debugfs_remove_recursive(tphy->debugfs_root);
}
EXPORT_SYMBOL_GPL(tphy_phy_exit_debugfs);