blob: a78a4d63f3ae5b7bb881d7fe82043657f4e7890d [file] [log] [blame]
Calvin Johnson781b8382018-03-08 15:30:25 +05301/*
2 * Copyright 2015-2016 Freescale Semiconductor, Inc.
3 * Copyright 2017 NXP
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7#include <common.h>
8#include <dm.h>
9#include <dm/platform_data/pfe_dm_eth.h>
10#include <net.h>
11#include <net/pfe_eth/pfe_eth.h>
12
13extern struct gemac_s gem_info[];
14#if defined(CONFIG_PHYLIB)
15
16#define MDIO_TIMEOUT 5000
17static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
18 int reg_addr)
19{
20 void *reg_base = bus->priv;
21 u32 devadr;
22 u32 phy;
23 u32 reg_data;
24 int timeout = MDIO_TIMEOUT;
25
26 devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
27 phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
28
29 reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
30
31 writel(reg_data, reg_base + EMAC_MII_DATA_REG);
32
33 /*
34 * wait for the MII interrupt
35 */
36 while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
37 if (timeout-- <= 0) {
38 printf("Phy MDIO read/write timeout\n");
39 return -1;
40 }
41 }
42
43 /*
44 * clear MII interrupt
45 */
46 writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
47
48 return 0;
49}
50
51static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
52 int reg_addr)
53{
54 void *reg_base = bus->priv;
55 u32 reg;
56 u32 phy;
57 u32 reg_data;
58 u16 val;
59 int timeout = MDIO_TIMEOUT;
60
61 if (dev_addr == MDIO_DEVAD_NONE) {
62 reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
63 EMAC_MII_DATA_RA_SHIFT);
64 } else {
65 pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
66 reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
67 EMAC_MII_DATA_RA_SHIFT);
68 }
69
70 phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
71
72 if (dev_addr == MDIO_DEVAD_NONE)
73 reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
74 EMAC_MII_DATA_TA | phy | reg);
75 else
76 reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
77 phy | reg);
78
79 writel(reg_data, reg_base + EMAC_MII_DATA_REG);
80
81 /*
82 * wait for the MII interrupt
83 */
84 while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
85 if (timeout-- <= 0) {
86 printf("Phy MDIO read/write timeout\n");
87 return -1;
88 }
89 }
90
91 /*
92 * clear MII interrupt
93 */
94 writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
95
96 /*
97 * it's now safe to read the PHY's register
98 */
99 val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
100 debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
101 phy_addr, reg_addr, val);
102
103 return val;
104}
105
106static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
107 int reg_addr, u16 data)
108{
109 void *reg_base = bus->priv;
110 u32 reg;
111 u32 phy;
112 u32 reg_data;
113 int timeout = MDIO_TIMEOUT;
114 int val;
115
116 if (dev_addr == MDIO_DEVAD_NONE) {
117 reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
118 EMAC_MII_DATA_RA_SHIFT);
119 } else {
120 pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
121 reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
122 EMAC_MII_DATA_RA_SHIFT);
123 }
124
125 phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
126
127 if (dev_addr == MDIO_DEVAD_NONE)
128 reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
129 EMAC_MII_DATA_TA | phy | reg | data);
130 else
131 reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
132 phy | reg | data);
133
134 writel(reg_data, reg_base + EMAC_MII_DATA_REG);
135
136 /*
137 * wait for the MII interrupt
138 */
139 while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
140 if (timeout-- <= 0) {
141 printf("Phy MDIO read/write timeout\n");
142 return -1;
143 }
144 }
145
146 /*
147 * clear MII interrupt
148 */
149 writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
150
151 debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
152 reg_addr, data);
153
154 return val;
155}
156
157static void pfe_configure_serdes(struct pfe_eth_dev *priv)
158{
159 struct mii_dev bus;
160 int value, sgmii_2500 = 0;
161 struct gemac_s *gem = priv->gem;
162
163 if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500)
164 sgmii_2500 = 1;
165
166 printf("%s %d\n", __func__, priv->gemac_port);
167
168 /* PCS configuration done with corresponding GEMAC */
169 bus.priv = gem_info[priv->gemac_port].gemac_base;
170
171 pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0);
172 pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1);
173 pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2);
174 pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3);
175
176 /* Reset serdes */
177 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000);
178
179 /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
180 value = PHY_SGMII_IF_MODE_SGMII;
181 if (!sgmii_2500)
182 value |= PHY_SGMII_IF_MODE_AN;
183 else
184 value |= PHY_SGMII_IF_MODE_SGMII_GBT;
185
186 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
187
188 /* Dev ability according to SGMII specification */
189 value = PHY_SGMII_DEV_ABILITY_SGMII;
190 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
191
192 /* These values taken from validation team */
193 if (!sgmii_2500) {
194 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0);
195 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400);
196 } else {
197 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7);
198 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120);
199 }
200
201 /* Restart AN */
202 value = PHY_SGMII_CR_DEF_VAL;
203 if (!sgmii_2500)
204 value |= PHY_SGMII_CR_RESET_AN;
205 /* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/
206 if (sgmii_2500)
207 value &= ~PHY_SGMII_ENABLE_AN;
208 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
209}
210
211int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id)
212{
213 struct phy_device *phydev = NULL;
214 struct udevice *dev = priv->dev;
215 struct gemac_s *gem = priv->gem;
216 struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
217
218 if (!gem->bus)
219 return -1;
220
221 /* Configure SGMII PCS */
222 if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII ||
223 gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) {
224 out_be32(&scfg->mdioselcr, 0x00000000);
225 pfe_configure_serdes(priv);
226 }
227
228 mdelay(100);
229
230 /* By this time on-chip SGMII initialization is done
231 * we can switch mdio interface to external PHYs
232 */
233 out_be32(&scfg->mdioselcr, 0x80000000);
234
235 phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode);
236 if (!phydev) {
237 printf("phy_connect failed\n");
238 return -ENODEV;
239 }
240
241 phy_config(phydev);
242
243 priv->phydev = phydev;
244
245 return 0;
246}
247#endif
248
249struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info)
250{
251 struct mii_dev *bus;
252 int ret;
253 u32 mdio_speed;
254 u32 pclk = 250000000;
255
256 bus = mdio_alloc();
257 if (!bus) {
258 printf("mdio_alloc failed\n");
259 return NULL;
260 }
261 bus->read = pfe_phy_read;
262 bus->write = pfe_phy_write;
263
264 /* MAC1 MDIO used to communicate with external PHYS */
265 bus->priv = mdio_info->reg_base;
266 sprintf(bus->name, mdio_info->name);
267
268 /* configure mdio speed */
269 mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT);
270 mdio_speed |= EMAC_HOLDTIME(0x5);
271 writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG);
272
273 ret = mdio_register(bus);
274 if (ret) {
275 printf("mdio_register failed\n");
276 free(bus);
277 return NULL;
278 }
279 return bus;
280}
281
282void pfe_set_mdio(int dev_id, struct mii_dev *bus)
283{
284 gem_info[dev_id].bus = bus;
285}
286
287void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode)
288{
289 gem_info[dev_id].phy_address = phy_id;
290 gem_info[dev_id].phy_mode = phy_mode;
291}