xref: /OK3568_Linux_fs/kernel/drivers/phy/marvell/phy-mvebu-a3700-comphy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2018 Marvell
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors:
6*4882a593Smuzhiyun  *   Evan Wang <xswang@marvell.com>
7*4882a593Smuzhiyun  *   Miquèl Raynal <miquel.raynal@bootlin.com>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart.
10*4882a593Smuzhiyun  * SMC call initial support done by Grzegorz Jaszczyk.
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/arm-smccc.h>
14*4882a593Smuzhiyun #include <linux/io.h>
15*4882a593Smuzhiyun #include <linux/iopoll.h>
16*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/phy.h>
19*4882a593Smuzhiyun #include <linux/phy/phy.h>
20*4882a593Smuzhiyun #include <linux/platform_device.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define MVEBU_A3700_COMPHY_LANES		3
23*4882a593Smuzhiyun #define MVEBU_A3700_COMPHY_PORTS		2
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /* COMPHY Fast SMC function identifiers */
26*4882a593Smuzhiyun #define COMPHY_SIP_POWER_ON			0x82000001
27*4882a593Smuzhiyun #define COMPHY_SIP_POWER_OFF			0x82000002
28*4882a593Smuzhiyun #define COMPHY_SIP_PLL_LOCK			0x82000003
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define COMPHY_FW_MODE_SATA			0x1
31*4882a593Smuzhiyun #define COMPHY_FW_MODE_SGMII			0x2
32*4882a593Smuzhiyun #define COMPHY_FW_MODE_HS_SGMII			0x3
33*4882a593Smuzhiyun #define COMPHY_FW_MODE_USB3H			0x4
34*4882a593Smuzhiyun #define COMPHY_FW_MODE_USB3D			0x5
35*4882a593Smuzhiyun #define COMPHY_FW_MODE_PCIE			0x6
36*4882a593Smuzhiyun #define COMPHY_FW_MODE_RXAUI			0x7
37*4882a593Smuzhiyun #define COMPHY_FW_MODE_XFI			0x8
38*4882a593Smuzhiyun #define COMPHY_FW_MODE_SFI			0x9
39*4882a593Smuzhiyun #define COMPHY_FW_MODE_USB3			0xa
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define COMPHY_FW_SPEED_1_25G			0 /* SGMII 1G */
42*4882a593Smuzhiyun #define COMPHY_FW_SPEED_2_5G			1
43*4882a593Smuzhiyun #define COMPHY_FW_SPEED_3_125G			2 /* SGMII 2.5G */
44*4882a593Smuzhiyun #define COMPHY_FW_SPEED_5G			3
45*4882a593Smuzhiyun #define COMPHY_FW_SPEED_5_15625G		4 /* XFI 5G */
46*4882a593Smuzhiyun #define COMPHY_FW_SPEED_6G			5
47*4882a593Smuzhiyun #define COMPHY_FW_SPEED_10_3125G		6 /* XFI 10G */
48*4882a593Smuzhiyun #define COMPHY_FW_SPEED_MAX			0x3F
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define COMPHY_FW_MODE(mode)			((mode) << 12)
51*4882a593Smuzhiyun #define COMPHY_FW_NET(mode, idx, speed)		(COMPHY_FW_MODE(mode) | \
52*4882a593Smuzhiyun 						 ((idx) << 8) |	\
53*4882a593Smuzhiyun 						 ((speed) << 2))
54*4882a593Smuzhiyun #define COMPHY_FW_PCIE(mode, idx, speed, width)	(COMPHY_FW_NET(mode, idx, speed) | \
55*4882a593Smuzhiyun 						 ((width) << 18))
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun struct mvebu_a3700_comphy_conf {
58*4882a593Smuzhiyun 	unsigned int lane;
59*4882a593Smuzhiyun 	enum phy_mode mode;
60*4882a593Smuzhiyun 	int submode;
61*4882a593Smuzhiyun 	unsigned int port;
62*4882a593Smuzhiyun 	u32 fw_mode;
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw)	\
66*4882a593Smuzhiyun 	{								\
67*4882a593Smuzhiyun 		.lane = _lane,						\
68*4882a593Smuzhiyun 		.mode = _mode,						\
69*4882a593Smuzhiyun 		.submode = _smode,					\
70*4882a593Smuzhiyun 		.port = _port,						\
71*4882a593Smuzhiyun 		.fw_mode = _fw,						\
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun #define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \
75*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \
78*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw)
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = {
81*4882a593Smuzhiyun 	/* lane 0 */
82*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0,
83*4882a593Smuzhiyun 				    COMPHY_FW_MODE_USB3H),
84*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1,
85*4882a593Smuzhiyun 				    COMPHY_FW_MODE_SGMII),
86*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1,
87*4882a593Smuzhiyun 				    COMPHY_FW_MODE_HS_SGMII),
88*4882a593Smuzhiyun 	/* lane 1 */
89*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0,
90*4882a593Smuzhiyun 				    COMPHY_FW_MODE_PCIE),
91*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0,
92*4882a593Smuzhiyun 				    COMPHY_FW_MODE_SGMII),
93*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0,
94*4882a593Smuzhiyun 				    COMPHY_FW_MODE_HS_SGMII),
95*4882a593Smuzhiyun 	/* lane 2 */
96*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0,
97*4882a593Smuzhiyun 				    COMPHY_FW_MODE_SATA),
98*4882a593Smuzhiyun 	MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0,
99*4882a593Smuzhiyun 				    COMPHY_FW_MODE_USB3H),
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun struct mvebu_a3700_comphy_lane {
103*4882a593Smuzhiyun 	struct device *dev;
104*4882a593Smuzhiyun 	unsigned int id;
105*4882a593Smuzhiyun 	enum phy_mode mode;
106*4882a593Smuzhiyun 	int submode;
107*4882a593Smuzhiyun 	int port;
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
mvebu_a3700_comphy_smc(unsigned long function,unsigned long lane,unsigned long mode)110*4882a593Smuzhiyun static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane,
111*4882a593Smuzhiyun 				  unsigned long mode)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	struct arm_smccc_res res;
114*4882a593Smuzhiyun 	s32 ret;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res);
117*4882a593Smuzhiyun 	ret = res.a0;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	switch (ret) {
120*4882a593Smuzhiyun 	case SMCCC_RET_SUCCESS:
121*4882a593Smuzhiyun 		return 0;
122*4882a593Smuzhiyun 	case SMCCC_RET_NOT_SUPPORTED:
123*4882a593Smuzhiyun 		return -EOPNOTSUPP;
124*4882a593Smuzhiyun 	default:
125*4882a593Smuzhiyun 		return -EINVAL;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
mvebu_a3700_comphy_get_fw_mode(int lane,int port,enum phy_mode mode,int submode)129*4882a593Smuzhiyun static int mvebu_a3700_comphy_get_fw_mode(int lane, int port,
130*4882a593Smuzhiyun 					  enum phy_mode mode,
131*4882a593Smuzhiyun 					  int submode)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	/* Unused PHY mux value is 0x0 */
136*4882a593Smuzhiyun 	if (mode == PHY_MODE_INVALID)
137*4882a593Smuzhiyun 		return -EINVAL;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	for (i = 0; i < n; i++) {
140*4882a593Smuzhiyun 		if (mvebu_a3700_comphy_modes[i].lane == lane &&
141*4882a593Smuzhiyun 		    mvebu_a3700_comphy_modes[i].port == port &&
142*4882a593Smuzhiyun 		    mvebu_a3700_comphy_modes[i].mode == mode &&
143*4882a593Smuzhiyun 		    mvebu_a3700_comphy_modes[i].submode == submode)
144*4882a593Smuzhiyun 			break;
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (i == n)
148*4882a593Smuzhiyun 		return -EINVAL;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return mvebu_a3700_comphy_modes[i].fw_mode;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
mvebu_a3700_comphy_set_mode(struct phy * phy,enum phy_mode mode,int submode)153*4882a593Smuzhiyun static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode,
154*4882a593Smuzhiyun 				       int submode)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
157*4882a593Smuzhiyun 	int fw_mode;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	if (submode == PHY_INTERFACE_MODE_1000BASEX)
160*4882a593Smuzhiyun 		submode = PHY_INTERFACE_MODE_SGMII;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode,
163*4882a593Smuzhiyun 						 submode);
164*4882a593Smuzhiyun 	if (fw_mode < 0) {
165*4882a593Smuzhiyun 		dev_err(lane->dev, "invalid COMPHY mode\n");
166*4882a593Smuzhiyun 		return fw_mode;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	/* Just remember the mode, ->power_on() will do the real setup */
170*4882a593Smuzhiyun 	lane->mode = mode;
171*4882a593Smuzhiyun 	lane->submode = submode;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
mvebu_a3700_comphy_power_on(struct phy * phy)176*4882a593Smuzhiyun static int mvebu_a3700_comphy_power_on(struct phy *phy)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
179*4882a593Smuzhiyun 	u32 fw_param;
180*4882a593Smuzhiyun 	int fw_mode;
181*4882a593Smuzhiyun 	int ret;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port,
184*4882a593Smuzhiyun 						 lane->mode, lane->submode);
185*4882a593Smuzhiyun 	if (fw_mode < 0) {
186*4882a593Smuzhiyun 		dev_err(lane->dev, "invalid COMPHY mode\n");
187*4882a593Smuzhiyun 		return fw_mode;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	switch (lane->mode) {
191*4882a593Smuzhiyun 	case PHY_MODE_USB_HOST_SS:
192*4882a593Smuzhiyun 		dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id);
193*4882a593Smuzhiyun 		fw_param = COMPHY_FW_MODE(fw_mode);
194*4882a593Smuzhiyun 		break;
195*4882a593Smuzhiyun 	case PHY_MODE_SATA:
196*4882a593Smuzhiyun 		dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id);
197*4882a593Smuzhiyun 		fw_param = COMPHY_FW_MODE(fw_mode);
198*4882a593Smuzhiyun 		break;
199*4882a593Smuzhiyun 	case PHY_MODE_ETHERNET:
200*4882a593Smuzhiyun 		switch (lane->submode) {
201*4882a593Smuzhiyun 		case PHY_INTERFACE_MODE_SGMII:
202*4882a593Smuzhiyun 			dev_dbg(lane->dev, "set lane %d to SGMII mode\n",
203*4882a593Smuzhiyun 				lane->id);
204*4882a593Smuzhiyun 			fw_param = COMPHY_FW_NET(fw_mode, lane->port,
205*4882a593Smuzhiyun 						 COMPHY_FW_SPEED_1_25G);
206*4882a593Smuzhiyun 			break;
207*4882a593Smuzhiyun 		case PHY_INTERFACE_MODE_2500BASEX:
208*4882a593Smuzhiyun 			dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n",
209*4882a593Smuzhiyun 				lane->id);
210*4882a593Smuzhiyun 			fw_param = COMPHY_FW_NET(fw_mode, lane->port,
211*4882a593Smuzhiyun 						 COMPHY_FW_SPEED_3_125G);
212*4882a593Smuzhiyun 			break;
213*4882a593Smuzhiyun 		default:
214*4882a593Smuzhiyun 			dev_err(lane->dev, "unsupported PHY submode (%d)\n",
215*4882a593Smuzhiyun 				lane->submode);
216*4882a593Smuzhiyun 			return -ENOTSUPP;
217*4882a593Smuzhiyun 		}
218*4882a593Smuzhiyun 		break;
219*4882a593Smuzhiyun 	case PHY_MODE_PCIE:
220*4882a593Smuzhiyun 		dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id);
221*4882a593Smuzhiyun 		fw_param = COMPHY_FW_PCIE(fw_mode, lane->port,
222*4882a593Smuzhiyun 					  COMPHY_FW_SPEED_5G,
223*4882a593Smuzhiyun 					  phy->attrs.bus_width);
224*4882a593Smuzhiyun 		break;
225*4882a593Smuzhiyun 	default:
226*4882a593Smuzhiyun 		dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode);
227*4882a593Smuzhiyun 		return -ENOTSUPP;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	ret = mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param);
231*4882a593Smuzhiyun 	if (ret == -EOPNOTSUPP)
232*4882a593Smuzhiyun 		dev_err(lane->dev,
233*4882a593Smuzhiyun 			"unsupported SMC call, try updating your firmware\n");
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	return ret;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
mvebu_a3700_comphy_power_off(struct phy * phy)238*4882a593Smuzhiyun static int mvebu_a3700_comphy_power_off(struct phy *phy)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun static const struct phy_ops mvebu_a3700_comphy_ops = {
246*4882a593Smuzhiyun 	.power_on	= mvebu_a3700_comphy_power_on,
247*4882a593Smuzhiyun 	.power_off	= mvebu_a3700_comphy_power_off,
248*4882a593Smuzhiyun 	.set_mode	= mvebu_a3700_comphy_set_mode,
249*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
250*4882a593Smuzhiyun };
251*4882a593Smuzhiyun 
mvebu_a3700_comphy_xlate(struct device * dev,struct of_phandle_args * args)252*4882a593Smuzhiyun static struct phy *mvebu_a3700_comphy_xlate(struct device *dev,
253*4882a593Smuzhiyun 					    struct of_phandle_args *args)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	struct mvebu_a3700_comphy_lane *lane;
256*4882a593Smuzhiyun 	struct phy *phy;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS))
259*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	phy = of_phy_simple_xlate(dev, args);
262*4882a593Smuzhiyun 	if (IS_ERR(phy))
263*4882a593Smuzhiyun 		return phy;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	lane = phy_get_drvdata(phy);
266*4882a593Smuzhiyun 	lane->port = args->args[0];
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	return phy;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
mvebu_a3700_comphy_probe(struct platform_device * pdev)271*4882a593Smuzhiyun static int mvebu_a3700_comphy_probe(struct platform_device *pdev)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct phy_provider *provider;
274*4882a593Smuzhiyun 	struct device_node *child;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	for_each_available_child_of_node(pdev->dev.of_node, child) {
277*4882a593Smuzhiyun 		struct mvebu_a3700_comphy_lane *lane;
278*4882a593Smuzhiyun 		struct phy *phy;
279*4882a593Smuzhiyun 		int ret;
280*4882a593Smuzhiyun 		u32 lane_id;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 		ret = of_property_read_u32(child, "reg", &lane_id);
283*4882a593Smuzhiyun 		if (ret < 0) {
284*4882a593Smuzhiyun 			dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
285*4882a593Smuzhiyun 				ret);
286*4882a593Smuzhiyun 			continue;
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 		if (lane_id >= MVEBU_A3700_COMPHY_LANES) {
290*4882a593Smuzhiyun 			dev_err(&pdev->dev, "invalid 'reg' property\n");
291*4882a593Smuzhiyun 			continue;
292*4882a593Smuzhiyun 		}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL);
295*4882a593Smuzhiyun 		if (!lane) {
296*4882a593Smuzhiyun 			of_node_put(child);
297*4882a593Smuzhiyun 			return -ENOMEM;
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 		phy = devm_phy_create(&pdev->dev, child,
301*4882a593Smuzhiyun 				      &mvebu_a3700_comphy_ops);
302*4882a593Smuzhiyun 		if (IS_ERR(phy)) {
303*4882a593Smuzhiyun 			of_node_put(child);
304*4882a593Smuzhiyun 			return PTR_ERR(phy);
305*4882a593Smuzhiyun 		}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 		lane->dev = &pdev->dev;
308*4882a593Smuzhiyun 		lane->mode = PHY_MODE_INVALID;
309*4882a593Smuzhiyun 		lane->submode = PHY_INTERFACE_MODE_NA;
310*4882a593Smuzhiyun 		lane->id = lane_id;
311*4882a593Smuzhiyun 		lane->port = -1;
312*4882a593Smuzhiyun 		phy_set_drvdata(phy, lane);
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	provider = devm_of_phy_provider_register(&pdev->dev,
316*4882a593Smuzhiyun 						 mvebu_a3700_comphy_xlate);
317*4882a593Smuzhiyun 	return PTR_ERR_OR_ZERO(provider);
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun static const struct of_device_id mvebu_a3700_comphy_of_match_table[] = {
321*4882a593Smuzhiyun 	{ .compatible = "marvell,comphy-a3700" },
322*4882a593Smuzhiyun 	{ },
323*4882a593Smuzhiyun };
324*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mvebu_a3700_comphy_of_match_table);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun static struct platform_driver mvebu_a3700_comphy_driver = {
327*4882a593Smuzhiyun 	.probe	= mvebu_a3700_comphy_probe,
328*4882a593Smuzhiyun 	.driver	= {
329*4882a593Smuzhiyun 		.name = "mvebu-a3700-comphy",
330*4882a593Smuzhiyun 		.of_match_table = mvebu_a3700_comphy_of_match_table,
331*4882a593Smuzhiyun 	},
332*4882a593Smuzhiyun };
333*4882a593Smuzhiyun module_platform_driver(mvebu_a3700_comphy_driver);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun MODULE_AUTHOR("Miquèl Raynal <miquel.raynal@bootlin.com>");
336*4882a593Smuzhiyun MODULE_DESCRIPTION("Common PHY driver for A3700");
337*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
338