powerpc/powernv: Get rid of old scom_controller abstraction
authorAndrew Donnellan <ajd@linux.ibm.com>
Thu, 9 May 2019 05:11:17 +0000 (15:11 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 5 Aug 2019 08:53:03 +0000 (18:53 +1000)
Once upon a time, the SCOM access code was used by the WSP platform as
well as powernv. Thus it made sense to have a generic SCOM access
interface to abstract between different platforms.

Now that it's just powernv, with no other platforms currently on the
horizon, let's rip out scom_controller and make everything much
simpler and more direct.

While we're here, fix up the comment block at the top.

Signed-off-by: Andrew Donnellan <ajd@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190509051119.7694-3-ajd@linux.ibm.com
arch/powerpc/platforms/powernv/Makefile
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/scom.c [deleted file]
arch/powerpc/platforms/powernv/scom.h [deleted file]

index 4b16441..69a3aef 100644 (file)
@@ -4,7 +4,6 @@ obj-y                   += idle.o opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
 obj-y                  += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
 obj-y                  += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
 obj-y                  += opal-kmsg.o opal-powercap.o opal-psr.o opal-sensor-groups.o
-obj-y                  += opal-xscom.o scom.o
 
 obj-$(CONFIG_SMP)      += smp.o subcore.o subcore-asm.o
 obj-$(CONFIG_PCI)      += pci.o pci-ioda.o npu-dma.o pci-ioda-tce.o
@@ -16,3 +15,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE)     += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)        += ocxl.o
+obj-$(CONFIG_SCOM_DEBUGFS) += opal-xscom.o
index 3f48ee6..cb172af 100644 (file)
@@ -1,7 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * PowerNV LPC bus handling.
+ * PowerNV SCOM bus debugfs interface
  *
+ * Copyright 2010 Benjamin Herrenschmidt, IBM Corp
+ *                <benh@kernel.crashing.org>
+ *     and        David Gibson, IBM Corporation.
  * Copyright 2013 IBM Corp.
  */
 
 #include <linux/bug.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
 #include <asm/opal.h>
-
-#include "scom.h"
-
-/*
- * We could probably fit that inside the scom_map_t
- * which is a void* after all but it's really too ugly
- * so let's kmalloc it for now
- */
-struct opal_scom_map {
-       uint32_t chip;
-       uint64_t addr;
-};
-
-static scom_map_t opal_scom_map(struct device_node *dev, u64 reg, u64 count)
-{
-       struct opal_scom_map *m;
-       const __be32 *gcid;
-
-       if (!of_get_property(dev, "scom-controller", NULL)) {
-               pr_err("%s: device %pOF is not a SCOM controller\n",
-                       __func__, dev);
-               return SCOM_MAP_INVALID;
-       }
-       gcid = of_get_property(dev, "ibm,chip-id", NULL);
-       if (!gcid) {
-               pr_err("%s: device %pOF has no ibm,chip-id\n",
-                       __func__, dev);
-               return SCOM_MAP_INVALID;
-       }
-       m = kmalloc(sizeof(*m), GFP_KERNEL);
-       if (!m)
-               return NULL;
-       m->chip = be32_to_cpup(gcid);
-       m->addr = reg;
-
-       return (scom_map_t)m;
-}
-
-static void opal_scom_unmap(scom_map_t map)
-{
-       kfree(map);
-}
-
-static int opal_xscom_err_xlate(int64_t rc)
-{
-       switch(rc) {
-       case 0:
-               return 0;
-       /* Add more translations if necessary */
-       default:
-               return -EIO;
-       }
-}
+#include <asm/debugfs.h>
+#include <asm/prom.h>
 
 static u64 opal_scom_unmangle(u64 addr)
 {
@@ -99,39 +52,154 @@ static u64 opal_scom_unmangle(u64 addr)
        return addr;
 }
 
-static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
+static int opal_scom_read(uint32_t chip, uint64_t addr, u64 reg, u64 *value)
 {
-       struct opal_scom_map *m = map;
        int64_t rc;
        __be64 v;
 
-       reg = opal_scom_unmangle(m->addr + reg);
-       rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v));
+       reg = opal_scom_unmangle(addr + reg);
+       rc = opal_xscom_read(chip, reg, (__be64 *)__pa(&v));
+       if (rc) {
+               *value = 0xfffffffffffffffful;
+               return -EIO;
+       }
        *value = be64_to_cpu(v);
-       return opal_xscom_err_xlate(rc);
+       return 0;
 }
 
-static int opal_scom_write(scom_map_t map, u64 reg, u64 value)
+static int opal_scom_write(uint32_t chip, uint64_t addr, u64 reg, u64 value)
 {
-       struct opal_scom_map *m = map;
        int64_t rc;
 
-       reg = opal_scom_unmangle(m->addr + reg);
-       rc = opal_xscom_write(m->chip, reg, value);
-       return opal_xscom_err_xlate(rc);
+       reg = opal_scom_unmangle(addr + reg);
+       rc = opal_xscom_write(chip, reg, value);
+       if (rc)
+               return -EIO;
+       return 0;
+}
+
+struct scom_debug_entry {
+       u32 chip;
+       struct debugfs_blob_wrapper path;
+       char name[16];
+};
+
+static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
+                              size_t count, loff_t *ppos)
+{
+       struct scom_debug_entry *ent = filp->private_data;
+       u64 __user *ubuf64 = (u64 __user *)ubuf;
+       loff_t off = *ppos;
+       ssize_t done = 0; 
+       u64 reg, reg_base, reg_cnt, val;
+       int rc;
+
+       if (off < 0 || (off & 7) || (count & 7))
+               return -EINVAL;
+       reg_base = off >> 3;
+       reg_cnt = count >> 3;
+
+       for (reg = 0; reg < reg_cnt; reg++) {
+               rc = opal_scom_read(ent->chip, reg_base, reg, &val);
+               if (!rc)
+                       rc = put_user(val, ubuf64);
+               if (rc) {
+                       if (!done)
+                               done = rc;
+                       break;
+               }
+               ubuf64++;
+               *ppos += 8;
+               done += 8;
+       }
+       return done;
+}
+
+static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
+                               size_t count, loff_t *ppos)
+{
+       struct scom_debug_entry *ent = filp->private_data;
+       u64 __user *ubuf64 = (u64 __user *)ubuf;
+       loff_t off = *ppos;
+       ssize_t done = 0; 
+       u64 reg, reg_base, reg_cnt, val;
+       int rc;
+
+       if (off < 0 || (off & 7) || (count & 7))
+               return -EINVAL;
+       reg_base = off >> 3;
+       reg_cnt = count >> 3;
+
+       for (reg = 0; reg < reg_cnt; reg++) {
+               rc = get_user(val, ubuf64);
+               if (!rc)
+                       rc = opal_scom_write(ent->chip, reg_base, reg,  val);
+               if (rc) {
+                       if (!done)
+                               done = rc;
+                       break;
+               }
+               ubuf64++;
+               done += 8;
+       }
+       return done;
 }
 
-static const struct scom_controller opal_scom_controller = {
-       .map    = opal_scom_map,
-       .unmap  = opal_scom_unmap,
-       .read   = opal_scom_read,
-       .write  = opal_scom_write
+static const struct file_operations scom_debug_fops = {
+       .read =         scom_debug_read,
+       .write =        scom_debug_write,
+       .open =         simple_open,
+       .llseek =       default_llseek,
 };
 
-static int opal_xscom_init(void)
+static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
+                              int chip)
 {
-       if (firmware_has_feature(FW_FEATURE_OPAL))
-               scom_init(&opal_scom_controller);
+       struct scom_debug_entry *ent;
+       struct dentry *dir;
+
+       ent = kzalloc(sizeof(*ent), GFP_KERNEL);
+       if (!ent)
+               return -ENOMEM;
+
+       ent->chip = chip;
+       snprintf(ent->name, 16, "%08x", chip);
+       ent->path.data = (void*)kasprintf(GFP_KERNEL, "%pOF", dn);
+       ent->path.size = strlen((char *)ent->path.data);
+
+       dir = debugfs_create_dir(ent->name, root);
+       if (!dir) {
+               kfree(ent->path.data);
+               kfree(ent);
+               return -1;
+       }
+
+       debugfs_create_blob("devspec", 0400, dir, &ent->path);
+       debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
+
        return 0;
 }
-machine_arch_initcall(powernv, opal_xscom_init);
+
+static int scom_debug_init(void)
+{
+       struct device_node *dn;
+       struct dentry *root;
+       int chip, rc;
+
+       if (!firmware_has_feature(FW_FEATURE_OPAL))
+               return 0;
+
+       root = debugfs_create_dir("scom", powerpc_debugfs_root);
+       if (!root)
+               return -1;
+
+       rc = 0;
+       for_each_node_with_property(dn, "scom-controller") {
+               chip = of_get_ibm_chip_id(dn);
+               WARN_ON(chip == -1);
+               rc |= scom_debug_init_one(root, dn, chip);
+       }
+
+       return rc;
+}
+device_initcall(scom_debug_init);
diff --git a/arch/powerpc/platforms/powernv/scom.c b/arch/powerpc/platforms/powernv/scom.c
deleted file mode 100644 (file)
index acd6968..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2010 Benjamin Herrenschmidt, IBM Corp
- *                <benh@kernel.crashing.org>
- *     and        David Gibson, IBM Corporation.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <asm/debugfs.h>
-#include <asm/prom.h>
-#include <linux/uaccess.h>
-
-#include "scom.h"
-
-const struct scom_controller *scom_controller;
-
-#ifdef CONFIG_SCOM_DEBUGFS
-struct scom_debug_entry {
-       struct device_node *dn;
-       struct debugfs_blob_wrapper path;
-       char name[16];
-};
-
-static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
-                              size_t count, loff_t *ppos)
-{
-       struct scom_debug_entry *ent = filp->private_data;
-       u64 __user *ubuf64 = (u64 __user *)ubuf;
-       loff_t off = *ppos;
-       ssize_t done = 0; 
-       u64 reg, reg_cnt, val;
-       scom_map_t map;
-       int rc;
-
-       if (off < 0 || (off & 7) || (count & 7))
-               return -EINVAL;
-       reg = off >> 3;
-       reg_cnt = count >> 3;
-
-       map = scom_map(ent->dn, reg, reg_cnt);
-       if (!scom_map_ok(map))
-               return -ENXIO;
-
-       for (reg = 0; reg < reg_cnt; reg++) {
-               rc = scom_read(map, reg, &val);
-               if (!rc)
-                       rc = put_user(val, ubuf64);
-               if (rc) {
-                       if (!done)
-                               done = rc;
-                       break;
-               }
-               ubuf64++;
-               *ppos += 8;
-               done += 8;
-       }
-       scom_unmap(map);
-       return done;
-}
-
-static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
-                               size_t count, loff_t *ppos)
-{
-       struct scom_debug_entry *ent = filp->private_data;
-       u64 __user *ubuf64 = (u64 __user *)ubuf;
-       loff_t off = *ppos;
-       ssize_t done = 0; 
-       u64 reg, reg_cnt, val;
-       scom_map_t map;
-       int rc;
-
-       if (off < 0 || (off & 7) || (count & 7))
-               return -EINVAL;
-       reg = off >> 3;
-       reg_cnt = count >> 3;
-
-       map = scom_map(ent->dn, reg, reg_cnt);
-       if (!scom_map_ok(map))
-               return -ENXIO;
-
-       for (reg = 0; reg < reg_cnt; reg++) {
-               rc = get_user(val, ubuf64);
-               if (!rc)
-                       rc = scom_write(map, reg,  val);
-               if (rc) {
-                       if (!done)
-                               done = rc;
-                       break;
-               }
-               ubuf64++;
-               done += 8;
-       }
-       scom_unmap(map);
-       return done;
-}
-
-static const struct file_operations scom_debug_fops = {
-       .read =         scom_debug_read,
-       .write =        scom_debug_write,
-       .open =         simple_open,
-       .llseek =       default_llseek,
-};
-
-static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
-                              int i)
-{
-       struct scom_debug_entry *ent;
-       struct dentry *dir;
-
-       ent = kzalloc(sizeof(*ent), GFP_KERNEL);
-       if (!ent)
-               return -ENOMEM;
-
-       ent->dn = of_node_get(dn);
-       snprintf(ent->name, 16, "%08x", i);
-       ent->path.data = (void*)kasprintf(GFP_KERNEL, "%pOF", dn);
-       ent->path.size = strlen((char *)ent->path.data);
-
-       dir = debugfs_create_dir(ent->name, root);
-       if (!dir) {
-               of_node_put(dn);
-               kfree(ent->path.data);
-               kfree(ent);
-               return -1;
-       }
-
-       debugfs_create_blob("devspec", 0400, dir, &ent->path);
-       debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
-
-       return 0;
-}
-
-static int scom_debug_init(void)
-{
-       struct device_node *dn;
-       struct dentry *root;
-       int i, rc;
-
-       root = debugfs_create_dir("scom", powerpc_debugfs_root);
-       if (!root)
-               return -1;
-
-       i = rc = 0;
-       for_each_node_with_property(dn, "scom-controller") {
-               int id = of_get_ibm_chip_id(dn);
-               if (id == -1)
-                       id = i;
-               rc |= scom_debug_init_one(root, dn, id);
-               i++;
-       }
-
-       return rc;
-}
-device_initcall(scom_debug_init);
-#endif /* CONFIG_SCOM_DEBUGFS */
diff --git a/arch/powerpc/platforms/powernv/scom.h b/arch/powerpc/platforms/powernv/scom.h
deleted file mode 100644 (file)
index 9827a66..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright 2010 Benjamin Herrenschmidt, IBM Corp
- *                <benh@kernel.crashing.org>
- *     and        David Gibson, IBM Corporation.
- */
-
-#ifndef _SCOM_H
-#define _SCOM_H
-
-/*
- * The SCOM bus is a sideband bus used for accessing various internal
- * registers of the processor or the chipset. The implementation details
- * differ between processors and platforms, and the access method as
- * well.
- *
- * This API allows to "map" ranges of SCOM register numbers associated
- * with a given SCOM controller. The later must be represented by a
- * device node, though some implementations might support NULL if there
- * is no possible ambiguity
- *
- * Then, scom_read/scom_write can be used to accesses registers inside
- * that range. The argument passed is a register number relative to
- * the beginning of the range mapped.
- */
-
-typedef void *scom_map_t;
-
-/* Value for an invalid SCOM map */
-#define SCOM_MAP_INVALID       (NULL)
-
-/* The scom_controller data structure is what the platform passes
- * to the core code in scom_init, it provides the actual implementation
- * of all the SCOM functions
- */
-struct scom_controller {
-       scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count);
-       void (*unmap)(scom_map_t map);
-
-       int (*read)(scom_map_t map, u64 reg, u64 *value);
-       int (*write)(scom_map_t map, u64 reg, u64 value);
-};
-
-extern const struct scom_controller *scom_controller;
-
-/**
- * scom_init - Initialize the SCOM backend, called by the platform
- * @controller: The platform SCOM controller
- */
-static inline void scom_init(const struct scom_controller *controller)
-{
-       scom_controller = controller;
-}
-
-/**
- * scom_map_ok - Test is a SCOM mapping is successful
- * @map: The result of scom_map to test
- */
-static inline int scom_map_ok(scom_map_t map)
-{
-       return map != SCOM_MAP_INVALID;
-}
-
-/**
- * scom_map - Map a block of SCOM registers
- * @ctrl_dev: Device node of the SCOM controller
- *            some implementations allow NULL here
- * @reg: first SCOM register to map
- * @count: Number of SCOM registers to map
- */
-
-static inline scom_map_t scom_map(struct device_node *ctrl_dev,
-                                 u64 reg, u64 count)
-{
-       return scom_controller->map(ctrl_dev, reg, count);
-}
-
-/**
- * scom_unmap - Unmap a block of SCOM registers
- * @map: Result of scom_map is to be unmapped
- */
-static inline void scom_unmap(scom_map_t map)
-{
-       if (scom_map_ok(map))
-               scom_controller->unmap(map);
-}
-
-/**
- * scom_read - Read a SCOM register
- * @map: Result of scom_map
- * @reg: Register index within that map
- * @value: Updated with the value read
- *
- * Returns 0 (success) or a negative error code
- */
-static inline int scom_read(scom_map_t map, u64 reg, u64 *value)
-{
-       int rc;
-
-       rc = scom_controller->read(map, reg, value);
-       if (rc)
-               *value = 0xfffffffffffffffful;
-       return rc;
-}
-
-/**
- * scom_write - Write to a SCOM register
- * @map: Result of scom_map
- * @reg: Register index within that map
- * @value: Value to write
- *
- * Returns 0 (success) or a negative error code
- */
-static inline int scom_write(scom_map_t map, u64 reg, u64 value)
-{
-       return scom_controller->write(map, reg, value);
-}
-
-
-#endif /* _SCOM_H */