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