162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 Rockchip Electronics Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <dt-bindings/phy/phy.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1162306a36Sopenharmony_ci#include <linux/of.h> 1262306a36Sopenharmony_ci#include <linux/phy/phy.h> 1362306a36Sopenharmony_ci#include <linux/platform_device.h> 1462306a36Sopenharmony_ci#include <linux/regmap.h> 1562306a36Sopenharmony_ci#include <linux/reset.h> 1662306a36Sopenharmony_ci#include <linux/units.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define BIT_WRITEABLE_SHIFT 16 1962306a36Sopenharmony_ci#define REF_CLOCK_24MHz (24 * HZ_PER_MHZ) 2062306a36Sopenharmony_ci#define REF_CLOCK_25MHz (25 * HZ_PER_MHZ) 2162306a36Sopenharmony_ci#define REF_CLOCK_100MHz (100 * HZ_PER_MHZ) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* COMBO PHY REG */ 2462306a36Sopenharmony_ci#define PHYREG6 0x14 2562306a36Sopenharmony_ci#define PHYREG6_PLL_DIV_MASK GENMASK(7, 6) 2662306a36Sopenharmony_ci#define PHYREG6_PLL_DIV_SHIFT 6 2762306a36Sopenharmony_ci#define PHYREG6_PLL_DIV_2 1 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define PHYREG7 0x18 3062306a36Sopenharmony_ci#define PHYREG7_TX_RTERM_MASK GENMASK(7, 4) 3162306a36Sopenharmony_ci#define PHYREG7_TX_RTERM_SHIFT 4 3262306a36Sopenharmony_ci#define PHYREG7_TX_RTERM_50OHM 8 3362306a36Sopenharmony_ci#define PHYREG7_RX_RTERM_MASK GENMASK(3, 0) 3462306a36Sopenharmony_ci#define PHYREG7_RX_RTERM_SHIFT 0 3562306a36Sopenharmony_ci#define PHYREG7_RX_RTERM_44OHM 15 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define PHYREG8 0x1C 3862306a36Sopenharmony_ci#define PHYREG8_SSC_EN BIT(4) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define PHYREG11 0x28 4162306a36Sopenharmony_ci#define PHYREG11_SU_TRIM_0_7 0xF0 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define PHYREG12 0x2C 4462306a36Sopenharmony_ci#define PHYREG12_PLL_LPF_ADJ_VALUE 4 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define PHYREG13 0x30 4762306a36Sopenharmony_ci#define PHYREG13_RESISTER_MASK GENMASK(5, 4) 4862306a36Sopenharmony_ci#define PHYREG13_RESISTER_SHIFT 0x4 4962306a36Sopenharmony_ci#define PHYREG13_RESISTER_HIGH_Z 3 5062306a36Sopenharmony_ci#define PHYREG13_CKRCV_AMP0 BIT(7) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define PHYREG14 0x34 5362306a36Sopenharmony_ci#define PHYREG14_CKRCV_AMP1 BIT(0) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define PHYREG15 0x38 5662306a36Sopenharmony_ci#define PHYREG15_CTLE_EN BIT(0) 5762306a36Sopenharmony_ci#define PHYREG15_SSC_CNT_MASK GENMASK(7, 6) 5862306a36Sopenharmony_ci#define PHYREG15_SSC_CNT_SHIFT 6 5962306a36Sopenharmony_ci#define PHYREG15_SSC_CNT_VALUE 1 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define PHYREG16 0x3C 6262306a36Sopenharmony_ci#define PHYREG16_SSC_CNT_VALUE 0x5f 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define PHYREG18 0x44 6562306a36Sopenharmony_ci#define PHYREG18_PLL_LOOP 0x32 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define PHYREG27 0x6C 6862306a36Sopenharmony_ci#define PHYREG27_RX_TRIM_RK3588 0x4C 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define PHYREG32 0x7C 7162306a36Sopenharmony_ci#define PHYREG32_SSC_MASK GENMASK(7, 4) 7262306a36Sopenharmony_ci#define PHYREG32_SSC_DIR_SHIFT 4 7362306a36Sopenharmony_ci#define PHYREG32_SSC_UPWARD 0 7462306a36Sopenharmony_ci#define PHYREG32_SSC_DOWNWARD 1 7562306a36Sopenharmony_ci#define PHYREG32_SSC_OFFSET_SHIFT 6 7662306a36Sopenharmony_ci#define PHYREG32_SSC_OFFSET_500PPM 1 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define PHYREG33 0x80 7962306a36Sopenharmony_ci#define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2) 8062306a36Sopenharmony_ci#define PHYREG33_PLL_KVCO_SHIFT 2 8162306a36Sopenharmony_ci#define PHYREG33_PLL_KVCO_VALUE 2 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistruct rockchip_combphy_priv; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct combphy_reg { 8662306a36Sopenharmony_ci u16 offset; 8762306a36Sopenharmony_ci u16 bitend; 8862306a36Sopenharmony_ci u16 bitstart; 8962306a36Sopenharmony_ci u16 disable; 9062306a36Sopenharmony_ci u16 enable; 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct rockchip_combphy_grfcfg { 9462306a36Sopenharmony_ci struct combphy_reg pcie_mode_set; 9562306a36Sopenharmony_ci struct combphy_reg usb_mode_set; 9662306a36Sopenharmony_ci struct combphy_reg sgmii_mode_set; 9762306a36Sopenharmony_ci struct combphy_reg qsgmii_mode_set; 9862306a36Sopenharmony_ci struct combphy_reg pipe_rxterm_set; 9962306a36Sopenharmony_ci struct combphy_reg pipe_txelec_set; 10062306a36Sopenharmony_ci struct combphy_reg pipe_txcomp_set; 10162306a36Sopenharmony_ci struct combphy_reg pipe_clk_25m; 10262306a36Sopenharmony_ci struct combphy_reg pipe_clk_100m; 10362306a36Sopenharmony_ci struct combphy_reg pipe_phymode_sel; 10462306a36Sopenharmony_ci struct combphy_reg pipe_rate_sel; 10562306a36Sopenharmony_ci struct combphy_reg pipe_rxterm_sel; 10662306a36Sopenharmony_ci struct combphy_reg pipe_txelec_sel; 10762306a36Sopenharmony_ci struct combphy_reg pipe_txcomp_sel; 10862306a36Sopenharmony_ci struct combphy_reg pipe_clk_ext; 10962306a36Sopenharmony_ci struct combphy_reg pipe_sel_usb; 11062306a36Sopenharmony_ci struct combphy_reg pipe_sel_qsgmii; 11162306a36Sopenharmony_ci struct combphy_reg pipe_phy_status; 11262306a36Sopenharmony_ci struct combphy_reg con0_for_pcie; 11362306a36Sopenharmony_ci struct combphy_reg con1_for_pcie; 11462306a36Sopenharmony_ci struct combphy_reg con2_for_pcie; 11562306a36Sopenharmony_ci struct combphy_reg con3_for_pcie; 11662306a36Sopenharmony_ci struct combphy_reg con0_for_sata; 11762306a36Sopenharmony_ci struct combphy_reg con1_for_sata; 11862306a36Sopenharmony_ci struct combphy_reg con2_for_sata; 11962306a36Sopenharmony_ci struct combphy_reg con3_for_sata; 12062306a36Sopenharmony_ci struct combphy_reg pipe_con0_for_sata; 12162306a36Sopenharmony_ci struct combphy_reg pipe_con1_for_sata; 12262306a36Sopenharmony_ci struct combphy_reg pipe_xpcs_phy_ready; 12362306a36Sopenharmony_ci struct combphy_reg pipe_pcie1l0_sel; 12462306a36Sopenharmony_ci struct combphy_reg pipe_pcie1l1_sel; 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistruct rockchip_combphy_cfg { 12862306a36Sopenharmony_ci const struct rockchip_combphy_grfcfg *grfcfg; 12962306a36Sopenharmony_ci int (*combphy_cfg)(struct rockchip_combphy_priv *priv); 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistruct rockchip_combphy_priv { 13362306a36Sopenharmony_ci u8 type; 13462306a36Sopenharmony_ci void __iomem *mmio; 13562306a36Sopenharmony_ci int num_clks; 13662306a36Sopenharmony_ci struct clk_bulk_data *clks; 13762306a36Sopenharmony_ci struct device *dev; 13862306a36Sopenharmony_ci struct regmap *pipe_grf; 13962306a36Sopenharmony_ci struct regmap *phy_grf; 14062306a36Sopenharmony_ci struct phy *phy; 14162306a36Sopenharmony_ci struct reset_control *phy_rst; 14262306a36Sopenharmony_ci const struct rockchip_combphy_cfg *cfg; 14362306a36Sopenharmony_ci bool enable_ssc; 14462306a36Sopenharmony_ci bool ext_refclk; 14562306a36Sopenharmony_ci struct clk *refclk; 14662306a36Sopenharmony_ci}; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv, 14962306a36Sopenharmony_ci int mask, int val, int reg) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci unsigned int temp; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci temp = readl(priv->mmio + reg); 15462306a36Sopenharmony_ci temp = (temp & ~(mask)) | val; 15562306a36Sopenharmony_ci writel(temp, priv->mmio + reg); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic int rockchip_combphy_param_write(struct regmap *base, 15962306a36Sopenharmony_ci const struct combphy_reg *reg, bool en) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci u32 val, mask, tmp; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci tmp = en ? reg->enable : reg->disable; 16462306a36Sopenharmony_ci mask = GENMASK(reg->bitend, reg->bitstart); 16562306a36Sopenharmony_ci val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return regmap_write(base, reg->offset, val); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 17362306a36Sopenharmony_ci u32 mask, val; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci mask = GENMASK(cfg->pipe_phy_status.bitend, 17662306a36Sopenharmony_ci cfg->pipe_phy_status.bitstart); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); 17962306a36Sopenharmony_ci val = (val & mask) >> cfg->pipe_phy_status.bitstart; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return val; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic int rockchip_combphy_init(struct phy *phy) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); 18762306a36Sopenharmony_ci const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 18862306a36Sopenharmony_ci u32 val; 18962306a36Sopenharmony_ci int ret; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); 19262306a36Sopenharmony_ci if (ret) { 19362306a36Sopenharmony_ci dev_err(priv->dev, "failed to enable clks\n"); 19462306a36Sopenharmony_ci return ret; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci switch (priv->type) { 19862306a36Sopenharmony_ci case PHY_TYPE_PCIE: 19962306a36Sopenharmony_ci case PHY_TYPE_USB3: 20062306a36Sopenharmony_ci case PHY_TYPE_SATA: 20162306a36Sopenharmony_ci case PHY_TYPE_SGMII: 20262306a36Sopenharmony_ci case PHY_TYPE_QSGMII: 20362306a36Sopenharmony_ci if (priv->cfg->combphy_cfg) 20462306a36Sopenharmony_ci ret = priv->cfg->combphy_cfg(priv); 20562306a36Sopenharmony_ci break; 20662306a36Sopenharmony_ci default: 20762306a36Sopenharmony_ci dev_err(priv->dev, "incompatible PHY type\n"); 20862306a36Sopenharmony_ci ret = -EINVAL; 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (ret) { 21362306a36Sopenharmony_ci dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type); 21462306a36Sopenharmony_ci goto err_clk; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ret = reset_control_deassert(priv->phy_rst); 21862306a36Sopenharmony_ci if (ret) 21962306a36Sopenharmony_ci goto err_clk; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (priv->type == PHY_TYPE_USB3) { 22262306a36Sopenharmony_ci ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, 22362306a36Sopenharmony_ci priv, val, 22462306a36Sopenharmony_ci val == cfg->pipe_phy_status.enable, 22562306a36Sopenharmony_ci 10, 1000); 22662306a36Sopenharmony_ci if (ret) 22762306a36Sopenharmony_ci dev_warn(priv->dev, "wait phy status ready timeout\n"); 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return 0; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cierr_clk: 23362306a36Sopenharmony_ci clk_bulk_disable_unprepare(priv->num_clks, priv->clks); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return ret; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int rockchip_combphy_exit(struct phy *phy) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci clk_bulk_disable_unprepare(priv->num_clks, priv->clks); 24362306a36Sopenharmony_ci reset_control_assert(priv->phy_rst); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic const struct phy_ops rochchip_combphy_ops = { 24962306a36Sopenharmony_ci .init = rockchip_combphy_init, 25062306a36Sopenharmony_ci .exit = rockchip_combphy_exit, 25162306a36Sopenharmony_ci .owner = THIS_MODULE, 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct rockchip_combphy_priv *priv = dev_get_drvdata(dev); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (args->args_count != 1) { 25962306a36Sopenharmony_ci dev_err(dev, "invalid number of arguments\n"); 26062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (priv->type != PHY_NONE && priv->type != args->args[0]) 26462306a36Sopenharmony_ci dev_warn(dev, "phy type select %d overwriting type %d\n", 26562306a36Sopenharmony_ci args->args[0], priv->type); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci priv->type = args->args[0]; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return priv->phy; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci int i; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); 27762306a36Sopenharmony_ci if (priv->num_clks < 1) 27862306a36Sopenharmony_ci return -EINVAL; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci priv->refclk = NULL; 28162306a36Sopenharmony_ci for (i = 0; i < priv->num_clks; i++) { 28262306a36Sopenharmony_ci if (!strncmp(priv->clks[i].id, "ref", 3)) { 28362306a36Sopenharmony_ci priv->refclk = priv->clks[i].clk; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (!priv->refclk) { 28962306a36Sopenharmony_ci dev_err(dev, "no refclk found\n"); 29062306a36Sopenharmony_ci return -EINVAL; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf"); 29462306a36Sopenharmony_ci if (IS_ERR(priv->pipe_grf)) { 29562306a36Sopenharmony_ci dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n"); 29662306a36Sopenharmony_ci return PTR_ERR(priv->pipe_grf); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf"); 30062306a36Sopenharmony_ci if (IS_ERR(priv->phy_grf)) { 30162306a36Sopenharmony_ci dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n"); 30262306a36Sopenharmony_ci return PTR_ERR(priv->phy_grf); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc"); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk"); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci priv->phy_rst = devm_reset_control_array_get_exclusive(dev); 31062306a36Sopenharmony_ci if (IS_ERR(priv->phy_rst)) 31162306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n"); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return 0; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic int rockchip_combphy_probe(struct platform_device *pdev) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci struct phy_provider *phy_provider; 31962306a36Sopenharmony_ci struct device *dev = &pdev->dev; 32062306a36Sopenharmony_ci struct rockchip_combphy_priv *priv; 32162306a36Sopenharmony_ci const struct rockchip_combphy_cfg *phy_cfg; 32262306a36Sopenharmony_ci struct resource *res; 32362306a36Sopenharmony_ci int ret; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci phy_cfg = of_device_get_match_data(dev); 32662306a36Sopenharmony_ci if (!phy_cfg) { 32762306a36Sopenharmony_ci dev_err(dev, "no OF match data provided\n"); 32862306a36Sopenharmony_ci return -EINVAL; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 33262306a36Sopenharmony_ci if (!priv) 33362306a36Sopenharmony_ci return -ENOMEM; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 33662306a36Sopenharmony_ci if (IS_ERR(priv->mmio)) { 33762306a36Sopenharmony_ci ret = PTR_ERR(priv->mmio); 33862306a36Sopenharmony_ci return ret; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci priv->dev = dev; 34262306a36Sopenharmony_ci priv->type = PHY_NONE; 34362306a36Sopenharmony_ci priv->cfg = phy_cfg; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ret = rockchip_combphy_parse_dt(dev, priv); 34662306a36Sopenharmony_ci if (ret) 34762306a36Sopenharmony_ci return ret; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci ret = reset_control_assert(priv->phy_rst); 35062306a36Sopenharmony_ci if (ret) { 35162306a36Sopenharmony_ci dev_err(dev, "failed to reset phy\n"); 35262306a36Sopenharmony_ci return ret; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops); 35662306a36Sopenharmony_ci if (IS_ERR(priv->phy)) { 35762306a36Sopenharmony_ci dev_err(dev, "failed to create combphy\n"); 35862306a36Sopenharmony_ci return PTR_ERR(priv->phy); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci dev_set_drvdata(dev, priv); 36262306a36Sopenharmony_ci phy_set_drvdata(priv->phy, priv); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(phy_provider); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 37262306a36Sopenharmony_ci unsigned long rate; 37362306a36Sopenharmony_ci u32 val; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci switch (priv->type) { 37662306a36Sopenharmony_ci case PHY_TYPE_PCIE: 37762306a36Sopenharmony_ci /* Set SSC downward spread spectrum. */ 37862306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 37962306a36Sopenharmony_ci PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 38062306a36Sopenharmony_ci PHYREG32); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 38362306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 38462306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 38562306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci case PHY_TYPE_USB3: 38962306a36Sopenharmony_ci /* Set SSC downward spread spectrum. */ 39062306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 39162306a36Sopenharmony_ci PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 39262306a36Sopenharmony_ci PHYREG32); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Enable adaptive CTLE for USB3.0 Rx. */ 39562306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG15); 39662306a36Sopenharmony_ci val |= PHYREG15_CTLE_EN; 39762306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG15); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* Set PLL KVCO fine tuning signals. */ 40062306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 40162306a36Sopenharmony_ci PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT, 40262306a36Sopenharmony_ci PHYREG33); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* Enable controlling random jitter. */ 40562306a36Sopenharmony_ci writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci /* Set PLL input clock divider 1/2. */ 40862306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 40962306a36Sopenharmony_ci PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT, 41062306a36Sopenharmony_ci PHYREG6); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 41362306a36Sopenharmony_ci writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 41662306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 41762306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 41862306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci case PHY_TYPE_SATA: 42262306a36Sopenharmony_ci /* Enable adaptive CTLE for SATA Rx. */ 42362306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG15); 42462306a36Sopenharmony_ci val |= PHYREG15_CTLE_EN; 42562306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG15); 42662306a36Sopenharmony_ci /* 42762306a36Sopenharmony_ci * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA. 42862306a36Sopenharmony_ci * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm) 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_ci val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT; 43162306a36Sopenharmony_ci val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT; 43262306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG7); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true); 43562306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true); 43662306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true); 43762306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true); 43862306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 43962306a36Sopenharmony_ci break; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci case PHY_TYPE_SGMII: 44262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 44362306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 44462306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 44562306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true); 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci case PHY_TYPE_QSGMII: 44962306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true); 45062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true); 45162306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true); 45262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true); 45362306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true); 45462306a36Sopenharmony_ci break; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci default: 45762306a36Sopenharmony_ci dev_err(priv->dev, "incompatible PHY type\n"); 45862306a36Sopenharmony_ci return -EINVAL; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci rate = clk_get_rate(priv->refclk); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci switch (rate) { 46462306a36Sopenharmony_ci case REF_CLOCK_24MHz: 46562306a36Sopenharmony_ci if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) { 46662306a36Sopenharmony_ci /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */ 46762306a36Sopenharmony_ci val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT; 46862306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, 46962306a36Sopenharmony_ci val, PHYREG15); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci case REF_CLOCK_25MHz: 47662306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 47762306a36Sopenharmony_ci break; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci case REF_CLOCK_100MHz: 48062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 48162306a36Sopenharmony_ci if (priv->type == PHY_TYPE_PCIE) { 48262306a36Sopenharmony_ci /* PLL KVCO fine tuning. */ 48362306a36Sopenharmony_ci val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT; 48462306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 48562306a36Sopenharmony_ci val, PHYREG33); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* Enable controlling random jitter. */ 48862306a36Sopenharmony_ci writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT; 49162306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 49262306a36Sopenharmony_ci val, PHYREG6); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 49562306a36Sopenharmony_ci writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 49662306a36Sopenharmony_ci } else if (priv->type == PHY_TYPE_SATA) { 49762306a36Sopenharmony_ci /* downward spread spectrum +500ppm */ 49862306a36Sopenharmony_ci val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT; 49962306a36Sopenharmony_ci val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT; 50062306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32); 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci default: 50562306a36Sopenharmony_ci dev_err(priv->dev, "unsupported rate: %lu\n", rate); 50662306a36Sopenharmony_ci return -EINVAL; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci if (priv->ext_refclk) { 51062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); 51162306a36Sopenharmony_ci if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { 51262306a36Sopenharmony_ci val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; 51362306a36Sopenharmony_ci val |= PHYREG13_CKRCV_AMP0; 51462306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG14); 51762306a36Sopenharmony_ci val |= PHYREG14_CKRCV_AMP1; 51862306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG14); 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (priv->enable_ssc) { 52362306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG8); 52462306a36Sopenharmony_ci val |= PHYREG8_SSC_EN; 52562306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG8); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci return 0; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { 53262306a36Sopenharmony_ci /* pipe-phy-grf */ 53362306a36Sopenharmony_ci .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 53462306a36Sopenharmony_ci .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 53562306a36Sopenharmony_ci .sgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x01 }, 53662306a36Sopenharmony_ci .qsgmii_mode_set = { 0x0000, 5, 0, 0x00, 0x21 }, 53762306a36Sopenharmony_ci .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 53862306a36Sopenharmony_ci .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 53962306a36Sopenharmony_ci .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 54062306a36Sopenharmony_ci .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 54162306a36Sopenharmony_ci .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 54262306a36Sopenharmony_ci .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 54362306a36Sopenharmony_ci .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 54462306a36Sopenharmony_ci .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 54562306a36Sopenharmony_ci .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 54662306a36Sopenharmony_ci .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 54762306a36Sopenharmony_ci .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 54862306a36Sopenharmony_ci .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 54962306a36Sopenharmony_ci .pipe_sel_qsgmii = { 0x000c, 15, 13, 0x00, 0x07 }, 55062306a36Sopenharmony_ci .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 55162306a36Sopenharmony_ci .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 55262306a36Sopenharmony_ci .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 55362306a36Sopenharmony_ci .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 55462306a36Sopenharmony_ci .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 55562306a36Sopenharmony_ci .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0119 }, 55662306a36Sopenharmony_ci .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, 55762306a36Sopenharmony_ci .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c3 }, 55862306a36Sopenharmony_ci .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x4407 }, 55962306a36Sopenharmony_ci /* pipe-grf */ 56062306a36Sopenharmony_ci .pipe_con0_for_sata = { 0x0000, 15, 0, 0x00, 0x2220 }, 56162306a36Sopenharmony_ci .pipe_xpcs_phy_ready = { 0x0040, 2, 2, 0x00, 0x01 }, 56262306a36Sopenharmony_ci}; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { 56562306a36Sopenharmony_ci .grfcfg = &rk3568_combphy_grfcfgs, 56662306a36Sopenharmony_ci .combphy_cfg = rk3568_combphy_cfg, 56762306a36Sopenharmony_ci}; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 57262306a36Sopenharmony_ci unsigned long rate; 57362306a36Sopenharmony_ci u32 val; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci switch (priv->type) { 57662306a36Sopenharmony_ci case PHY_TYPE_PCIE: 57762306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 57862306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 57962306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 58062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 58162306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true); 58262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true); 58362306a36Sopenharmony_ci break; 58462306a36Sopenharmony_ci case PHY_TYPE_USB3: 58562306a36Sopenharmony_ci /* Set SSC downward spread spectrum */ 58662306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 58762306a36Sopenharmony_ci PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 58862306a36Sopenharmony_ci PHYREG32); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci /* Enable adaptive CTLE for USB3.0 Rx. */ 59162306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG15); 59262306a36Sopenharmony_ci val |= PHYREG15_CTLE_EN; 59362306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG15); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* Set PLL KVCO fine tuning signals. */ 59662306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 59762306a36Sopenharmony_ci PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT, 59862306a36Sopenharmony_ci PHYREG33); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* Enable controlling random jitter. */ 60162306a36Sopenharmony_ci writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Set PLL input clock divider 1/2. */ 60462306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 60562306a36Sopenharmony_ci PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT, 60662306a36Sopenharmony_ci PHYREG6); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 60962306a36Sopenharmony_ci writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 61262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 61362306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); 61462306a36Sopenharmony_ci break; 61562306a36Sopenharmony_ci case PHY_TYPE_SATA: 61662306a36Sopenharmony_ci /* Enable adaptive CTLE for SATA Rx. */ 61762306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG15); 61862306a36Sopenharmony_ci val |= PHYREG15_CTLE_EN; 61962306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG15); 62062306a36Sopenharmony_ci /* 62162306a36Sopenharmony_ci * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA. 62262306a36Sopenharmony_ci * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm) 62362306a36Sopenharmony_ci */ 62462306a36Sopenharmony_ci val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT; 62562306a36Sopenharmony_ci val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT; 62662306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG7); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true); 62962306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true); 63062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true); 63162306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true); 63262306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); 63362306a36Sopenharmony_ci rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); 63462306a36Sopenharmony_ci break; 63562306a36Sopenharmony_ci case PHY_TYPE_SGMII: 63662306a36Sopenharmony_ci case PHY_TYPE_QSGMII: 63762306a36Sopenharmony_ci default: 63862306a36Sopenharmony_ci dev_err(priv->dev, "incompatible PHY type\n"); 63962306a36Sopenharmony_ci return -EINVAL; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci rate = clk_get_rate(priv->refclk); 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci switch (rate) { 64562306a36Sopenharmony_ci case REF_CLOCK_24MHz: 64662306a36Sopenharmony_ci if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) { 64762306a36Sopenharmony_ci /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */ 64862306a36Sopenharmony_ci val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT; 64962306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, 65062306a36Sopenharmony_ci val, PHYREG15); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci break; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci case REF_CLOCK_25MHz: 65762306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 65862306a36Sopenharmony_ci break; 65962306a36Sopenharmony_ci case REF_CLOCK_100MHz: 66062306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 66162306a36Sopenharmony_ci if (priv->type == PHY_TYPE_PCIE) { 66262306a36Sopenharmony_ci /* PLL KVCO fine tuning. */ 66362306a36Sopenharmony_ci val = 4 << PHYREG33_PLL_KVCO_SHIFT; 66462306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 66562306a36Sopenharmony_ci val, PHYREG33); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* Enable controlling random jitter. */ 66862306a36Sopenharmony_ci writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ 67162306a36Sopenharmony_ci writel(PHYREG27_RX_TRIM_RK3588, priv->mmio + PHYREG27); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* Set up su_trim: */ 67462306a36Sopenharmony_ci writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 67562306a36Sopenharmony_ci } else if (priv->type == PHY_TYPE_SATA) { 67662306a36Sopenharmony_ci /* downward spread spectrum +500ppm */ 67762306a36Sopenharmony_ci val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT; 67862306a36Sopenharmony_ci val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT; 67962306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32); 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci break; 68262306a36Sopenharmony_ci default: 68362306a36Sopenharmony_ci dev_err(priv->dev, "Unsupported rate: %lu\n", rate); 68462306a36Sopenharmony_ci return -EINVAL; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci if (priv->ext_refclk) { 68862306a36Sopenharmony_ci rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); 68962306a36Sopenharmony_ci if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { 69062306a36Sopenharmony_ci val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; 69162306a36Sopenharmony_ci val |= PHYREG13_CKRCV_AMP0; 69262306a36Sopenharmony_ci rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG14); 69562306a36Sopenharmony_ci val |= PHYREG14_CKRCV_AMP1; 69662306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG14); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (priv->enable_ssc) { 70162306a36Sopenharmony_ci val = readl(priv->mmio + PHYREG8); 70262306a36Sopenharmony_ci val |= PHYREG8_SSC_EN; 70362306a36Sopenharmony_ci writel(val, priv->mmio + PHYREG8); 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci return 0; 70762306a36Sopenharmony_ci} 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_cistatic const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = { 71062306a36Sopenharmony_ci /* pipe-phy-grf */ 71162306a36Sopenharmony_ci .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 71262306a36Sopenharmony_ci .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 71362306a36Sopenharmony_ci .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 71462306a36Sopenharmony_ci .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 71562306a36Sopenharmony_ci .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 71662306a36Sopenharmony_ci .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 71762306a36Sopenharmony_ci .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 71862306a36Sopenharmony_ci .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 71962306a36Sopenharmony_ci .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 72062306a36Sopenharmony_ci .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 72162306a36Sopenharmony_ci .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 72262306a36Sopenharmony_ci .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 72362306a36Sopenharmony_ci .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 72462306a36Sopenharmony_ci .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 72562306a36Sopenharmony_ci .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 72662306a36Sopenharmony_ci .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 72762306a36Sopenharmony_ci .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, 72862306a36Sopenharmony_ci .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0000 }, 72962306a36Sopenharmony_ci .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, 73062306a36Sopenharmony_ci .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, 73162306a36Sopenharmony_ci /* pipe-grf */ 73262306a36Sopenharmony_ci .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 }, 73362306a36Sopenharmony_ci .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 }, 73462306a36Sopenharmony_ci .pipe_pcie1l0_sel = { 0x0100, 0, 0, 0x01, 0x0 }, 73562306a36Sopenharmony_ci .pipe_pcie1l1_sel = { 0x0100, 1, 1, 0x01, 0x0 }, 73662306a36Sopenharmony_ci}; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic const struct rockchip_combphy_cfg rk3588_combphy_cfgs = { 73962306a36Sopenharmony_ci .grfcfg = &rk3588_combphy_grfcfgs, 74062306a36Sopenharmony_ci .combphy_cfg = rk3588_combphy_cfg, 74162306a36Sopenharmony_ci}; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic const struct of_device_id rockchip_combphy_of_match[] = { 74462306a36Sopenharmony_ci { 74562306a36Sopenharmony_ci .compatible = "rockchip,rk3568-naneng-combphy", 74662306a36Sopenharmony_ci .data = &rk3568_combphy_cfgs, 74762306a36Sopenharmony_ci }, 74862306a36Sopenharmony_ci { 74962306a36Sopenharmony_ci .compatible = "rockchip,rk3588-naneng-combphy", 75062306a36Sopenharmony_ci .data = &rk3588_combphy_cfgs, 75162306a36Sopenharmony_ci }, 75262306a36Sopenharmony_ci { }, 75362306a36Sopenharmony_ci}; 75462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rockchip_combphy_of_match); 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic struct platform_driver rockchip_combphy_driver = { 75762306a36Sopenharmony_ci .probe = rockchip_combphy_probe, 75862306a36Sopenharmony_ci .driver = { 75962306a36Sopenharmony_ci .name = "rockchip-naneng-combphy", 76062306a36Sopenharmony_ci .of_match_table = rockchip_combphy_of_match, 76162306a36Sopenharmony_ci }, 76262306a36Sopenharmony_ci}; 76362306a36Sopenharmony_cimodule_platform_driver(rockchip_combphy_driver); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ciMODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver"); 76662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 767