[PATCH linux dev-4.7 1/4] misc: Expose Aspeed SuperIO scratch registers (SCRxSIO)

Andrew Jeffery andrew at aj.id.au
Thu Nov 10 12:35:53 AEDT 2016


Exposes a sysfs interface to manipulate the SuperIO scratch registers
present in the LPC controller.

Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
 drivers/misc/Kconfig         |   7 +++
 drivers/misc/Makefile        |   1 +
 drivers/misc/aspeed-scrsio.c | 141 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 drivers/misc/aspeed-scrsio.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4617ddc3c538..27327f44a709 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -51,6 +51,13 @@ config AD525X_DPOT_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad525x_dpot-spi.
 
+config ASPEED_SCRSIO
+	bool "Support for Aspeed SuperIO scratch registers"
+	depends on ARCH_ASPEED || COMPILE_TEST
+	help
+	  Select this if you wish to expose to userspace the SuperIO scratch
+	  registers in the LPC control space on an Aspeed BMC SoC.
+
 config ATMEL_TCLIB
 	bool "Atmel AT32/AT91 Timer/Counter Library"
 	depends on (AVR32 || ARCH_AT91)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 724861b7f291..0bcd6ff61a12 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
+obj-$(CONFIG_ASPEED_SCRSIO)	+= aspeed-scrsio.o
 obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
diff --git a/drivers/misc/aspeed-scrsio.c b/drivers/misc/aspeed-scrsio.c
new file mode 100644
index 000000000000..8d097b35612e
--- /dev/null
+++ b/drivers/misc/aspeed-scrsio.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * Andrew Jeffery <andrew at aj.id.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define LPC_SCR0SIO	0x0
+#define LPC_SCR1SIO	0x4
+#define LPC_SCR2SIO	0x8
+#define LPC_SCR3SIO	0xc
+
+struct aspeed_scrsio {
+	void __iomem *base;
+};
+
+static ssize_t scrsio_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t len, int reg)
+{
+	struct aspeed_scrsio *scrsio = dev_get_drvdata(dev);
+	int r;
+	u32 value;
+
+	r = kstrtou32(buf, 0, &value);
+	if (r)
+		return r;
+
+	iowrite32(value, scrsio->base + reg);
+
+	return len;
+}
+
+ssize_t scrsio_show(struct device *dev, struct device_attribute *attr,
+		    char *buf, int reg)
+{
+	struct aspeed_scrsio *scrsio = dev_get_drvdata(dev);
+	u32 value;
+
+	value = ioread32(scrsio->base + reg);
+
+	return scnprintf(buf, PAGE_SIZE, "0x%08x\n", value);
+}
+
+static ssize_t scr0sio_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t len)
+{
+	return scrsio_store(dev, attr, buf, len, LPC_SCR0SIO);
+}
+
+static ssize_t scr0sio_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return scrsio_show(dev, attr, buf, LPC_SCR0SIO);
+}
+DEVICE_ATTR_RW(scr0sio);
+
+static ssize_t scr1sio_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t len)
+{
+	return scrsio_store(dev, attr, buf, len, LPC_SCR1SIO);
+}
+
+static ssize_t scr1sio_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return scrsio_show(dev, attr, buf, LPC_SCR1SIO);
+}
+DEVICE_ATTR_RW(scr1sio);
+
+static ssize_t scr2sio_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return scrsio_show(dev, attr, buf, LPC_SCR2SIO);
+}
+DEVICE_ATTR_RO(scr2sio);
+
+static ssize_t scr3sio_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return scrsio_show(dev, attr, buf, LPC_SCR3SIO);
+}
+DEVICE_ATTR_RO(scr3sio);
+
+static struct attribute *sio_attrs[] = {
+	&dev_attr_scr0sio.attr,
+	&dev_attr_scr1sio.attr,
+	&dev_attr_scr2sio.attr,
+	&dev_attr_scr3sio.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(sio);
+
+static const struct attribute_group sio_attr_group = {
+	.attrs = sio_attrs,
+};
+
+static int __init aspeed_scrsio_probe(struct platform_device *pdev)
+{
+	struct aspeed_scrsio *scrsio;
+	struct resource *res;
+
+	scrsio = devm_kzalloc(&pdev->dev, sizeof(*scrsio), GFP_KERNEL);
+	if (!scrsio)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	scrsio->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(scrsio->base))
+		return PTR_ERR(scrsio->base);
+
+	dev_set_drvdata(&pdev->dev, scrsio);
+
+	return sysfs_create_groups(&pdev->dev.kobj, sio_groups);
+};
+
+static const struct of_device_id aspeed_scrsio_of_match[] = {
+	{ .compatible = "aspeed,ast2400-scrsio"},
+	{ .compatible = "aspeed,ast2500-scrsio"},
+};
+
+static struct platform_driver aspeed_scrsio_driver = {
+	.driver = {
+		.name = "aspeed_scrsio",
+		.of_match_table = aspeed_scrsio_of_match,
+	},
+};
+module_platform_driver_probe(aspeed_scrsio_driver, aspeed_scrsio_probe);
+
+MODULE_AUTHOR("Andrew Jeffery <andrew at aj.id.au>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Aspeed SuperIO scratch registers");
-- 
2.9.3



More information about the openbmc mailing list