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 <log.h>
9#include <malloc.h>
10#include <dm/platform_data/pfe_dm_eth.h>
11#include <net.h>
12#include <linux/delay.h>
13#include <net/pfe_eth/pfe_eth.h>
14
15extern struct gemac_s gem_info[];
16#if defined(CONFIG_PHYLIB)
17
18#define MDIO_TIMEOUT    5000
19static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
20			  int reg_addr)
21{
22	void *reg_base = bus->priv;
23	u32 devadr;
24	u32 phy;
25	u32 reg_data;
26	int timeout = MDIO_TIMEOUT;
27
28	devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
29	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
30
31	reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
32
33	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
34
35	/*
36	 * wait for the MII interrupt
37	 */
38	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
39		if (timeout-- <= 0) {
40			printf("Phy MDIO read/write timeout\n");
41			return -1;
42		}
43	}
44
45	/*
46	 * clear MII interrupt
47	 */
48	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
49
50	return 0;
51}
52
53static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
54			int reg_addr)
55{
56	void *reg_base = bus->priv;
57	u32 reg;
58	u32 phy;
59	u32 reg_data;
60	u16 val;
61	int timeout = MDIO_TIMEOUT;
62
63	if (dev_addr == MDIO_DEVAD_NONE) {
64		reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
65			EMAC_MII_DATA_RA_SHIFT);
66	} else {
67		pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
68		reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
69		       EMAC_MII_DATA_RA_SHIFT);
70	}
71
72	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
73
74	if (dev_addr == MDIO_DEVAD_NONE)
75		reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
76			    EMAC_MII_DATA_TA | phy | reg);
77	else
78		reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
79			    phy | reg);
80
81	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
82
83	/*
84	 * wait for the MII interrupt
85	 */
86	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
87		if (timeout-- <= 0) {
88			printf("Phy MDIO read/write timeout\n");
89			return -1;
90		}
91	}
92
93	/*
94	 * clear MII interrupt
95	 */
96	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
97
98	/*
99	 * it's now safe to read the PHY's register
100	 */
101	val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
102	debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
103	      phy_addr, reg_addr, val);
104
105	return val;
106}
107
108static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
109			 int reg_addr, u16 data)
110{
111	void *reg_base = bus->priv;
112	u32 reg;
113	u32 phy;
114	u32 reg_data;
115	int timeout = MDIO_TIMEOUT;
116
117	if (dev_addr == MDIO_DEVAD_NONE) {
118		reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
119		       EMAC_MII_DATA_RA_SHIFT);
120	} else {
121		pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
122		reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
123		       EMAC_MII_DATA_RA_SHIFT);
124	}
125
126	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
127
128	if (dev_addr == MDIO_DEVAD_NONE)
129		reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
130			    EMAC_MII_DATA_TA | phy | reg | data);
131	else
132		reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
133			    phy | reg | data);
134
135	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
136
137	/*
138	 * wait for the MII interrupt
139	 */
140	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
141		if (timeout-- <= 0) {
142			printf("Phy MDIO read/write timeout\n");
143			return -1;
144		}
145	}
146
147	/*
148	 * clear MII interrupt
149	 */
150	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
151
152	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
153	      reg_addr, data);
154
155	return 0;
156}
157
158static void pfe_configure_serdes(struct pfe_eth_dev *priv)
159{
160	struct mii_dev bus;
161	int value, sgmii_2500 = 0;
162	struct gemac_s *gem = priv->gem;
163
164	if (gem->phy_mode == PHY_INTERFACE_MODE_2500BASEX)
165		sgmii_2500 = 1;
166
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 *)CFG_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_2500BASEX) {
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}
292