summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/ixp4xx/Kconfig1
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-npe.c33
2 files changed, 25 insertions, 9 deletions
diff --git a/drivers/soc/ixp4xx/Kconfig b/drivers/soc/ixp4xx/Kconfig
index e3eb19b85fa4..c55f0c9ae513 100644
--- a/drivers/soc/ixp4xx/Kconfig
+++ b/drivers/soc/ixp4xx/Kconfig
@@ -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.
diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c
index f490c4ca51f5..613935cb6a48 100644
--- a/drivers/soc/ixp4xx/ixp4xx-npe.c
+++ b/drivers/soc/ixp4xx/ixp4xx-npe.c
@@ -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",