Skip to content

Commit 8eb896a

Browse files
committed
Merge branch 'net-fsl-xgmac_mdio-add-workaround-for-erratum-a-009885'
Tobias Waldekranz says: ==================== net/fsl: xgmac_mdio: Add workaround for erratum A-009885 The individual messages mostly speak for themselves. It is very possible that there are more chips out there that are impacted by this, but I only have access to the errata document for the T1024 family, so I've limited the DT changes to the exact FMan version used in that device. Hopefully someone from NXP can supply a follow-up if need be. The final commit is an unrelated fix that was brought to my attention by sparse. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents baa5950 + 3f7c239 commit 8eb896a

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

Documentation/devicetree/bindings/net/fsl-fman.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,15 @@ PROPERTIES
410410
The settings and programming routines for internal/external
411411
MDIO are different. Must be included for internal MDIO.
412412

413+
- fsl,erratum-a009885
414+
Usage: optional
415+
Value type: <boolean>
416+
Definition: Indicates the presence of the A009885
417+
erratum describing that the contents of MDIO_DATA may
418+
become corrupt unless it is read within 16 MDC cycles
419+
of MDIO_CFG[BSY] being cleared, when performing an
420+
MDIO read operation.
421+
413422
- fsl,erratum-a011043
414423
Usage: optional
415424
Value type: <boolean>

arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ fman0: fman@400000 {
7979
#size-cells = <0>;
8080
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
8181
reg = <0xfc000 0x1000>;
82+
fsl,erratum-a009885;
8283
};
8384

8485
xmdio0: mdio@fd000 {
8586
#address-cells = <1>;
8687
#size-cells = <0>;
8788
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
8889
reg = <0xfd000 0x1000>;
90+
fsl,erratum-a009885;
8991
};
9092
};
9193

drivers/net/ethernet/freescale/xgmac_mdio.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ struct tgec_mdio_controller {
5151
struct mdio_fsl_priv {
5252
struct tgec_mdio_controller __iomem *mdio_base;
5353
bool is_little_endian;
54+
bool has_a009885;
5455
bool has_a011043;
5556
};
5657

@@ -186,10 +187,10 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
186187
{
187188
struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
188189
struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
190+
unsigned long flags;
189191
uint16_t dev_addr;
190192
uint32_t mdio_stat;
191193
uint32_t mdio_ctl;
192-
uint16_t value;
193194
int ret;
194195
bool endian = priv->is_little_endian;
195196

@@ -221,26 +222,36 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
221222
return ret;
222223
}
223224

225+
if (priv->has_a009885)
226+
/* Once the operation completes, i.e. MDIO_STAT_BSY clears, we
227+
* must read back the data register within 16 MDC cycles.
228+
*/
229+
local_irq_save(flags);
230+
224231
/* Initiate the read */
225232
xgmac_write32(mdio_ctl | MDIO_CTL_READ, &regs->mdio_ctl, endian);
226233

227234
ret = xgmac_wait_until_done(&bus->dev, regs, endian);
228235
if (ret)
229-
return ret;
236+
goto irq_restore;
230237

231238
/* Return all Fs if nothing was there */
232239
if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) &&
233240
!priv->has_a011043) {
234241
dev_dbg(&bus->dev,
235242
"Error while reading PHY%d reg at %d.%hhu\n",
236243
phy_id, dev_addr, regnum);
237-
return 0xffff;
244+
ret = 0xffff;
245+
} else {
246+
ret = xgmac_read32(&regs->mdio_data, endian) & 0xffff;
247+
dev_dbg(&bus->dev, "read %04x\n", ret);
238248
}
239249

240-
value = xgmac_read32(&regs->mdio_data, endian) & 0xffff;
241-
dev_dbg(&bus->dev, "read %04x\n", value);
250+
irq_restore:
251+
if (priv->has_a009885)
252+
local_irq_restore(flags);
242253

243-
return value;
254+
return ret;
244255
}
245256

246257
static int xgmac_mdio_probe(struct platform_device *pdev)
@@ -287,6 +298,8 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
287298
priv->is_little_endian = device_property_read_bool(&pdev->dev,
288299
"little-endian");
289300

301+
priv->has_a009885 = device_property_read_bool(&pdev->dev,
302+
"fsl,erratum-a009885");
290303
priv->has_a011043 = device_property_read_bool(&pdev->dev,
291304
"fsl,erratum-a011043");
292305

@@ -318,9 +331,10 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
318331
static int xgmac_mdio_remove(struct platform_device *pdev)
319332
{
320333
struct mii_bus *bus = platform_get_drvdata(pdev);
334+
struct mdio_fsl_priv *priv = bus->priv;
321335

322336
mdiobus_unregister(bus);
323-
iounmap(bus->priv);
337+
iounmap(priv->mdio_base);
324338
mdiobus_free(bus);
325339

326340
return 0;

0 commit comments

Comments
 (0)