xref: /OK3568_Linux_fs/kernel/drivers/phy/rockchip/phy-rockchip-inno-combphy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Rockchip USB3.0 and PCIE COMBPHY with Innosilicon IP block driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/clk.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/iopoll.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/of_device.h>
16*4882a593Smuzhiyun #include <linux/phy/phy.h>
17*4882a593Smuzhiyun #include <linux/phy/pcie.h>
18*4882a593Smuzhiyun #include <linux/regmap.h>
19*4882a593Smuzhiyun #include <linux/reset.h>
20*4882a593Smuzhiyun #include <dt-bindings/phy/phy.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define BIT_WRITEABLE_SHIFT		16
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun struct rockchip_combphy_priv;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun enum rockchip_combphy_rst {
27*4882a593Smuzhiyun 	OTG_RSTN	= 0,
28*4882a593Smuzhiyun 	PHY_POR_RSTN	= 1,
29*4882a593Smuzhiyun 	PHY_APB_RSTN	= 2,
30*4882a593Smuzhiyun 	PHY_PIPE_RSTN	= 3,
31*4882a593Smuzhiyun 	PHY_GRF_P_RSTN  = 4,
32*4882a593Smuzhiyun 	PHY_RESET_MAX	= 5,
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun struct combphy_reg {
36*4882a593Smuzhiyun 	u32	offset;
37*4882a593Smuzhiyun 	u32	bitend;
38*4882a593Smuzhiyun 	u32	bitstart;
39*4882a593Smuzhiyun 	u32	disable;
40*4882a593Smuzhiyun 	u32	enable;
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct rockchip_combphy_grfcfg {
44*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1_sel;
45*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1_set;
46*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1pd_sel;
47*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1pd_p3;
48*4882a593Smuzhiyun 	struct combphy_reg	pipe_l0pd_sel;
49*4882a593Smuzhiyun 	struct combphy_reg	pipe_l0pd_p3;
50*4882a593Smuzhiyun 	struct combphy_reg	pipe_clk_sel;
51*4882a593Smuzhiyun 	struct combphy_reg	pipe_clk_set;
52*4882a593Smuzhiyun 	struct combphy_reg	pipe_rate_sel;
53*4882a593Smuzhiyun 	struct combphy_reg	pipe_rate_set;
54*4882a593Smuzhiyun 	struct combphy_reg	pipe_mode_sel;
55*4882a593Smuzhiyun 	struct combphy_reg	pipe_mode_set;
56*4882a593Smuzhiyun 	struct combphy_reg	pipe_txrx_sel;
57*4882a593Smuzhiyun 	struct combphy_reg	pipe_txrx_set;
58*4882a593Smuzhiyun 	struct combphy_reg	pipe_width_sel;
59*4882a593Smuzhiyun 	struct combphy_reg	pipe_width_set;
60*4882a593Smuzhiyun 	struct combphy_reg	pipe_usb3_sel;
61*4882a593Smuzhiyun 	struct combphy_reg	pipe_pll_lock;
62*4882a593Smuzhiyun 	struct combphy_reg	pipe_status_l0;
63*4882a593Smuzhiyun 	struct combphy_reg	pipe_l0rxterm_sel;
64*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1rxterm_sel;
65*4882a593Smuzhiyun 	struct combphy_reg	pipe_l0rxterm_set;
66*4882a593Smuzhiyun 	struct combphy_reg	pipe_l1rxterm_set;
67*4882a593Smuzhiyun 	struct combphy_reg	pipe_l0rxelec_set;
68*4882a593Smuzhiyun 	struct combphy_reg	u3_port_disable;
69*4882a593Smuzhiyun 	struct combphy_reg      u3_port_num;
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun struct rockchip_combphy_cfg {
73*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg grfcfg;
74*4882a593Smuzhiyun 	int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
75*4882a593Smuzhiyun 	int (*combphy_low_power_ctrl)(struct rockchip_combphy_priv *priv,
76*4882a593Smuzhiyun 				      bool en);
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun struct rockchip_combphy_priv {
80*4882a593Smuzhiyun 	bool phy_initialized;
81*4882a593Smuzhiyun 	bool phy_suspended;
82*4882a593Smuzhiyun 	u8 phy_type;
83*4882a593Smuzhiyun 	void __iomem *mmio;
84*4882a593Smuzhiyun 	struct device *dev;
85*4882a593Smuzhiyun 	struct clk *ref_clk;
86*4882a593Smuzhiyun 	struct phy *phy;
87*4882a593Smuzhiyun 	struct regmap *combphy_grf;
88*4882a593Smuzhiyun 	struct regmap *usb_pcie_grf;
89*4882a593Smuzhiyun 	struct reset_control *rsts[PHY_RESET_MAX];
90*4882a593Smuzhiyun 	const struct rockchip_combphy_cfg *cfg;
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun 
get_reset_name(enum rockchip_combphy_rst rst)93*4882a593Smuzhiyun static const char *get_reset_name(enum rockchip_combphy_rst rst)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	switch (rst) {
96*4882a593Smuzhiyun 	case OTG_RSTN:
97*4882a593Smuzhiyun 		return "otg-rst";
98*4882a593Smuzhiyun 	case PHY_POR_RSTN:
99*4882a593Smuzhiyun 		return "combphy-por";
100*4882a593Smuzhiyun 	case PHY_APB_RSTN:
101*4882a593Smuzhiyun 		return "combphy-apb";
102*4882a593Smuzhiyun 	case PHY_PIPE_RSTN:
103*4882a593Smuzhiyun 		return "combphy-pipe";
104*4882a593Smuzhiyun 	case PHY_GRF_P_RSTN:
105*4882a593Smuzhiyun 		return "usb3phy_grf_p";
106*4882a593Smuzhiyun 	default:
107*4882a593Smuzhiyun 		return "invalid";
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
param_read(struct regmap * base,const struct combphy_reg * reg,u32 val)111*4882a593Smuzhiyun static inline bool param_read(struct regmap *base,
112*4882a593Smuzhiyun 			      const struct combphy_reg *reg, u32 val)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	int ret;
115*4882a593Smuzhiyun 	u32 mask, orig, tmp;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	ret = regmap_read(base, reg->offset, &orig);
118*4882a593Smuzhiyun 	if (ret)
119*4882a593Smuzhiyun 		return false;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	mask = GENMASK(reg->bitend, reg->bitstart);
122*4882a593Smuzhiyun 	tmp = (orig & mask) >> reg->bitstart;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	return tmp == val;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
param_write(struct regmap * base,const struct combphy_reg * reg,bool en)127*4882a593Smuzhiyun static inline int param_write(struct regmap *base,
128*4882a593Smuzhiyun 			      const struct combphy_reg *reg, bool en)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	u32 val, mask, tmp;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	tmp = en ? reg->enable : reg->disable;
133*4882a593Smuzhiyun 	mask = GENMASK(reg->bitend, reg->bitstart);
134*4882a593Smuzhiyun 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	return regmap_write(base, reg->offset, val);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
u3phy_mode_show(struct device * device,struct device_attribute * attr,char * buf)139*4882a593Smuzhiyun static ssize_t u3phy_mode_show(struct device *device,
140*4882a593Smuzhiyun 			       struct device_attribute *attr,
141*4882a593Smuzhiyun 			       char *buf)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = dev_get_drvdata(device);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	if (param_read(priv->usb_pcie_grf, &priv->cfg->grfcfg.u3_port_num, 0))
146*4882a593Smuzhiyun 		return sprintf(buf, "u2\n");
147*4882a593Smuzhiyun 	else
148*4882a593Smuzhiyun 		return sprintf(buf, "u3\n");
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
u3phy_mode_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)151*4882a593Smuzhiyun static ssize_t u3phy_mode_store(struct device *device,
152*4882a593Smuzhiyun 				struct device_attribute *attr,
153*4882a593Smuzhiyun 				const char *buf, size_t count)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = dev_get_drvdata(device);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (!strncmp(buf, "u3", 2) &&
158*4882a593Smuzhiyun 	    param_read(priv->usb_pcie_grf, &priv->cfg->grfcfg.u3_port_num, 0)) {
159*4882a593Smuzhiyun 		/*
160*4882a593Smuzhiyun 		 * Enable USB 3.0 rx termination, need to select
161*4882a593Smuzhiyun 		 * pipe_l0_rxtermination from USB 3.0 controller.
162*4882a593Smuzhiyun 		 */
163*4882a593Smuzhiyun 		param_write(priv->combphy_grf,
164*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.pipe_l0rxterm_sel, false);
165*4882a593Smuzhiyun 		/* Set xHCI USB 3.0 port number to 1 */
166*4882a593Smuzhiyun 		param_write(priv->usb_pcie_grf,
167*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.u3_port_num, true);
168*4882a593Smuzhiyun 		/* Enable xHCI USB 3.0 port */
169*4882a593Smuzhiyun 		param_write(priv->usb_pcie_grf,
170*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.u3_port_disable, false);
171*4882a593Smuzhiyun 		dev_info(priv->dev, "Set usb3.0 and usb2.0 mode successfully\n");
172*4882a593Smuzhiyun 	} else if (!strncmp(buf, "u2", 2) &&
173*4882a593Smuzhiyun 		   param_read(priv->usb_pcie_grf,
174*4882a593Smuzhiyun 			      &priv->cfg->grfcfg.u3_port_num, 1)) {
175*4882a593Smuzhiyun 		/*
176*4882a593Smuzhiyun 		 * Disable USB 3.0 rx termination, need to select
177*4882a593Smuzhiyun 		 * pipe_l0_rxtermination from grf and remove rx
178*4882a593Smuzhiyun 		 * termimation by grf.
179*4882a593Smuzhiyun 		 */
180*4882a593Smuzhiyun 		param_write(priv->combphy_grf,
181*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.pipe_l0rxterm_set, false);
182*4882a593Smuzhiyun 		param_write(priv->combphy_grf,
183*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.pipe_l0rxterm_sel, true);
184*4882a593Smuzhiyun 		/* Set xHCI USB 3.0 port number to 0 */
185*4882a593Smuzhiyun 		param_write(priv->usb_pcie_grf,
186*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.u3_port_num, false);
187*4882a593Smuzhiyun 		/* Disable xHCI USB 3.0 port */
188*4882a593Smuzhiyun 		param_write(priv->usb_pcie_grf,
189*4882a593Smuzhiyun 			    &priv->cfg->grfcfg.u3_port_disable, true);
190*4882a593Smuzhiyun 		/*
191*4882a593Smuzhiyun 		 * Note:
192*4882a593Smuzhiyun 		 * Don't disable the USB 3.0 PIPE pclk here(set reg
193*4882a593Smuzhiyun 		 * pipe_usb3_sel to false), because USB 3.0 PHY depend
194*4882a593Smuzhiyun 		 * on this clk, if we disable it, we need to reinit
195*4882a593Smuzhiyun 		 * the USB 3.0 PHY when use USB 3.0 mode, in order to
196*4882a593Smuzhiyun 		 * simplify the process, don't disable this PIPE pclk.
197*4882a593Smuzhiyun 		 */
198*4882a593Smuzhiyun 		dev_info(priv->dev, "Set usb2.0 only mode successfully\n");
199*4882a593Smuzhiyun 	} else {
200*4882a593Smuzhiyun 		dev_info(priv->dev, "Same or illegal mode\n");
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	return count;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun static DEVICE_ATTR_RW(u3phy_mode);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static struct attribute *rockchip_combphy_u3phy_mode_attrs[] = {
209*4882a593Smuzhiyun 	&dev_attr_u3phy_mode.attr,
210*4882a593Smuzhiyun 	NULL,
211*4882a593Smuzhiyun };
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun static struct attribute_group rockchip_combphy_u3phy_mode_attr_group = {
214*4882a593Smuzhiyun 	.name = NULL,	/* we want them in the same directory */
215*4882a593Smuzhiyun 	.attrs = rockchip_combphy_u3phy_mode_attrs,
216*4882a593Smuzhiyun };
217*4882a593Smuzhiyun 
rockchip_combphy_pll_lock(struct rockchip_combphy_priv * priv)218*4882a593Smuzhiyun static u32 rockchip_combphy_pll_lock(struct rockchip_combphy_priv *priv)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
221*4882a593Smuzhiyun 	u32 mask, val;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
224*4882a593Smuzhiyun 	mask = GENMASK(grfcfg->pipe_pll_lock.bitend,
225*4882a593Smuzhiyun 		       grfcfg->pipe_pll_lock.bitstart);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	regmap_read(priv->combphy_grf, grfcfg->pipe_pll_lock.offset, &val);
228*4882a593Smuzhiyun 	val = (val & mask) >> grfcfg->pipe_pll_lock.bitstart;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	return val;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
rockchip_combphy_is_ready(struct rockchip_combphy_priv * priv)233*4882a593Smuzhiyun static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
236*4882a593Smuzhiyun 	u32 mask, val;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
239*4882a593Smuzhiyun 	mask = GENMASK(grfcfg->pipe_status_l0.bitend,
240*4882a593Smuzhiyun 		       grfcfg->pipe_status_l0.bitstart);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	regmap_read(priv->combphy_grf, grfcfg->pipe_status_l0.offset, &val);
243*4882a593Smuzhiyun 	val = (val & mask) >> grfcfg->pipe_status_l0.bitstart;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	return val;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
phy_pcie_init(struct rockchip_combphy_priv * priv)248*4882a593Smuzhiyun static int phy_pcie_init(struct rockchip_combphy_priv *priv)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
251*4882a593Smuzhiyun 	u32 val;
252*4882a593Smuzhiyun 	int ret = 0;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* reset PCIe phy to default configuration */
257*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_POR_RSTN]);
258*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_APB_RSTN]);
259*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_PIPE_RSTN]);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_POR_RSTN]);
262*4882a593Smuzhiyun 	/* Wait PHY power on stable */
263*4882a593Smuzhiyun 	udelay(5);
264*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_APB_RSTN]);
265*4882a593Smuzhiyun 	udelay(5);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	/* Set rxtermination for lane0 */
268*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l0rxterm_set, true);
269*4882a593Smuzhiyun 	/* Set rxtermination for lane1 */
270*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l1rxterm_set, true);
271*4882a593Smuzhiyun 	/* Select pipe_l0_rxtermination from grf */
272*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l0rxterm_sel, true);
273*4882a593Smuzhiyun 	/* Select pipe_l1_rxtermination from grf */
274*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l1rxterm_sel, true);
275*4882a593Smuzhiyun 	/* Select rxelecidle_disable and txcommonmode from PCIe controller */
276*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_txrx_sel, false);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	/* Start to configurate PHY registers for PCIE. */
279*4882a593Smuzhiyun 	if (priv->cfg->combphy_cfg) {
280*4882a593Smuzhiyun 		ret = priv->cfg->combphy_cfg(priv);
281*4882a593Smuzhiyun 		if (ret)
282*4882a593Smuzhiyun 			goto error;
283*4882a593Smuzhiyun 	}
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	/* Wait Tx PLL lock */
286*4882a593Smuzhiyun 	usleep_range(300, 350);
287*4882a593Smuzhiyun 	ret = readx_poll_timeout_atomic(rockchip_combphy_pll_lock, priv, val,
288*4882a593Smuzhiyun 					val == grfcfg->pipe_pll_lock.enable,
289*4882a593Smuzhiyun 					10, 1000);
290*4882a593Smuzhiyun 	if (ret) {
291*4882a593Smuzhiyun 		dev_err(priv->dev, "wait phy PLL lock timeout\n");
292*4882a593Smuzhiyun 		goto error;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_PIPE_RSTN]);
296*4882a593Smuzhiyun error:
297*4882a593Smuzhiyun 	return ret;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
phy_u3_init(struct rockchip_combphy_priv * priv)300*4882a593Smuzhiyun static int phy_u3_init(struct rockchip_combphy_priv *priv)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
303*4882a593Smuzhiyun 	u32 val;
304*4882a593Smuzhiyun 	int ret = 0;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	/* Reset the USB3 controller first. */
309*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[OTG_RSTN]);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_POR_RSTN]);
312*4882a593Smuzhiyun 	/* Wait PHY power on stable. */
313*4882a593Smuzhiyun 	udelay(5);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_APB_RSTN]);
316*4882a593Smuzhiyun 	udelay(5);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	/*
319*4882a593Smuzhiyun 	 * Start to configurate PHY registers for USB3.
320*4882a593Smuzhiyun 	 * Note: set operation must be done before corresponding
321*4882a593Smuzhiyun 	 * sel operation, otherwise, the PIPE PHY status lane0
322*4882a593Smuzhiyun 	 * may be unable to get ready.
323*4882a593Smuzhiyun 	 */
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	/* Disable PHY lane1 which isn't needed for USB3 */
326*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l1_set, true);
327*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_l1_sel, true);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* Set PHY Tx and Rx for USB3 */
330*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_txrx_set, true);
331*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_txrx_sel, true);
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	/* Set PHY PIPE MAC pclk request */
334*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_clk_set, true);
335*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_clk_sel, true);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	/* Set PHY PIPE rate for USB3 */
338*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_rate_set, true);
339*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_rate_sel, true);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	/* Set PHY mode for USB3 */
342*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_mode_set, true);
343*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_mode_sel, true);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	/* Set PHY data bus width for USB3 */
346*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_width_set, true);
347*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_width_sel, true);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	/* Select PIPE for USB3 */
350*4882a593Smuzhiyun 	param_write(priv->combphy_grf, &grfcfg->pipe_usb3_sel, true);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	if (priv->cfg->combphy_cfg) {
353*4882a593Smuzhiyun 		ret = priv->cfg->combphy_cfg(priv);
354*4882a593Smuzhiyun 		if (ret)
355*4882a593Smuzhiyun 			goto error;
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	/* Wait Tx PLL lock */
359*4882a593Smuzhiyun 	usleep_range(300, 350);
360*4882a593Smuzhiyun 	ret = readx_poll_timeout_atomic(rockchip_combphy_pll_lock, priv, val,
361*4882a593Smuzhiyun 					val == grfcfg->pipe_pll_lock.enable,
362*4882a593Smuzhiyun 					10, 1000);
363*4882a593Smuzhiyun 	if (ret) {
364*4882a593Smuzhiyun 		dev_err(priv->dev, "wait phy PLL lock timeout\n");
365*4882a593Smuzhiyun 		goto error;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[PHY_PIPE_RSTN]);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	/* Wait PIPE PHY status lane0 ready */
371*4882a593Smuzhiyun 	ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, priv, val,
372*4882a593Smuzhiyun 					val == grfcfg->pipe_status_l0.enable,
373*4882a593Smuzhiyun 					10, 1000);
374*4882a593Smuzhiyun 	if (ret) {
375*4882a593Smuzhiyun 		dev_err(priv->dev, "wait phy status lane0 ready timeout\n");
376*4882a593Smuzhiyun 		goto error;
377*4882a593Smuzhiyun 	}
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	reset_control_deassert(priv->rsts[OTG_RSTN]);
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun error:
382*4882a593Smuzhiyun 	return ret;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
rockchip_combphy_set_phy_type(struct rockchip_combphy_priv * priv)385*4882a593Smuzhiyun static int rockchip_combphy_set_phy_type(struct rockchip_combphy_priv *priv)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	int ret = 0;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	if (priv->phy_initialized)
390*4882a593Smuzhiyun 		return ret;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	switch (priv->phy_type) {
393*4882a593Smuzhiyun 	case PHY_TYPE_PCIE:
394*4882a593Smuzhiyun 		ret = phy_pcie_init(priv);
395*4882a593Smuzhiyun 		break;
396*4882a593Smuzhiyun 	case PHY_TYPE_USB3:
397*4882a593Smuzhiyun 		ret = phy_u3_init(priv);
398*4882a593Smuzhiyun 		if (ret)
399*4882a593Smuzhiyun 			return ret;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		/* Attributes */
402*4882a593Smuzhiyun 		ret = sysfs_create_group(&priv->dev->kobj,
403*4882a593Smuzhiyun 					 &rockchip_combphy_u3phy_mode_attr_group);
404*4882a593Smuzhiyun 		break;
405*4882a593Smuzhiyun 	default:
406*4882a593Smuzhiyun 		dev_err(priv->dev, "incompatible PHY type\n");
407*4882a593Smuzhiyun 		return -EINVAL;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	return ret;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
rockchip_combphy_init(struct phy * phy)413*4882a593Smuzhiyun static int rockchip_combphy_init(struct phy *phy)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
416*4882a593Smuzhiyun 	int ret;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	ret = clk_prepare_enable(priv->ref_clk);
419*4882a593Smuzhiyun 	if (ret) {
420*4882a593Smuzhiyun 		dev_err(priv->dev, "failed to enable ref_clk\n");
421*4882a593Smuzhiyun 		return ret;
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	ret = rockchip_combphy_set_phy_type(priv);
425*4882a593Smuzhiyun 	if (ret) {
426*4882a593Smuzhiyun 		dev_err(priv->dev, "failed to set phy type\n");
427*4882a593Smuzhiyun 		return ret;
428*4882a593Smuzhiyun 	}
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	priv->phy_initialized = true;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return 0;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
rockchip_combphy_exit(struct phy * phy)435*4882a593Smuzhiyun static int rockchip_combphy_exit(struct phy *phy)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	/*
440*4882a593Smuzhiyun 	 * Note: don't assert PHY reset here, because
441*4882a593Smuzhiyun 	 * we set many phy configurations during phy
442*4882a593Smuzhiyun 	 * init to reduce PHY power consumption, if we
443*4882a593Smuzhiyun 	 * assert PHY reset here, these configurations
444*4882a593Smuzhiyun 	 * will be lost, and increase power consumption.
445*4882a593Smuzhiyun 	 */
446*4882a593Smuzhiyun 	clk_disable_unprepare(priv->ref_clk);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	/* in case of waiting phy PLL lock timeout */
449*4882a593Smuzhiyun 	if (priv->phy_type == PHY_TYPE_PCIE) {
450*4882a593Smuzhiyun 		reset_control_assert(priv->rsts[PHY_GRF_P_RSTN]);
451*4882a593Smuzhiyun 		udelay(5);
452*4882a593Smuzhiyun 		reset_control_deassert(priv->rsts[PHY_GRF_P_RSTN]);
453*4882a593Smuzhiyun 		priv->phy_initialized = false;
454*4882a593Smuzhiyun 	}
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	return 0;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
rockchip_combphy_power_on(struct phy * phy)459*4882a593Smuzhiyun static int rockchip_combphy_power_on(struct phy *phy)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
462*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (!priv->phy_suspended)
465*4882a593Smuzhiyun 		return 0;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	if (priv->phy_type == PHY_TYPE_USB3) {
470*4882a593Smuzhiyun 		if (priv->cfg->combphy_low_power_ctrl)
471*4882a593Smuzhiyun 			priv->cfg->combphy_low_power_ctrl(priv, false);
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 		/* Enable lane 0 squelch detection  */
474*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0rxelec_set,
475*4882a593Smuzhiyun 			    false);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 		/*
478*4882a593Smuzhiyun 		 * Check if lane 0 powerdown is already
479*4882a593Smuzhiyun 		 * controlled by USB 3.0 controller.
480*4882a593Smuzhiyun 		 */
481*4882a593Smuzhiyun 		if (param_read(priv->combphy_grf,
482*4882a593Smuzhiyun 			       &grfcfg->pipe_l0pd_sel, 0))
483*4882a593Smuzhiyun 			goto done;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		/* Exit to P0 from P3 */
486*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, false);
487*4882a593Smuzhiyun 		usleep_range(250, 300);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 		/*
490*4882a593Smuzhiyun 		 * Set lane 0 powerdown to be controlled
491*4882a593Smuzhiyun 		 * by USB 3.0 controller.
492*4882a593Smuzhiyun 		 */
493*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_sel, false);
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun done:
497*4882a593Smuzhiyun 	priv->phy_suspended = false;
498*4882a593Smuzhiyun 	return 0;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
rockchip_combphy_power_off(struct phy * phy)501*4882a593Smuzhiyun static int rockchip_combphy_power_off(struct phy *phy)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
504*4882a593Smuzhiyun 	const struct rockchip_combphy_grfcfg *grfcfg;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	if (priv->phy_suspended)
507*4882a593Smuzhiyun 		return 0;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	grfcfg = &priv->cfg->grfcfg;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	if (priv->phy_type == PHY_TYPE_USB3 ||
512*4882a593Smuzhiyun 	    priv->phy_type == PHY_TYPE_PCIE) {
513*4882a593Smuzhiyun 		/*
514*4882a593Smuzhiyun 		 * Check if lane 0 powerdown is already
515*4882a593Smuzhiyun 		 * controlled by grf and in P3 state.
516*4882a593Smuzhiyun 		 */
517*4882a593Smuzhiyun 		if (param_read(priv->combphy_grf,
518*4882a593Smuzhiyun 			       &grfcfg->pipe_l0pd_sel, 1) &&
519*4882a593Smuzhiyun 		    param_read(priv->combphy_grf,
520*4882a593Smuzhiyun 			       &grfcfg->pipe_l0pd_p3, 3))
521*4882a593Smuzhiyun 			goto done;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 		/* Exit to P0 */
524*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, false);
525*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_sel, true);
526*4882a593Smuzhiyun 		udelay(1);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 		/* Enter to P3 from P0 */
529*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, true);
530*4882a593Smuzhiyun 		udelay(2);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 		/*
533*4882a593Smuzhiyun 		 * Disable lane 0 squelch detection.
534*4882a593Smuzhiyun 		 * Note: if squelch detection is disabled,
535*4882a593Smuzhiyun 		 * the PHY can't detect LFPS.
536*4882a593Smuzhiyun 		 */
537*4882a593Smuzhiyun 		param_write(priv->combphy_grf, &grfcfg->pipe_l0rxelec_set,
538*4882a593Smuzhiyun 			    true);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 		if (priv->cfg->combphy_low_power_ctrl)
541*4882a593Smuzhiyun 			priv->cfg->combphy_low_power_ctrl(priv, true);
542*4882a593Smuzhiyun 	}
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun done:
545*4882a593Smuzhiyun 	priv->phy_suspended = true;
546*4882a593Smuzhiyun 	return 0;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun 
rockchip_combphy_set_mode(struct phy * phy,enum phy_mode mode,int submode)549*4882a593Smuzhiyun static int rockchip_combphy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
552*4882a593Smuzhiyun 	u32 reg;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	if (priv->phy_type != PHY_TYPE_PCIE)
555*4882a593Smuzhiyun 		return -EINVAL;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	reg = readl(priv->mmio + 0x21a8);
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	if (PHY_MODE_PCIE_EP == submode)
560*4882a593Smuzhiyun 		reg |= (0x1 << 2);
561*4882a593Smuzhiyun 	else if (PHY_MODE_PCIE_RC == submode)
562*4882a593Smuzhiyun 		reg &= ~(0x1 << 2);
563*4882a593Smuzhiyun 	else
564*4882a593Smuzhiyun 		return -EINVAL;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	writel(reg, priv->mmio + 0x21a8);
567*4882a593Smuzhiyun 	return 0;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun static const struct phy_ops rockchip_combphy_ops = {
571*4882a593Smuzhiyun 	.init		= rockchip_combphy_init,
572*4882a593Smuzhiyun 	.exit		= rockchip_combphy_exit,
573*4882a593Smuzhiyun 	.power_on	= rockchip_combphy_power_on,
574*4882a593Smuzhiyun 	.power_off	= rockchip_combphy_power_off,
575*4882a593Smuzhiyun 	.set_mode       = rockchip_combphy_set_mode,
576*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
577*4882a593Smuzhiyun };
578*4882a593Smuzhiyun 
rockchip_combphy_xlate(struct device * dev,struct of_phandle_args * args)579*4882a593Smuzhiyun static struct phy *rockchip_combphy_xlate(struct device *dev,
580*4882a593Smuzhiyun 					  struct of_phandle_args *args)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	if (args->args_count < 1) {
585*4882a593Smuzhiyun 		dev_err(dev, "invalid number of arguments\n");
586*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
587*4882a593Smuzhiyun 	}
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	if (priv->phy_type != PHY_NONE && priv->phy_type != args->args[0]) {
590*4882a593Smuzhiyun 		dev_err(dev, "type select %d overwriting phy type %d\n",
591*4882a593Smuzhiyun 			args->args[0], priv->phy_type);
592*4882a593Smuzhiyun 		return ERR_PTR(-ENODEV);
593*4882a593Smuzhiyun 	}
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	priv->phy_type = args->args[0];
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if (priv->phy_type < PHY_TYPE_SATA || priv->phy_type > PHY_TYPE_USB3) {
598*4882a593Smuzhiyun 		dev_err(dev, "invalid phy type select argument\n");
599*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
600*4882a593Smuzhiyun 	}
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	return priv->phy;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun 
rockchip_combphy_parse_dt(struct device * dev,struct rockchip_combphy_priv * priv)605*4882a593Smuzhiyun static int rockchip_combphy_parse_dt(struct device *dev,
606*4882a593Smuzhiyun 				     struct rockchip_combphy_priv *priv)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun 	u32 i;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	priv->combphy_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
611*4882a593Smuzhiyun 							    "rockchip,combphygrf");
612*4882a593Smuzhiyun 	if (IS_ERR(priv->combphy_grf)) {
613*4882a593Smuzhiyun 		dev_err(dev, "failed to find combphy grf regmap\n");
614*4882a593Smuzhiyun 		return PTR_ERR(priv->combphy_grf);
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	priv->usb_pcie_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
618*4882a593Smuzhiyun 							 "rockchip,usbpciegrf");
619*4882a593Smuzhiyun 	if (IS_ERR(priv->usb_pcie_grf)) {
620*4882a593Smuzhiyun 		dev_err(dev, "failed to find usb_pcie_grf regmap\n");
621*4882a593Smuzhiyun 		return PTR_ERR(priv->usb_pcie_grf);
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	priv->ref_clk = devm_clk_get(dev, "refclk");
625*4882a593Smuzhiyun 	if (IS_ERR(priv->ref_clk)) {
626*4882a593Smuzhiyun 		dev_err(dev, "failed to find ref clock\n");
627*4882a593Smuzhiyun 		return PTR_ERR(priv->ref_clk);
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	for (i = 0; i < PHY_RESET_MAX; i++) {
631*4882a593Smuzhiyun 		priv->rsts[i] = devm_reset_control_get(dev, get_reset_name(i));
632*4882a593Smuzhiyun 		if (IS_ERR(priv->rsts[i])) {
633*4882a593Smuzhiyun 			dev_warn(dev, "no %s reset control specified\n",
634*4882a593Smuzhiyun 				 get_reset_name(i));
635*4882a593Smuzhiyun 			priv->rsts[i] = NULL;
636*4882a593Smuzhiyun 		}
637*4882a593Smuzhiyun 	}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	return 0;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
rockchip_combphy_probe(struct platform_device * pdev)642*4882a593Smuzhiyun static int rockchip_combphy_probe(struct platform_device *pdev)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	struct phy_provider *phy_provider;
645*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
646*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv;
647*4882a593Smuzhiyun 	struct resource *res;
648*4882a593Smuzhiyun 	const struct rockchip_combphy_cfg *phy_cfg;
649*4882a593Smuzhiyun 	int ret;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	phy_cfg = of_device_get_match_data(dev);
652*4882a593Smuzhiyun 	if (!phy_cfg) {
653*4882a593Smuzhiyun 		dev_err(dev, "No OF match data provided\n");
654*4882a593Smuzhiyun 		return -EINVAL;
655*4882a593Smuzhiyun 	}
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
658*4882a593Smuzhiyun 	if (!priv)
659*4882a593Smuzhiyun 		return -ENOMEM;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
662*4882a593Smuzhiyun 	priv->mmio = devm_ioremap_resource(dev, res);
663*4882a593Smuzhiyun 	if (IS_ERR(priv->mmio)) {
664*4882a593Smuzhiyun 		ret = PTR_ERR(priv->mmio);
665*4882a593Smuzhiyun 		return ret;
666*4882a593Smuzhiyun 	}
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	ret = rockchip_combphy_parse_dt(dev, priv);
669*4882a593Smuzhiyun 	if (ret) {
670*4882a593Smuzhiyun 		dev_err(dev, "parse dt failed, ret(%d)\n", ret);
671*4882a593Smuzhiyun 		return ret;
672*4882a593Smuzhiyun 	}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_POR_RSTN]);
675*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_APB_RSTN]);
676*4882a593Smuzhiyun 	reset_control_assert(priv->rsts[PHY_PIPE_RSTN]);
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	priv->phy_type = PHY_NONE;
679*4882a593Smuzhiyun 	priv->dev = dev;
680*4882a593Smuzhiyun 	priv->cfg = phy_cfg;
681*4882a593Smuzhiyun 	priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);
682*4882a593Smuzhiyun 	if (IS_ERR(priv->phy)) {
683*4882a593Smuzhiyun 		dev_err(dev, "failed to create combphy\n");
684*4882a593Smuzhiyun 		return PTR_ERR(priv->phy);
685*4882a593Smuzhiyun 	}
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	dev_set_drvdata(dev, priv);
688*4882a593Smuzhiyun 	phy_set_drvdata(priv->phy, priv);
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	phy_provider = devm_of_phy_provider_register(dev,
691*4882a593Smuzhiyun 						     rockchip_combphy_xlate);
692*4882a593Smuzhiyun 	return PTR_ERR_OR_ZERO(phy_provider);
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun 
rockchip_combphy_remove(struct platform_device * pdev)695*4882a593Smuzhiyun static int rockchip_combphy_remove(struct platform_device *pdev)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun 	struct rockchip_combphy_priv *priv = platform_get_drvdata(pdev);
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	if (priv->phy_type == PHY_TYPE_USB3 && priv->phy_initialized)
700*4882a593Smuzhiyun 		sysfs_remove_group(&priv->dev->kobj,
701*4882a593Smuzhiyun 				   &rockchip_combphy_u3phy_mode_attr_group);
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	return 0;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
rk1808_combphy_cfg(struct rockchip_combphy_priv * priv)706*4882a593Smuzhiyun static int rk1808_combphy_cfg(struct rockchip_combphy_priv *priv)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun 	unsigned long rate;
709*4882a593Smuzhiyun 	u32 reg;
710*4882a593Smuzhiyun 	bool ssc_en = false;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	rate = clk_get_rate(priv->ref_clk);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	/* Configure PHY reference clock frequency */
715*4882a593Smuzhiyun 	switch (rate) {
716*4882a593Smuzhiyun 	case 24000000:
717*4882a593Smuzhiyun 		/*
718*4882a593Smuzhiyun 		 * The default PHY refclk frequency
719*4882a593Smuzhiyun 		 * configuration is 24MHz.
720*4882a593Smuzhiyun 		 */
721*4882a593Smuzhiyun 		break;
722*4882a593Smuzhiyun 	case 25000000:
723*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x2118);
724*4882a593Smuzhiyun 		writel(0x64, priv->mmio + 0x211c);
725*4882a593Smuzhiyun 		writel(0x01, priv->mmio + 0x2020);
726*4882a593Smuzhiyun 		writel(0x64, priv->mmio + 0x2028);
727*4882a593Smuzhiyun 		writel(0x21, priv->mmio + 0x2030);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 		if (priv->phy_type == PHY_TYPE_PCIE) {
730*4882a593Smuzhiyun 			writel(0x1,  priv->mmio + 0x3020);
731*4882a593Smuzhiyun 			writel(0x64, priv->mmio + 0x3028);
732*4882a593Smuzhiyun 			writel(0x21, priv->mmio + 0x3030);
733*4882a593Smuzhiyun 		}
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 		break;
736*4882a593Smuzhiyun 	case 50000000:
737*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x2118);
738*4882a593Smuzhiyun 		writel(0x32, priv->mmio + 0x211c);
739*4882a593Smuzhiyun 		writel(0x01, priv->mmio + 0x2020);
740*4882a593Smuzhiyun 		writel(0x32, priv->mmio + 0x2028);
741*4882a593Smuzhiyun 		writel(0x21, priv->mmio + 0x2030);
742*4882a593Smuzhiyun 		break;
743*4882a593Smuzhiyun 	default:
744*4882a593Smuzhiyun 		dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
745*4882a593Smuzhiyun 		return -EINVAL;
746*4882a593Smuzhiyun 	}
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	if (priv->phy_type == PHY_TYPE_PCIE) {
749*4882a593Smuzhiyun 		/* turn on pcie phy pd */
750*4882a593Smuzhiyun 		writel(0x08400000, priv->mmio + 0x0);
751*4882a593Smuzhiyun 		writel(0x03030000, priv->mmio + 0x8);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 		/* Adjust Lane 0 Rx interface timing */
754*4882a593Smuzhiyun 		writel(0x20, priv->mmio + 0x20ac);
755*4882a593Smuzhiyun 		writel(0x12, priv->mmio + 0x20c8);
756*4882a593Smuzhiyun 		writel(0x76, priv->mmio + 0x2150);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 		/* Adjust Lane 1 Rx interface timing */
759*4882a593Smuzhiyun 		writel(0x20, priv->mmio + 0x30ac);
760*4882a593Smuzhiyun 		writel(0x12, priv->mmio + 0x30c8);
761*4882a593Smuzhiyun 		writel(0x76, priv->mmio + 0x3150);
762*4882a593Smuzhiyun 		/* Set PHY output refclk path */
763*4882a593Smuzhiyun 		writel(0x0, priv->mmio + 0x21a4);
764*4882a593Smuzhiyun 		writel(0x0, priv->mmio + 0x21a8);
765*4882a593Smuzhiyun 		writel(0xb, priv->mmio + 0x21ec);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 		/* Physical ordered set for PCIe */
768*4882a593Smuzhiyun 		writel(0x02, priv->mmio + 0x45c0);
769*4882a593Smuzhiyun 		writel(0x83, priv->mmio + 0x45c4);
770*4882a593Smuzhiyun 		writel(0x03, priv->mmio + 0x45c8);
771*4882a593Smuzhiyun 		writel(0x43, priv->mmio + 0x45cc);
772*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x45d0);
773*4882a593Smuzhiyun 		writel(0xbc, priv->mmio + 0x45d4);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 		/* Boost pre-emphasis */
776*4882a593Smuzhiyun 		writel(0xaa, priv->mmio + 0x21b8);
777*4882a593Smuzhiyun 		writel(0xaa, priv->mmio + 0x31b8);
778*4882a593Smuzhiyun 	} else if (priv->phy_type == PHY_TYPE_USB3) {
779*4882a593Smuzhiyun 		/*
780*4882a593Smuzhiyun 		 * Disable PHY Lane 1 which isn't needed
781*4882a593Smuzhiyun 		 * for USB3 to reduce power consumption.
782*4882a593Smuzhiyun 		 */
783*4882a593Smuzhiyun 		/* Lane 1 cdr power down */
784*4882a593Smuzhiyun 		writel(0x09, priv->mmio + 0x3148);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 		/* Lane 1 rx bias disable */
787*4882a593Smuzhiyun 		writel(0x01, priv->mmio + 0x21cc);
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 		/* Lane 1 cdr disable */
790*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x30c4);
791*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x20f4);
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 		/* Lane 1 rx lock disable and tx bias disable */
794*4882a593Smuzhiyun 		writel(0x12, priv->mmio + 0x3150);
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 		/* Lane 1 rx termination disable, and tx_cmenb disable */
797*4882a593Smuzhiyun 		writel(0x04, priv->mmio + 0x3080);
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 		/* Lane 1 tx termination disable */
800*4882a593Smuzhiyun 		writel(0x1d, priv->mmio + 0x3090);
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 		/* Lane 1 tx driver disable */
803*4882a593Smuzhiyun 		writel(0x50, priv->mmio + 0x21c4);
804*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x2050);
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 		/* Lane 1 txldo_refsel disable */
807*4882a593Smuzhiyun 		writel(0x81, priv->mmio + 0x31a8);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 		/* Lane 1 txdetrx_en disable */
810*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x31e8);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 		/* Lane 1 rxcm_en disable */
813*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x30c0);
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 		/* Adjust Lane 0 Rx interface timing */
816*4882a593Smuzhiyun 		writel(0x20, priv->mmio + 0x20ac);
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 		/* Set and enable SSC */
819*4882a593Smuzhiyun 		switch (rate) {
820*4882a593Smuzhiyun 		case 24000000:
821*4882a593Smuzhiyun 			/* Set SSC rate to 31.25KHz */
822*4882a593Smuzhiyun 			reg = readl(priv->mmio + 0x2108);
823*4882a593Smuzhiyun 			reg = (reg & ~0xf) | 0x1;
824*4882a593Smuzhiyun 			writel(reg, priv->mmio + 0x2108);
825*4882a593Smuzhiyun 			ssc_en = true;
826*4882a593Smuzhiyun 			break;
827*4882a593Smuzhiyun 		case 25000000:
828*4882a593Smuzhiyun 			/* Set SSC rate to 32.55KHz */
829*4882a593Smuzhiyun 			reg = readl(priv->mmio + 0x2108);
830*4882a593Smuzhiyun 			reg = (reg & ~0xf) | 0x6;
831*4882a593Smuzhiyun 			writel(reg, priv->mmio + 0x2108);
832*4882a593Smuzhiyun 			ssc_en = true;
833*4882a593Smuzhiyun 			break;
834*4882a593Smuzhiyun 		default:
835*4882a593Smuzhiyun 			dev_warn(priv->dev,
836*4882a593Smuzhiyun 				 "failed to set SSC on rate: %lu\n", rate);
837*4882a593Smuzhiyun 			break;
838*4882a593Smuzhiyun 		}
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 		if (ssc_en) {
841*4882a593Smuzhiyun 			/* Enable SSC */
842*4882a593Smuzhiyun 			reg = readl(priv->mmio + 0x2120);
843*4882a593Smuzhiyun 			reg &= ~BIT(4);
844*4882a593Smuzhiyun 			writel(reg, priv->mmio + 0x2120);
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 			reg = readl(priv->mmio + 0x2000);
847*4882a593Smuzhiyun 			reg &= ~0x6;
848*4882a593Smuzhiyun 			writel(reg, priv->mmio + 0x2000);
849*4882a593Smuzhiyun 		}
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 		/*
852*4882a593Smuzhiyun 		 * Tuning Tx:
853*4882a593Smuzhiyun 		 * offset 0x21b8 bit[7:4]: lane 0 TX driver swing
854*4882a593Smuzhiyun 		 * tuning bits with weight, "1111" represents the
855*4882a593Smuzhiyun 		 * largest swing and "0000" the smallest.
856*4882a593Smuzhiyun 		 */
857*4882a593Smuzhiyun 		reg = readl(priv->mmio + 0x21b8);
858*4882a593Smuzhiyun 		reg = (reg & ~0xf0) | 0xe0;
859*4882a593Smuzhiyun 		writel(reg, priv->mmio + 0x21b8);
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 		/*
862*4882a593Smuzhiyun 		 * Tuning Rx for RJTL:
863*4882a593Smuzhiyun 		 * Decrease CDR Chump Bump current.
864*4882a593Smuzhiyun 		 */
865*4882a593Smuzhiyun 		reg = readl(priv->mmio + 0x20c8);
866*4882a593Smuzhiyun 		reg = (reg & ~0x6) | BIT(1);
867*4882a593Smuzhiyun 		writel(reg, priv->mmio + 0x20c8);
868*4882a593Smuzhiyun 		reg = readl(priv->mmio + 0x2150);
869*4882a593Smuzhiyun 		reg |= BIT(2);
870*4882a593Smuzhiyun 		writel(reg, priv->mmio + 0x2150);
871*4882a593Smuzhiyun 	} else {
872*4882a593Smuzhiyun 		dev_err(priv->dev, "failed to cfg incompatible PHY type\n");
873*4882a593Smuzhiyun 		return -EINVAL;
874*4882a593Smuzhiyun 	}
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	return 0;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun 
rk1808_combphy_low_power_control(struct rockchip_combphy_priv * priv,bool en)879*4882a593Smuzhiyun static int rk1808_combphy_low_power_control(struct rockchip_combphy_priv *priv,
880*4882a593Smuzhiyun 					    bool en)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun 	if (priv->phy_type != PHY_TYPE_USB3) {
883*4882a593Smuzhiyun 		/* turn off pcie phy pd */
884*4882a593Smuzhiyun 		writel(0x08400840, priv->mmio + 0x0);
885*4882a593Smuzhiyun 		writel(0x03030303, priv->mmio + 0x8);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 		/* enter PCIe phy low power mode */
888*4882a593Smuzhiyun 		writel(0x36, priv->mmio + 0x2150);
889*4882a593Smuzhiyun 		writel(0x36, priv->mmio + 0x3150);
890*4882a593Smuzhiyun 		writel(0x02, priv->mmio + 0x21e8);
891*4882a593Smuzhiyun 		writel(0x02, priv->mmio + 0x31e8);
892*4882a593Smuzhiyun 		writel(0x0c, priv->mmio + 0x2080);
893*4882a593Smuzhiyun 		writel(0x0c, priv->mmio + 0x3080);
894*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x20c0);
895*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x30c0);
896*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x2058);
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x2044);
899*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x21a8);
900*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x31a8);
901*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x2058);
902*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x3058);
903*4882a593Smuzhiyun 		writel(0x40, priv->mmio + 0x205c);
904*4882a593Smuzhiyun 		writel(0x40, priv->mmio + 0x305c);
905*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x2184);
906*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x3184);
907*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x2150);
908*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x3150);
909*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x20e0);
910*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x21e8);
911*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x31e8);
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 		return 0;
914*4882a593Smuzhiyun 	}
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	if (en) {
917*4882a593Smuzhiyun 		/* Lane 0 tx_biasen disable */
918*4882a593Smuzhiyun 		writel(0x36, priv->mmio + 0x2150);
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 		/* Lane 0 txdetrx_en disable */
921*4882a593Smuzhiyun 		writel(0x02, priv->mmio + 0x21e8);
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun 		/* Lane 0 tx_cmenb disable */
924*4882a593Smuzhiyun 		writel(0x0c, priv->mmio + 0x2080);
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 		/* Lane 0 rxcm_en disable */
927*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x20c0);
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 		/* Lane 0 and Lane 1 bg_pwrdn */
930*4882a593Smuzhiyun 		writel(0x10, priv->mmio + 0x2044);
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 		/* Lane 0 and Lane 1 rcomp_osenseampen disable */
933*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x2058);
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 		/* Lane 0 txldo_refsel disable and LDO disable */
936*4882a593Smuzhiyun 		writel(0x91, priv->mmio + 0x21a8);
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 		/* Lane 1 LDO disable */
939*4882a593Smuzhiyun 		writel(0x91, priv->mmio + 0x31a8);
940*4882a593Smuzhiyun 	} else {
941*4882a593Smuzhiyun 		/* Lane 0 tx_biasen enable */
942*4882a593Smuzhiyun 		writel(0x76, priv->mmio + 0x2150);
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 		/* Lane 0 txdetrx_en enable */
945*4882a593Smuzhiyun 		writel(0x02, priv->mmio + 0x21e8);
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 		/* Lane 0 tx_cmenb enable */
948*4882a593Smuzhiyun 		writel(0x08, priv->mmio + 0x2080);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 		/* Lane 0 rxcm_en enable */
951*4882a593Smuzhiyun 		writel(0x18, priv->mmio + 0x20c0);
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 		/* Lane 0 and Lane 1 bg_pwrdn */
954*4882a593Smuzhiyun 		writel(0x00, priv->mmio + 0x2044);
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 		/* Lane 0 and Lane 1 rcomp_osenseampen enable */
957*4882a593Smuzhiyun 		writel(0x28, priv->mmio + 0x2058);
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 		/* Lane 0 txldo_refsel enable and LDO enable */
960*4882a593Smuzhiyun 		writel(0x01, priv->mmio + 0x21a8);
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 		/* Lane 1 LDO enable */
963*4882a593Smuzhiyun 		writel(0x81, priv->mmio + 0x31a8);
964*4882a593Smuzhiyun 	}
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	return 0;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun static const struct rockchip_combphy_cfg rk1808_combphy_cfgs = {
970*4882a593Smuzhiyun 	.grfcfg	= {
971*4882a593Smuzhiyun 		.pipe_l1_sel	= { 0x0000, 15, 11, 0x00, 0x1f },
972*4882a593Smuzhiyun 		.pipe_l1_set	= { 0x0008, 13, 8, 0x00, 0x13 },
973*4882a593Smuzhiyun 		.pipe_l1rxterm_sel = { 0x0000, 12, 12, 0x0, 0x1 },
974*4882a593Smuzhiyun 		.pipe_l1pd_sel	= { 0x0000, 11, 11, 0x0, 0x1},
975*4882a593Smuzhiyun 		.pipe_l1pd_p3	= { 0x0008, 9, 8, 0x0, 0x3 },
976*4882a593Smuzhiyun 		.pipe_l0rxterm_sel = { 0x0000, 7, 7, 0x0, 0x1 },
977*4882a593Smuzhiyun 		.pipe_l0pd_sel	= { 0x0000, 6, 6, 0x0, 0x1 },
978*4882a593Smuzhiyun 		.pipe_l0pd_p3	= { 0x0008, 1, 0, 0x0, 0x3 },
979*4882a593Smuzhiyun 		.pipe_clk_sel	= { 0x0000, 3, 3, 0x0, 0x1 },
980*4882a593Smuzhiyun 		.pipe_clk_set	= { 0x0004, 7, 6, 0x1, 0x0 },
981*4882a593Smuzhiyun 		.pipe_rate_sel	= { 0x0000, 2, 2, 0x0, 0x1 },
982*4882a593Smuzhiyun 		.pipe_rate_set	= { 0x0004, 5, 4, 0x0, 0x1 },
983*4882a593Smuzhiyun 		.pipe_mode_sel	= { 0x0000, 1, 1, 0x0, 0x1 },
984*4882a593Smuzhiyun 		.pipe_mode_set	= { 0x0004, 3, 2, 0x0, 0x1 },
985*4882a593Smuzhiyun 		.pipe_txrx_sel	= { 0x0004, 15, 8, 0x10, 0x2f },
986*4882a593Smuzhiyun 		.pipe_txrx_set	= { 0x0008, 15, 14, 0x0, 0x3 },
987*4882a593Smuzhiyun 		.pipe_l1rxterm_set = { 0x0008, 10, 10, 0x0, 0x1 },
988*4882a593Smuzhiyun 		.pipe_l0rxterm_set = { 0x0008, 2, 2, 0x0, 0x1 },
989*4882a593Smuzhiyun 		.pipe_l0rxelec_set = { 0x0008, 6, 6, 0x0, 0x1 },
990*4882a593Smuzhiyun 		.pipe_width_sel	= { 0x0000, 0, 0, 0x0, 0x1 },
991*4882a593Smuzhiyun 		.pipe_width_set	= { 0x0004, 1, 0, 0x2, 0x0 },
992*4882a593Smuzhiyun 		.pipe_usb3_sel	= { 0x000c, 0, 0, 0x0, 0x1 },
993*4882a593Smuzhiyun 		.pipe_pll_lock	= { 0x0034, 14, 14, 0x0, 0x1 },
994*4882a593Smuzhiyun 		.pipe_status_l0	= { 0x0034, 7, 7, 0x1, 0x0 },
995*4882a593Smuzhiyun 		.u3_port_disable = { 0x0434, 0, 0, 0, 1},
996*4882a593Smuzhiyun 		.u3_port_num	= { 0x0434, 15, 12, 0, 1},
997*4882a593Smuzhiyun 	},
998*4882a593Smuzhiyun 	.combphy_cfg		= rk1808_combphy_cfg,
999*4882a593Smuzhiyun 	.combphy_low_power_ctrl	= rk1808_combphy_low_power_control,
1000*4882a593Smuzhiyun };
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun static const struct of_device_id rockchip_combphy_of_match[] = {
1003*4882a593Smuzhiyun 	{
1004*4882a593Smuzhiyun 		.compatible = "rockchip,rk1808-combphy",
1005*4882a593Smuzhiyun 		.data = &rk1808_combphy_cfgs,
1006*4882a593Smuzhiyun 	},
1007*4882a593Smuzhiyun 	{ },
1008*4882a593Smuzhiyun };
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun static struct platform_driver rockchip_combphy_driver = {
1013*4882a593Smuzhiyun 	.probe	= rockchip_combphy_probe,
1014*4882a593Smuzhiyun 	.remove = rockchip_combphy_remove,
1015*4882a593Smuzhiyun 	.driver = {
1016*4882a593Smuzhiyun 		.name = "rockchip-combphy",
1017*4882a593Smuzhiyun 		.of_match_table = rockchip_combphy_of_match,
1018*4882a593Smuzhiyun 	},
1019*4882a593Smuzhiyun };
1020*4882a593Smuzhiyun module_platform_driver(rockchip_combphy_driver);
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun MODULE_AUTHOR("William Wu <william.wu@rock-chips.com>");
1023*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip USB3.0 and PCIE COMBPHY driver");
1024*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1025