misc: smpro-misc: Add Ampere's Altra SMpro misc driver
authorQuan Nguyen <quan@os.amperecomputing.com>
Mon, 31 Oct 2022 02:44:42 +0000 (09:44 +0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Nov 2022 18:03:03 +0000 (19:03 +0100)
Add driver support for accessing various information reported by
Ampere's SMpro co-processor such as Boot Progress and other
miscellaneous data.

Signed-off-by: Quan Nguyen <quan@os.amperecomputing.com>
Link: https://lore.kernel.org/r/20221031024442.2490881-4-quan@os.amperecomputing.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/ABI/testing/sysfs-bus-platform-devices-ampere-smpro
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/smpro-misc.c [new file with mode: 0644]

index 2b84dc8c3149d04be0306021051528a61b952a32..ca93c215ef995e3619f79f7624065269955a55e1 100644 (file)
@@ -262,3 +262,51 @@ Description:
                For more details, see section `5.7 GPI Status Registers,
                Altra Family Soc BMC Interface Specification`.
 
+What:          /sys/bus/platform/devices/smpro-misc.*/boot_progress
+KernelVersion: 6.1
+Contact:       Quan Nguyen <quan@os.amperecomputing.com>
+Description:
+               (RO) Contains the boot stages information in hex as format below::
+
+                   AABBCCCCCCCC
+
+               where:
+
+                 - ``AA``      : The boot stages
+
+                   - 00: SMpro firmware booting
+                   - 01: PMpro firmware booting
+                   - 02: ATF BL1 firmware booting
+                   - 03: DDR initialization
+                   - 04: DDR training report status
+                   - 05: ATF BL2 firmware booting
+                   - 06: ATF BL31 firmware booting
+                   - 07: ATF BL32 firmware booting
+                   - 08: UEFI firmware booting
+                   - 09: OS booting
+
+                 - ``BB``      : Boot status
+
+                   - 00: Not started
+                   - 01: Started
+                   - 02: Completed without error
+                   - 03: Failed.
+
+                 - ``CCCCCCCC``: Boot status information defined for each boot stages
+
+               For details, see section `5.11 Boot Stage Register Definitions`
+               and section `6. Processor Boot Progress Codes, Altra Family Soc BMC
+               Interface Specification`.
+
+
+What:          /sys/bus/platform/devices/smpro-misc*/soc_power_limit
+KernelVersion: 6.1
+Contact:       Quan Nguyen <quan@os.amperecomputing.com>
+Description:
+               (RW) Contains the desired SoC power limit in Watt.
+               Writes to this sysfs set the desired SoC power limit (W).
+               Reads from this register return the current SoC power limit (W).
+               The value ranges:
+
+                 - Minimum: 120 W
+                 - Maximum: Socket TDP power
index b9ceee949dab8eb121116cc7dc74100e960f22f0..9947b7892bd5af61c016f3f27c30a78827996414 100644 (file)
@@ -188,6 +188,16 @@ config SMPRO_ERRMON
          To compile this driver as a module, say M here. The driver will be
          called smpro-errmon.
 
+config SMPRO_MISC
+       tristate "Ampere Computing SMPro miscellaneous driver"
+       depends on MFD_SMPRO || COMPILE_TEST
+       help
+         Say Y here to get support for the SMpro error miscellalenous function
+         provided by Ampere Computing's Altra and Altra Max SoCs.
+
+         To compile this driver as a module, say M here. The driver will be
+         called smpro-misc.
+
 config CS5535_MFGPT
        tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support"
        depends on MFD_CS5535
index bbe24d4511a33bb89b6ea2db83b9ebc8d9beb6da..87b54a4a442244e273697f1d96970c2c04d95a76 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_KGDB_TESTS)      += kgdbts.o
 obj-$(CONFIG_SGI_XP)           += sgi-xp/
 obj-$(CONFIG_SGI_GRU)          += sgi-gru/
 obj-$(CONFIG_SMPRO_ERRMON)     += smpro-errmon.o
+obj-$(CONFIG_SMPRO_MISC)       += smpro-misc.o
 obj-$(CONFIG_CS5535_MFGPT)     += cs5535-mfgpt.o
 obj-$(CONFIG_GEHC_ACHC)                += gehc-achc.o
 obj-$(CONFIG_HP_ILO)           += hpilo.o
diff --git a/drivers/misc/smpro-misc.c b/drivers/misc/smpro-misc.c
new file mode 100644 (file)
index 0000000..6c42714
--- /dev/null
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ampere Computing SoC's SMpro Misc Driver
+ *
+ * Copyright (c) 2022, Ampere Computing LLC
+ */
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Boot Stage/Progress Registers */
+#define BOOTSTAGE      0xB0
+#define BOOTSTAGE_LO   0xB1
+#define CUR_BOOTSTAGE  0xB2
+#define BOOTSTAGE_HI   0xB3
+
+/* SOC State Registers */
+#define SOC_POWER_LIMIT                0xE5
+
+struct smpro_misc {
+       struct regmap *regmap;
+};
+
+static ssize_t boot_progress_show(struct device *dev, struct device_attribute *da, char *buf)
+{
+       struct smpro_misc *misc = dev_get_drvdata(dev);
+       u16 boot_progress[3] = { 0 };
+       u32 bootstage;
+       u8 boot_stage;
+       u8 cur_stage;
+       u32 reg_lo;
+       u32 reg;
+       int ret;
+
+       /* Read current boot stage */
+       ret = regmap_read(misc->regmap, CUR_BOOTSTAGE, &reg);
+       if (ret)
+               return ret;
+
+       cur_stage = reg & 0xff;
+
+       ret = regmap_read(misc->regmap, BOOTSTAGE, &bootstage);
+       if (ret)
+               return ret;
+
+       boot_stage = (bootstage >> 8) & 0xff;
+
+       if (boot_stage > cur_stage)
+               return -EINVAL;
+
+       ret = regmap_read(misc->regmap, BOOTSTAGE_LO, &reg_lo);
+       if (!ret)
+               ret = regmap_read(misc->regmap, BOOTSTAGE_HI, &reg);
+       if (ret)
+               return ret;
+
+       /* Firmware to report new boot stage next time */
+       if (boot_stage < cur_stage) {
+               ret = regmap_write(misc->regmap, BOOTSTAGE, ((bootstage & 0xff00) | 0x1));
+               if (ret)
+                       return ret;
+       }
+
+       boot_progress[0] = bootstage;
+       boot_progress[1] = swab16(reg);
+       boot_progress[2] = swab16(reg_lo);
+
+       return sysfs_emit(buf, "%*phN\n", (int)sizeof(boot_progress), boot_progress);
+}
+
+static DEVICE_ATTR_RO(boot_progress);
+
+static ssize_t soc_power_limit_show(struct device *dev, struct device_attribute *da, char *buf)
+{
+       struct smpro_misc *misc = dev_get_drvdata(dev);
+       unsigned int value;
+       int ret;
+
+       ret = regmap_read(misc->regmap, SOC_POWER_LIMIT, &value);
+       if (ret)
+               return ret;
+
+       return sysfs_emit(buf, "%d\n", value);
+}
+
+static ssize_t soc_power_limit_store(struct device *dev, struct device_attribute *da,
+                                    const char *buf, size_t count)
+{
+       struct smpro_misc *misc = dev_get_drvdata(dev);
+       unsigned long val;
+       s32 ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       ret = regmap_write(misc->regmap, SOC_POWER_LIMIT, (unsigned int)val);
+       if (ret)
+               return -EPROTO;
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(soc_power_limit);
+
+static struct attribute *smpro_misc_attrs[] = {
+       &dev_attr_boot_progress.attr,
+       &dev_attr_soc_power_limit.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(smpro_misc);
+
+static int smpro_misc_probe(struct platform_device *pdev)
+{
+       struct smpro_misc *misc;
+
+       misc = devm_kzalloc(&pdev->dev, sizeof(struct smpro_misc), GFP_KERNEL);
+       if (!misc)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, misc);
+
+       misc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       if (!misc->regmap)
+               return -ENODEV;
+
+       return 0;
+}
+
+static struct platform_driver smpro_misc_driver = {
+       .probe          = smpro_misc_probe,
+       .driver = {
+               .name   = "smpro-misc",
+               .dev_groups = smpro_misc_groups,
+       },
+};
+
+module_platform_driver(smpro_misc_driver);
+
+MODULE_AUTHOR("Tung Nguyen <tungnguyen@os.amperecomputing.com>");
+MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
+MODULE_DESCRIPTION("Ampere Altra SMpro Misc driver");
+MODULE_LICENSE("GPL");