blob: 26425d94ae5573e48be8865447a775f09f1dcade [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Roy Zangbafd8032012-10-08 07:44:21 +00002/*
3 * Copyright 2012 Freescale Semiconductor, Inc.
Andy Flemingb36a4d42014-07-25 17:39:08 -05004 * Andy Fleming <afleming@gmail.com>
Roy Zangbafd8032012-10-08 07:44:21 +00005 * Roy Zang <tie-fei.zang@freescale.com>
Roy Zangbafd8032012-10-08 07:44:21 +00006 * Some part is taken from tsec.c
7 */
Roy Zangbafd8032012-10-08 07:44:21 +00008#include <miiphy.h>
9#include <phy.h>
10#include <asm/io.h>
Shaohui Xie835c72b2015-03-20 19:28:19 -070011#include <fsl_memac.h>
Roy Zangbafd8032012-10-08 07:44:21 +000012#include <fm_eth.h>
13
Shaohui Xie835c72b2015-03-20 19:28:19 -070014#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
15#define memac_out_32(a, v) out_le32(a, v)
16#define memac_clrbits_32(a, v) clrbits_le32(a, v)
17#define memac_setbits_32(a, v) setbits_le32(a, v)
18#else
19#define memac_out_32(a, v) out_be32(a, v)
20#define memac_clrbits_32(a, v) clrbits_be32(a, v)
21#define memac_setbits_32(a, v) setbits_be32(a, v)
22#endif
23
Madalin Bucur9d327b02020-04-23 16:25:18 +030024struct fm_mdio_priv {
25 struct memac_mdio_controller *regs;
26};
Madalin Bucur9d327b02020-04-23 16:25:18 +030027
Ioana Ciorneif78f21d2020-12-09 13:31:58 +020028#define MAX_NUM_RETRIES 1000
29
Shaohui Xie835c72b2015-03-20 19:28:19 -070030static u32 memac_in_32(u32 *reg)
31{
32#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
33 return in_le32(reg);
34#else
35 return in_be32(reg);
36#endif
37}
38
Roy Zangbafd8032012-10-08 07:44:21 +000039/*
Ioana Ciorneif78f21d2020-12-09 13:31:58 +020040 * Wait until the MDIO bus is free
41 */
42static int memac_wait_until_free(struct memac_mdio_controller *regs)
43{
44 unsigned int timeout = MAX_NUM_RETRIES;
45
46 while ((memac_in_32(&regs->mdio_stat) & MDIO_STAT_BSY) && timeout--)
47 ;
48
49 if (!timeout) {
50 printf("timeout waiting for MDIO bus to be free\n");
51 return -ETIMEDOUT;
52 }
53
54 return 0;
55}
56
57/*
58 * Wait till the MDIO read or write operation is complete
59 */
60static int memac_wait_until_done(struct memac_mdio_controller *regs)
61{
62 unsigned int timeout = MAX_NUM_RETRIES;
63
Markus Koch9c878992022-01-11 19:22:54 +010064 while ((memac_in_32(&regs->mdio_stat) & MDIO_STAT_BSY) && timeout--)
Ioana Ciorneif78f21d2020-12-09 13:31:58 +020065 ;
66
67 if (!timeout) {
68 printf("timeout waiting for MDIO operation to complete\n");
69 return -ETIMEDOUT;
70 }
71
72 return 0;
73}
74
75/*
Roy Zangbafd8032012-10-08 07:44:21 +000076 * Write value to the PHY for this device to the register at regnum, waiting
77 * until the write is done before it returns. All PHY configuration has to be
78 * done through the TSEC1 MIIM regs
79 */
80int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
81 int regnum, u16 value)
82{
Madalin Bucur9d327b02020-04-23 16:25:18 +030083 struct memac_mdio_controller *regs;
Roy Zangbafd8032012-10-08 07:44:21 +000084 u32 mdio_ctl;
Roy Zangbafd8032012-10-08 07:44:21 +000085 u32 c45 = 1; /* Default to 10G interface */
Ioana Ciorneif78f21d2020-12-09 13:31:58 +020086 int err;
Roy Zangbafd8032012-10-08 07:44:21 +000087
Madalin Bucur9d327b02020-04-23 16:25:18 +030088 struct fm_mdio_priv *priv;
89
90 if (!bus->priv)
91 return -EINVAL;
92 priv = dev_get_priv(bus->priv);
93 regs = priv->regs;
94 debug("memac_mdio_write(regs %p, port %d, dev %d, reg %d, val %#x)\n",
95 regs, port_addr, dev_addr, regnum, value);
Madalin Bucur9d327b02020-04-23 16:25:18 +030096
Roy Zangbafd8032012-10-08 07:44:21 +000097 if (dev_addr == MDIO_DEVAD_NONE) {
98 c45 = 0; /* clause 22 */
99 dev_addr = regnum & 0x1f;
Shaohui Xie835c72b2015-03-20 19:28:19 -0700100 memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
Shaohui Xieadbcb9c2014-04-22 18:21:37 +0800101 } else
Shaohui Xie835c72b2015-03-20 19:28:19 -0700102 memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
Roy Zangbafd8032012-10-08 07:44:21 +0000103
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200104 err = memac_wait_until_free(regs);
105 if (err)
106 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000107
108 /* Set the port and dev addr */
109 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
Shaohui Xie835c72b2015-03-20 19:28:19 -0700110 memac_out_32(&regs->mdio_ctl, mdio_ctl);
Roy Zangbafd8032012-10-08 07:44:21 +0000111
112 /* Set the register address */
113 if (c45)
Shaohui Xie835c72b2015-03-20 19:28:19 -0700114 memac_out_32(&regs->mdio_addr, regnum & 0xffff);
Roy Zangbafd8032012-10-08 07:44:21 +0000115
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200116 err = memac_wait_until_free(regs);
117 if (err)
118 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000119
120 /* Write the value to the register */
Shaohui Xie835c72b2015-03-20 19:28:19 -0700121 memac_out_32(&regs->mdio_data, MDIO_DATA(value));
Roy Zangbafd8032012-10-08 07:44:21 +0000122
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200123 err = memac_wait_until_done(regs);
124 if (err)
125 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000126
127 return 0;
128}
129
130/*
131 * Reads from register regnum in the PHY for device dev, returning the value.
132 * Clears miimcom first. All PHY configuration has to be done through the
133 * TSEC1 MIIM regs
134 */
135int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
136 int regnum)
137{
Madalin Bucur9d327b02020-04-23 16:25:18 +0300138 struct memac_mdio_controller *regs;
Roy Zangbafd8032012-10-08 07:44:21 +0000139 u32 mdio_ctl;
Roy Zangbafd8032012-10-08 07:44:21 +0000140 u32 c45 = 1;
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200141 int err;
Roy Zangbafd8032012-10-08 07:44:21 +0000142
Madalin Bucur9d327b02020-04-23 16:25:18 +0300143 struct fm_mdio_priv *priv;
144
145 if (!bus->priv)
146 return -EINVAL;
147 priv = dev_get_priv(bus->priv);
148 regs = priv->regs;
Madalin Bucur9d327b02020-04-23 16:25:18 +0300149
Roy Zangbafd8032012-10-08 07:44:21 +0000150 if (dev_addr == MDIO_DEVAD_NONE) {
151 c45 = 0; /* clause 22 */
152 dev_addr = regnum & 0x1f;
Shaohui Xie835c72b2015-03-20 19:28:19 -0700153 memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
Shaohui Xieadbcb9c2014-04-22 18:21:37 +0800154 } else
Shaohui Xie835c72b2015-03-20 19:28:19 -0700155 memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
Roy Zangbafd8032012-10-08 07:44:21 +0000156
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200157 err = memac_wait_until_free(regs);
158 if (err)
159 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000160
161 /* Set the Port and Device Addrs */
162 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
Shaohui Xie835c72b2015-03-20 19:28:19 -0700163 memac_out_32(&regs->mdio_ctl, mdio_ctl);
Roy Zangbafd8032012-10-08 07:44:21 +0000164
165 /* Set the register address */
166 if (c45)
Shaohui Xie835c72b2015-03-20 19:28:19 -0700167 memac_out_32(&regs->mdio_addr, regnum & 0xffff);
Roy Zangbafd8032012-10-08 07:44:21 +0000168
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200169 err = memac_wait_until_free(regs);
170 if (err)
171 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000172
173 /* Initiate the read */
174 mdio_ctl |= MDIO_CTL_READ;
Shaohui Xie835c72b2015-03-20 19:28:19 -0700175 memac_out_32(&regs->mdio_ctl, mdio_ctl);
Roy Zangbafd8032012-10-08 07:44:21 +0000176
Ioana Ciorneif78f21d2020-12-09 13:31:58 +0200177 err = memac_wait_until_done(regs);
178 if (err)
179 return err;
Roy Zangbafd8032012-10-08 07:44:21 +0000180
181 /* Return all Fs if nothing was there */
Shaohui Xie835c72b2015-03-20 19:28:19 -0700182 if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
Roy Zangbafd8032012-10-08 07:44:21 +0000183 return 0xffff;
184
Shaohui Xie835c72b2015-03-20 19:28:19 -0700185 return memac_in_32(&regs->mdio_data) & 0xffff;
Roy Zangbafd8032012-10-08 07:44:21 +0000186}
187
188int memac_mdio_reset(struct mii_dev *bus)
189{
190 return 0;
191}
192
Madalin Bucur9d327b02020-04-23 16:25:18 +0300193#if defined(CONFIG_PHYLIB) && defined(CONFIG_DM_MDIO)
194static int fm_mdio_read(struct udevice *dev, int addr, int devad, int reg)
195{
196 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
197 NULL;
198
199 if (pdata && pdata->mii_bus)
200 return memac_mdio_read(pdata->mii_bus, addr, devad, reg);
201
202 return -1;
203}
204
205static int fm_mdio_write(struct udevice *dev, int addr, int devad, int reg,
206 u16 val)
207{
208 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
209 NULL;
210
211 if (pdata && pdata->mii_bus)
212 return memac_mdio_write(pdata->mii_bus, addr, devad, reg, val);
213
214 return -1;
215}
216
217static int fm_mdio_reset(struct udevice *dev)
218{
219 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
220 NULL;
221
222 if (pdata && pdata->mii_bus)
223 return memac_mdio_reset(pdata->mii_bus);
224
225 return -1;
226}
227
228static const struct mdio_ops fm_mdio_ops = {
229 .read = fm_mdio_read,
230 .write = fm_mdio_write,
231 .reset = fm_mdio_reset,
232};
233
234static const struct udevice_id fm_mdio_ids[] = {
235 { .compatible = "fsl,fman-memac-mdio" },
236 {}
237};
238
239static int fm_mdio_probe(struct udevice *dev)
240{
241 struct fm_mdio_priv *priv = (dev) ? dev_get_priv(dev) : NULL;
242 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
243 NULL;
244
245 if (!dev) {
246 printf("%s dev = NULL\n", __func__);
247 return -1;
248 }
249 if (!priv) {
250 printf("dev_get_priv(dev %p) = NULL\n", dev);
251 return -1;
252 }
253 priv->regs = (void *)(uintptr_t)dev_read_addr(dev);
254 debug("%s priv %p @ regs %p, pdata %p\n", __func__,
255 priv, priv->regs, pdata);
256
257 /*
258 * On some platforms like B4860, default value of MDIO_CLK_DIV bits
259 * in mdio_stat(mdio_cfg) register generates MDIO clock too high
260 * (much higher than 2.5MHz), violating the IEEE specs.
261 * On other platforms like T1040, default value of MDIO_CLK_DIV bits
262 * is zero, so MDIO clock is disabled.
263 * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
264 * be properly initialized.
265 * The default NEG bit should be '1' as per FMANv3 RM, but on platforms
266 * like T2080QDS, this bit default is '0', which leads to MDIO failure
267 * on XAUI PHY, so set this bit definitely.
268 */
269 if (priv && priv->regs && priv->regs->mdio_stat)
270 memac_setbits_32(&priv->regs->mdio_stat,
271 MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
272
273 return 0;
274}
275
276static int fm_mdio_remove(struct udevice *dev)
277{
278 return 0;
279}
280
281U_BOOT_DRIVER(fman_mdio) = {
282 .name = "fman_mdio",
283 .id = UCLASS_MDIO,
284 .of_match = fm_mdio_ids,
285 .probe = fm_mdio_probe,
286 .remove = fm_mdio_remove,
287 .ops = &fm_mdio_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700288 .priv_auto = sizeof(struct fm_mdio_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -0700289 .plat_auto = sizeof(struct mdio_perdev_priv),
Madalin Bucur9d327b02020-04-23 16:25:18 +0300290};
291#endif /* CONFIG_PHYLIB && CONFIG_DM_MDIO */