xref: /rk3399_rockchip-uboot/drivers/net/phy/xilinx_phy.c (revision 21342d4aed6c77a4aa7a5b2579b3c23e21aea31a)
1ed6fad3eSSiva Durga Prasad Paladugu /*
2ed6fad3eSSiva Durga Prasad Paladugu  * Xilinx PCS/PMA Core phy driver
3ed6fad3eSSiva Durga Prasad Paladugu  *
4ed6fad3eSSiva Durga Prasad Paladugu  * Copyright (C) 2015 - 2016 Xilinx, Inc.
5ed6fad3eSSiva Durga Prasad Paladugu  *
6ed6fad3eSSiva Durga Prasad Paladugu  * SPDX-License-Identifier:	GPL-2.0+
7ed6fad3eSSiva Durga Prasad Paladugu  */
8ed6fad3eSSiva Durga Prasad Paladugu 
9ed6fad3eSSiva Durga Prasad Paladugu #include <config.h>
10ed6fad3eSSiva Durga Prasad Paladugu #include <common.h>
11ed6fad3eSSiva Durga Prasad Paladugu #include <phy.h>
12ed6fad3eSSiva Durga Prasad Paladugu #include <dm.h>
13ed6fad3eSSiva Durga Prasad Paladugu 
14ed6fad3eSSiva Durga Prasad Paladugu DECLARE_GLOBAL_DATA_PTR;
15ed6fad3eSSiva Durga Prasad Paladugu 
16ed6fad3eSSiva Durga Prasad Paladugu #define MII_PHY_STATUS_SPD_MASK		0x0C00
17ed6fad3eSSiva Durga Prasad Paladugu #define MII_PHY_STATUS_FULLDUPLEX	0x1000
18ed6fad3eSSiva Durga Prasad Paladugu #define MII_PHY_STATUS_1000		0x0800
19ed6fad3eSSiva Durga Prasad Paladugu #define MII_PHY_STATUS_100		0x0400
20ed6fad3eSSiva Durga Prasad Paladugu #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
21ed6fad3eSSiva Durga Prasad Paladugu 
22ed6fad3eSSiva Durga Prasad Paladugu /* Mask used for ID comparisons */
23ed6fad3eSSiva Durga Prasad Paladugu #define XILINX_PHY_ID_MASK		0xfffffff0
24ed6fad3eSSiva Durga Prasad Paladugu 
25ed6fad3eSSiva Durga Prasad Paladugu /* Known PHY IDs */
26ed6fad3eSSiva Durga Prasad Paladugu #define XILINX_PHY_ID			0x01740c00
27ed6fad3eSSiva Durga Prasad Paladugu 
28ed6fad3eSSiva Durga Prasad Paladugu /* struct phy_device dev_flags definitions */
29ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_MII		0
30ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_GMII		1
31ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_RGMII_1_3		2
32ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_RGMII_2_0		3
33ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_SGMII		4
34ed6fad3eSSiva Durga Prasad Paladugu #define XAE_PHY_TYPE_1000BASE_X		5
35ed6fad3eSSiva Durga Prasad Paladugu 
xilinxphy_startup(struct phy_device * phydev)36ed6fad3eSSiva Durga Prasad Paladugu static int xilinxphy_startup(struct phy_device *phydev)
37ed6fad3eSSiva Durga Prasad Paladugu {
38ed6fad3eSSiva Durga Prasad Paladugu 	int err;
39ed6fad3eSSiva Durga Prasad Paladugu 	int status = 0;
40ed6fad3eSSiva Durga Prasad Paladugu 
41ed6fad3eSSiva Durga Prasad Paladugu 	debug("%s\n", __func__);
42ed6fad3eSSiva Durga Prasad Paladugu 	/* Update the link, but return if there
43ed6fad3eSSiva Durga Prasad Paladugu 	 * was an error
44ed6fad3eSSiva Durga Prasad Paladugu 	 */
45ed6fad3eSSiva Durga Prasad Paladugu 	err = genphy_update_link(phydev);
46ed6fad3eSSiva Durga Prasad Paladugu 	if (err)
47ed6fad3eSSiva Durga Prasad Paladugu 		return err;
48ed6fad3eSSiva Durga Prasad Paladugu 
49ed6fad3eSSiva Durga Prasad Paladugu 	if (AUTONEG_ENABLE == phydev->autoneg) {
50ed6fad3eSSiva Durga Prasad Paladugu 		status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
51ed6fad3eSSiva Durga Prasad Paladugu 		status = status & MII_PHY_STATUS_SPD_MASK;
52ed6fad3eSSiva Durga Prasad Paladugu 
53ed6fad3eSSiva Durga Prasad Paladugu 		if (status & MII_PHY_STATUS_FULLDUPLEX)
54ed6fad3eSSiva Durga Prasad Paladugu 			phydev->duplex = DUPLEX_FULL;
55ed6fad3eSSiva Durga Prasad Paladugu 		else
56ed6fad3eSSiva Durga Prasad Paladugu 			phydev->duplex = DUPLEX_HALF;
57ed6fad3eSSiva Durga Prasad Paladugu 
58ed6fad3eSSiva Durga Prasad Paladugu 		switch (status) {
59ed6fad3eSSiva Durga Prasad Paladugu 		case MII_PHY_STATUS_1000:
60ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_1000;
61ed6fad3eSSiva Durga Prasad Paladugu 			break;
62ed6fad3eSSiva Durga Prasad Paladugu 
63ed6fad3eSSiva Durga Prasad Paladugu 		case MII_PHY_STATUS_100:
64ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_100;
65ed6fad3eSSiva Durga Prasad Paladugu 			break;
66ed6fad3eSSiva Durga Prasad Paladugu 
67ed6fad3eSSiva Durga Prasad Paladugu 		default:
68ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_10;
69ed6fad3eSSiva Durga Prasad Paladugu 			break;
70ed6fad3eSSiva Durga Prasad Paladugu 		}
71ed6fad3eSSiva Durga Prasad Paladugu 	} else {
72ed6fad3eSSiva Durga Prasad Paladugu 		int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
73ed6fad3eSSiva Durga Prasad Paladugu 
74ed6fad3eSSiva Durga Prasad Paladugu 		if (bmcr < 0)
75ed6fad3eSSiva Durga Prasad Paladugu 			return bmcr;
76ed6fad3eSSiva Durga Prasad Paladugu 
77ed6fad3eSSiva Durga Prasad Paladugu 		if (bmcr & BMCR_FULLDPLX)
78ed6fad3eSSiva Durga Prasad Paladugu 			phydev->duplex = DUPLEX_FULL;
79ed6fad3eSSiva Durga Prasad Paladugu 		else
80ed6fad3eSSiva Durga Prasad Paladugu 			phydev->duplex = DUPLEX_HALF;
81ed6fad3eSSiva Durga Prasad Paladugu 
82ed6fad3eSSiva Durga Prasad Paladugu 		if (bmcr & BMCR_SPEED1000)
83ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_1000;
84ed6fad3eSSiva Durga Prasad Paladugu 		else if (bmcr & BMCR_SPEED100)
85ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_100;
86ed6fad3eSSiva Durga Prasad Paladugu 		else
87ed6fad3eSSiva Durga Prasad Paladugu 			phydev->speed = SPEED_10;
88ed6fad3eSSiva Durga Prasad Paladugu 	}
89ed6fad3eSSiva Durga Prasad Paladugu 
90ed6fad3eSSiva Durga Prasad Paladugu 	/*
91ed6fad3eSSiva Durga Prasad Paladugu 	 * For 1000BASE-X Phy Mode the speed/duplex will always be
92ed6fad3eSSiva Durga Prasad Paladugu 	 * 1000Mbps/fullduplex
93ed6fad3eSSiva Durga Prasad Paladugu 	 */
94ed6fad3eSSiva Durga Prasad Paladugu 	if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) {
95ed6fad3eSSiva Durga Prasad Paladugu 		phydev->duplex = DUPLEX_FULL;
96ed6fad3eSSiva Durga Prasad Paladugu 		phydev->speed = SPEED_1000;
97ed6fad3eSSiva Durga Prasad Paladugu 	}
98ed6fad3eSSiva Durga Prasad Paladugu 
99ed6fad3eSSiva Durga Prasad Paladugu 	return 0;
100ed6fad3eSSiva Durga Prasad Paladugu }
101ed6fad3eSSiva Durga Prasad Paladugu 
xilinxphy_of_init(struct phy_device * phydev)102ed6fad3eSSiva Durga Prasad Paladugu static int xilinxphy_of_init(struct phy_device *phydev)
103ed6fad3eSSiva Durga Prasad Paladugu {
104ed6fad3eSSiva Durga Prasad Paladugu 	u32 phytype;
105ed6fad3eSSiva Durga Prasad Paladugu 
106ed6fad3eSSiva Durga Prasad Paladugu 	debug("%s\n", __func__);
107*e160f7d4SSimon Glass 	phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev),
1081e946297SKamensky Ivan 				 "phy-type", -1);
109ed6fad3eSSiva Durga Prasad Paladugu 	if (phytype == XAE_PHY_TYPE_1000BASE_X)
110ed6fad3eSSiva Durga Prasad Paladugu 		phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
111ed6fad3eSSiva Durga Prasad Paladugu 
112ed6fad3eSSiva Durga Prasad Paladugu 	return 0;
113ed6fad3eSSiva Durga Prasad Paladugu }
114ed6fad3eSSiva Durga Prasad Paladugu 
xilinxphy_config(struct phy_device * phydev)115ed6fad3eSSiva Durga Prasad Paladugu static int xilinxphy_config(struct phy_device *phydev)
116ed6fad3eSSiva Durga Prasad Paladugu {
117ed6fad3eSSiva Durga Prasad Paladugu 	int temp;
118ed6fad3eSSiva Durga Prasad Paladugu 
119ed6fad3eSSiva Durga Prasad Paladugu 	debug("%s\n", __func__);
120ed6fad3eSSiva Durga Prasad Paladugu 	xilinxphy_of_init(phydev);
121ed6fad3eSSiva Durga Prasad Paladugu 	temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
122ed6fad3eSSiva Durga Prasad Paladugu 	temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
123ed6fad3eSSiva Durga Prasad Paladugu 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp);
124ed6fad3eSSiva Durga Prasad Paladugu 
125ed6fad3eSSiva Durga Prasad Paladugu 	return 0;
126ed6fad3eSSiva Durga Prasad Paladugu }
127ed6fad3eSSiva Durga Prasad Paladugu 
128ed6fad3eSSiva Durga Prasad Paladugu static struct phy_driver xilinxphy_driver = {
129ed6fad3eSSiva Durga Prasad Paladugu 	.uid = XILINX_PHY_ID,
130ed6fad3eSSiva Durga Prasad Paladugu 	.mask = XILINX_PHY_ID_MASK,
131ed6fad3eSSiva Durga Prasad Paladugu 	.name = "Xilinx PCS/PMA PHY",
132ed6fad3eSSiva Durga Prasad Paladugu 	.features = PHY_GBIT_FEATURES,
133ed6fad3eSSiva Durga Prasad Paladugu 	.config = &xilinxphy_config,
134ed6fad3eSSiva Durga Prasad Paladugu 	.startup = &xilinxphy_startup,
135ed6fad3eSSiva Durga Prasad Paladugu 	.shutdown = &genphy_shutdown,
136ed6fad3eSSiva Durga Prasad Paladugu };
137ed6fad3eSSiva Durga Prasad Paladugu 
phy_xilinx_init(void)138ed6fad3eSSiva Durga Prasad Paladugu int phy_xilinx_init(void)
139ed6fad3eSSiva Durga Prasad Paladugu {
140ed6fad3eSSiva Durga Prasad Paladugu 	debug("%s\n", __func__);
141ed6fad3eSSiva Durga Prasad Paladugu 	phy_register(&xilinxphy_driver);
142ed6fad3eSSiva Durga Prasad Paladugu 
143ed6fad3eSSiva Durga Prasad Paladugu 	return 0;
144ed6fad3eSSiva Durga Prasad Paladugu }
145