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