brintos

brintos / linux-shallow public Read only

0
0
Text · 23.5 KiB · 0a9989e Raw
797 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Rockchip PIPE USB3.0 PCIE SATA Combo Phy driver4 *5 * Copyright (C) 2021 Rockchip Electronics Co., Ltd.6 */7 8#include <dt-bindings/phy/phy.h>9#include <linux/clk.h>10#include <linux/mfd/syscon.h>11#include <linux/of.h>12#include <linux/phy/phy.h>13#include <linux/platform_device.h>14#include <linux/regmap.h>15#include <linux/reset.h>16#include <linux/units.h>17 18#define BIT_WRITEABLE_SHIFT		1619#define REF_CLOCK_24MHz			(24 * HZ_PER_MHZ)20#define REF_CLOCK_25MHz			(25 * HZ_PER_MHZ)21#define REF_CLOCK_100MHz		(100 * HZ_PER_MHZ)22 23/* COMBO PHY REG */24#define PHYREG6				0x1425#define PHYREG6_PLL_DIV_MASK		GENMASK(7, 6)26#define PHYREG6_PLL_DIV_SHIFT		627#define PHYREG6_PLL_DIV_2		128 29#define PHYREG7				0x1830#define PHYREG7_TX_RTERM_MASK		GENMASK(7, 4)31#define PHYREG7_TX_RTERM_SHIFT		432#define PHYREG7_TX_RTERM_50OHM		833#define PHYREG7_RX_RTERM_MASK		GENMASK(3, 0)34#define PHYREG7_RX_RTERM_SHIFT		035#define PHYREG7_RX_RTERM_44OHM		1536 37#define PHYREG8				0x1C38#define PHYREG8_SSC_EN			BIT(4)39 40#define PHYREG11			0x2841#define PHYREG11_SU_TRIM_0_7		0xF042 43#define PHYREG12			0x2C44#define PHYREG12_PLL_LPF_ADJ_VALUE	445 46#define PHYREG13			0x3047#define PHYREG13_RESISTER_MASK		GENMASK(5, 4)48#define PHYREG13_RESISTER_SHIFT		0x449#define PHYREG13_RESISTER_HIGH_Z	350#define PHYREG13_CKRCV_AMP0		BIT(7)51 52#define PHYREG14			0x3453#define PHYREG14_CKRCV_AMP1		BIT(0)54 55#define PHYREG15			0x3856#define PHYREG15_CTLE_EN		BIT(0)57#define PHYREG15_SSC_CNT_MASK		GENMASK(7, 6)58#define PHYREG15_SSC_CNT_SHIFT		659#define PHYREG15_SSC_CNT_VALUE		160 61#define PHYREG16			0x3C62#define PHYREG16_SSC_CNT_VALUE		0x5f63 64#define PHYREG18			0x4465#define PHYREG18_PLL_LOOP		0x3266 67#define PHYREG27			0x6C68#define PHYREG27_RX_TRIM_RK3588		0x4C69 70#define PHYREG32			0x7C71#define PHYREG32_SSC_MASK		GENMASK(7, 4)72#define PHYREG32_SSC_DIR_SHIFT		473#define PHYREG32_SSC_UPWARD		074#define PHYREG32_SSC_DOWNWARD		175#define PHYREG32_SSC_OFFSET_SHIFT	676#define PHYREG32_SSC_OFFSET_500PPM	177 78#define PHYREG33			0x8079#define PHYREG33_PLL_KVCO_MASK		GENMASK(4, 2)80#define PHYREG33_PLL_KVCO_SHIFT		281#define PHYREG33_PLL_KVCO_VALUE		282 83struct rockchip_combphy_priv;84 85struct combphy_reg {86	u16 offset;87	u16 bitend;88	u16 bitstart;89	u16 disable;90	u16 enable;91};92 93struct rockchip_combphy_grfcfg {94	struct combphy_reg pcie_mode_set;95	struct combphy_reg usb_mode_set;96	struct combphy_reg sgmii_mode_set;97	struct combphy_reg qsgmii_mode_set;98	struct combphy_reg pipe_rxterm_set;99	struct combphy_reg pipe_txelec_set;100	struct combphy_reg pipe_txcomp_set;101	struct combphy_reg pipe_clk_25m;102	struct combphy_reg pipe_clk_100m;103	struct combphy_reg pipe_phymode_sel;104	struct combphy_reg pipe_rate_sel;105	struct combphy_reg pipe_rxterm_sel;106	struct combphy_reg pipe_txelec_sel;107	struct combphy_reg pipe_txcomp_sel;108	struct combphy_reg pipe_clk_ext;109	struct combphy_reg pipe_sel_usb;110	struct combphy_reg pipe_sel_qsgmii;111	struct combphy_reg pipe_phy_status;112	struct combphy_reg con0_for_pcie;113	struct combphy_reg con1_for_pcie;114	struct combphy_reg con2_for_pcie;115	struct combphy_reg con3_for_pcie;116	struct combphy_reg con0_for_sata;117	struct combphy_reg con1_for_sata;118	struct combphy_reg con2_for_sata;119	struct combphy_reg con3_for_sata;120	struct combphy_reg pipe_con0_for_sata;121	struct combphy_reg pipe_con1_for_sata;122	struct combphy_reg pipe_xpcs_phy_ready;123	struct combphy_reg pipe_pcie1l0_sel;124	struct combphy_reg pipe_pcie1l1_sel;125};126 127struct rockchip_combphy_cfg {128	unsigned int num_phys;129	unsigned int phy_ids[3];130	const struct rockchip_combphy_grfcfg *grfcfg;131	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);132};133 134struct rockchip_combphy_priv {135	u8 type;136	int id;137	void __iomem *mmio;138	int num_clks;139	struct clk_bulk_data *clks;140	struct device *dev;141	struct regmap *pipe_grf;142	struct regmap *phy_grf;143	struct phy *phy;144	struct reset_control *phy_rst;145	const struct rockchip_combphy_cfg *cfg;146	bool enable_ssc;147	bool ext_refclk;148	struct clk *refclk;149};150 151static void rockchip_combphy_updatel(struct rockchip_combphy_priv *priv,152				     int mask, int val, int reg)153{154	unsigned int temp;155 156	temp = readl(priv->mmio + reg);157	temp = (temp & ~(mask)) | val;158	writel(temp, priv->mmio + reg);159}160 161static int rockchip_combphy_param_write(struct regmap *base,162					const struct combphy_reg *reg, bool en)163{164	u32 val, mask, tmp;165 166	tmp = en ? reg->enable : reg->disable;167	mask = GENMASK(reg->bitend, reg->bitstart);168	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);169 170	return regmap_write(base, reg->offset, val);171}172 173static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)174{175	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;176	u32 mask, val;177 178	mask = GENMASK(cfg->pipe_phy_status.bitend,179		       cfg->pipe_phy_status.bitstart);180 181	regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val);182	val = (val & mask) >> cfg->pipe_phy_status.bitstart;183 184	return val;185}186 187static int rockchip_combphy_init(struct phy *phy)188{189	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);190	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;191	u32 val;192	int ret;193 194	ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);195	if (ret) {196		dev_err(priv->dev, "failed to enable clks\n");197		return ret;198	}199 200	switch (priv->type) {201	case PHY_TYPE_PCIE:202	case PHY_TYPE_USB3:203	case PHY_TYPE_SATA:204	case PHY_TYPE_SGMII:205	case PHY_TYPE_QSGMII:206		if (priv->cfg->combphy_cfg)207			ret = priv->cfg->combphy_cfg(priv);208		break;209	default:210		dev_err(priv->dev, "incompatible PHY type\n");211		ret = -EINVAL;212		break;213	}214 215	if (ret) {216		dev_err(priv->dev, "failed to init phy for phy type %x\n", priv->type);217		goto err_clk;218	}219 220	ret = reset_control_deassert(priv->phy_rst);221	if (ret)222		goto err_clk;223 224	if (priv->type == PHY_TYPE_USB3) {225		ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready,226						priv, val,227						val == cfg->pipe_phy_status.enable,228						10, 1000);229		if (ret)230			dev_warn(priv->dev, "wait phy status ready timeout\n");231	}232 233	return 0;234 235err_clk:236	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);237 238	return ret;239}240 241static int rockchip_combphy_exit(struct phy *phy)242{243	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);244 245	clk_bulk_disable_unprepare(priv->num_clks, priv->clks);246	reset_control_assert(priv->phy_rst);247 248	return 0;249}250 251static const struct phy_ops rockchip_combphy_ops = {252	.init = rockchip_combphy_init,253	.exit = rockchip_combphy_exit,254	.owner = THIS_MODULE,255};256 257static struct phy *rockchip_combphy_xlate(struct device *dev, const struct of_phandle_args *args)258{259	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);260 261	if (args->args_count != 1) {262		dev_err(dev, "invalid number of arguments\n");263		return ERR_PTR(-EINVAL);264	}265 266	if (priv->type != PHY_NONE && priv->type != args->args[0])267		dev_warn(dev, "phy type select %d overwriting type %d\n",268			 args->args[0], priv->type);269 270	priv->type = args->args[0];271 272	return priv->phy;273}274 275static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy_priv *priv)276{277	int i;278 279	priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);280	if (priv->num_clks < 1)281		return -EINVAL;282 283	priv->refclk = NULL;284	for (i = 0; i < priv->num_clks; i++) {285		if (!strncmp(priv->clks[i].id, "ref", 3)) {286			priv->refclk = priv->clks[i].clk;287			break;288		}289	}290 291	if (!priv->refclk) {292		dev_err(dev, "no refclk found\n");293		return -EINVAL;294	}295 296	priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-grf");297	if (IS_ERR(priv->pipe_grf)) {298		dev_err(dev, "failed to find peri_ctrl pipe-grf regmap\n");299		return PTR_ERR(priv->pipe_grf);300	}301 302	priv->phy_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pipe-phy-grf");303	if (IS_ERR(priv->phy_grf)) {304		dev_err(dev, "failed to find peri_ctrl pipe-phy-grf regmap\n");305		return PTR_ERR(priv->phy_grf);306	}307 308	priv->enable_ssc = device_property_present(dev, "rockchip,enable-ssc");309 310	priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");311 312	priv->phy_rst = devm_reset_control_array_get_exclusive(dev);313	if (IS_ERR(priv->phy_rst))314		return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");315 316	return 0;317}318 319static int rockchip_combphy_probe(struct platform_device *pdev)320{321	struct phy_provider *phy_provider;322	struct device *dev = &pdev->dev;323	struct rockchip_combphy_priv *priv;324	const struct rockchip_combphy_cfg *phy_cfg;325	struct resource *res;326	int ret, id;327 328	phy_cfg = of_device_get_match_data(dev);329	if (!phy_cfg) {330		dev_err(dev, "no OF match data provided\n");331		return -EINVAL;332	}333 334	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);335	if (!priv)336		return -ENOMEM;337 338	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);339	if (IS_ERR(priv->mmio)) {340		ret = PTR_ERR(priv->mmio);341		return ret;342	}343 344	/* find the phy-id from the io address */345	priv->id = -ENODEV;346	for (id = 0; id < phy_cfg->num_phys; id++) {347		if (res->start == phy_cfg->phy_ids[id]) {348			priv->id = id;349			break;350		}351	}352 353	priv->dev = dev;354	priv->type = PHY_NONE;355	priv->cfg = phy_cfg;356 357	ret = rockchip_combphy_parse_dt(dev, priv);358	if (ret)359		return ret;360 361	ret = reset_control_assert(priv->phy_rst);362	if (ret) {363		dev_err(dev, "failed to reset phy\n");364		return ret;365	}366 367	priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);368	if (IS_ERR(priv->phy)) {369		dev_err(dev, "failed to create combphy\n");370		return PTR_ERR(priv->phy);371	}372 373	dev_set_drvdata(dev, priv);374	phy_set_drvdata(priv->phy, priv);375 376	phy_provider = devm_of_phy_provider_register(dev, rockchip_combphy_xlate);377 378	return PTR_ERR_OR_ZERO(phy_provider);379}380 381static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv)382{383	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;384	unsigned long rate;385	u32 val;386 387	switch (priv->type) {388	case PHY_TYPE_PCIE:389		/* Set SSC downward spread spectrum. */390		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,391					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,392					 PHYREG32);393 394		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);395		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);396		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);397		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);398		break;399 400	case PHY_TYPE_USB3:401		/* Set SSC downward spread spectrum. */402		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,403					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,404					 PHYREG32);405 406		/* Enable adaptive CTLE for USB3.0 Rx. */407		val = readl(priv->mmio + PHYREG15);408		val |= PHYREG15_CTLE_EN;409		writel(val, priv->mmio + PHYREG15);410 411		/* Set PLL KVCO fine tuning signals. */412		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,413					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,414					 PHYREG33);415 416		/* Enable controlling random jitter. */417		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);418 419		/* Set PLL input clock divider 1/2. */420		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,421					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,422					 PHYREG6);423 424		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);425		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);426 427		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true);428		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);429		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);430		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);431		break;432 433	case PHY_TYPE_SATA:434		/* Enable adaptive CTLE for SATA Rx. */435		val = readl(priv->mmio + PHYREG15);436		val |= PHYREG15_CTLE_EN;437		writel(val, priv->mmio + PHYREG15);438		/*439		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.440		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)441		 */442		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;443		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;444		writel(val, priv->mmio + PHYREG7);445 446		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);447		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);448		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);449		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);450		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);451		break;452 453	case PHY_TYPE_SGMII:454		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);455		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);456		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);457		rockchip_combphy_param_write(priv->phy_grf, &cfg->sgmii_mode_set, true);458		break;459 460	case PHY_TYPE_QSGMII:461		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_xpcs_phy_ready, true);462		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_phymode_sel, true);463		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_rate_sel, true);464		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_qsgmii, true);465		rockchip_combphy_param_write(priv->phy_grf, &cfg->qsgmii_mode_set, true);466		break;467 468	default:469		dev_err(priv->dev, "incompatible PHY type\n");470		return -EINVAL;471	}472 473	rate = clk_get_rate(priv->refclk);474 475	switch (rate) {476	case REF_CLOCK_24MHz:477		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {478			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */479			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;480			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,481						 val, PHYREG15);482 483			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);484		}485		break;486 487	case REF_CLOCK_25MHz:488		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);489		break;490 491	case REF_CLOCK_100MHz:492		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);493		if (priv->type == PHY_TYPE_PCIE) {494			/* PLL KVCO  fine tuning. */495			val = PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT;496			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,497						 val, PHYREG33);498 499			/* Enable controlling random jitter. */500			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);501 502			val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT;503			rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,504						 val, PHYREG6);505 506			writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);507			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);508		} else if (priv->type == PHY_TYPE_SATA) {509			/* downward spread spectrum +500ppm */510			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;511			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;512			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);513		}514		break;515 516	default:517		dev_err(priv->dev, "unsupported rate: %lu\n", rate);518		return -EINVAL;519	}520 521	if (priv->ext_refclk) {522		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);523		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {524			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;525			val |= PHYREG13_CKRCV_AMP0;526			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);527 528			val = readl(priv->mmio + PHYREG14);529			val |= PHYREG14_CKRCV_AMP1;530			writel(val, priv->mmio + PHYREG14);531		}532	}533 534	if (priv->enable_ssc) {535		val = readl(priv->mmio + PHYREG8);536		val |= PHYREG8_SSC_EN;537		writel(val, priv->mmio + PHYREG8);538	}539 540	return 0;541}542 543static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {544	/* pipe-phy-grf */545	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },546	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },547	.sgmii_mode_set		= { 0x0000, 5, 0, 0x00, 0x01 },548	.qsgmii_mode_set	= { 0x0000, 5, 0, 0x00, 0x21 },549	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },550	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },551	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },552	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },553	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },554	.pipe_phymode_sel	= { 0x0008, 1, 1, 0x00, 0x01 },555	.pipe_rate_sel		= { 0x0008, 2, 2, 0x00, 0x01 },556	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },557	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },558	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },559	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },560	.pipe_sel_usb		= { 0x000c, 14, 13, 0x00, 0x01 },561	.pipe_sel_qsgmii	= { 0x000c, 15, 13, 0x00, 0x07 },562	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },563	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },564	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },565	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },566	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },567	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0119 },568	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0040 },569	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c3 },570	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x4407 },571	/* pipe-grf */572	.pipe_con0_for_sata	= { 0x0000, 15, 0, 0x00, 0x2220 },573	.pipe_xpcs_phy_ready	= { 0x0040, 2, 2, 0x00, 0x01 },574};575 576static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {577	.num_phys = 3,578	.phy_ids = {579		0xfe820000,580		0xfe830000,581		0xfe840000,582	},583	.grfcfg		= &rk3568_combphy_grfcfgs,584	.combphy_cfg	= rk3568_combphy_cfg,585};586 587static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)588{589	const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;590	unsigned long rate;591	u32 val;592 593	switch (priv->type) {594	case PHY_TYPE_PCIE:595		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);596		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);597		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);598		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);599		switch (priv->id) {600		case 1:601			rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);602			break;603		case 2:604			rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);605			break;606		}607		break;608	case PHY_TYPE_USB3:609		/* Set SSC downward spread spectrum */610		rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK,611					 PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT,612					 PHYREG32);613 614		/* Enable adaptive CTLE for USB3.0 Rx. */615		val = readl(priv->mmio + PHYREG15);616		val |= PHYREG15_CTLE_EN;617		writel(val, priv->mmio + PHYREG15);618 619		/* Set PLL KVCO fine tuning signals. */620		rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,621					 PHYREG33_PLL_KVCO_VALUE << PHYREG33_PLL_KVCO_SHIFT,622					 PHYREG33);623 624		/* Enable controlling random jitter. */625		writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);626 627		/* Set PLL input clock divider 1/2. */628		rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK,629					 PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT,630					 PHYREG6);631 632		writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);633		writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);634 635		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);636		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);637		rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);638		break;639	case PHY_TYPE_SATA:640		/* Enable adaptive CTLE for SATA Rx. */641		val = readl(priv->mmio + PHYREG15);642		val |= PHYREG15_CTLE_EN;643		writel(val, priv->mmio + PHYREG15);644		/*645		 * Set tx_rterm=50ohm and rx_rterm=44ohm for SATA.646		 * 0: 60ohm, 8: 50ohm 15: 44ohm (by step abort 1ohm)647		 */648		val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;649		val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;650		writel(val, priv->mmio + PHYREG7);651 652		rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);653		rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);654		rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);655		rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);656		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);657		rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);658		break;659	case PHY_TYPE_SGMII:660	case PHY_TYPE_QSGMII:661	default:662		dev_err(priv->dev, "incompatible PHY type\n");663		return -EINVAL;664	}665 666	rate = clk_get_rate(priv->refclk);667 668	switch (rate) {669	case REF_CLOCK_24MHz:670		if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {671			/* Set ssc_cnt[9:0]=0101111101 & 31.5KHz. */672			val = PHYREG15_SSC_CNT_VALUE << PHYREG15_SSC_CNT_SHIFT;673			rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,674						 val, PHYREG15);675 676			writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);677		}678		break;679 680	case REF_CLOCK_25MHz:681		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);682		break;683	case REF_CLOCK_100MHz:684		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);685		if (priv->type == PHY_TYPE_PCIE) {686			/* PLL KVCO fine tuning. */687			val = 4 << PHYREG33_PLL_KVCO_SHIFT;688			rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,689						 val, PHYREG33);690 691			/* Enable controlling random jitter. */692			writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);693 694			/* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */695			writel(PHYREG27_RX_TRIM_RK3588, priv->mmio + PHYREG27);696 697			/* Set up su_trim:  */698			writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);699		} else if (priv->type == PHY_TYPE_SATA) {700			/* downward spread spectrum +500ppm */701			val = PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT;702			val |= PHYREG32_SSC_OFFSET_500PPM << PHYREG32_SSC_OFFSET_SHIFT;703			rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);704		}705		break;706	default:707		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);708		return -EINVAL;709	}710 711	if (priv->ext_refclk) {712		rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);713		if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {714			val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT;715			val |= PHYREG13_CKRCV_AMP0;716			rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13);717 718			val = readl(priv->mmio + PHYREG14);719			val |= PHYREG14_CKRCV_AMP1;720			writel(val, priv->mmio + PHYREG14);721		}722	}723 724	if (priv->enable_ssc) {725		val = readl(priv->mmio + PHYREG8);726		val |= PHYREG8_SSC_EN;727		writel(val, priv->mmio + PHYREG8);728	}729 730	return 0;731}732 733static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {734	/* pipe-phy-grf */735	.pcie_mode_set		= { 0x0000, 5, 0, 0x00, 0x11 },736	.usb_mode_set		= { 0x0000, 5, 0, 0x00, 0x04 },737	.pipe_rxterm_set	= { 0x0000, 12, 12, 0x00, 0x01 },738	.pipe_txelec_set	= { 0x0004, 1, 1, 0x00, 0x01 },739	.pipe_txcomp_set	= { 0x0004, 4, 4, 0x00, 0x01 },740	.pipe_clk_25m		= { 0x0004, 14, 13, 0x00, 0x01 },741	.pipe_clk_100m		= { 0x0004, 14, 13, 0x00, 0x02 },742	.pipe_rxterm_sel	= { 0x0008, 8, 8, 0x00, 0x01 },743	.pipe_txelec_sel	= { 0x0008, 12, 12, 0x00, 0x01 },744	.pipe_txcomp_sel	= { 0x0008, 15, 15, 0x00, 0x01 },745	.pipe_clk_ext		= { 0x000c, 9, 8, 0x02, 0x01 },746	.pipe_phy_status	= { 0x0034, 6, 6, 0x01, 0x00 },747	.con0_for_pcie		= { 0x0000, 15, 0, 0x00, 0x1000 },748	.con1_for_pcie		= { 0x0004, 15, 0, 0x00, 0x0000 },749	.con2_for_pcie		= { 0x0008, 15, 0, 0x00, 0x0101 },750	.con3_for_pcie		= { 0x000c, 15, 0, 0x00, 0x0200 },751	.con0_for_sata		= { 0x0000, 15, 0, 0x00, 0x0129 },752	.con1_for_sata		= { 0x0004, 15, 0, 0x00, 0x0000 },753	.con2_for_sata		= { 0x0008, 15, 0, 0x00, 0x80c1 },754	.con3_for_sata		= { 0x000c, 15, 0, 0x00, 0x0407 },755	/* pipe-grf */756	.pipe_con0_for_sata	= { 0x0000, 11, 5, 0x00, 0x22 },757	.pipe_con1_for_sata	= { 0x0000, 2, 0, 0x00, 0x2 },758	.pipe_pcie1l0_sel	= { 0x0100, 0, 0, 0x01, 0x0 },759	.pipe_pcie1l1_sel	= { 0x0100, 1, 1, 0x01, 0x0 },760};761 762static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {763	.num_phys = 3,764	.phy_ids = {765		0xfee00000,766		0xfee10000,767		0xfee20000,768	},769	.grfcfg		= &rk3588_combphy_grfcfgs,770	.combphy_cfg	= rk3588_combphy_cfg,771};772 773static const struct of_device_id rockchip_combphy_of_match[] = {774	{775		.compatible = "rockchip,rk3568-naneng-combphy",776		.data = &rk3568_combphy_cfgs,777	},778	{779		.compatible = "rockchip,rk3588-naneng-combphy",780		.data = &rk3588_combphy_cfgs,781	},782	{ },783};784MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);785 786static struct platform_driver rockchip_combphy_driver = {787	.probe	= rockchip_combphy_probe,788	.driver = {789		.name = "rockchip-naneng-combphy",790		.of_match_table = rockchip_combphy_of_match,791	},792};793module_platform_driver(rockchip_combphy_driver);794 795MODULE_DESCRIPTION("Rockchip NANENG COMBPHY driver");796MODULE_LICENSE("GPL v2");797