blob: 1df639d6f4438f9d7927b2f2f10eb28fc91a7997 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +05302/*
3 * Xilinx PCS/PMA Core phy driver
4 *
5 * Copyright (C) 2015 - 2016 Xilinx, Inc.
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +05306 */
7
8#include <config.h>
9#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +053011#include <phy.h>
12#include <dm.h>
13
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +053014#define MII_PHY_STATUS_SPD_MASK 0x0C00
15#define MII_PHY_STATUS_FULLDUPLEX 0x1000
16#define MII_PHY_STATUS_1000 0x0800
17#define MII_PHY_STATUS_100 0x0400
18#define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
19
20/* Mask used for ID comparisons */
21#define XILINX_PHY_ID_MASK 0xfffffff0
22
23/* Known PHY IDs */
24#define XILINX_PHY_ID 0x01740c00
25
26/* struct phy_device dev_flags definitions */
27#define XAE_PHY_TYPE_MII 0
28#define XAE_PHY_TYPE_GMII 1
29#define XAE_PHY_TYPE_RGMII_1_3 2
30#define XAE_PHY_TYPE_RGMII_2_0 3
31#define XAE_PHY_TYPE_SGMII 4
32#define XAE_PHY_TYPE_1000BASE_X 5
33
34static int xilinxphy_startup(struct phy_device *phydev)
35{
36 int err;
37 int status = 0;
38
39 debug("%s\n", __func__);
40 /* Update the link, but return if there
41 * was an error
42 */
43 err = genphy_update_link(phydev);
44 if (err)
45 return err;
46
47 if (AUTONEG_ENABLE == phydev->autoneg) {
48 status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
49 status = status & MII_PHY_STATUS_SPD_MASK;
50
51 if (status & MII_PHY_STATUS_FULLDUPLEX)
52 phydev->duplex = DUPLEX_FULL;
53 else
54 phydev->duplex = DUPLEX_HALF;
55
56 switch (status) {
57 case MII_PHY_STATUS_1000:
58 phydev->speed = SPEED_1000;
59 break;
60
61 case MII_PHY_STATUS_100:
62 phydev->speed = SPEED_100;
63 break;
64
65 default:
66 phydev->speed = SPEED_10;
67 break;
68 }
69 } else {
70 int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
71
72 if (bmcr < 0)
73 return bmcr;
74
75 if (bmcr & BMCR_FULLDPLX)
76 phydev->duplex = DUPLEX_FULL;
77 else
78 phydev->duplex = DUPLEX_HALF;
79
80 if (bmcr & BMCR_SPEED1000)
81 phydev->speed = SPEED_1000;
82 else if (bmcr & BMCR_SPEED100)
83 phydev->speed = SPEED_100;
84 else
85 phydev->speed = SPEED_10;
86 }
87
88 /*
89 * For 1000BASE-X Phy Mode the speed/duplex will always be
90 * 1000Mbps/fullduplex
91 */
92 if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) {
93 phydev->duplex = DUPLEX_FULL;
94 phydev->speed = SPEED_1000;
95 }
96
97 return 0;
98}
99
100static int xilinxphy_of_init(struct phy_device *phydev)
101{
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +0530102 u32 phytype;
Grygorii Strashkoc7cc65e2018-07-05 12:02:50 -0500103 ofnode node;
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +0530104
105 debug("%s\n", __func__);
Grygorii Strashkoc7cc65e2018-07-05 12:02:50 -0500106 node = phy_get_ofnode(phydev);
107 if (!ofnode_valid(node))
108 return -EINVAL;
109
110 phytype = ofnode_read_u32_default(node, "xlnx,phy-type", -1);
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +0530111 if (phytype == XAE_PHY_TYPE_1000BASE_X)
112 phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
113
114 return 0;
115}
116
117static int xilinxphy_config(struct phy_device *phydev)
118{
119 int temp;
120
121 debug("%s\n", __func__);
122 xilinxphy_of_init(phydev);
123 temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
124 temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
125 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp);
126
127 return 0;
128}
129
Marek Vasutd918b532023-03-19 18:03:06 +0100130U_BOOT_PHY_DRIVER(xilinxphy) = {
Siva Durga Prasad Paladugudd6cbd32016-02-05 13:22:10 +0530131 .uid = XILINX_PHY_ID,
132 .mask = XILINX_PHY_ID_MASK,
133 .name = "Xilinx PCS/PMA PHY",
134 .features = PHY_GBIT_FEATURES,
135 .config = &xilinxphy_config,
136 .startup = &xilinxphy_startup,
137 .shutdown = &genphy_shutdown,
138};