提交 8eb896a7 编写于 作者: J Jakub Kicinski

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/20220118215054.2629314-1-tobias@waldekranz.comSigned-off-by: NJakub Kicinski <kuba@kernel.org>
...@@ -410,6 +410,15 @@ PROPERTIES ...@@ -410,6 +410,15 @@ PROPERTIES
The settings and programming routines for internal/external The settings and programming routines for internal/external
MDIO are different. Must be included for internal MDIO. MDIO are different. Must be included for internal MDIO.
- fsl,erratum-a009885
Usage: optional
Value type: <boolean>
Definition: Indicates the presence of the A009885
erratum describing that the contents of MDIO_DATA may
become corrupt unless it is read within 16 MDC cycles
of MDIO_CFG[BSY] being cleared, when performing an
MDIO read operation.
- fsl,erratum-a011043 - fsl,erratum-a011043
Usage: optional Usage: optional
Value type: <boolean> Value type: <boolean>
......
...@@ -79,6 +79,7 @@ fman0: fman@400000 { ...@@ -79,6 +79,7 @@ fman0: fman@400000 {
#size-cells = <0>; #size-cells = <0>;
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfc000 0x1000>; reg = <0xfc000 0x1000>;
fsl,erratum-a009885;
}; };
xmdio0: mdio@fd000 { xmdio0: mdio@fd000 {
...@@ -86,6 +87,7 @@ fman0: fman@400000 { ...@@ -86,6 +87,7 @@ fman0: fman@400000 {
#size-cells = <0>; #size-cells = <0>;
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>; reg = <0xfd000 0x1000>;
fsl,erratum-a009885;
}; };
}; };
......
...@@ -51,6 +51,7 @@ struct tgec_mdio_controller { ...@@ -51,6 +51,7 @@ struct tgec_mdio_controller {
struct mdio_fsl_priv { struct mdio_fsl_priv {
struct tgec_mdio_controller __iomem *mdio_base; struct tgec_mdio_controller __iomem *mdio_base;
bool is_little_endian; bool is_little_endian;
bool has_a009885;
bool has_a011043; bool has_a011043;
}; };
...@@ -186,10 +187,10 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -186,10 +187,10 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
{ {
struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
struct tgec_mdio_controller __iomem *regs = priv->mdio_base; struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
unsigned long flags;
uint16_t dev_addr; uint16_t dev_addr;
uint32_t mdio_stat; uint32_t mdio_stat;
uint32_t mdio_ctl; uint32_t mdio_ctl;
uint16_t value;
int ret; int ret;
bool endian = priv->is_little_endian; bool endian = priv->is_little_endian;
...@@ -221,12 +222,18 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -221,12 +222,18 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
return ret; return ret;
} }
if (priv->has_a009885)
/* Once the operation completes, i.e. MDIO_STAT_BSY clears, we
* must read back the data register within 16 MDC cycles.
*/
local_irq_save(flags);
/* Initiate the read */ /* Initiate the read */
xgmac_write32(mdio_ctl | MDIO_CTL_READ, &regs->mdio_ctl, endian); xgmac_write32(mdio_ctl | MDIO_CTL_READ, &regs->mdio_ctl, endian);
ret = xgmac_wait_until_done(&bus->dev, regs, endian); ret = xgmac_wait_until_done(&bus->dev, regs, endian);
if (ret) if (ret)
return ret; goto irq_restore;
/* Return all Fs if nothing was there */ /* Return all Fs if nothing was there */
if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) && if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) &&
...@@ -234,13 +241,17 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -234,13 +241,17 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
dev_dbg(&bus->dev, dev_dbg(&bus->dev,
"Error while reading PHY%d reg at %d.%hhu\n", "Error while reading PHY%d reg at %d.%hhu\n",
phy_id, dev_addr, regnum); phy_id, dev_addr, regnum);
return 0xffff; ret = 0xffff;
} else {
ret = xgmac_read32(&regs->mdio_data, endian) & 0xffff;
dev_dbg(&bus->dev, "read %04x\n", ret);
} }
value = xgmac_read32(&regs->mdio_data, endian) & 0xffff; irq_restore:
dev_dbg(&bus->dev, "read %04x\n", value); if (priv->has_a009885)
local_irq_restore(flags);
return value; return ret;
} }
static int xgmac_mdio_probe(struct platform_device *pdev) static int xgmac_mdio_probe(struct platform_device *pdev)
...@@ -287,6 +298,8 @@ static int xgmac_mdio_probe(struct platform_device *pdev) ...@@ -287,6 +298,8 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
priv->is_little_endian = device_property_read_bool(&pdev->dev, priv->is_little_endian = device_property_read_bool(&pdev->dev,
"little-endian"); "little-endian");
priv->has_a009885 = device_property_read_bool(&pdev->dev,
"fsl,erratum-a009885");
priv->has_a011043 = device_property_read_bool(&pdev->dev, priv->has_a011043 = device_property_read_bool(&pdev->dev,
"fsl,erratum-a011043"); "fsl,erratum-a011043");
...@@ -318,9 +331,10 @@ static int xgmac_mdio_probe(struct platform_device *pdev) ...@@ -318,9 +331,10 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
static int xgmac_mdio_remove(struct platform_device *pdev) static int xgmac_mdio_remove(struct platform_device *pdev)
{ {
struct mii_bus *bus = platform_get_drvdata(pdev); struct mii_bus *bus = platform_get_drvdata(pdev);
struct mdio_fsl_priv *priv = bus->priv;
mdiobus_unregister(bus); mdiobus_unregister(bus);
iounmap(bus->priv); iounmap(priv->mdio_base);
mdiobus_free(bus); mdiobus_free(bus);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册