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