soc: ixp4xx-npe: Access syscon regs using regmap
authorLinus Walleij <linus.walleij@linaro.org>
Fri, 11 Feb 2022 22:32:32 +0000 (23:32 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Sat, 12 Feb 2022 17:20:03 +0000 (18:20 +0100)
If we access the syscon (expansion bus config registers) using the
syscon regmap instead of relying on direct accessor functions,
we do not need to call this static code in the machine
(arch/arm/mach-ixp4xx/common.c) which makes things less dependent
on custom machine-dependent code.

Look up the syscon regmap and handle the error: this will make
deferred probe work with relation to the syscon.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20220211223238.648934-8-linus.walleij@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/soc/ixp4xx/Kconfig
drivers/soc/ixp4xx/ixp4xx-npe.c
include/linux/soc/ixp4xx/npe.h

index e3eb19b85fa4b358950f702d4a74f35889ee84eb..c55f0c9ae513354728f8905a2d20a1edfdc1fc57 100644 (file)
@@ -12,6 +12,7 @@ config IXP4XX_QMGR
 config IXP4XX_NPE
        tristate "IXP4xx Network Processor Engine support"
        select FW_LOADER
+       select MFD_SYSCON
        help
          This driver supports IXP4xx built-in network coprocessors
          and is automatically selected by Ethernet and HSS drivers.
index f490c4ca51f51ed4b366a7161e2692e46282cd1b..613935cb6a488fbdeb1a7e38d22b4aecc6517f48 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/firmware.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -284,6 +285,7 @@ static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
 
 static int npe_reset(struct npe *npe)
 {
+       u32 reset_bit = (IXP4XX_FEATURE_RESET_NPEA << npe->id);
        u32 val, ctl, exec_count, ctx_reg2;
        int i;
 
@@ -380,16 +382,19 @@ static int npe_reset(struct npe *npe)
        __raw_writel(0, &npe->regs->action_points[3]);
        __raw_writel(0, &npe->regs->watch_count);
 
-       val = ixp4xx_read_feature_bits();
+       /*
+        * We need to work on cached values here because the register
+        * will read inverted but needs to be written non-inverted.
+        */
+       val = cpu_ixp4xx_features(npe->rmap);
        /* reset the NPE */
-       ixp4xx_write_feature_bits(val &
-                                 ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
+       regmap_write(npe->rmap, IXP4XX_EXP_CNFG2, val & ~reset_bit);
        /* deassert reset */
-       ixp4xx_write_feature_bits(val |
-                                 (IXP4XX_FEATURE_RESET_NPEA << npe->id));
+       regmap_write(npe->rmap, IXP4XX_EXP_CNFG2, val | reset_bit);
+
        for (i = 0; i < MAX_RETRIES; i++) {
-               if (ixp4xx_read_feature_bits() &
-                   (IXP4XX_FEATURE_RESET_NPEA << npe->id))
+               val = cpu_ixp4xx_features(npe->rmap);
+               if (val & reset_bit)
                        break;  /* NPE is back alive */
                udelay(1);
        }
@@ -683,6 +688,14 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
        struct resource *res;
+       struct regmap *rmap;
+       u32 val;
+
+       /* This system has only one syscon, so fetch it */
+       rmap = syscon_regmap_lookup_by_compatible("syscon");
+       if (IS_ERR(rmap))
+               return dev_err_probe(dev, PTR_ERR(rmap),
+                                    "failed to look up syscon\n");
 
        for (i = 0; i < NPE_COUNT; i++) {
                struct npe *npe = &npe_tab[i];
@@ -691,8 +704,9 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
                if (!res)
                        return -ENODEV;
 
-               if (!(ixp4xx_read_feature_bits() &
-                     (IXP4XX_FEATURE_RESET_NPEA << i))) {
+               val = cpu_ixp4xx_features(rmap);
+
+               if (!(val & (IXP4XX_FEATURE_RESET_NPEA << i))) {
                        dev_info(dev, "NPE%d at %pR not available\n",
                                 i, res);
                        continue; /* NPE already disabled or not present */
@@ -700,6 +714,7 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
                npe->regs = devm_ioremap_resource(dev, res);
                if (IS_ERR(npe->regs))
                        return PTR_ERR(npe->regs);
+               npe->rmap = rmap;
 
                if (npe_reset(npe)) {
                        dev_info(dev, "NPE%d at %pR does not reset\n",
index 2a91f465d4568bdfc595e722a9c9788128920ecf..9efeac777da10730a911afa0d2baac67ccae295f 100644 (file)
@@ -3,6 +3,7 @@
 #define __IXP4XX_NPE_H
 
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 
 extern const char *npe_names[];
 
@@ -17,6 +18,7 @@ struct npe_regs {
 
 struct npe {
        struct npe_regs __iomem *regs;
+       struct regmap *rmap;
        int id;
        int valid;
 };