diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 08:35:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 08:35:06 -0700 |
commit | ba1dc7f273c73b93e0e1dd9707b239ed69eebd70 (patch) | |
tree | f79ee28c2b88fde1a901619f9b4c72dffeaa2337 /drivers/phy | |
parent | 9e9fb7655ed585da8f468e29221f0ba194a5f613 (diff) | |
parent | 0dc3ad3f859d3a65b335c861ec342d31d91e8bc8 (diff) | |
download | linux-ba1dc7f273c73b93e0e1dd9707b239ed69eebd70.tar.gz linux-ba1dc7f273c73b93e0e1dd9707b239ed69eebd70.tar.bz2 linux-ba1dc7f273c73b93e0e1dd9707b239ed69eebd70.zip |
Merge tag 'char-misc-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc driver updates from Greg KH:
"Here is the big set of char/misc driver changes for 5.15-rc1.
Lots of different driver subsystems are being updated in here,
notably:
- mhi subsystem update
- fpga subsystem update
- coresight/hwtracing subsystem update
- interconnect subsystem update
- nvmem subsystem update
- parport drivers update
- phy subsystem update
- soundwire subsystem update
and there are some other char/misc drivers being updated as well:
- binder driver additions
- new misc drivers
- lkdtm driver updates
- mei driver updates
- sram driver updates
- other minor driver updates.
Note, there are no habanalabs driver updates in this pull request,
that will probably come later before -rc1 is out in a different
request.
All of these have been in linux-next for a while with no reported
problems"
* tag 'char-misc-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits)
Revert "bus: mhi: Add inbound buffers allocation flag"
misc/pvpanic: fix set driver data
VMCI: fix NULL pointer dereference when unmapping queue pair
char: mware: fix returnvar.cocci warnings
parport: remove non-zero check on count
soundwire: cadence: do not extend reset delay
soundwire: intel: conditionally exit clock stop mode on system suspend
soundwire: intel: skip suspend/resume/wake when link was not started
soundwire: intel: fix potential race condition during power down
phy: qcom-qmp: Add support for SM6115 UFS phy
dt-bindings: phy: qcom,qmp: Add SM6115 UFS PHY bindings
phy: qmp: Provide unique clock names for DP clocks
lkdtm: remove IDE_CORE_CP crashpoint
lkdtm: replace SCSI_DISPATCH_CMD with SCSI_QUEUE_RQ
coresight: Replace deprecated CPU-hotplug functions.
Documentation: coresight: Add documentation for CoreSight config
coresight: syscfg: Add initial configfs support
coresight: config: Add preloaded configurations
coresight: etm4x: Add complex configuration handlers to etmv4
coresight: etm-perf: Update to activate selected configuration
...
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/amlogic/phy-meson8b-usb2.c | 8 | ||||
-rw-r--r-- | drivers/phy/cadence/phy-cadence-torrent.c | 2577 | ||||
-rw-r--r-- | drivers/phy/mediatek/phy-mtk-hdmi.c | 7 | ||||
-rw-r--r-- | drivers/phy/mediatek/phy-mtk-mipi-dsi.c | 13 | ||||
-rw-r--r-- | drivers/phy/mediatek/phy-mtk-tphy.c | 224 | ||||
-rw-r--r-- | drivers/phy/mediatek/phy-mtk-ufs.c | 44 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.c | 321 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.h | 18 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-usb-hs.c | 2 | ||||
-rw-r--r-- | drivers/phy/renesas/phy-rcar-gen3-usb2.c | 97 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 4 | ||||
-rw-r--r-- | drivers/phy/samsung/Makefile | 5 | ||||
-rw-r--r-- | drivers/phy/samsung/phy-exynos7-ufs.c (renamed from drivers/phy/samsung/phy-exynos7-ufs.h) | 8 | ||||
-rw-r--r-- | drivers/phy/samsung/phy-exynosautov9-ufs.c | 67 | ||||
-rw-r--r-- | drivers/phy/samsung/phy-samsung-ufs.c | 3 | ||||
-rw-r--r-- | drivers/phy/samsung/phy-samsung-ufs.h | 13 | ||||
-rw-r--r-- | drivers/phy/tegra/xusb.c | 4 | ||||
-rw-r--r-- | drivers/phy/ti/phy-twl4030-usb.c | 15 | ||||
-rw-r--r-- | drivers/phy/xilinx/phy-zynqmp.c | 3 |
19 files changed, 2171 insertions, 1262 deletions
diff --git a/drivers/phy/amlogic/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c index 03c061dd5f0d..cf10bed40528 100644 --- a/drivers/phy/amlogic/phy-meson8b-usb2.c +++ b/drivers/phy/amlogic/phy-meson8b-usb2.c @@ -219,6 +219,10 @@ static int phy_meson8b_usb2_power_off(struct phy *phy) clk_disable_unprepare(priv->clk_usb); clk_disable_unprepare(priv->clk_usb_general); + /* power off the PHY by putting it into reset mode */ + regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, + REG_CTRL_POWER_ON_RESET); + return 0; } @@ -273,8 +277,8 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev) phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops); if (IS_ERR(phy)) { - dev_err(&pdev->dev, "failed to create PHY\n"); - return PTR_ERR(phy); + return dev_err_probe(&pdev->dev, PTR_ERR(phy), + "failed to create PHY\n"); } phy_set_drvdata(phy, priv); diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 0477e7beebbf..415ace64adc5 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -24,13 +24,15 @@ #include <linux/reset.h> #include <linux/regmap.h> -#define REF_CLK_19_2MHz 19200000 -#define REF_CLK_25MHz 25000000 +#define REF_CLK_19_2MHZ 19200000 +#define REF_CLK_25MHZ 25000000 +#define REF_CLK_100MHZ 100000000 #define MAX_NUM_LANES 4 #define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */ #define NUM_SSC_MODE 3 +#define NUM_REF_CLK 3 #define NUM_PHY_TYPE 6 #define POLL_TIMEOUT_US 5000 @@ -49,6 +51,10 @@ #define TORRENT_PHY_PCS_COMMON_OFFSET(block_offset) \ (0xC000 << (block_offset)) +#define TORRENT_PHY_PCS_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ + ((0xD000 << (block_offset)) + \ + (((ln) << 8) << (reg_offset))) + #define TORRENT_PHY_PMA_COMMON_OFFSET(block_offset) \ (0xE000 << (block_offset)) @@ -101,6 +107,7 @@ #define CMN_PLL0_FRACDIVH_M0 0x0092U #define CMN_PLL0_HIGH_THR_M0 0x0093U #define CMN_PLL0_DSM_DIAG_M0 0x0094U +#define CMN_PLL0_DSM_FBH_OVRD_M0 0x0095U #define CMN_PLL0_SS_CTRL1_M0 0x0098U #define CMN_PLL0_SS_CTRL2_M0 0x0099U #define CMN_PLL0_SS_CTRL3_M0 0x009AU @@ -220,6 +227,9 @@ #define PHY_PIPE_USB3_GEN2_POST_CFG0 0x0022U #define PHY_PIPE_USB3_GEN2_POST_CFG1 0x0023U +/* PHY PCS lane registers */ +#define PHY_PCS_ISO_LINK_CTRL 0x000BU + /* PHY PMA common registers */ #define PHY_PMA_CMN_CTRL1 0x0000U #define PHY_PMA_CMN_CTRL2 0x0001U @@ -244,6 +254,9 @@ static const struct reg_field phy_pma_pll_raw_ctrl = static const struct reg_field phy_reset_ctrl = REG_FIELD(PHY_RESET, 8, 8); +static const struct reg_field phy_pcs_iso_link_ctrl_1 = + REG_FIELD(PHY_PCS_ISO_LINK_CTRL, 1, 1); + static const struct reg_field phy_pipe_cmn_ctrl1_0 = REG_FIELD(PHY_PIPE_CMN_CTRL1, 0, 0); #define REFCLK_OUT_NUM_CMN_CONFIG 5 @@ -273,6 +286,12 @@ enum cdns_torrent_phy_type { TYPE_USB, }; +enum cdns_torrent_ref_clk { + CLK_19_2_MHZ, + CLK_25_MHZ, + CLK_100_MHZ +}; + enum cdns_torrent_ssc_mode { NO_SSC, EXTERNAL_SSC, @@ -296,7 +315,7 @@ struct cdns_torrent_phy { struct reset_control *apb_rst; struct device *dev; struct clk *clk; - unsigned long ref_clk_rate; + enum cdns_torrent_ref_clk ref_clk_rate; struct cdns_torrent_inst phys[MAX_NUM_LANES]; int nsubnodes; const struct cdns_torrent_data *init_data; @@ -306,12 +325,14 @@ struct cdns_torrent_phy { struct regmap *regmap_phy_pma_common_cdb; struct regmap *regmap_tx_lane_cdb[MAX_NUM_LANES]; struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES]; + struct regmap *regmap_phy_pcs_lane_cdb[MAX_NUM_LANES]; struct regmap *regmap_dptx_phy_reg; struct regmap_field *phy_pll_cfg; struct regmap_field *phy_pma_cmn_ctrl_1; struct regmap_field *phy_pma_cmn_ctrl_2; struct regmap_field *phy_pma_pll_raw_ctrl; struct regmap_field *phy_reset_ctrl; + struct regmap_field *phy_pcs_iso_link_ctrl_1[MAX_NUM_LANES]; struct clk *clks[CDNS_TORRENT_REFCLK_DRIVER + 1]; struct clk_onecell_data clk_data; }; @@ -333,57 +354,6 @@ struct cdns_torrent_derived_refclk { #define to_cdns_torrent_derived_refclk(_hw) \ container_of(_hw, struct cdns_torrent_derived_refclk, hw) -static int cdns_torrent_phy_init(struct phy *phy); -static int cdns_torrent_dp_init(struct phy *phy); -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes); -static -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy); -static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, - struct cdns_torrent_inst *inst); -static -void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy); -static -void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy, - u32 rate, bool ssc); -static -void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy); -static -void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, - u32 rate, bool ssc); -static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, - unsigned int lane); -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, - u32 rate, u32 num_lanes); -static int cdns_torrent_dp_configure(struct phy *phy, - union phy_configure_opts *opts); -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes, - enum phy_powerstate powerstate); -static int cdns_torrent_phy_on(struct phy *phy); -static int cdns_torrent_phy_off(struct phy *phy); - -static const struct phy_ops cdns_torrent_phy_ops = { - .init = cdns_torrent_phy_init, - .configure = cdns_torrent_dp_configure, - .power_on = cdns_torrent_phy_on, - .power_off = cdns_torrent_phy_off, - .owner = THIS_MODULE, -}; - -static int cdns_torrent_noop_phy_on(struct phy *phy) -{ - /* Give 5ms to 10ms delay for the PIPE clock to be stable */ - usleep_range(5000, 10000); - - return 0; -} - -static const struct phy_ops noop_ops = { - .power_on = cdns_torrent_noop_phy_on, - .owner = THIS_MODULE, -}; - struct cdns_reg_pairs { u32 val; u32 off; @@ -403,12 +373,12 @@ struct cdns_torrent_data { [NUM_SSC_MODE]; struct cdns_torrent_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] [NUM_SSC_MODE]; - struct cdns_torrent_vals *cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] - [NUM_SSC_MODE]; - struct cdns_torrent_vals *tx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] - [NUM_SSC_MODE]; - struct cdns_torrent_vals *rx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] - [NUM_SSC_MODE]; + struct cdns_torrent_vals *cmn_vals[NUM_REF_CLK][NUM_PHY_TYPE] + [NUM_PHY_TYPE][NUM_SSC_MODE]; + struct cdns_torrent_vals *tx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE] + [NUM_PHY_TYPE][NUM_SSC_MODE]; + struct cdns_torrent_vals *rx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE] + [NUM_PHY_TYPE][NUM_SSC_MODE]; }; struct cdns_regmap_cdb_context { @@ -497,6 +467,22 @@ static const struct regmap_config cdns_torrent_common_cdb_config = { .reg_read = cdns_regmap_read, }; +#define TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF(n) \ +{ \ + .name = "torrent_phy_pcs_lane" n "_cdb", \ + .reg_stride = 1, \ + .fast_io = true, \ + .reg_write = cdns_regmap_write, \ + .reg_read = cdns_regmap_read, \ +} + +static const struct regmap_config cdns_torrent_phy_pcs_lane_cdb_config[] = { + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("0"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("1"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("2"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("3"), +}; + static const struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = { .name = "torrent_phy_pcs_cmn_cdb", .reg_stride = 1, @@ -615,6 +601,351 @@ static const struct coefficients vltg_coeff[4][4] = { } }; +static const char *cdns_torrent_get_phy_type(enum cdns_torrent_phy_type phy_type) +{ + switch (phy_type) { + case TYPE_DP: + return "DisplayPort"; + case TYPE_PCIE: + return "PCIe"; + case TYPE_SGMII: + return "SGMII"; + case TYPE_QSGMII: + return "QSGMII"; + case TYPE_USB: + return "USB"; + default: + return "None"; + } +} + +/* + * Set registers responsible for enabling and configuring SSC, with second and + * third register values provided by parameters. + */ +static +void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy, + u32 ctrl2_val, u32 ctrl3_val) +{ + struct regmap *regmap = cdns_phy->regmap_common_cdb; + + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl3_val); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl3_val); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003); +} + +static +void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy, + u32 rate, bool ssc) +{ + struct regmap *regmap = cdns_phy->regmap_common_cdb; + + /* Assumes 19.2 MHz refclock */ + switch (rate) { + /* Setting VCO for 10.8GHz */ + case 2700: + case 5400: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0119); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x4000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00BC); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0012); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0119); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x4000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00BC); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0012); + if (ssc) + cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A, 0x006A); + break; + /* Setting VCO for 9.72GHz */ + case 1620: + case 2430: + case 3240: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01FA); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x4000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0152); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01FA); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x4000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0152); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (ssc) + cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD, 0x0069); + break; + /* Setting VCO for 8.64GHz */ + case 2160: + case 4320: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01C2); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x012C); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01C2); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x012C); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (ssc) + cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536, 0x0069); + break; + /* Setting VCO for 8.1GHz */ + case 8100: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01A5); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xE000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x011A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01A5); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xE000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x011A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (ssc) + cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7, 0x006A); + break; + } + + if (ssc) { + cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E); + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_THR, 0x0005); + cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_THR, 0x0005); + } else { + cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260); + cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260); + /* Set reset register values to disable SSC */ + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_THR, 0x0003); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_THR, 0x0003); + } + + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x0099); + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x0099); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x0099); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x0099); +} + +/* + * Set registers responsible for enabling and configuring SSC, with second + * register value provided by a parameter. + */ +static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy, + u32 ctrl2_val) +{ + struct regmap *regmap = cdns_phy->regmap_common_cdb; + + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x007F); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x007F); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003); +} + +static +void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, + u32 rate, bool ssc) +{ + struct regmap *regmap = cdns_phy->regmap_common_cdb; + + /* Assumes 25 MHz refclock */ + switch (rate) { + /* Setting VCO for 10.8GHz */ + case 2700: + case 5400: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01B0); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0120); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01B0); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0120); + if (ssc) + cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423); + break; + /* Setting VCO for 9.72GHz */ + case 1620: + case 2430: + case 3240: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0184); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xCCCD); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0104); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0184); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xCCCD); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0104); + if (ssc) + cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9); + break; + /* Setting VCO for 8.64GHz */ + case 2160: + case 4320: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0159); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x999A); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00E7); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0159); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x999A); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00E7); + if (ssc) + cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F); + break; + /* Setting VCO for 8.1GHz */ + case 8100: + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0144); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00D8); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0144); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00D8); + if (ssc) + cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A); + break; + } + + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + + if (ssc) { + cdns_torrent_phy_write(regmap, + CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315); + cdns_torrent_phy_write(regmap, + CMN_PLL0_LOCK_PLLCNT_THR, 0x0005); + cdns_torrent_phy_write(regmap, + CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315); + cdns_torrent_phy_write(regmap, + CMN_PLL1_LOCK_PLLCNT_THR, 0x0005); + } else { + cdns_torrent_phy_write(regmap, + CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317); + cdns_torrent_phy_write(regmap, + CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317); + /* Set reset register values to disable SSC */ + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000); + cdns_torrent_phy_write(regmap, + CMN_PLL0_LOCK_PLLCNT_THR, 0x0003); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000); + cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000); + cdns_torrent_phy_write(regmap, + CMN_PLL1_LOCK_PLLCNT_THR, 0x0003); + } + + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x00C7); + cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x00C7); + cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7); +} + +static +void cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(struct cdns_torrent_phy *cdns_phy, + u32 rate, bool ssc) +{ + struct regmap *regmap = cdns_phy->regmap_common_cdb; + + /* Assumes 100 MHz refclock */ + switch (rate) { + /* Setting VCO for 10.8GHz */ + case 2700: + case 5400: + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); + break; + /* Setting VCO for 9.72GHz */ + case 1620: + case 2430: + case 3240: + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + break; + /* Setting VCO for 8.64GHz */ + case 2160: + case 4320: + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + break; + /* Setting VCO for 8.1GHz */ + case 8100: + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + break; + } +} + /* * Enable or disable PLL for selected lanes. */ @@ -669,6 +1000,161 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, return ret; } +static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, + u32 num_lanes, + enum phy_powerstate powerstate) +{ + /* Register value for power state for a single byte. */ + u32 value_part; + u32 value; + u32 mask; + u32 read_val; + u32 ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + switch (powerstate) { + case (POWERSTATE_A0): + value_part = 0x01U; + break; + case (POWERSTATE_A2): + value_part = 0x04U; + break; + default: + /* Powerstate A3 */ + value_part = 0x08U; + break; + } + + /* Select values of registers and mask, depending on enabled + * lane count. + */ + switch (num_lanes) { + /* lane 0 */ + case (1): + value = value_part; + mask = 0x0000003FU; + break; + /* lanes 0-1 */ + case (2): + value = (value_part + | (value_part << 8)); + mask = 0x00003F3FU; + break; + /* lanes 0-3, all */ + default: + value = (value_part + | (value_part << 8) + | (value_part << 16) + | (value_part << 24)); + mask = 0x3F3F3F3FU; + break; + } + + /* Set power state A<n>. */ + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); + /* Wait, until PHY acknowledges power state completion. */ + ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, + read_val, (read_val & mask) == value, 0, + POLL_TIMEOUT_US); + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); + ndelay(100); + + return ret; +} + +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) +{ + unsigned int read_val; + int ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + /* + * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the + * master lane + */ + ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK, + read_val, read_val & 1, + 0, POLL_TIMEOUT_US); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, + "timeout waiting for link PLL clock enable ack\n"); + return ret; + } + + ndelay(100); + + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + POWERSTATE_A2); + if (ret) + return ret; + + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + POWERSTATE_A0); + + return ret; +} + +static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) +{ + unsigned int reg; + int ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, + reg & 1, 0, POLL_TIMEOUT_US); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, + "timeout waiting for PMA common ready\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, + u32 rate, u32 num_lanes) +{ + unsigned int clk_sel_val = 0; + unsigned int hsclk_div_val = 0; + unsigned int i; + + switch (rate) { + case 1620: + clk_sel_val = 0x0f01; + hsclk_div_val = 2; + break; + case 2160: + case 2430: + case 2700: + clk_sel_val = 0x0701; + hsclk_div_val = 1; + break; + case 3240: + clk_sel_val = 0x0b00; + hsclk_div_val = 2; + break; + case 4320: + case 5400: + clk_sel_val = 0x0301; + hsclk_div_val = 0; + break; + case 8100: + clk_sel_val = 0x0200; + hsclk_div_val = 0; + break; + } + + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); + + /* PMA lane configuration to deal with multi-link operation */ + for (i = 0; i < num_lanes; i++) + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i], + XCVR_DIAG_HSCLK_DIV, hsclk_div_val); +} + /* * Perform register operations related to setting link rate, once powerstate is * set and PLL disable request was processed. @@ -676,8 +1162,7 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, struct phy_configure_opts_dp *dp) { - u32 ret; - u32 read_val; + u32 read_val, ret; /* Disable the cmn_pll0_en before re-programming the new data rate. */ regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0); @@ -695,17 +1180,16 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, ndelay(200); /* DP Rate Change - VCO Output settings. */ - if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) { + if (cdns_phy->ref_clk_rate == CLK_19_2_MHZ) /* PMA common configuration 19.2MHz */ - cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate, - dp->ssc); - cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy); - } else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) { + cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, dp->link_rate, dp->ssc); + else if (cdns_phy->ref_clk_rate == CLK_25_MHZ) /* PMA common configuration 25MHz */ - cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate, - dp->ssc); - cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy); - } + cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, dp->link_rate, dp->ssc); + else if (cdns_phy->ref_clk_rate == CLK_100_MHZ) + /* PMA common configuration 100MHz */ + cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc); + cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes); /* Enable the cmn_pll0_en. */ @@ -984,28 +1468,71 @@ static int cdns_torrent_dp_configure(struct phy *phy, return ret; } -static int cdns_torrent_dp_init(struct phy *phy) +static int cdns_torrent_phy_on(struct phy *phy) { - unsigned char lane_bits; - int ret; struct cdns_torrent_inst *inst = phy_get_drvdata(phy); struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + u32 read_val; + int ret; - switch (cdns_phy->ref_clk_rate) { - case REF_CLK_19_2MHz: - case REF_CLK_25MHz: - /* Valid Ref Clock Rate */ - break; - default: - dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); - return -EINVAL; + if (cdns_phy->nsubnodes == 1) { + /* Take the PHY lane group out of reset */ + reset_control_deassert(inst->lnk_rst); + + /* Take the PHY out of reset */ + ret = reset_control_deassert(cdns_phy->phy_rst); + if (ret) + return ret; } - cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */ + /* + * Wait for cmn_ready assertion + * PHY_PMA_CMN_CTRL1[0] == 1 + */ + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, + read_val, read_val, 1000, + PLL_LOCK_TIMEOUT); + if (ret) { + dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); + return ret; + } + + if (inst->phy_type == TYPE_PCIE || inst->phy_type == TYPE_USB) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pcs_iso_link_ctrl_1[inst->mlane], + read_val, !read_val, 1000, + PLL_LOCK_TIMEOUT); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, "Timeout waiting for PHY status ready\n"); + return ret; + } + } + + return 0; +} + +static int cdns_torrent_phy_off(struct phy *phy) +{ + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); + int ret; - /* PHY PMA registers configuration function */ - cdns_torrent_dp_pma_cfg(cdns_phy, inst); + if (cdns_phy->nsubnodes != 1) + return 0; + + ret = reset_control_assert(cdns_phy->phy_rst); + if (ret) + return ret; + + return reset_control_assert(inst->lnk_rst); +} + +static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst) +{ + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + unsigned char lane_bits; + + cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */ /* * Set lines power state to A0 @@ -1024,21 +1551,35 @@ static int cdns_torrent_dp_init(struct phy *phy) /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); - /* PHY PMA registers configuration functions */ - /* Initialize PHY with max supported link rate, without SSC. */ - if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) + /* + * PHY PMA registers configuration functions + * Initialize PHY with max supported link rate, without SSC. + */ + if (cdns_phy->ref_clk_rate == CLK_19_2_MHZ) cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(cdns_phy, cdns_phy->max_bit_rate, false); - else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) + else if (cdns_phy->ref_clk_rate == CLK_25_MHZ) cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(cdns_phy, cdns_phy->max_bit_rate, false); + else if (cdns_phy->ref_clk_rate == CLK_100_MHZ) + cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, + cdns_phy->max_bit_rate, + false); + cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate, inst->num_lanes); /* take out of reset */ regmap_field_write(cdns_phy->phy_reset_ctrl, 0x1); +} + +static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, + struct phy *phy) +{ + int ret; cdns_torrent_phy_on(phy); @@ -1051,615 +1592,25 @@ static int cdns_torrent_dp_init(struct phy *phy) return ret; } -static -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) -{ - unsigned int reg; - int ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, - reg & 1, 0, POLL_TIMEOUT_US); - if (ret == -ETIMEDOUT) { - dev_err(cdns_phy->dev, - "timeout waiting for PMA common ready\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, - struct cdns_torrent_inst *inst) -{ - unsigned int i; - - if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) - /* PMA common configuration 19.2MHz */ - cdns_torrent_dp_pma_cmn_cfg_19_2mhz(cdns_phy); - else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) - /* PMA common configuration 25MHz */ - cdns_torrent_dp_pma_cmn_cfg_25mhz(cdns_phy); - - /* PMA lane configuration to deal with multi-link operation */ - for (i = 0; i < inst->num_lanes; i++) - cdns_torrent_dp_pma_lane_cfg(cdns_phy, i); -} - -static -void cdns_torrent_dp_pma_cmn_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - /* refclock registers - assumes 19.2 MHz refclock */ - cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0014); - cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0027); - cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00A1); - cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0027); - cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00A1); - cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x0060); - cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x0060); - cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0014); - cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x0018); - cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0005); - cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x0018); - cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0005); - cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x0240); - cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0005); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000B); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x0137); - - /* PLL registers */ - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00C0); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00C0); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0260); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0260); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003); -} - -/* - * Set registers responsible for enabling and configuring SSC, with second and - * third register values provided by parameters. - */ -static -void cdns_torrent_dp_enable_ssc_19_2mhz(struct cdns_torrent_phy *cdns_phy, - u32 ctrl2_val, u32 ctrl3_val) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl3_val); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl3_val); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003); -} - -static -void cdns_torrent_dp_pma_cmn_vco_cfg_19_2mhz(struct cdns_torrent_phy *cdns_phy, - u32 rate, bool ssc) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - /* Assumes 19.2 MHz refclock */ - switch (rate) { - /* Setting VCO for 10.8GHz */ - case 2700: - case 5400: - cdns_torrent_phy_write(regmap, - CMN_PLL0_INTDIV_M0, 0x0119); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVL_M0, 0x4000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL0_HIGH_THR_M0, 0x00BC); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL0_CTRL_M0, 0x0012); - cdns_torrent_phy_write(regmap, - CMN_PLL1_INTDIV_M0, 0x0119); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVL_M0, 0x4000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_HIGH_THR_M0, 0x00BC); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL1_CTRL_M0, 0x0012); - if (ssc) - cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x033A, - 0x006A); - break; - /* Setting VCO for 9.72GHz */ - case 1620: - case 2430: - case 3240: - cdns_torrent_phy_write(regmap, - CMN_PLL0_INTDIV_M0, 0x01FA); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVL_M0, 0x4000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL0_HIGH_THR_M0, 0x0152); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_INTDIV_M0, 0x01FA); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVL_M0, 0x4000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_HIGH_THR_M0, 0x0152); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL1_CTRL_M0, 0x0002); - if (ssc) - cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x05DD, - 0x0069); - break; - /* Setting VCO for 8.64GHz */ - case 2160: - case 4320: - cdns_torrent_phy_write(regmap, - CMN_PLL0_INTDIV_M0, 0x01C2); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL0_HIGH_THR_M0, 0x012C); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_INTDIV_M0, 0x01C2); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_HIGH_THR_M0, 0x012C); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL1_CTRL_M0, 0x0002); - if (ssc) - cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x0536, - 0x0069); - break; - /* Setting VCO for 8.1GHz */ - case 8100: - cdns_torrent_phy_write(regmap, - CMN_PLL0_INTDIV_M0, 0x01A5); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVL_M0, 0xE000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL0_HIGH_THR_M0, 0x011A); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_INTDIV_M0, 0x01A5); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVL_M0, 0xE000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_HIGH_THR_M0, 0x011A); - cdns_torrent_phy_write(regmap, - CMN_PDIAG_PLL1_CTRL_M0, 0x0002); - if (ssc) - cdns_torrent_dp_enable_ssc_19_2mhz(cdns_phy, 0x04D7, - 0x006A); - break; - } - - if (ssc) { - cdns_torrent_phy_write(regmap, - CMN_PLL0_VCOCAL_PLLCNT_START, 0x025E); - cdns_torrent_phy_write(regmap, - CMN_PLL0_LOCK_PLLCNT_THR, 0x0005); - cdns_torrent_phy_write(regmap, - CMN_PLL1_VCOCAL_PLLCNT_START, 0x025E); - cdns_torrent_phy_write(regmap, - CMN_PLL1_LOCK_PLLCNT_THR, 0x0005); - } else { - cdns_torrent_phy_write(regmap, - CMN_PLL0_VCOCAL_PLLCNT_START, 0x0260); - cdns_torrent_phy_write(regmap, - CMN_PLL1_VCOCAL_PLLCNT_START, 0x0260); - /* Set reset register values to disable SSC */ - cdns_torrent_phy_write(regmap, - CMN_PLL0_SS_CTRL1_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL0_SS_CTRL2_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_SS_CTRL3_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_SS_CTRL4_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_LOCK_PLLCNT_THR, 0x0003); - cdns_torrent_phy_write(regmap, - CMN_PLL1_SS_CTRL1_M0, 0x0002); - cdns_torrent_phy_write(regmap, - CMN_PLL1_SS_CTRL2_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_SS_CTRL3_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_SS_CTRL4_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_LOCK_PLLCNT_THR, 0x0003); - } - - cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x0099); - cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x0099); - cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x0099); - cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x0099); -} - -static -void cdns_torrent_dp_pma_cmn_cfg_25mhz(struct cdns_torrent_phy *cdns_phy) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - /* refclock registers - assumes 25 MHz refclock */ - cdns_torrent_phy_write(regmap, CMN_SSM_BIAS_TMR, 0x0019); - cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLPRE_TMR, 0x0032); - cdns_torrent_phy_write(regmap, CMN_PLLSM0_PLLLOCK_TMR, 0x00D1); - cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLPRE_TMR, 0x0032); - cdns_torrent_phy_write(regmap, CMN_PLLSM1_PLLLOCK_TMR, 0x00D1); - cdns_torrent_phy_write(regmap, CMN_BGCAL_INIT_TMR, 0x007D); - cdns_torrent_phy_write(regmap, CMN_BGCAL_ITER_TMR, 0x007D); - cdns_torrent_phy_write(regmap, CMN_IBCAL_INIT_TMR, 0x0019); - cdns_torrent_phy_write(regmap, CMN_TXPUCAL_INIT_TMR, 0x001E); - cdns_torrent_phy_write(regmap, CMN_TXPUCAL_ITER_TMR, 0x0006); - cdns_torrent_phy_write(regmap, CMN_TXPDCAL_INIT_TMR, 0x001E); - cdns_torrent_phy_write(regmap, CMN_TXPDCAL_ITER_TMR, 0x0006); - cdns_torrent_phy_write(regmap, CMN_RXCAL_INIT_TMR, 0x02EE); - cdns_torrent_phy_write(regmap, CMN_RXCAL_ITER_TMR, 0x0006); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_INIT_TMR, 0x0002); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_ITER_TMR, 0x0002); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_REFTIM_START, 0x000E); - cdns_torrent_phy_write(regmap, CMN_SD_CAL_PLLCNT_START, 0x012B); - - /* PLL registers */ - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_INIT_TMR, 0x00FA); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_ITER_TMR, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_INIT_TMR, 0x00FA); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_ITER_TMR, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_REFTIM_START, 0x0317); - cdns_torrent_phy_write(regmap, CMN_PLL0_VCOCAL_TCTRL, 0x0003); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_REFTIM_START, 0x0317); - cdns_torrent_phy_write(regmap, CMN_PLL1_VCOCAL_TCTRL, 0x0003); -} - -/* - * Set registers responsible for enabling and configuring SSC, with second - * register value provided by a parameter. - */ -static void cdns_torrent_dp_enable_ssc_25mhz(struct cdns_torrent_phy *cdns_phy, - u32 ctrl2_val) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0001); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, ctrl2_val); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x007F); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0003); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0001); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, ctrl2_val); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x007F); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0003); -} - -static -void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, - u32 rate, bool ssc) -{ - struct regmap *regmap = cdns_phy->regmap_common_cdb; - - /* Assumes 25 MHz refclock */ - switch (rate) { - /* Setting VCO for 10.8GHz */ - case 2700: - case 5400: - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x01B0); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0120); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x01B0); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0120); - if (ssc) - cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x0423); - break; - /* Setting VCO for 9.72GHz */ - case 1620: - case 2430: - case 3240: - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0184); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0xCCCD); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0104); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0184); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0xCCCD); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0104); - if (ssc) - cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x03B9); - break; - /* Setting VCO for 8.64GHz */ - case 2160: - case 4320: - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0159); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x999A); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00E7); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0159); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x999A); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00E7); - if (ssc) - cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x034F); - break; - /* Setting VCO for 8.1GHz */ - case 8100: - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0144); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x00D8); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0144); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x00D8); - if (ssc) - cdns_torrent_dp_enable_ssc_25mhz(cdns_phy, 0x031A); - break; - } - - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); - - if (ssc) { - cdns_torrent_phy_write(regmap, - CMN_PLL0_VCOCAL_PLLCNT_START, 0x0315); - cdns_torrent_phy_write(regmap, - CMN_PLL0_LOCK_PLLCNT_THR, 0x0005); - cdns_torrent_phy_write(regmap, - CMN_PLL1_VCOCAL_PLLCNT_START, 0x0315); - cdns_torrent_phy_write(regmap, - CMN_PLL1_LOCK_PLLCNT_THR, 0x0005); - } else { - cdns_torrent_phy_write(regmap, - CMN_PLL0_VCOCAL_PLLCNT_START, 0x0317); - cdns_torrent_phy_write(regmap, - CMN_PLL1_VCOCAL_PLLCNT_START, 0x0317); - /* Set reset register values to disable SSC */ - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL1_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL2_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL3_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL0_SS_CTRL4_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL0_LOCK_PLLCNT_THR, 0x0003); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL1_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL2_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL3_M0, 0x0000); - cdns_torrent_phy_write(regmap, CMN_PLL1_SS_CTRL4_M0, 0x0000); - cdns_torrent_phy_write(regmap, - CMN_PLL1_LOCK_PLLCNT_THR, 0x0003); - } - - cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_REFCNT_START, 0x00C7); - cdns_torrent_phy_write(regmap, CMN_PLL0_LOCK_PLLCNT_START, 0x00C7); - cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_REFCNT_START, 0x00C7); - cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7); -} - -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, - u32 rate, u32 num_lanes) -{ - unsigned int clk_sel_val = 0; - unsigned int hsclk_div_val = 0; - unsigned int i; - - /* 16'h0000 for single DP link configuration */ - regmap_field_write(cdns_phy->phy_pll_cfg, 0x0); - - switch (rate) { - case 1620: - clk_sel_val = 0x0f01; - hsclk_div_val = 2; - break; - case 2160: - case 2430: - case 2700: - clk_sel_val = 0x0701; - hsclk_div_val = 1; - break; - case 3240: - clk_sel_val = 0x0b00; - hsclk_div_val = 2; - break; - case 4320: - case 5400: - clk_sel_val = 0x0301; - hsclk_div_val = 0; - break; - case 8100: - clk_sel_val = 0x0200; - hsclk_div_val = 0; - break; - } - - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); - - /* PMA lane configuration to deal with multi-link operation */ - for (i = 0; i < num_lanes; i++) - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i], - XCVR_DIAG_HSCLK_DIV, hsclk_div_val); -} - -static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, - unsigned int lane) -{ - /* Per lane, refclock-dependent receiver detection setting */ - if (cdns_phy->ref_clk_rate == REF_CLK_19_2MHz) - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - TX_RCVDET_ST_TMR, 0x0780); - else if (cdns_phy->ref_clk_rate == REF_CLK_25MHz) - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - TX_RCVDET_ST_TMR, 0x09C4); - - /* Writing Tx/Rx Power State Controllers registers */ - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - TX_PSC_A0, 0x00FB); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - TX_PSC_A2, 0x04AA); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - TX_PSC_A3, 0x04AA); - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_PSC_A0, 0x0000); - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_PSC_A2, 0x0000); - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_PSC_A3, 0x0000); - - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_PSC_CAL, 0x0000); - - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_REE_GCSM1_CTRL, 0x0000); - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_REE_GCSM2_CTRL, 0x0000); - cdns_torrent_phy_write(cdns_phy->regmap_rx_lane_cdb[lane], - RX_REE_PERGCSM_CTRL, 0x0000); - - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - XCVR_DIAG_BIDI_CTRL, 0x000F); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - XCVR_DIAG_PLLDRC_CTRL, 0x0001); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], - XCVR_DIAG_HSCLK_SEL, 0x0000); -} - -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes, - enum phy_powerstate powerstate) +static int cdns_torrent_dp_init(struct phy *phy) { - /* Register value for power state for a single byte. */ - u32 value_part; - u32 value; - u32 mask; - u32 read_val; - u32 ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - switch (powerstate) { - case (POWERSTATE_A0): - value_part = 0x01U; - break; - case (POWERSTATE_A2): - value_part = 0x04U; - break; - default: - /* Powerstate A3 */ - value_part = 0x08U; - break; - } + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - /* Select values of registers and mask, depending on enabled - * lane count. - */ - switch (num_lanes) { - /* lane 0 */ - case (1): - value = value_part; - mask = 0x0000003FU; - break; - /* lanes 0-1 */ - case (2): - value = (value_part - | (value_part << 8)); - mask = 0x00003F3FU; + switch (cdns_phy->ref_clk_rate) { + case CLK_19_2_MHZ: + case CLK_25_MHZ: + case CLK_100_MHZ: + /* Valid Ref Clock Rate */ break; - /* lanes 0-3, all */ default: - value = (value_part - | (value_part << 8) - | (value_part << 16) - | (value_part << 24)); - mask = 0x3F3F3F3FU; - break; - } - - /* Set power state A<n>. */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); - /* Wait, until PHY acknowledges power state completion. */ - ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, - read_val, (read_val & mask) == value, 0, - POLL_TIMEOUT_US); - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); - ndelay(100); - - return ret; -} - -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) -{ - unsigned int read_val; - int ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - /* - * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the - * master lane - */ - ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK, - read_val, read_val & 1, - 0, POLL_TIMEOUT_US); - if (ret == -ETIMEDOUT) { - dev_err(cdns_phy->dev, - "timeout waiting for link PLL clock enable ack\n"); - return ret; + dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); + return -EINVAL; } - ndelay(100); - - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, - POWERSTATE_A2); - if (ret) - return ret; - - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, - POWERSTATE_A0); + cdns_torrent_dp_common_init(cdns_phy, inst); - return ret; + return cdns_torrent_dp_start(cdns_phy, inst, phy); } static int cdns_torrent_derived_refclk_enable(struct clk_hw *hw) @@ -1764,56 +1715,6 @@ static int cdns_torrent_derived_refclk_register(struct cdns_torrent_phy *cdns_ph return 0; } -static int cdns_torrent_phy_on(struct phy *phy) -{ - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - u32 read_val; - int ret; - - if (cdns_phy->nsubnodes == 1) { - /* Take the PHY lane group out of reset */ - reset_control_deassert(inst->lnk_rst); - - /* Take the PHY out of reset */ - ret = reset_control_deassert(cdns_phy->phy_rst); - if (ret) - return ret; - } - - /* - * Wait for cmn_ready assertion - * PHY_PMA_CMN_CTRL1[0] == 1 - */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, - read_val, read_val, 1000, - PLL_LOCK_TIMEOUT); - if (ret) { - dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); - return ret; - } - - mdelay(10); - - return 0; -} - -static int cdns_torrent_phy_off(struct phy *phy) -{ - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - int ret; - - if (cdns_phy->nsubnodes != 1) - return 0; - - ret = reset_control_assert(cdns_phy->phy_rst); - if (ret) - return ret; - - return reset_control_assert(inst->lnk_rst); -} - static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base, u32 block_offset, u8 reg_offset_shift, @@ -1854,6 +1755,7 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy) struct device *dev = cdns_phy->dev; struct regmap_field *field; struct regmap *regmap; + int i; regmap = cdns_phy->regmap_phy_pcs_common_cdb; field = devm_regmap_field_alloc(dev, regmap, phy_pll_cfg); @@ -1887,6 +1789,16 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy) } cdns_phy->phy_pma_pll_raw_ctrl = field; + for (i = 0; i < MAX_NUM_LANES; i++) { + regmap = cdns_phy->regmap_phy_pcs_lane_cdb[i]; + field = devm_regmap_field_alloc(dev, regmap, phy_pcs_iso_link_ctrl_1); + if (IS_ERR(field)) { + dev_err(dev, "PHY_PCS_ISO_LINK_CTRL reg field init for ln %d failed\n", i); + return PTR_ERR(field); + } + cdns_phy->phy_pcs_iso_link_ctrl_1[i] = field; + } + return 0; } @@ -1947,6 +1859,17 @@ static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy) return PTR_ERR(regmap); } cdns_phy->regmap_rx_lane_cdb[i] = regmap; + + block_offset = TORRENT_PHY_PCS_LANE_CDB_OFFSET(i, block_offset_shift, + reg_offset_shift); + regmap = cdns_regmap_init(dev, sd_base, block_offset, + reg_offset_shift, + &cdns_torrent_phy_pcs_lane_cdb_config[i]); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to init PHY PCS lane CDB regmap\n"); + return PTR_ERR(regmap); + } + cdns_phy->regmap_phy_pcs_lane_cdb[i] = regmap; } block_offset = TORRENT_COMMON_CDB_OFFSET; @@ -1987,6 +1910,7 @@ static int cdns_torrent_phy_init(struct phy *phy) struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); const struct cdns_torrent_data *init_data = cdns_phy->init_data; struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals; + enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate; struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals; struct cdns_torrent_inst *inst = phy_get_drvdata(phy); enum cdns_torrent_phy_type phy_type = inst->phy_type; @@ -2000,9 +1924,6 @@ static int cdns_torrent_phy_init(struct phy *phy) if (cdns_phy->nsubnodes > 1) return 0; - if (phy_type == TYPE_DP) - return cdns_torrent_dp_init(phy); - /** * Spread spectrum generation is not required or supported * for SGMII/QSGMII @@ -2052,7 +1973,7 @@ static int cdns_torrent_phy_init(struct phy *phy) } /* PMA common registers configurations */ - cmn_vals = init_data->cmn_vals[phy_type][TYPE_NONE][ssc]; + cmn_vals = init_data->cmn_vals[ref_clk][phy_type][TYPE_NONE][ssc]; if (cmn_vals) { reg_pairs = cmn_vals->reg_pairs; num_regs = cmn_vals->num_regs; @@ -2063,7 +1984,7 @@ static int cdns_torrent_phy_init(struct phy *phy) } /* PMA TX lane registers configurations */ - tx_ln_vals = init_data->tx_ln_vals[phy_type][TYPE_NONE][ssc]; + tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc]; if (tx_ln_vals) { reg_pairs = tx_ln_vals->reg_pairs; num_regs = tx_ln_vals->num_regs; @@ -2076,7 +1997,7 @@ static int cdns_torrent_phy_init(struct phy *phy) } /* PMA RX lane registers configurations */ - rx_ln_vals = init_data->rx_ln_vals[phy_type][TYPE_NONE][ssc]; + rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc]; if (rx_ln_vals) { reg_pairs = rx_ln_vals->reg_pairs; num_regs = rx_ln_vals->num_regs; @@ -2088,14 +2009,39 @@ static int cdns_torrent_phy_init(struct phy *phy) } } + if (phy_type == TYPE_DP) + return cdns_torrent_dp_init(phy); + + return 0; +} + +static const struct phy_ops cdns_torrent_phy_ops = { + .init = cdns_torrent_phy_init, + .configure = cdns_torrent_dp_configure, + .power_on = cdns_torrent_phy_on, + .power_off = cdns_torrent_phy_off, + .owner = THIS_MODULE, +}; + +static int cdns_torrent_noop_phy_on(struct phy *phy) +{ + /* Give 5ms to 10ms delay for the PIPE clock to be stable */ + usleep_range(5000, 10000); + return 0; } +static const struct phy_ops noop_ops = { + .power_on = cdns_torrent_noop_phy_on, + .owner = THIS_MODULE, +}; + static int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) { const struct cdns_torrent_data *init_data = cdns_phy->init_data; struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals; + enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate; struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals; enum cdns_torrent_phy_type phy_t1, phy_t2, tmp_phy_type; struct cdns_torrent_vals *pcs_cmn_vals; @@ -2184,7 +2130,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) } /* PMA common registers configurations */ - cmn_vals = init_data->cmn_vals[phy_t1][phy_t2][ssc]; + cmn_vals = init_data->cmn_vals[ref_clk][phy_t1][phy_t2][ssc]; if (cmn_vals) { reg_pairs = cmn_vals->reg_pairs; num_regs = cmn_vals->num_regs; @@ -2195,7 +2141,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) } /* PMA TX lane registers configurations */ - tx_ln_vals = init_data->tx_ln_vals[phy_t1][phy_t2][ssc]; + tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_t1][phy_t2][ssc]; if (tx_ln_vals) { reg_pairs = tx_ln_vals->reg_pairs; num_regs = tx_ln_vals->num_regs; @@ -2208,7 +2154,7 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) } /* PMA RX lane registers configurations */ - rx_ln_vals = init_data->rx_ln_vals[phy_t1][phy_t2][ssc]; + rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_t1][phy_t2][ssc]; if (rx_ln_vals) { reg_pairs = rx_ln_vals->reg_pairs; num_regs = rx_ln_vals->num_regs; @@ -2286,6 +2232,7 @@ static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy) static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy) { struct device *dev = cdns_phy->dev; + unsigned long ref_clk_rate; int ret; cdns_phy->clk = devm_clk_get(dev, "refclk"); @@ -2300,13 +2247,29 @@ static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy) return ret; } - cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk); - if (!(cdns_phy->ref_clk_rate)) { + ref_clk_rate = clk_get_rate(cdns_phy->clk); + if (!ref_clk_rate) { dev_err(cdns_phy->dev, "Failed to get ref clock rate\n"); clk_disable_unprepare(cdns_phy->clk); return -EINVAL; } + switch (ref_clk_rate) { + case REF_CLK_19_2MHZ: + cdns_phy->ref_clk_rate = CLK_19_2_MHZ; + break; + case REF_CLK_25MHZ: + cdns_phy->ref_clk_rate = CLK_25_MHZ; + break; + case REF_CLK_100MHZ: + cdns_phy->ref_clk_rate = CLK_100_MHZ; + break; + default: + dev_err(cdns_phy->dev, "Invalid Ref Clock Rate\n"); + clk_disable_unprepare(cdns_phy->clk); + return -EINVAL; + } + return 0; } @@ -2505,10 +2468,9 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) init_dp_regmap++; } - dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n", - cdns_phy->phys[node].num_lanes, - cdns_phy->max_bit_rate / 1000, - cdns_phy->max_bit_rate % 1000); + dev_dbg(dev, "DP max bit rate %d.%03d Gbps\n", + cdns_phy->max_bit_rate / 1000, + cdns_phy->max_bit_rate % 1000); gphy->attrs.bus_width = cdns_phy->phys[node].num_lanes; gphy->attrs.max_link_rate = cdns_phy->max_bit_rate; @@ -2540,6 +2502,17 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) goto put_lnk_rst; } + if (cdns_phy->nsubnodes > 1) + dev_dbg(dev, "Multi-link: %s (%d lanes) & %s (%d lanes)", + cdns_torrent_get_phy_type(cdns_phy->phys[0].phy_type), + cdns_phy->phys[0].num_lanes, + cdns_torrent_get_phy_type(cdns_phy->phys[1].phy_type), + cdns_phy->phys[1].num_lanes); + else + dev_dbg(dev, "Single link: %s (%d lanes)", + cdns_torrent_get_phy_type(cdns_phy->phys[0].phy_type), + cdns_phy->phys[0].num_lanes); + return 0; put_child: @@ -2573,6 +2546,206 @@ static int cdns_torrent_phy_remove(struct platform_device *pdev) return 0; } +/* Single DisplayPort(DP) link configuration */ +static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = { + {0x0000, PHY_PLL_CFG}, +}; + +static struct cdns_reg_pairs sl_dp_xcvr_diag_ln_regs[] = { + {0x0000, XCVR_DIAG_HSCLK_SEL}, + {0x0001, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_torrent_vals sl_dp_link_cmn_vals = { + .reg_pairs = sl_dp_link_cmn_regs, + .num_regs = ARRAY_SIZE(sl_dp_link_cmn_regs), +}; + +static struct cdns_torrent_vals sl_dp_xcvr_diag_ln_vals = { + .reg_pairs = sl_dp_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_xcvr_diag_ln_regs), +}; + +/* Single DP, 19.2 MHz Ref clk, no SSC */ +static struct cdns_reg_pairs sl_dp_19_2_no_ssc_cmn_regs[] = { + {0x0014, CMN_SSM_BIAS_TMR}, + {0x0027, CMN_PLLSM0_PLLPRE_TMR}, + {0x00A1, CMN_PLLSM0_PLLLOCK_TMR}, + {0x0027, CMN_PLLSM1_PLLPRE_TMR}, + {0x00A1, CMN_PLLSM1_PLLLOCK_TMR}, + {0x0060, CMN_BGCAL_INIT_TMR}, + {0x0060, CMN_BGCAL_ITER_TMR}, + {0x0014, CMN_IBCAL_INIT_TMR}, + {0x0018, CMN_TXPUCAL_INIT_TMR}, + {0x0005, CMN_TXPUCAL_ITER_TMR}, + {0x0018, CMN_TXPDCAL_INIT_TMR}, + {0x0005, CMN_TXPDCAL_ITER_TMR}, + {0x0240, CMN_RXCAL_INIT_TMR}, + {0x0005, CMN_RXCAL_ITER_TMR}, + {0x0002, CMN_SD_CAL_INIT_TMR}, + {0x0002, CMN_SD_CAL_ITER_TMR}, + {0x000B, CMN_SD_CAL_REFTIM_START}, + {0x0137, CMN_SD_CAL_PLLCNT_START}, + {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, + {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, + {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, + {0x0004, CMN_PLL0_DSM_DIAG_M0}, + {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, + {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, + {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, + {0x0004, CMN_PLL1_DSM_DIAG_M0}, + {0x00C0, CMN_PLL0_VCOCAL_INIT_TMR}, + {0x0004, CMN_PLL0_VCOCAL_ITER_TMR}, + {0x00C0, CMN_PLL1_VCOCAL_INIT_TMR}, + {0x0004, CMN_PLL1_VCOCAL_ITER_TMR}, + {0x0260, CMN_PLL0_VCOCAL_REFTIM_START}, + {0x0003, CMN_PLL0_VCOCAL_TCTRL}, + {0x0260, CMN_PLL1_VCOCAL_REFTIM_START}, + {0x0003, CMN_PLL1_VCOCAL_TCTRL} +}; + +static struct cdns_reg_pairs sl_dp_19_2_no_ssc_tx_ln_regs[] = { + {0x0780, TX_RCVDET_ST_TMR}, + {0x00FB, TX_PSC_A0}, + {0x04AA, TX_PSC_A2}, + {0x04AA, TX_PSC_A3}, + {0x000F, XCVR_DIAG_BIDI_CTRL} +}; + +static struct cdns_reg_pairs sl_dp_19_2_no_ssc_rx_ln_regs[] = { + {0x0000, RX_PSC_A0}, + {0x0000, RX_PSC_A2}, + {0x0000, RX_PSC_A3}, + {0x0000, RX_PSC_CAL}, + {0x0000, RX_REE_GCSM1_CTRL}, + {0x0000, RX_REE_GCSM2_CTRL}, + {0x0000, RX_REE_PERGCSM_CTRL} +}; + +static struct cdns_torrent_vals sl_dp_19_2_no_ssc_cmn_vals = { + .reg_pairs = sl_dp_19_2_no_ssc_cmn_regs, + .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_cmn_regs), +}; + +static struct cdns_torrent_vals sl_dp_19_2_no_ssc_tx_ln_vals = { + .reg_pairs = sl_dp_19_2_no_ssc_tx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_tx_ln_regs), +}; + +static struct cdns_torrent_vals sl_dp_19_2_no_ssc_rx_ln_vals = { + .reg_pairs = sl_dp_19_2_no_ssc_rx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_rx_ln_regs), +}; + +/* Single DP, 25 MHz Ref clk, no SSC */ +static struct cdns_reg_pairs sl_dp_25_no_ssc_cmn_regs[] = { + {0x0019, CMN_SSM_BIAS_TMR}, + {0x0032, CMN_PLLSM0_PLLPRE_TMR}, + {0x00D1, CMN_PLLSM0_PLLLOCK_TMR}, + {0x0032, CMN_PLLSM1_PLLPRE_TMR}, + {0x00D1, CMN_PLLSM1_PLLLOCK_TMR}, + {0x007D, CMN_BGCAL_INIT_TMR}, + {0x007D, CMN_BGCAL_ITER_TMR}, + {0x0019, CMN_IBCAL_INIT_TMR}, + {0x001E, CMN_TXPUCAL_INIT_TMR}, + {0x0006, CMN_TXPUCAL_ITER_TMR}, + {0x001E, CMN_TXPDCAL_INIT_TMR}, + {0x0006, CMN_TXPDCAL_ITER_TMR}, + {0x02EE, CMN_RXCAL_INIT_TMR}, + {0x0006, CMN_RXCAL_ITER_TMR}, + {0x0002, CMN_SD_CAL_INIT_TMR}, + {0x0002, CMN_SD_CAL_ITER_TMR}, + {0x000E, CMN_SD_CAL_REFTIM_START}, + {0x012B, CMN_SD_CAL_PLLCNT_START}, + {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, + {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, + {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, + {0x0004, CMN_PLL0_DSM_DIAG_M0}, + {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, + {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, + {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, + {0x0004, CMN_PLL1_DSM_DIAG_M0}, + {0x00FA, CMN_PLL0_VCOCAL_INIT_TMR}, + {0x0004, CMN_PLL0_VCOCAL_ITER_TMR}, + {0x00FA, CMN_PLL1_VCOCAL_INIT_TMR}, + {0x0004, CMN_PLL1_VCOCAL_ITER_TMR}, + {0x0317, CMN_PLL0_VCOCAL_REFTIM_START}, + {0x0003, CMN_PLL0_VCOCAL_TCTRL}, + {0x0317, CMN_PLL1_VCOCAL_REFTIM_START}, + {0x0003, CMN_PLL1_VCOCAL_TCTRL} +}; + +static struct cdns_reg_pairs sl_dp_25_no_ssc_tx_ln_regs[] = { + {0x09C4, TX_RCVDET_ST_TMR}, + {0x00FB, TX_PSC_A0}, + {0x04AA, TX_PSC_A2}, + {0x04AA, TX_PSC_A3}, + {0x000F, XCVR_DIAG_BIDI_CTRL} +}; + +static struct cdns_reg_pairs sl_dp_25_no_ssc_rx_ln_regs[] = { + {0x0000, RX_PSC_A0}, + {0x0000, RX_PSC_A2}, + {0x0000, RX_PSC_A3}, + {0x0000, RX_PSC_CAL}, + {0x0000, RX_REE_GCSM1_CTRL}, + {0x0000, RX_REE_GCSM2_CTRL}, + {0x0000, RX_REE_PERGCSM_CTRL} +}; + +static struct cdns_torrent_vals sl_dp_25_no_ssc_cmn_vals = { + .reg_pairs = sl_dp_25_no_ssc_cmn_regs, + .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_cmn_regs), +}; + +static struct cdns_torrent_vals sl_dp_25_no_ssc_tx_ln_vals = { + .reg_pairs = sl_dp_25_no_ssc_tx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_tx_ln_regs), +}; + +static struct cdns_torrent_vals sl_dp_25_no_ssc_rx_ln_vals = { + .reg_pairs = sl_dp_25_no_ssc_rx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_rx_ln_regs), +}; + +/* Single DP, 100 MHz Ref clk, no SSC */ +static struct cdns_reg_pairs sl_dp_100_no_ssc_cmn_regs[] = { + {0x0003, CMN_PLL0_VCOCAL_TCTRL}, + {0x0003, CMN_PLL1_VCOCAL_TCTRL} +}; + +static struct cdns_reg_pairs sl_dp_100_no_ssc_tx_ln_regs[] = { + {0x00FB, TX_PSC_A0}, + {0x04AA, TX_PSC_A2}, + {0x04AA, TX_PSC_A3}, + {0x000F, XCVR_DIAG_BIDI_CTRL} +}; + +static struct cdns_reg_pairs sl_dp_100_no_ssc_rx_ln_regs[] = { + {0x0000, RX_PSC_A0}, + {0x0000, RX_PSC_A2}, + {0x0000, RX_PSC_A3}, + {0x0000, RX_PSC_CAL}, + {0x0000, RX_REE_GCSM1_CTRL}, + {0x0000, RX_REE_GCSM2_CTRL}, + {0x0000, RX_REE_PERGCSM_CTRL} +}; + +static struct cdns_torrent_vals sl_dp_100_no_ssc_cmn_vals = { + .reg_pairs = sl_dp_100_no_ssc_cmn_regs, + .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_cmn_regs), +}; + +static struct cdns_torrent_vals sl_dp_100_no_ssc_tx_ln_vals = { + .reg_pairs = sl_dp_100_no_ssc_tx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_tx_ln_regs), +}; + +static struct cdns_torrent_vals sl_dp_100_no_ssc_rx_ln_vals = { + .reg_pairs = sl_dp_100_no_ssc_rx_ln_regs, + .num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_rx_ln_regs), +}; + /* USB and SGMII/QSGMII link configuration */ static struct cdns_reg_pairs usb_sgmii_link_cmn_regs[] = { {0x0002, PHY_PLL_CFG}, @@ -3311,6 +3484,11 @@ static const struct cdns_torrent_data cdns_map_torrent = { .block_offset_shift = 0x2, .reg_offset_shift = 0x2, .link_cmn_vals = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_link_cmn_vals, + }, + }, [TYPE_PCIE] = { [TYPE_NONE] = { [NO_SSC] = NULL, @@ -3387,6 +3565,11 @@ static const struct cdns_torrent_data cdns_map_torrent = { }, }, .xcvr_diag_vals = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, + }, + }, [TYPE_PCIE] = { [TYPE_NONE] = { [NO_SSC] = NULL, @@ -3487,230 +3670,293 @@ static const struct cdns_torrent_data cdns_map_torrent = { }, }, .cmn_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, - }, - [TYPE_SGMII] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - [TYPE_QSGMII] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_cmn_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, + [TYPE_NONE] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + [TYPE_NONE] = { + [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, - }, - }, - }, - .tx_ln_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, - }, - [TYPE_SGMII] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, - }, - [TYPE_QSGMII] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, + [TYPE_NONE] = { + [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + }, }, [TYPE_USB] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, + [TYPE_NONE] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, }, }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + }, + .tx_ln_vals = { + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_SGMII] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_QSGMII] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_USB] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - }, - }, - }, - .rx_ln_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - }, - [TYPE_SGMII] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - }, - [TYPE_QSGMII] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, + }, }, [TYPE_USB] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + .rx_ln_vals = { + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + }, + [TYPE_USB] = { + [TYPE_NONE] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, @@ -3720,6 +3966,11 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { .block_offset_shift = 0x0, .reg_offset_shift = 0x1, .link_cmn_vals = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_link_cmn_vals, + }, + }, [TYPE_PCIE] = { [TYPE_NONE] = { [NO_SSC] = NULL, @@ -3796,6 +4047,11 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { }, }, .xcvr_diag_vals = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, + }, + }, [TYPE_PCIE] = { [TYPE_NONE] = { [NO_SSC] = NULL, @@ -3896,230 +4152,293 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { }, }, .cmn_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, - }, - [TYPE_SGMII] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - [TYPE_QSGMII] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &pcie_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, - }, - }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_cmn_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, + [TYPE_NONE] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &pcie_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + [TYPE_NONE] = { + [NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, - [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, - }, - }, - }, - .tx_ln_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, - }, - [TYPE_SGMII] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, - }, - [TYPE_QSGMII] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, + [TYPE_NONE] = { + [NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, + }, }, [TYPE_USB] = { - [NO_SSC] = NULL, - [EXTERNAL_SSC] = NULL, - [INTERNAL_SSC] = NULL, + [TYPE_NONE] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, + [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, + }, }, }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + }, + .tx_ln_vals = { + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - }, - [TYPE_SGMII] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - }, - [TYPE_QSGMII] = { - [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, - }, - }, - }, - .rx_ln_vals = { - [TYPE_PCIE] = { - [TYPE_NONE] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_SGMII] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_QSGMII] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, + [TYPE_USB] = { + [NO_SSC] = NULL, + [EXTERNAL_SSC] = NULL, + [INTERNAL_SSC] = NULL, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals, + }, }, [TYPE_USB] = { - [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, - [TYPE_SGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + .rx_ln_vals = { + [CLK_19_2_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals, + }, }, }, - [TYPE_QSGMII] = { - [TYPE_NONE] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_PCIE] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - }, - [TYPE_USB] = { - [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [CLK_25_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals, + }, }, }, - [TYPE_USB] = { - [TYPE_NONE] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [CLK_100_MHZ] = { + [TYPE_DP] = { + [TYPE_NONE] = { + [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, + }, }, [TYPE_QSGMII] = { - [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, - [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, - [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [TYPE_NONE] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, + }, + }, + [TYPE_USB] = { + [TYPE_NONE] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_PCIE] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_SGMII] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, + [TYPE_QSGMII] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c index 8ad8f717ef43..5fb4217fb8e0 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c @@ -100,7 +100,6 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_hdmi_phy *hdmi_phy; - struct resource *mem; struct clk *ref_clk; const char *ref_clk_name; struct clk_init_data clk_init = { @@ -116,11 +115,9 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev) if (!hdmi_phy) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hdmi_phy->regs = devm_ioremap_resource(dev, mem); - if (IS_ERR(hdmi_phy->regs)) { + hdmi_phy->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hdmi_phy->regs)) return PTR_ERR(hdmi_phy->regs); - } ref_clk = devm_clk_get(dev, "pll_ref"); if (IS_ERR(ref_clk)) { diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c index 01cf31633019..28ad9403c441 100644 --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c @@ -130,7 +130,6 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_mipi_tx *mipi_tx; - struct resource *mem; const char *ref_clk_name; struct clk *ref_clk; struct clk_init_data clk_init = { @@ -148,11 +147,9 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) mipi_tx->driver_data = of_device_get_match_data(dev); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mipi_tx->regs = devm_ioremap_resource(dev, mem); - if (IS_ERR(mipi_tx->regs)) { + mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mipi_tx->regs)) return PTR_ERR(mipi_tx->regs); - } ref_clk = devm_clk_get(dev, NULL); if (IS_ERR(ref_clk)) { @@ -203,10 +200,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) phy_set_drvdata(phy, mipi_tx); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) { - ret = PTR_ERR(phy_provider); - return ret; - } + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); mipi_tx->dev = dev; diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 731c483a04de..cdcef865fe9e 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -10,11 +10,13 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/regmap.h> /* version V1 sub-banks offset base address */ /* banks shared by multiple phys */ @@ -27,7 +29,8 @@ #define SSUSB_SIFSLV_V1_U3PHYD 0x000 #define SSUSB_SIFSLV_V1_U3PHYA 0x200 -/* version V2 sub-banks offset base address */ +/* 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 @@ -40,6 +43,8 @@ #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 @@ -51,6 +56,8 @@ #define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 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 @@ -72,6 +79,14 @@ #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) @@ -267,14 +282,31 @@ #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0) #define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x)) +/* 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 + 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; enum mtk_phy_version version; }; @@ -298,10 +330,12 @@ struct mtk_phy_instance { struct u2phy_banks u2_banks; struct u3phy_banks u3_banks; }; - struct clk *ref_clk; /* reference clock of (digital) phy */ - struct clk *da_ref_clk; /* reference clock of analog phy */ + struct clk_bulk_data clks[TPHY_CLKS_CNT]; u32 index; - u8 type; + u32 type; + struct regmap *type_sw; + u32 type_sw_reg; + u32 type_sw_index; int eye_src; int eye_vrt; int eye_term; @@ -330,6 +364,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy, int fm_out; u32 tmp; + /* HW V3 doesn't support slew rate cal anymore */ + if (tphy->pdata->version == MTK_PHY_V3) + return; + /* use force value */ if (instance->eye_src) return; @@ -450,6 +488,33 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy, dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); } +static void u2_phy_pll_26m_set(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct u2phy_banks *u2_banks = &instance->u2_banks; + void __iomem *com = u2_banks->com; + u32 tmp; + + if (!tphy->pdata->sw_pll_48m_to_26m) + return; + + tmp = readl(com + U3P_USBPHYACR0); + tmp &= ~PA0_USB20_PLL_PREDIV; + tmp |= PA0_USB20_PLL_PREDIV_VAL(0); + writel(tmp, com + U3P_USBPHYACR0); + + tmp = readl(com + U3P_USBPHYACR2); + tmp &= ~PA2_RG_U2PLL_BW; + tmp |= PA2_RG_U2PLL_BW_VAL(3); + writel(tmp, com + U3P_USBPHYACR2); + + writel(P2R_RG_U2PLL_FBDIV_26M, com + U3P_U2PHYA_RESV); + + tmp = readl(com + U3P_U2PHYA_RESV1); + tmp |= P2R_RG_U2PLL_FRA_EN | P2R_RG_U2PLL_REFCLK_SEL; + writel(tmp, com + U3P_U2PHYA_RESV1); +} + static void u2_phy_instance_init(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) { @@ -509,6 +574,9 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, tmp |= PA6_RG_U2_SQTH_VAL(2); writel(tmp, com + U3P_USBPHYACR6); + /* Workaround only for mt8195, HW fix it for others (V3) */ + u2_phy_pll_26m_set(tphy, instance); + dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); } @@ -878,7 +946,7 @@ static void u2_phy_props_set(struct mtk_tphy *tphy, writel(tmp, com + U3P_U2PHYBC12C); } - if (instance->eye_src) { + if (tphy->pdata->version < MTK_PHY_V3 && instance->eye_src) { tmp = readl(com + U3P_USBPHYACR5); tmp &= ~PA5_RG_U2_HSTX_SRCTRL; tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src); @@ -914,24 +982,73 @@ static void u2_phy_props_set(struct mtk_tphy *tphy, } } -static int mtk_phy_init(struct phy *phy) +/* type switch for usb3/pcie/sgmii/sata */ +static int phy_type_syscon_get(struct mtk_phy_instance *instance, + struct device_node *dn) { - struct mtk_phy_instance *instance = phy_get_drvdata(phy); - struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); + struct of_phandle_args args; int ret; - ret = clk_prepare_enable(instance->ref_clk); - if (ret) { - dev_err(tphy->dev, "failed to enable ref_clk\n"); + /* type switch function is optional */ + if (!of_property_read_bool(dn, "mediatek,syscon-type")) + return 0; + + ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type", + 2, 0, &args); + if (ret) return ret; + + instance->type_sw_reg = args.args[0]; + instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ + instance->type_sw = syscon_node_to_regmap(args.np); + of_node_put(args.np); + dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n", + instance->type_sw_reg, instance->type_sw_index); + + return PTR_ERR_OR_ZERO(instance->type_sw); +} + +static int phy_type_set(struct mtk_phy_instance *instance) +{ + int type; + u32 mask; + + if (!instance->type_sw) + return 0; + + switch (instance->type) { + case PHY_TYPE_USB3: + type = RG_PHY_SW_USB3; + break; + case PHY_TYPE_PCIE: + type = RG_PHY_SW_PCIE; + break; + case PHY_TYPE_SGMII: + type = RG_PHY_SW_SGMII; + break; + case PHY_TYPE_SATA: + type = RG_PHY_SW_SATA; + break; + case PHY_TYPE_USB2: + default: + return 0; } - ret = clk_prepare_enable(instance->da_ref_clk); - if (ret) { - dev_err(tphy->dev, "failed to enable da_ref\n"); - clk_disable_unprepare(instance->ref_clk); + mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE); + regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type); + + return 0; +} + +static int mtk_phy_init(struct phy *phy) +{ + struct mtk_phy_instance *instance = phy_get_drvdata(phy); + struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); + int ret; + + ret = clk_bulk_prepare_enable(TPHY_CLKS_CNT, instance->clks); + if (ret) return ret; - } switch (instance->type) { case PHY_TYPE_USB2: @@ -947,10 +1064,12 @@ static int mtk_phy_init(struct phy *phy) case PHY_TYPE_SATA: sata_phy_instance_init(tphy, instance); break; + case PHY_TYPE_SGMII: + /* nothing to do, only used to set type */ + break; default: dev_err(tphy->dev, "incompatible PHY type\n"); - clk_disable_unprepare(instance->ref_clk); - clk_disable_unprepare(instance->da_ref_clk); + clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks); return -EINVAL; } @@ -993,8 +1112,7 @@ static int mtk_phy_exit(struct phy *phy) if (instance->type == PHY_TYPE_USB2) u2_phy_instance_exit(tphy, instance); - clk_disable_unprepare(instance->ref_clk); - clk_disable_unprepare(instance->da_ref_clk); + clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks); return 0; } @@ -1037,21 +1155,27 @@ static struct phy *mtk_phy_xlate(struct device *dev, if (!(instance->type == PHY_TYPE_USB2 || instance->type == PHY_TYPE_USB3 || instance->type == PHY_TYPE_PCIE || - instance->type == PHY_TYPE_SATA)) { + instance->type == PHY_TYPE_SATA || + instance->type == PHY_TYPE_SGMII)) { dev_err(dev, "unsupported device type: %d\n", instance->type); return ERR_PTR(-EINVAL); } - if (tphy->pdata->version == MTK_PHY_V1) { + switch (tphy->pdata->version) { + case MTK_PHY_V1: phy_v1_banks_init(tphy, instance); - } else if (tphy->pdata->version == MTK_PHY_V2) { + break; + case MTK_PHY_V2: + case MTK_PHY_V3: phy_v2_banks_init(tphy, instance); - } else { + break; + default: dev_err(dev, "phy version is not supported\n"); return ERR_PTR(-EINVAL); } phy_parse_property(tphy, instance); + phy_type_set(instance); return instance->phy; } @@ -1075,17 +1199,28 @@ static const struct mtk_phy_pdata tphy_v2_pdata = { .version = MTK_PHY_V2, }; +static const struct mtk_phy_pdata tphy_v3_pdata = { + .version = MTK_PHY_V3, +}; + static const struct mtk_phy_pdata mt8173_pdata = { .avoid_rx_sen_degradation = true, .version = MTK_PHY_V1, }; +static const struct mtk_phy_pdata mt8195_pdata = { + .sw_pll_48m_to_26m = true, + .version = MTK_PHY_V3, +}; + static const struct of_device_id mtk_tphy_id_table[] = { { .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata }, { .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata }, { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, + { .compatible = "mediatek,mt8195-tphy", .data = &mt8195_pdata }, { .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata }, { .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata }, + { .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata }, { }, }; MODULE_DEVICE_TABLE(of, mtk_tphy_id_table); @@ -1129,16 +1264,21 @@ static int mtk_tphy_probe(struct platform_device *pdev) } } - tphy->src_ref_clk = U3P_REF_CLK; - tphy->src_coef = U3P_SLEW_RATE_COEF; - /* update parameters of slew rate calibrate if exist */ - device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", - &tphy->src_ref_clk); - device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef); + if (tphy->pdata->version < MTK_PHY_V3) { + tphy->src_ref_clk = U3P_REF_CLK; + tphy->src_coef = U3P_SLEW_RATE_COEF; + /* update parameters of slew rate calibrate if exist */ + device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", + &tphy->src_ref_clk); + device_property_read_u32(dev, "mediatek,src-coef", + &tphy->src_coef); + } port = 0; for_each_child_of_node(np, child_np) { struct mtk_phy_instance *instance; + struct clk_bulk_data *clks; + struct device *subdev; struct phy *phy; instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); @@ -1156,16 +1296,16 @@ static int mtk_tphy_probe(struct platform_device *pdev) goto put_child; } + subdev = &phy->dev; retval = of_address_to_resource(child_np, 0, &res); if (retval) { - dev_err(dev, "failed to get address resource(id-%d)\n", + dev_err(subdev, "failed to get address resource(id-%d)\n", port); goto put_child; } - instance->port_base = devm_ioremap_resource(&phy->dev, &res); + instance->port_base = devm_ioremap_resource(subdev, &res); if (IS_ERR(instance->port_base)) { - dev_err(dev, "failed to remap phy regs\n"); retval = PTR_ERR(instance->port_base); goto put_child; } @@ -1175,20 +1315,16 @@ static int mtk_tphy_probe(struct platform_device *pdev) phy_set_drvdata(phy, instance); port++; - instance->ref_clk = devm_clk_get_optional(&phy->dev, "ref"); - if (IS_ERR(instance->ref_clk)) { - dev_err(dev, "failed to get ref_clk(id-%d)\n", port); - retval = PTR_ERR(instance->ref_clk); + clks = instance->clks; + clks[0].id = "ref"; /* digital (& analog) clock */ + clks[1].id = "da_ref"; /* analog clock */ + retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks); + if (retval) goto put_child; - } - instance->da_ref_clk = - devm_clk_get_optional(&phy->dev, "da_ref"); - if (IS_ERR(instance->da_ref_clk)) { - dev_err(dev, "failed to get da_ref_clk(id-%d)\n", port); - retval = PTR_ERR(instance->da_ref_clk); + retval = phy_type_syscon_get(instance, child_np); + if (retval) goto put_child; - } } provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); diff --git a/drivers/phy/mediatek/phy-mtk-ufs.c b/drivers/phy/mediatek/phy-mtk-ufs.c index 769b00b038d8..a6af06941203 100644 --- a/drivers/phy/mediatek/phy-mtk-ufs.c +++ b/drivers/phy/mediatek/phy-mtk-ufs.c @@ -31,11 +31,12 @@ #define FRC_CDR_ISO_EN BIT(19) #define CDR_ISO_EN BIT(20) +#define UFSPHY_CLKS_CNT 2 + struct ufs_mtk_phy { struct device *dev; void __iomem *mmio; - struct clk *mp_clk; - struct clk *unipro_clk; + struct clk_bulk_data clks[UFSPHY_CLKS_CNT]; }; static inline u32 mphy_readl(struct ufs_mtk_phy *phy, u32 reg) @@ -74,20 +75,11 @@ static struct ufs_mtk_phy *get_ufs_mtk_phy(struct phy *generic_phy) static int ufs_mtk_phy_clk_init(struct ufs_mtk_phy *phy) { struct device *dev = phy->dev; + struct clk_bulk_data *clks = phy->clks; - phy->unipro_clk = devm_clk_get(dev, "unipro"); - if (IS_ERR(phy->unipro_clk)) { - dev_err(dev, "failed to get clock: unipro"); - return PTR_ERR(phy->unipro_clk); - } - - phy->mp_clk = devm_clk_get(dev, "mp"); - if (IS_ERR(phy->mp_clk)) { - dev_err(dev, "failed to get clock: mp"); - return PTR_ERR(phy->mp_clk); - } - - return 0; + clks[0].id = "unipro"; + clks[1].id = "mp"; + return devm_clk_bulk_get(dev, UFSPHY_CLKS_CNT, clks); } static void ufs_mtk_phy_set_active(struct ufs_mtk_phy *phy) @@ -150,26 +142,13 @@ static int ufs_mtk_phy_power_on(struct phy *generic_phy) struct ufs_mtk_phy *phy = get_ufs_mtk_phy(generic_phy); int ret; - ret = clk_prepare_enable(phy->unipro_clk); - if (ret) { - dev_err(phy->dev, "unipro_clk enable failed %d\n", ret); - goto out; - } - - ret = clk_prepare_enable(phy->mp_clk); - if (ret) { - dev_err(phy->dev, "mp_clk enable failed %d\n", ret); - goto out_unprepare_unipro_clk; - } + ret = clk_bulk_prepare_enable(UFSPHY_CLKS_CNT, phy->clks); + if (ret) + return ret; ufs_mtk_phy_set_active(phy); return 0; - -out_unprepare_unipro_clk: - clk_disable_unprepare(phy->unipro_clk); -out: - return ret; } static int ufs_mtk_phy_power_off(struct phy *generic_phy) @@ -178,8 +157,7 @@ static int ufs_mtk_phy_power_off(struct phy *generic_phy) ufs_mtk_phy_set_deep_hibern(phy); - clk_disable_unprepare(phy->unipro_clk); - clk_disable_unprepare(phy->mp_clk); + clk_bulk_disable_unprepare(UFSPHY_CLKS_CNT, phy->clks); return 0; } diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index cfe359488f5c..f14032170b1c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -234,6 +234,11 @@ static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_READY_STATUS] = 0x160, }; +static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_START_CTRL] = 0x00, + [QPHY_PCS_READY_STATUS] = 0x168, +}; + static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x44, @@ -1329,6 +1334,97 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), }; +static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), + QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), + + /* Rate B */ + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), +}; + +static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), +}; + +static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), +}; + +static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), + QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), + QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), + QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), + QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), + QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), + QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), + QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), + QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ +}; + static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), @@ -2035,6 +2131,113 @@ static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), }; +static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), +}; + +static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), +}; + +static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), +}; + +static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), +}; + +static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), +}; + static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), @@ -3289,6 +3492,31 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { .no_pcs_sw_reset = true, }; +static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { + .type = PHY_TYPE_UFS, + .nlanes = 1, + + .serdes_tbl = sm6115_ufsphy_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), + .tx_tbl = sm6115_ufsphy_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), + .rx_tbl = sm6115_ufsphy_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), + .pcs_tbl = sm6115_ufsphy_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), + .clk_list = sdm845_ufs_phy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = sm6115_ufsphy_regs_layout, + + .start_ctrl = SERDES_START, + .pwrdn_ctrl = SW_PWRDN, + + .is_dual_lane_phy = false, + .no_pcs_sw_reset = true, +}; + static const struct qmp_phy_cfg msm8998_pciephy_cfg = { .type = PHY_TYPE_PCIE, .nlanes = 1, @@ -3399,6 +3627,76 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { .is_dual_lane_phy = true, }; +static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { + .type = PHY_TYPE_PCIE, + .nlanes = 1, + + .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), + .tx_tbl = sc8180x_qmp_pcie_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), + .rx_tbl = sc8180x_qmp_pcie_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), + .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), + .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, + .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = sm8250_pcie_regs_layout, + + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = 995, /* us */ + .pwrdn_delay_max = 1005, /* us */ +}; + +static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { + .type = PHY_TYPE_DP, + .nlanes = 1, + + .serdes_tbl = qmp_v4_dp_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), + .tx_tbl = qmp_v4_dp_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), + + .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), + .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), + .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), + .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, + .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), + + .clk_list = qmp_v3_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), + .reset_list = sc7180_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + + .has_phy_dp_com_ctrl = true, + .is_dual_lane_phy = true, + + .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, + .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, + .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, + .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, +}; + +static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { + .usb_cfg = &sm8150_usb3phy_cfg, + .dp_cfg = &sc8180x_dpphy_cfg, +}; + static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { .type = PHY_TYPE_USB3, .nlanes = 1, @@ -5018,6 +5316,7 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, { struct clk_init_data init = { }; struct qmp_phy_dp_clks *dp_clks; + char name[64]; int ret; dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); @@ -5027,15 +5326,17 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, dp_clks->qphy = qphy; qphy->dp_clks = dp_clks; + snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); init.ops = &qcom_qmp_dp_link_clk_ops; - init.name = "qmp_dp_phy_pll_link_clk"; + init.name = name; dp_clks->dp_link_hw.init = &init; ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); if (ret) return ret; + snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); init.ops = &qcom_qmp_dp_pixel_clk_ops; - init.name = "qmp_dp_phy_pll_vco_div_clk"; + init.name = name; dp_clks->dp_pixel_hw.init = &init; ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); if (ret) @@ -5226,18 +5527,27 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { .compatible = "qcom,ipq6018-qmp-pcie-phy", .data = &ipq6018_pciephy_cfg, }, { + .compatible = "qcom,ipq6018-qmp-usb3-phy", + .data = &ipq8074_usb3phy_cfg, + }, { .compatible = "qcom,sc7180-qmp-usb3-phy", .data = &sc7180_usb3phy_cfg, }, { .compatible = "qcom,sc7180-qmp-usb3-dp-phy", /* It's a combo phy */ }, { + .compatible = "qcom,sc8180x-qmp-pcie-phy", + .data = &sc8180x_pciephy_cfg, + }, { .compatible = "qcom,sc8180x-qmp-ufs-phy", .data = &sm8150_ufsphy_cfg, }, { .compatible = "qcom,sc8180x-qmp-usb3-phy", .data = &sm8150_usb3phy_cfg, }, { + .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", + /* It's a combo phy */ + }, { .compatible = "qcom,sdm845-qhp-pcie-phy", .data = &sdm845_qhp_pciephy_cfg, }, { @@ -5256,6 +5566,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { .compatible = "qcom,msm8998-qmp-usb3-phy", .data = &msm8998_usb3phy_cfg, }, { + .compatible = "qcom,sm6115-qmp-ufs-phy", + .data = &sm6115_ufsphy_cfg, + }, { .compatible = "qcom,sm8150-qmp-ufs-phy", .data = &sm8150_ufsphy_cfg, }, { @@ -5314,6 +5627,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { .compatible = "qcom,sm8250-qmp-usb3-dp-phy", .data = &sm8250_usb3dpphy_cfg, }, + { + .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", + .data = &sc8180x_usb3dpphy_cfg, + }, { } }; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index 6592b58b13f6..bebeac2c091c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -191,6 +191,8 @@ #define QSERDES_COM_VCO_TUNE2_MODE0 0x130 #define QSERDES_COM_VCO_TUNE1_MODE1 0x134 #define QSERDES_COM_VCO_TUNE2_MODE1 0x138 +#define QSERDES_COM_VCO_TUNE_INITVAL1 0x13c +#define QSERDES_COM_VCO_TUNE_INITVAL2 0x140 #define QSERDES_COM_VCO_TUNE_TIMER1 0x144 #define QSERDES_COM_VCO_TUNE_TIMER2 0x148 #define QSERDES_COM_BG_CTRL 0x170 @@ -220,6 +222,10 @@ /* Only for QMP V2 PHY - RX registers */ #define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010 #define QSERDES_RX_UCDR_SO_GAIN 0x01c +#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF 0x030 +#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER 0x034 +#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH 0x038 +#define QSERDES_RX_UCDR_SVS_SO_GAIN 0x03c #define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040 #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048 #define QSERDES_RX_RX_TERM_BW 0x090 @@ -243,6 +249,10 @@ #define QPHY_POWER_DOWN_CONTROL 0x04 #define QPHY_TXDEEMPH_M6DB_V0 0x24 #define QPHY_TXDEEMPH_M3P5DB_V0 0x28 +#define QPHY_TX_LARGE_AMP_DRV_LVL 0x34 +#define QPHY_TX_LARGE_AMP_POST_EMP_LVL 0x38 +#define QPHY_TX_SMALL_AMP_DRV_LVL 0x3c +#define QPHY_TX_SMALL_AMP_POST_EMP_LVL 0x40 #define QPHY_ENDPOINT_REFCLK_DRIVE 0x54 #define QPHY_RX_IDLE_DTCT_CNTRL 0x58 #define QPHY_POWER_STATE_CONFIG1 0x60 @@ -253,6 +263,11 @@ #define QPHY_LOCK_DETECT_CONFIG3 0x88 #define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0 #define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4 +#define QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP 0xcc +#define QPHY_RX_SYM_RESYNC_CTRL 0x13c +#define QPHY_RX_MIN_HIBERN8_TIME 0x140 +#define QPHY_RX_SIGDET_CTRL2 0x148 +#define QPHY_RX_PWM_GEAR_BAND 0x154 #define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8 #define QPHY_OSC_DTCT_ACTIONS 0x1AC #define QPHY_RX_SIGDET_LVL 0x1D8 @@ -280,6 +295,8 @@ #define QSERDES_V3_COM_SSC_PER2 0x020 #define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024 #define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028 +#define QSERDES_V3_COM_POST_DIV 0x02c +#define QSERDES_V3_COM_POST_DIV_MUX 0x030 #define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034 # define QSERDES_V3_COM_BIAS_EN 0x0001 # define QSERDES_V3_COM_BIAS_EN_MUX 0x0002 @@ -291,6 +308,7 @@ #define QSERDES_V3_COM_CLK_ENABLE1 0x038 #define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c #define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040 +#define QSERDES_V3_COM_PLL_EN 0x044 #define QSERDES_V3_COM_PLL_IVCO 0x048 #define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098 #define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 5c6c17673396..53e46c220a3a 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (C) 2016 Linaro Ltd */ #include <linux/module.h> diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index fbc55232120e..9de617ca9daa 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -64,6 +64,7 @@ /* VBCTRL */ #define USB2_VBCTRL_OCCLREN BIT(16) #define USB2_VBCTRL_DRVVBUSSEL BIT(8) +#define USB2_VBCTRL_VBOUT BIT(0) /* LINECTRL1 */ #define USB2_LINECTRL1_DPRPD_EN BIT(19) @@ -78,6 +79,10 @@ #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ #define USB2_ADPCTRL_DRVVBUS BIT(4) +/* RZ/G2L specific */ +#define USB2_OBINT_IDCHG_EN BIT(0) +#define USB2_LINECTRL1_USB2_IDMON BIT(0) + #define NUM_OF_PHYS 4 enum rcar_gen3_phy_index { PHY_INDEX_BOTH_HC, @@ -112,9 +117,16 @@ struct rcar_gen3_chan { struct mutex lock; /* protects rphys[...].powered */ enum usb_dr_mode dr_mode; int irq; + u32 obint_enable_bits; bool extcon_host; bool is_otg_channel; bool uses_otg_pins; + bool soc_no_adp_ctrl; +}; + +struct rcar_gen3_phy_drv_data { + const struct phy_ops *phy_usb2_ops; + bool no_adp_ctrl; }; /* @@ -172,14 +184,22 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) { void __iomem *usb2_base = ch->base; - u32 val = readl(usb2_base + USB2_ADPCTRL); + u32 vbus_ctrl_reg = USB2_ADPCTRL; + u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS; + u32 val; dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus); + if (ch->soc_no_adp_ctrl) { + vbus_ctrl_reg = USB2_VBCTRL; + vbus_ctrl_val = USB2_VBCTRL_VBOUT; + } + + val = readl(usb2_base + vbus_ctrl_reg); if (vbus) - val |= USB2_ADPCTRL_DRVVBUS; + val |= vbus_ctrl_val; else - val &= ~USB2_ADPCTRL_DRVVBUS; - writel(val, usb2_base + USB2_ADPCTRL); + val &= ~vbus_ctrl_val; + writel(val, usb2_base + vbus_ctrl_reg); } static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) @@ -188,9 +208,9 @@ static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) u32 val = readl(usb2_base + USB2_OBINTEN); if (ch->uses_otg_pins && enable) - val |= USB2_OBINT_BITS; + val |= ch->obint_enable_bits; else - val &= ~USB2_OBINT_BITS; + val &= ~ch->obint_enable_bits; writel(val, usb2_base + USB2_OBINTEN); } @@ -252,6 +272,9 @@ static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) if (!ch->uses_otg_pins) return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true; + if (ch->soc_no_adp_ctrl) + return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON); + return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); } @@ -376,16 +399,17 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD; writel(val, usb2_base + USB2_LINECTRL1); - val = readl(usb2_base + USB2_VBCTRL); - val &= ~USB2_VBCTRL_OCCLREN; - writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); - val = readl(usb2_base + USB2_ADPCTRL); - writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); - + if (!ch->soc_no_adp_ctrl) { + val = readl(usb2_base + USB2_VBCTRL); + val &= ~USB2_VBCTRL_OCCLREN; + writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); + val = readl(usb2_base + USB2_ADPCTRL); + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); + } msleep(20); writel(0xffffffff, usb2_base + USB2_OBINTSTA); - writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); rcar_gen3_device_recognition(ch); } @@ -397,9 +421,9 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) u32 status = readl(usb2_base + USB2_OBINTSTA); irqreturn_t ret = IRQ_NONE; - if (status & USB2_OBINT_BITS) { + if (status & ch->obint_enable_bits) { dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); - writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); rcar_gen3_device_recognition(ch); ret = IRQ_HANDLED; } @@ -535,26 +559,45 @@ static const struct phy_ops rz_g1c_phy_usb2_ops = { .owner = THIS_MODULE, }; +static const struct rcar_gen3_phy_drv_data rcar_gen3_phy_usb2_data = { + .phy_usb2_ops = &rcar_gen3_phy_usb2_ops, + .no_adp_ctrl = false, +}; + +static const struct rcar_gen3_phy_drv_data rz_g1c_phy_usb2_data = { + .phy_usb2_ops = &rz_g1c_phy_usb2_ops, + .no_adp_ctrl = false, +}; + +static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = { + .phy_usb2_ops = &rcar_gen3_phy_usb2_ops, + .no_adp_ctrl = true, +}; + static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { { .compatible = "renesas,usb2-phy-r8a77470", - .data = &rz_g1c_phy_usb2_ops, + .data = &rz_g1c_phy_usb2_data, }, { .compatible = "renesas,usb2-phy-r8a7795", - .data = &rcar_gen3_phy_usb2_ops, + .data = &rcar_gen3_phy_usb2_data, }, { .compatible = "renesas,usb2-phy-r8a7796", - .data = &rcar_gen3_phy_usb2_ops, + .data = &rcar_gen3_phy_usb2_data, }, { .compatible = "renesas,usb2-phy-r8a77965", - .data = &rcar_gen3_phy_usb2_ops, + .data = &rcar_gen3_phy_usb2_data, + }, + { + .compatible = "renesas,rzg2l-usb2-phy", + .data = &rz_g2l_phy_usb2_data, }, { .compatible = "renesas,rcar-gen3-usb2-phy", - .data = &rcar_gen3_phy_usb2_ops, + .data = &rcar_gen3_phy_usb2_data, }, { /* sentinel */ }, }; @@ -608,10 +651,10 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np) static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) { + const struct rcar_gen3_phy_drv_data *phy_data; struct device *dev = &pdev->dev; struct rcar_gen3_chan *channel; struct phy_provider *provider; - const struct phy_ops *phy_usb2_ops; int ret = 0, i; if (!dev->of_node) { @@ -627,6 +670,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) if (IS_ERR(channel->base)) return PTR_ERR(channel->base); + channel->obint_enable_bits = USB2_OBINT_BITS; /* get irq number here and request_irq for OTG in phy_init */ channel->irq = platform_get_irq_optional(pdev, 0); channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); @@ -653,16 +697,21 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) * And then, phy-core will manage runtime pm for this device. */ pm_runtime_enable(dev); - phy_usb2_ops = of_device_get_match_data(dev); - if (!phy_usb2_ops) { + + phy_data = of_device_get_match_data(dev); + if (!phy_data) { ret = -EINVAL; goto error; } + channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl; + if (phy_data->no_adp_ctrl) + channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; + mutex_init(&channel->lock); for (i = 0; i < NUM_OF_PHYS; i++) { channel->rphys[i].phy = devm_phy_create(dev, NULL, - phy_usb2_ops); + phy_data->phy_usb2_ops); if (IS_ERR(channel->rphys[i].phy)) { dev_err(dev, "Failed to create USB2 PHY\n"); ret = PTR_ERR(channel->rphys[i].phy); diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index beacac1dd253..4f569d9307b9 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -1180,8 +1180,10 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) next_child: /* to prevent out of boundary */ - if (++index >= rphy->phy_cfg->num_ports) + if (++index >= rphy->phy_cfg->num_ports) { + of_node_put(child_np); break; + } } provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile index 3959100fe8a2..65e4cc59403f 100644 --- a/drivers/phy/samsung/Makefile +++ b/drivers/phy/samsung/Makefile @@ -2,7 +2,10 @@ obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o -obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-samsung-ufs.o +obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-ufs.o +phy-exynos-ufs-y += phy-samsung-ufs.o +phy-exynos-ufs-y += phy-exynos7-ufs.o +phy-exynos-ufs-y += phy-exynosautov9-ufs.o obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o phy-exynos-usb2-y += phy-samsung-usb2.o phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o diff --git a/drivers/phy/samsung/phy-exynos7-ufs.h b/drivers/phy/samsung/phy-exynos7-ufs.c index 518923141958..7c9008e163db 100644 --- a/drivers/phy/samsung/phy-exynos7-ufs.h +++ b/drivers/phy/samsung/phy-exynos7-ufs.c @@ -1,11 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ +// SPDX-License-Identifier: GPL-2.0-only /* * UFS PHY driver data for Samsung EXYNOS7 SoC * * Copyright (C) 2020 Samsung Electronics Co., Ltd. */ -#ifndef _PHY_EXYNOS7_UFS_H_ -#define _PHY_EXYNOS7_UFS_H_ #include "phy-samsung-ufs.h" @@ -68,7 +66,7 @@ static const struct samsung_ufs_phy_cfg *exynos7_ufs_phy_cfgs[CFG_TAG_MAX] = { [CFG_POST_PWR_HS] = exynos7_post_pwr_hs_cfg, }; -static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = { +const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = { .cfg = exynos7_ufs_phy_cfgs, .isol = { .offset = EXYNOS7_EMBEDDED_COMBO_PHY_CTRL, @@ -77,5 +75,3 @@ static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = { }, .has_symbol_clk = 1, }; - -#endif /* _PHY_EXYNOS7_UFS_H_ */ diff --git a/drivers/phy/samsung/phy-exynosautov9-ufs.c b/drivers/phy/samsung/phy-exynosautov9-ufs.c new file mode 100644 index 000000000000..36398a15c2db --- /dev/null +++ b/drivers/phy/samsung/phy-exynosautov9-ufs.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * UFS PHY driver data for Samsung EXYNOSAUTO v9 SoC + * + * Copyright (C) 2021 Samsung Electronics Co., Ltd. + */ + +#include "phy-samsung-ufs.h" + +#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL 0x728 +#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK 0x1 +#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN BIT(0) + +#define PHY_TRSV_REG_CFG_AUTOV9(o, v, d) \ + PHY_TRSV_REG_CFG_OFFSET(o, v, d, 0x50) + +/* Calibration for phy initialization */ +static const struct samsung_ufs_phy_cfg exynosautov9_pre_init_cfg[] = { + PHY_COMN_REG_CFG(0x023, 0x80, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x01d, 0x10, PWR_MODE_ANY), + + PHY_TRSV_REG_CFG_AUTOV9(0x044, 0xb5, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x04d, 0x43, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x05b, 0x20, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x05e, 0xc0, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x038, 0x12, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x059, 0x58, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x06c, 0x18, PWR_MODE_ANY), + PHY_TRSV_REG_CFG_AUTOV9(0x06d, 0x02, PWR_MODE_ANY), + + PHY_COMN_REG_CFG(0x023, 0xc0, PWR_MODE_ANY), + PHY_COMN_REG_CFG(0x023, 0x00, PWR_MODE_ANY), + + PHY_TRSV_REG_CFG(0x042, 0x5d, PWR_MODE_ANY), + PHY_TRSV_REG_CFG(0x043, 0x80, PWR_MODE_ANY), + + END_UFS_PHY_CFG, +}; + +/* Calibration for HS mode series A/B */ +static const struct samsung_ufs_phy_cfg exynosautov9_pre_pwr_hs_cfg[] = { + PHY_TRSV_REG_CFG(0x032, 0xbc, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG(0x03c, 0x7f, PWR_MODE_HS_ANY), + PHY_TRSV_REG_CFG(0x048, 0xc0, PWR_MODE_HS_ANY), + + PHY_TRSV_REG_CFG(0x04a, 0x00, PWR_MODE_HS_G3_SER_B), + PHY_TRSV_REG_CFG(0x04b, 0x10, PWR_MODE_HS_G1_SER_B | + PWR_MODE_HS_G3_SER_B), + PHY_TRSV_REG_CFG(0x04d, 0x63, PWR_MODE_HS_G3_SER_B), + + END_UFS_PHY_CFG, +}; + +static const struct samsung_ufs_phy_cfg *exynosautov9_ufs_phy_cfgs[CFG_TAG_MAX] = { + [CFG_PRE_INIT] = exynosautov9_pre_init_cfg, + [CFG_PRE_PWR_HS] = exynosautov9_pre_pwr_hs_cfg, +}; + +const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = { + .cfg = exynosautov9_ufs_phy_cfgs, + .isol = { + .offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL, + .mask = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK, + .en = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN, + }, + .has_symbol_clk = 0, +}; diff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c index dd9ab1519d83..602ddef259eb 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.c +++ b/drivers/phy/samsung/phy-samsung-ufs.c @@ -347,6 +347,9 @@ static const struct of_device_id samsung_ufs_phy_match[] = { { .compatible = "samsung,exynos7-ufs-phy", .data = &exynos7_ufs_phy, + }, { + .compatible = "samsung,exynosautov9-ufs-phy", + .data = &exynosautov9_ufs_phy, }, {}, }; diff --git a/drivers/phy/samsung/phy-samsung-ufs.h b/drivers/phy/samsung/phy-samsung-ufs.h index 5de78710524c..91a0e9f94f98 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.h +++ b/drivers/phy/samsung/phy-samsung-ufs.h @@ -10,6 +10,9 @@ #ifndef _PHY_SAMSUNG_UFS_ #define _PHY_SAMSUNG_UFS_ +#include <linux/phy/phy.h> +#include <linux/regmap.h> + #define PHY_COMN_BLK 1 #define PHY_TRSV_BLK 2 #define END_UFS_PHY_CFG { 0 } @@ -24,14 +27,17 @@ .id = PHY_COMN_BLK, \ } -#define PHY_TRSV_REG_CFG(o, v, d) { \ +#define PHY_TRSV_REG_CFG_OFFSET(o, v, d, c) { \ .off_0 = PHY_APB_ADDR((o)), \ - .off_1 = PHY_APB_ADDR((o) + PHY_TRSV_CH_OFFSET), \ + .off_1 = PHY_APB_ADDR((o) + (c)), \ .val = (v), \ .desc = (d), \ .id = PHY_TRSV_BLK, \ } +#define PHY_TRSV_REG_CFG(o, v, d) \ + PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_TRSV_CH_OFFSET) + /* UFS PHY registers */ #define PHY_PLL_LOCK_STATUS 0x1e #define PHY_CDR_LOCK_STATUS 0x5e @@ -134,6 +140,7 @@ static inline void samsung_ufs_phy_ctrl_isol( phy->isol->mask, isol ? 0 : phy->isol->en); } -#include "phy-exynos7-ufs.h" +extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy; +extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy; #endif /* _PHY_SAMSUNG_UFS_ */ diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 0aadac678191..963de5913e50 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -1273,7 +1273,7 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) return err; } -static int tegra_xusb_padctl_suspend_noirq(struct device *dev) +static __maybe_unused int tegra_xusb_padctl_suspend_noirq(struct device *dev) { struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); @@ -1283,7 +1283,7 @@ static int tegra_xusb_padctl_suspend_noirq(struct device *dev) return 0; } -static int tegra_xusb_padctl_resume_noirq(struct device *dev) +static __maybe_unused int tegra_xusb_padctl_resume_noirq(struct device *dev) { struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c index 5771e2486a3b..ac71017a0bc1 100644 --- a/drivers/phy/ti/phy-twl4030-usb.c +++ b/drivers/phy/ti/phy-twl4030-usb.c @@ -162,6 +162,8 @@ struct twl4030_usb { atomic_t connected; bool vbus_supplied; bool musb_mailbox_pending; + unsigned long runtime_suspended:1; + unsigned long needs_resume:1; struct delayed_work id_workaround_work; }; @@ -384,6 +386,9 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on) WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); } +static int twl4030_usb_runtime_suspend(struct device *dev); +static int twl4030_usb_runtime_resume(struct device *dev); + static int __maybe_unused twl4030_usb_suspend(struct device *dev) { struct twl4030_usb *twl = dev_get_drvdata(dev); @@ -395,6 +400,10 @@ static int __maybe_unused twl4030_usb_suspend(struct device *dev) */ dev_dbg(twl->dev, "%s\n", __func__); disable_irq(twl->irq); + if (!twl->runtime_suspended && !atomic_read(&twl->connected)) { + twl4030_usb_runtime_suspend(dev); + twl->needs_resume = 1; + } return 0; } @@ -405,9 +414,13 @@ static int __maybe_unused twl4030_usb_resume(struct device *dev) dev_dbg(twl->dev, "%s\n", __func__); enable_irq(twl->irq); + if (twl->needs_resume) + twl4030_usb_runtime_resume(dev); /* check whether cable status changed */ twl4030_usb_irq(0, twl); + twl->runtime_suspended = 0; + return 0; } @@ -422,6 +435,8 @@ static int __maybe_unused twl4030_usb_runtime_suspend(struct device *dev) regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); + twl->runtime_suspended = 1; + return 0; } diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c index 35652152ce5d..f478d8a17115 100644 --- a/drivers/phy/xilinx/phy-zynqmp.c +++ b/drivers/phy/xilinx/phy-zynqmp.c @@ -626,6 +626,9 @@ static int xpsgtr_phy_power_on(struct phy *phy) struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy); int ret = 0; + /* Skip initialization if not required. */ + if (!xpsgtr_phy_init_required(gtr_phy)) + return ret; /* * Wait for the PLL to lock. For DP, only wait on DP0 to avoid * cumulating waits for both lanes. The user is expected to initialize |