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