xref: /openbmc/u-boot/drivers/net/pfe_eth/pfe_mdio.c (revision cf0bcd7d)
1 /*
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 
13 extern struct gemac_s gem_info[];
14 #if defined(CONFIG_PHYLIB)
15 
16 #define MDIO_TIMEOUT    5000
17 static 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 
51 static 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 
106 static 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 
157 static 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 
211 int 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 
249 struct 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 
282 void pfe_set_mdio(int dev_id, struct mii_dev *bus)
283 {
284 	gem_info[dev_id].bus = bus;
285 }
286 
287 void 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 }
292