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