[PATCH linux dev-4.7 2/4] misc: Add partial Aspeed LPC Host Interface Control (HIC) driver
Andrew Jeffery
andrew at aj.id.au
Thu Nov 10 12:35:54 AEDT 2016
Exposes some of the LPC controller's host interface control registers in
sysfs, specifically HICR5-HICR8, HICR9-HICRA. At the moment the
resource range also covers the SNPWADR and SNPWDR (LPC Snoop registers),
but they are not exposed in sysfs.
Signed-off-by: Andrew Jeffery <andrew at aj.id.au>
---
drivers/misc/Kconfig | 7 ++
drivers/misc/Makefile | 1 +
drivers/misc/aspeed-hic.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 206 insertions(+)
create mode 100644 drivers/misc/aspeed-hic.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 27327f44a709..1c5b9b2b26aa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -58,6 +58,13 @@ config ASPEED_SCRSIO
Select this if you wish to expose to userspace the SuperIO scratch
registers in the LPC control space on an Aspeed BMC SoC.
+config ASPEED_HIC
+ bool "Support for Aspeed LPC Host Interface Control Registers"
+ depends on ARCH_ASPEED || COMPILE_TEST
+ help
+ Select this if you wish to expose to userspace the LPC Host Interface
+ Control Registers 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 0bcd6ff61a12..b49051932471 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_HIC) += aspeed-hic.o
obj-$(CONFIG_ASPEED_SCRSIO) += aspeed-scrsio.o
obj-$(CONFIG_INTEL_MID_PTI) += pti.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
diff --git a/drivers/misc/aspeed-hic.c b/drivers/misc/aspeed-hic.c
new file mode 100644
index 000000000000..d26b9daab126
--- /dev/null
+++ b/drivers/misc/aspeed-hic.c
@@ -0,0 +1,198 @@
+/*
+ * 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_HICR5 0x0
+#define LPC_HICR6 0x4
+#define LPC_HICR7 0x8
+#define LPC_HICR8 0xc
+#define LPC_HICR9 0x18
+#define LPC_HICRA 0x1c
+
+struct aspeed_hic {
+ void __iomem *hicr5;
+};
+
+static ssize_t hic_store(void __iomem *base, int reg, const char *buf,
+ size_t len)
+{
+ int r;
+ u32 value;
+
+ r = kstrtou32(buf, 0, &value);
+ if (r)
+ return r;
+
+ iowrite32(value, base + reg);
+
+ return len;
+}
+
+ssize_t hic_show(void __iomem *base, int reg, char *buf)
+{
+ u32 value = ioread32(base + reg);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%08x\n", value);
+}
+
+static ssize_t hicr5_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICR5, buf, len);
+}
+
+static ssize_t hicr5_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICR5, buf);
+}
+DEVICE_ATTR_RW(hicr5);
+
+static ssize_t hicr6_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICR6, buf, len);
+}
+
+static ssize_t hicr6_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICR6, buf);
+}
+DEVICE_ATTR_RW(hicr6);
+
+static ssize_t hicr7_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICR7, buf, len);
+}
+
+static ssize_t hicr7_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICR7, buf);
+}
+DEVICE_ATTR_RW(hicr7);
+
+static ssize_t hicr8_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICR8, buf, len);
+}
+
+static ssize_t hicr8_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICR8, buf);
+}
+DEVICE_ATTR_RW(hicr8);
+
+static ssize_t hicr9_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICR9, buf, len);
+}
+
+static ssize_t hicr9_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICR9, buf);
+}
+DEVICE_ATTR_RW(hicr9);
+
+static ssize_t hicra_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_store(hic->hicr5, LPC_HICRA, buf, len);
+}
+
+static ssize_t hicra_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct aspeed_hic *hic = dev_get_drvdata(dev);
+
+ return hic_show(hic->hicr5, LPC_HICRA, buf);
+}
+DEVICE_ATTR_RW(hicra);
+
+static struct attribute *hic_attrs[] = {
+ &dev_attr_hicr5.attr,
+ &dev_attr_hicr6.attr,
+ &dev_attr_hicr7.attr,
+ &dev_attr_hicr8.attr,
+ &dev_attr_hicr9.attr,
+ &dev_attr_hicra.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(hic);
+
+static int __init aspeed_hic_probe(struct platform_device *pdev)
+{
+ struct aspeed_hic *hic;
+ struct resource *res;
+
+ hic = devm_kzalloc(&pdev->dev, sizeof(*hic), GFP_KERNEL);
+ if (!hic)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hic->hicr5 = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hic->hicr5))
+ return PTR_ERR(hic->hicr5);
+
+ dev_set_drvdata(&pdev->dev, hic);
+
+ return sysfs_create_groups(&pdev->dev.kobj, hic_groups);
+}
+
+static const struct of_device_id aspeed_hic_of_match[] = {
+ { .compatible = "aspeed,ast2400-hic"},
+ { .compatible = "aspeed,ast2500-hic"},
+};
+
+static struct platform_driver aspeed_hic_driver = {
+ .driver = {
+ .name = "aspeed_hic",
+ .of_match_table = aspeed_hic_of_match,
+ },
+};
+module_platform_driver_probe(aspeed_hic_driver, aspeed_hic_probe);
+
+MODULE_AUTHOR("Andrew Jeffery <andrew at aj.id.au>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Aspeed LPC Host Interface Controller");
--
2.9.3
More information about the openbmc
mailing list