]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
phy: lynx-28g: add support for big endian register maps
authorVladimir Oltean <vladimir.oltean@nxp.com>
Wed, 10 Jun 2026 15:19:47 +0000 (18:19 +0300)
committerVinod Koul <vkoul@kernel.org>
Thu, 11 Jun 2026 07:09:47 +0000 (12:39 +0530)
Some 10G Lynx SerDes blocks are big endian and require byte swapping
because the CPUs are little endian armv8 (LS1046A). Parse the
"big-endian" device tree property, and modify the base lynx_read() and
lynx_write() accessors to test this property before issuing either the
ioread32() or ioread32be() variants (as per
Documentation/driver-api/device-io.rst).

All other accessors - lynx_rmw(), lynx_lane_read(), lynx_lane_write(),
lynx_lane_rmw(), lynx_pll_read() - need to go through these endian-aware
helpers.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20260610151952.2141019-12-vladimir.oltean@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/phy/freescale/phy-fsl-lynx-core.c
drivers/phy/freescale/phy-fsl-lynx-core.h

index 3fb89bb4b0d66a31b018521f00879b9952bd01ce..226b2af2b599f6e10e5a6ea7b9be85136aac3fe9 100644 (file)
@@ -295,6 +295,7 @@ int lynx_probe(struct platform_device *pdev, const struct lynx_info *info,
 
        priv->dev = dev;
        priv->info = info;
+       priv->big_endian = device_property_read_bool(dev, "big-endian");
        dev_set_drvdata(dev, priv);
        spin_lock_init(&priv->pcc_lock);
        INIT_DELAYED_WORK(&priv->cdr_check, lynx_cdr_lock_check);
index e8b280cc9b38c4ca4a30dfcdce58e1c84860cad0..d82e529fa65a61f379734f3d677d6f3f01fc9785 100644 (file)
@@ -58,36 +58,52 @@ struct lynx_priv {
         * like PCCn
         */
        spinlock_t pcc_lock;
+       bool big_endian;
        struct lynx_pll pll[LYNX_NUM_PLL];
        struct lynx_lane *lane;
 
        struct delayed_work cdr_check;
 };
 
+static inline u32 lynx_read(struct lynx_priv *priv, unsigned long off)
+{
+       void __iomem *reg = priv->base + off;
+
+       if (priv->big_endian)
+               return ioread32be(reg);
+
+       return ioread32(reg);
+}
+
+static inline void lynx_write(struct lynx_priv *priv, unsigned long off, u32 val)
+{
+       void __iomem *reg = priv->base + off;
+
+       if (priv->big_endian)
+               return iowrite32be(val, reg);
+
+       return iowrite32(val, reg);
+}
+
 static inline void lynx_rmw(struct lynx_priv *priv, unsigned long off, u32 val,
                            u32 mask)
 {
-       void __iomem *reg = priv->base + off;
        u32 orig, tmp;
 
-       orig = ioread32(reg);
+       orig = lynx_read(priv, off);
        tmp = orig & ~mask;
        tmp |= val;
-       iowrite32(tmp, reg);
+       lynx_write(priv, off, tmp);
 }
 
-#define lynx_read(priv, off) \
-       ioread32((priv)->base + (off))
-#define lynx_write(priv, off, val) \
-       iowrite32(val, (priv)->base + (off))
 #define lynx_lane_rmw(lane, reg, val, mask)    \
        lynx_rmw((lane)->priv, reg(lane->id), val, mask)
 #define lynx_lane_read(lane, reg)                      \
-       ioread32((lane)->priv->base + reg((lane)->id))
+       lynx_read((lane)->priv, reg((lane)->id))
 #define lynx_lane_write(lane, reg, val)                \
-       iowrite32(val, (lane)->priv->base + reg((lane)->id))
+       lynx_write((lane)->priv, reg((lane)->id), val)
 #define lynx_pll_read(pll, reg)                        \
-       ioread32((pll)->priv->base + reg((pll)->id))
+       lynx_read((pll)->priv, reg((pll)->id))
 
 int lynx_probe(struct platform_device *pdev, const struct lynx_info *info,
               const struct phy_ops *phy_ops);