summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2019-10-23 00:01:54 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2019-10-23 00:48:48 +0300
commit456380bb272d3a301c887eee513a3937cc1f48e1 (patch)
tree124399167d539582befbe35ad28377eaea6cc8bc /meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
parent9722c6ee87766a45a337c094d1293de81cdcb106 (diff)
downloadopenbmc-456380bb272d3a301c887eee513a3937cc1f48e1.tar.xz
Update to internal 10-22-19
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch602
1 files changed, 337 insertions, 265 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
index a44667436..07283f54d 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
@@ -1,4 +1,4 @@
-From 0f0e0a03218f6a7bdcdd78d319959e6bb974502c Mon Sep 17 00:00:00 2001
+From 6e55e28db5eed85b7717aa4fc92c064f11429f6d Mon Sep 17 00:00:00 2001
From: Haiyue Wang <haiyue.wang@linux.intel.com>
Date: Sat, 24 Feb 2018 11:12:32 +0800
Subject: [PATCH] eSPI: add ASPEED AST2500 eSPI driver to boot a host with PCH
@@ -16,15 +16,20 @@ Also for the host power on / off actions, from BMC side, the following VW
3. OOB_RESET_ACK
4. HOST_RESET_ACK
+Also, it provides monitoring interface of PLTRST_N signal through
+/dev/espi-pltrstn
+
Signed-off-by: Haiyue Wang <haiyue.wang@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
---
- .../devicetree/bindings/misc/aspeed,espi-slave.txt | 19 ++
- Documentation/misc-devices/espi-slave.rst | 118 +++++++
+ .../devicetree/bindings/misc/aspeed,espi-slave.txt | 19 +
+ Documentation/misc-devices/espi-slave.rst | 118 ++++++
arch/arm/boot/dts/aspeed-g5.dtsi | 4 +
drivers/misc/Kconfig | 8 +
drivers/misc/Makefile | 1 +
- drivers/misc/aspeed-espi-slave.c | 353 +++++++++++++++++++++
- 6 files changed, 503 insertions(+)
+ drivers/misc/aspeed-espi-slave.c | 420 +++++++++++++++++++++
+ 6 files changed, 570 insertions(+)
create mode 100644 Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt
create mode 100644 Documentation/misc-devices/espi-slave.rst
create mode 100644 drivers/misc/aspeed-espi-slave.c
@@ -179,10 +184,10 @@ index 000000000000..887a69a7130a
+- Interface Base Specification (for Client and Server Platforms)
+<https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf>`_
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 2d6f730a7101..0e7f1d2fa08e 100644
+index 88f75736fe48..26671cc4dbd5 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -289,6 +289,7 @@
+@@ -317,6 +317,7 @@
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -190,7 +195,7 @@ index 2d6f730a7101..0e7f1d2fa08e 100644
};
sgpio: sgpio@1e780200 {
-@@ -383,6 +384,9 @@
+@@ -413,6 +414,9 @@
reg = <0x1e6ee000 0x100>;
interrupts = <23>;
status = "disabled";
@@ -201,10 +206,10 @@ index 2d6f730a7101..0e7f1d2fa08e 100644
lpc: lpc@1e789000 {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 9d96469fb41c..b6acddaa9421 100644
+index d681b7201f8c..50814caba1d3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
-@@ -473,6 +473,14 @@ config VEXPRESS_SYSCFG
+@@ -455,6 +455,14 @@ config VEXPRESS_SYSCFG
bus. System Configuration interface is one of the possible means
of generating transactions on this bus.
@@ -220,10 +225,10 @@ index 9d96469fb41c..b6acddaa9421 100644
depends on PCI
select CRC32
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index e13de4f0798f..f91f66a15484 100644
+index fdd404120ed8..f168e6713440 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
+@@ -53,6 +53,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
@@ -233,363 +238,430 @@ index e13de4f0798f..f91f66a15484 100644
obj-y += cardreader/
diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c
new file mode 100644
-index 000000000000..36ae867ca6f9
+index 000000000000..b0fc01692d3a
--- /dev/null
+++ b/drivers/misc/aspeed-espi-slave.c
-@@ -0,0 +1,353 @@
+@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2012-2015, ASPEED Technology Inc.
-+ * Copyright (c) 2015-2018, Intel Corporation.
-+ */
++// Copyright (c) 2015-2019, Intel Corporation.
+
-+#include <linux/atomic.h>
+#include <linux/clk.h>
-+#include <linux/errno.h>
++#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
-+#include <linux/poll.h>
+#include <linux/regmap.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/timer.h>
-+
-+#define DEVICE_NAME "aspeed-espi-slave"
-+
-+#define ESPI_CTRL 0x00
-+#define ESPI_CTRL_SW_RESET GENMASK(31, 24)
-+#define ESPI_CTRL_OOB_CHRDY BIT(4)
-+#define ESPI_ISR 0x08
-+#define ESPI_ISR_HW_RESET BIT(31)
-+#define ESPI_ISR_VW_SYS_EVT1 BIT(22)
-+#define ESPI_ISR_VW_SYS_EVT BIT(8)
-+#define ESPI_IER 0x0C
-+#define ESPI_DATA_PORT 0x28
-+#define ESPI_DATA_PORT_ASPEED 0xa8
-+#define ESPI_SYS_IER 0x94
-+#define ESPI_SYS_EVENT 0x98
-+#define ESPI_SYS_INT_T0 0x110
-+#define ESPI_SYS_INT_T1 0x114
-+#define ESPI_SYS_INT_T2 0x118
-+#define ESPI_SYS_ISR 0x11C
-+#define ESPI_SYSEVT_HOST_RST_ACK BIT(27)
-+#define ESPI_SYSEVT_SLAVE_BOOT_STATUS BIT(23)
-+#define ESPI_SYSEVT_SLAVE_BOOT_DONE BIT(20)
-+#define ESPI_SYSEVT_OOB_RST_ACK BIT(16)
-+#define ESPI_SYSEVT_HOST_RST_WARN BIT(8)
-+#define ESPI_SYSEVT_OOB_RST_WARN BIT(6)
-+#define ESPI_SYSEVT_PLT_RST_N BIT(5)
-+#define ESPI_SYS1_IER 0x100
-+#define ESPI_SYS1_EVENT 0x104
-+#define ESPI_SYS1_INT_T0 0x120
-+#define ESPI_SYS1_INT_T1 0x124
-+#define ESPI_SYS1_INT_T2 0x128
-+#define ESPI_SYS1_ISR 0x12C
-+#define ESPI_SYSEVT1_SUS_ACK BIT(20)
-+#define ESPI_SYSEVT1_SUS_WARN BIT(0)
-+
-+struct aspeed_espi_slave_data {
-+ struct regmap *map;
-+ struct clk *clk;
++#include <linux/sched/signal.h>
++#include <linux/spinlock.h>
++#include <linux/uaccess.h>
++
++#define ASPEED_ESPI_CTRL 0x00
++#define ASPEED_ESPI_CTRL_SW_RESET GENMASK(31, 24)
++#define ASPEED_ESPI_CTRL_OOB_CHRDY BIT(4)
++#define ASPEED_ESPI_INT_STS 0x08
++#define ASPEED_ESPI_HW_RESET BIT(31)
++#define ASPEED_ESPI_VW_SYSEVT1 BIT(22)
++#define ASPEED_ESPI_VW_SYSEVT BIT(8)
++#define ASPEED_ESPI_INT_EN 0x0C
++#define ASPEED_ESPI_DATA_PORT 0x28
++#define ASPEED_ESPI_SYSEVT_INT_EN 0x94
++#define ASPEED_ESPI_SYSEVT 0x98
++#define ASPEED_ESPI_SYSEVT_HOST_RST_ACK BIT(27)
++#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS BIT(23)
++#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE BIT(20)
++#define ASPEED_ESPI_SYSEVT_OOB_RST_ACK BIT(16)
++#define ASPEED_ESPI_SYSEVT_INT_T0 0x110
++#define ASPEED_ESPI_SYSEVT_INT_T1 0x114
++#define ASPEED_ESPI_SYSEVT_INT_T2 0x118
++#define ASPEED_ESPI_SYSEVT_INT_STS 0x11C
++#define ASPEED_ESPI_SYSEVT_HOST_RST_WARN BIT(8)
++#define ASPEED_ESPI_SYSEVT_OOB_RST_WARN BIT(6)
++#define ASPEED_ESPI_SYSEVT_PLTRSTN BIT(5)
++#define ASPEED_ESPI_SYSEVT1_INT_EN 0x100
++#define ASPEED_ESPI_SYSEVT1 0x104
++#define ASPEED_ESPI_SYSEVT1_SUS_ACK BIT(20)
++#define ASPEED_ESPI_SYSEVT1_INT_T0 0x120
++#define ASPEED_ESPI_SYSEVT1_INT_T1 0x124
++#define ASPEED_ESPI_SYSEVT1_INT_T2 0x128
++#define ASPEED_ESPI_SYSEVT1_INT_STS 0x12C
++#define ASPEED_ESPI_SYSEVT1_SUS_WARN BIT(0)
++
++#define ASPEED_ESPI_INT_MASK \
++ (ASPEED_ESPI_HW_RESET | \
++ ASPEED_ESPI_VW_SYSEVT1 | \
++ ASPEED_ESPI_VW_SYSEVT)
++
++/*
++ * Setup Interrupt Type / Enable of System Event from Master
++ * T2 T1 T0
++ * 1) HOST_RST_WARN : Dual Edge 1 0 0
++ * 2) OOB_RST_WARN : Dual Edge 1 0 0
++ * 3) PLTRSTN : Dual Edge 1 0 0
++ */
++#define ASPEED_ESPI_SYSEVT_INT_T0_MASK 0
++#define ASPEED_ESPI_SYSEVT_INT_T1_MASK 0
++#define ASPEED_ESPI_SYSEVT_INT_T2_MASK \
++ (ASPEED_ESPI_SYSEVT_HOST_RST_WARN | \
++ ASPEED_ESPI_SYSEVT_OOB_RST_WARN | \
++ ASPEED_ESPI_SYSEVT_PLTRSTN)
++#define ASPEED_ESPI_SYSEVT_INT_MASK \
++ (ASPEED_ESPI_SYSEVT_INT_T0_MASK | \
++ ASPEED_ESPI_SYSEVT_INT_T1_MASK | \
++ ASPEED_ESPI_SYSEVT_INT_T2_MASK)
++
++/*
++ * Setup Interrupt Type / Enable of System Event 1 from Master
++ * T2 T1 T0
++ * 1) SUS_WARN : Rising Edge 0 0 1
++ */
++#define ASPEED_ESPI_SYSEVT1_INT_T0_MASK ASPEED_ESPI_SYSEVT1_SUS_WARN
++#define ASPEED_ESPI_SYSEVT1_INT_T1_MASK 0
++#define ASPEED_ESPI_SYSEVT1_INT_T2_MASK 0
++#define ASPEED_ESPI_SYSEVT1_INT_MASK \
++ (ASPEED_ESPI_SYSEVT1_INT_T0_MASK | \
++ ASPEED_ESPI_SYSEVT1_INT_T1_MASK | \
++ ASPEED_ESPI_SYSEVT1_INT_T2_MASK)
++
++struct aspeed_espi {
++ struct regmap *map;
++ struct clk *clk;
++ struct device *dev;
++ int irq;
++
++ /* for PLTRST_N signal monitoring interface */
++ struct miscdevice pltrstn_miscdev;
++ spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */
++ wait_queue_head_t pltrstn_waitq;
++ char pltrstn;
+};
+
-+static void aspeed_espi_slave_sys_event(struct platform_device *pdev)
++static void aspeed_espi_sys_event(struct aspeed_espi *priv)
+{
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
+ u32 sts, evt;
+
-+ if (regmap_read(priv->map, ESPI_SYS_ISR, &sts) != 0 ||
-+ regmap_read(priv->map, ESPI_SYS_EVENT, &evt) != 0) {
-+ dev_err(dev, "regmap_read failed\n");
-+ return;
-+ }
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, &sts);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt);
+
-+ dev_dbg(dev, "sys: sts = %08x, evt = %08x\n", sts, evt);
++ dev_dbg(priv->dev, "sys: sts = %08x, evt = %08x\n", sts, evt);
+
-+ if ((evt & ESPI_SYSEVT_SLAVE_BOOT_STATUS) == 0) {
-+ dev_info(dev, "Setting espi slave boot done\n");
-+ regmap_write(priv->map, ESPI_SYS_EVENT,
-+ evt | ESPI_SYSEVT_SLAVE_BOOT_STATUS |
-+ ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT,
++ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ dev_dbg(priv->dev, "Setting espi slave boot done\n");
+ }
-+#if 0
-+ if (sts & ESPI_SYSEVT_HOST_RST_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT_HOST_RST_WARN; %s ack\n",
-+ (evt & ESPI_SYSEVT_HOST_RST_WARN ? "send" : "clr"));
-+ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
-+ ESPI_SYSEVT_HOST_RST_ACK,
-+ evt & ESPI_SYSEVT_HOST_RST_WARN ?
-+ ESPI_SYSEVT_HOST_RST_ACK : 0);
++ if (sts & ASPEED_ESPI_SYSEVT_HOST_RST_WARN &&
++ evt & ASPEED_ESPI_SYSEVT_HOST_RST_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT,
++ ASPEED_ESPI_SYSEVT_HOST_RST_ACK,
++ ASPEED_ESPI_SYSEVT_HOST_RST_ACK);
++ dev_dbg(priv->dev, "SYSEVT_HOST_RST_WARN: acked\n");
+ }
-+ if (sts & ESPI_SYSEVT_OOB_RST_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; %s ack\n",
-+ (evt & ESPI_SYSEVT_OOB_RST_WARN ? "send" : "clr"));
-+ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
-+ ESPI_SYSEVT_OOB_RST_ACK,
-+ evt & ESPI_SYSEVT_OOB_RST_WARN ?
-+ ESPI_SYSEVT_OOB_RST_ACK : 0);
++ if (sts & ASPEED_ESPI_SYSEVT_OOB_RST_WARN &&
++ evt & ASPEED_ESPI_SYSEVT_OOB_RST_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT,
++ ASPEED_ESPI_SYSEVT_OOB_RST_ACK,
++ ASPEED_ESPI_SYSEVT_OOB_RST_ACK);
++ dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n");
+ }
-+#else
-+ if (sts & ESPI_SYSEVT_HOST_RST_WARN) {
-+ if (evt & ESPI_SYSEVT_HOST_RST_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT_HOST_RST_WARN; send ack\n");
-+ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
-+ ESPI_SYSEVT_HOST_RST_ACK, ESPI_SYSEVT_HOST_RST_ACK);
-+ }
++ if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') {
++ priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0';
++ wake_up_interruptible(&priv->pltrstn_waitq);
++ dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn);
+ }
-+ if (sts & ESPI_SYSEVT_OOB_RST_WARN) {
-+ if (evt & ESPI_SYSEVT_OOB_RST_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; send ack\n");
-+ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
-+ ESPI_SYSEVT_OOB_RST_ACK, ESPI_SYSEVT_OOB_RST_ACK);
-+ }
-+ }
-+#endif
-+ regmap_write(priv->map, ESPI_SYS_ISR, sts);
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, sts);
+}
+
-+static void aspeed_espi_slave_sys1_event(struct platform_device *pdev)
++static void aspeed_espi_sys_event1(struct aspeed_espi *priv)
+{
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
+ u32 sts, evt;
+
-+ if (regmap_read(priv->map, ESPI_SYS1_ISR, &sts) != 0 ||
-+ regmap_read(priv->map, ESPI_SYS1_EVENT, &evt) != 0) {
-+ dev_err(dev, "regmap_read failed\n");
-+ return;
-+ }
-+ dev_dbg(dev, "sys1: sts = %08x, evt = %08x\n", sts, evt);
-+
-+#if 0
-+ if (sts & ESPI_SYSEVT1_SUS_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT1_SUS_WARN; %s ack\n",
-+ (evt & ESPI_SYSEVT1_SUS_WARN ? "send" : "clr"));
-+ regmap_write_bits(priv->map, ESPI_SYS1_EVENT,
-+ ESPI_SYSEVT1_SUS_ACK,
-+ evt & ESPI_SYSEVT1_SUS_WARN ?
-+ ESPI_SYSEVT1_SUS_ACK : 0);
-+ }
-+#else
-+ if (sts & ESPI_SYSEVT1_SUS_WARN) {
-+ if (evt & ESPI_SYSEVT1_SUS_WARN) {
-+ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; send ack\n");
-+ regmap_write_bits(priv->map, ESPI_SYS1_EVENT,
-+ ESPI_SYSEVT1_SUS_ACK, ESPI_SYSEVT1_SUS_ACK);
-+ }
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, &sts);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt);
++
++ dev_dbg(priv->dev, "sys event1: sts = %08x, evt = %08x\n", sts, evt);
++
++ if (sts & ASPEED_ESPI_SYSEVT1_SUS_WARN &&
++ evt & ASPEED_ESPI_SYSEVT1_SUS_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT1,
++ ASPEED_ESPI_SYSEVT1_SUS_ACK,
++ ASPEED_ESPI_SYSEVT1_SUS_ACK);
++ dev_dbg(priv->dev, "SYSEVT1_SUS_WARN: acked\n");
+ }
-+#endif
-+ regmap_write(priv->map, ESPI_SYS1_ISR, sts);
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, sts);
+}
+
-+static void aspeed_espi_slave_boot_ack(struct platform_device *pdev)
++static void aspeed_espi_boot_ack(struct aspeed_espi *priv)
+{
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
+ u32 evt;
+
-+ if (regmap_read(priv->map, ESPI_SYS_EVENT, &evt) == 0 &&
-+ (evt & ESPI_SYSEVT_SLAVE_BOOT_STATUS) == 0) {
-+ dev_info(dev, "Setting espi slave boot done\n");
-+ regmap_write(priv->map, ESPI_SYS_EVENT,
-+ evt | ESPI_SYSEVT_SLAVE_BOOT_STATUS |
-+ ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt);
++ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT,
++ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ dev_dbg(priv->dev, "Setting espi slave boot done\n");
+ }
+
-+ if (regmap_read(priv->map, ESPI_SYS1_EVENT, &evt) == 0 &&
-+ (evt & ESPI_SYSEVT1_SUS_WARN) != 0 &&
-+ (evt & ESPI_SYSEVT1_SUS_ACK) == 0) {
-+ dev_info(dev, "Boot SUS WARN set; send ack\n");
-+ regmap_write(priv->map, ESPI_SYS1_EVENT,
-+ evt | ESPI_SYSEVT1_SUS_ACK);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt);
++ if (evt & ASPEED_ESPI_SYSEVT1_SUS_WARN &&
++ !(evt & ASPEED_ESPI_SYSEVT1_SUS_ACK)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1,
++ evt | ASPEED_ESPI_SYSEVT1_SUS_ACK);
++ dev_dbg(priv->dev, "Boot SYSEVT1_SUS_WARN: acked\n");
+ }
+}
+
-+static irqreturn_t aspeed_espi_slave_irq(int irq, void *arg)
++static irqreturn_t aspeed_espi_irq(int irq, void *arg)
+{
-+ struct platform_device *pdev = arg;
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
-+ u32 sts;
-+
-+ if (regmap_read(priv->map, ESPI_ISR, &sts) != 0) {
-+ dev_err(dev, "regmap_read failed\n");
-+ return IRQ_NONE;
-+ }
++ struct aspeed_espi *priv = arg;
++ u32 sts, sts_handled = 0;
+
-+ dev_dbg(dev, "ESPI_ISR: %08x\n", sts);
++ regmap_read(priv->map, ASPEED_ESPI_INT_STS, &sts);
+
-+ if (sts & ESPI_ISR_VW_SYS_EVT)
-+ aspeed_espi_slave_sys_event(pdev);
++ dev_dbg(priv->dev, "INT_STS: 0x%08x\n", sts);
+
-+ if (sts & ESPI_ISR_VW_SYS_EVT1)
-+ aspeed_espi_slave_sys1_event(pdev);
++ if (sts & ASPEED_ESPI_VW_SYSEVT) {
++ aspeed_espi_sys_event(priv);
++ sts_handled |= ASPEED_ESPI_VW_SYSEVT;
++ }
+
-+ /*
-+ if (sts & ESPI_ISR_HW_RESET) {
-+ regmap_write_bits(priv->map, ESPI_CTRL,
-+ ESPI_CTRL_SW_RESET, 0);
-+ regmap_write_bits(priv->map, ESPI_CTRL,
-+ ESPI_CTRL_SW_RESET, ESPI_CTRL_SW_RESET);
++ if (sts & ASPEED_ESPI_VW_SYSEVT1) {
++ aspeed_espi_sys_event1(priv);
++ sts_handled |= ASPEED_ESPI_VW_SYSEVT1;
++ }
+
-+ aspeed_espi_slave_boot_ack(pdev);
++ if (sts & ASPEED_ESPI_HW_RESET) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET,
++ ASPEED_ESPI_CTRL_SW_RESET);
++ aspeed_espi_boot_ack(priv);
++ sts_handled |= ASPEED_ESPI_HW_RESET;
+ }
-+ */
+
-+ regmap_write(priv->map, ESPI_ISR, sts);
++ regmap_write(priv->map, ASPEED_ESPI_INT_STS, sts);
+
-+ return IRQ_HANDLED;
++ return sts != sts_handled ? IRQ_NONE : IRQ_HANDLED;
+}
+
-+/* Setup Interrupt Type/Enable of System Event from Master
-+ * T2 T1 T0
-+ * 1). HOST_RST_WARN : Dual Edge 1 0 0
-+ * 2). OOB_RST_WARN : Dual Edge 1 0 0
-+ * 3). PLTRST_N : Dual Edge 1 0 0
-+ */
-+#define ESPI_SYS_INT_T0_SET 0x00000000
-+#define ESPI_SYS_INT_T1_SET 0x00000000
-+#define ESPI_SYS_INT_T2_SET \
-+(ESPI_SYSEVT_HOST_RST_WARN | ESPI_SYSEVT_OOB_RST_WARN | ESPI_SYSEVT_PLT_RST_N)
-+#define ESPI_SYS_INT_SET \
-+(ESPI_SYSEVT_HOST_RST_WARN | ESPI_SYSEVT_OOB_RST_WARN | ESPI_SYSEVT_PLT_RST_N)
-+
-+/* Setup Interrupt Type/Enable of System Event 1 from Master
-+ * T2 T1 T0
-+ * 1). SUS_WARN : Rising Edge 0 0 1
-+ */
-+#define ESPI_SYS1_INT_T0_SET ESPI_SYSEVT1_SUS_WARN
-+#define ESPI_SYS1_INT_T1_SET 0x00000000
-+#define ESPI_SYS1_INT_T2_SET 0x00000000
-+#define ESPI_SYS1_INT_SET ESPI_SYSEVT1_SUS_WARN
++static void aspeed_espi_config_irq(struct aspeed_espi *priv)
++{
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T0,
++ ASPEED_ESPI_SYSEVT_INT_T0_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T1,
++ ASPEED_ESPI_SYSEVT_INT_T1_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T2,
++ ASPEED_ESPI_SYSEVT_INT_T2_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_EN,
++ ASPEED_ESPI_SYSEVT_INT_MASK);
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T0,
++ ASPEED_ESPI_SYSEVT1_INT_T0_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T1,
++ ASPEED_ESPI_SYSEVT1_INT_T1_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T2,
++ ASPEED_ESPI_SYSEVT1_INT_T2_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_EN,
++ ASPEED_ESPI_SYSEVT1_INT_MASK);
++
++ regmap_write(priv->map, ASPEED_ESPI_INT_EN, ASPEED_ESPI_INT_MASK);
++
++ aspeed_espi_boot_ack(priv);
++}
+
-+static int aspeed_espi_slave_config_irq(struct platform_device *pdev)
++static inline struct aspeed_espi *to_aspeed_espi(struct file *filp)
+{
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
-+ int irq;
-+ int rc;
++ return container_of(filp->private_data, struct aspeed_espi,
++ pltrstn_miscdev);
++}
+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0)
-+ return irq;
++static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp)
++{
++ if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
++ return -EACCES;
+
-+ regmap_write_bits(priv->map, ESPI_CTRL, ESPI_CTRL_OOB_CHRDY,
-+ ESPI_CTRL_OOB_CHRDY);
++ return 0;
++}
+
-+ regmap_write(priv->map, ESPI_SYS_INT_T0, ESPI_SYS_INT_T0_SET);
-+ regmap_write(priv->map, ESPI_SYS_INT_T1, ESPI_SYS_INT_T1_SET);
-+ regmap_write(priv->map, ESPI_SYS_INT_T2, ESPI_SYS_INT_T2_SET);
-+ regmap_write(priv->map, ESPI_SYS_IER, ESPI_SYS_INT_SET);
++static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf,
++ size_t count, loff_t *offset)
++{
++ struct aspeed_espi *priv = to_aspeed_espi(filp);
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long flags;
++ char old_sample;
++ int ret = 0;
+
-+ regmap_write(priv->map, ESPI_SYS1_INT_T0, ESPI_SYS1_INT_T0_SET);
-+ regmap_write(priv->map, ESPI_SYS1_INT_T1, ESPI_SYS1_INT_T1_SET);
-+ regmap_write(priv->map, ESPI_SYS1_INT_T2, ESPI_SYS1_INT_T2_SET);
-+ regmap_write(priv->map, ESPI_SYS1_IER, ESPI_SYS1_INT_SET);
++ spin_lock_irqsave(&priv->pltrstn_lock, flags);
+
-+ regmap_write(priv->map, ESPI_IER, 0xFFFFFFFF);
++ add_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
+
-+ aspeed_espi_slave_boot_ack(pdev);
++ old_sample = priv->pltrstn;
+
-+ rc = devm_request_irq(dev, irq, aspeed_espi_slave_irq, IRQF_SHARED,
-+ dev_name(dev), pdev);
-+ if (rc < 0)
-+ return rc;
++ do {
++ char new_sample = priv->pltrstn;
+
-+ return 0;
++ if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) {
++ ret = put_user(new_sample, (unsigned long __user *)buf);
++ if (!ret)
++ ret = sizeof(new_sample);
++ } else if (signal_pending(current)) {
++ ret = -ERESTARTSYS;
++ }
++
++ if (!ret) {
++ spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
++ schedule();
++ spin_lock_irqsave(&priv->pltrstn_lock, flags);
++ }
++ } while (!ret);
++
++ remove_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_RUNNING);
++
++ spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
++
++ return ret;
+}
+
-+static const struct regmap_config espi_slave_regmap_cfg = {
-+ .reg_bits = 32,
-+ .reg_stride = 4,
-+ .val_bits = 32,
-+ .max_register = ESPI_SYS1_ISR,
++static const struct file_operations aspeed_espi_pltrstn_fops = {
++ .owner = THIS_MODULE,
++ .open = aspeed_espi_pltrstn_open,
++ .read = aspeed_espi_pltrstn_read,
++};
++
++static const struct regmap_config aspeed_espi_regmap_cfg = {
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .max_register = ASPEED_ESPI_SYSEVT1_INT_STS,
+};
+
-+static int aspeed_espi_slave_probe(struct platform_device *pdev)
++static int aspeed_espi_probe(struct platform_device *pdev)
+{
-+ struct aspeed_espi_slave_data *priv;
-+ struct device *dev = &pdev->dev;
++ struct aspeed_espi *priv;
+ struct resource *res;
+ void __iomem *regs;
-+ int rc;
++ u32 ctrl;
++ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ regs = devm_ioremap_resource(dev, res);
++ regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
-+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
-+ priv->map = devm_regmap_init_mmio(dev, regs, &espi_slave_regmap_cfg);
++ dev_set_drvdata(&pdev->dev, priv);
++ priv->dev = &pdev->dev;
++
++ priv->map = devm_regmap_init_mmio(&pdev->dev, regs,
++ &aspeed_espi_regmap_cfg);
+ if (IS_ERR(priv->map))
+ return PTR_ERR(priv->map);
+
-+ priv->clk = devm_clk_get(dev, NULL);
++ spin_lock_init(&priv->pltrstn_lock);
++ init_waitqueue_head(&priv->pltrstn_waitq);
++ priv->pltrstn = 'U'; /* means it's not reported yet from master */
++
++ priv->irq = platform_get_irq(pdev, 0);
++ if (priv->irq < 0)
++ return priv->irq;
++
++ aspeed_espi_config_irq(priv);
++
++ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_espi_irq, 0,
++ "aspeed-espi-irq", priv);
++ if (ret)
++ return ret;
++
++ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
-+ dev_err(dev, "couldn't get clock\n");
-+ return PTR_ERR(priv->clk);
++ ret = PTR_ERR(priv->clk);
++ if (ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev, "couldn't get clock\n");
++ return ret;
+ }
-+ rc = clk_prepare_enable(priv->clk);
-+ if (rc) {
-+ dev_err(dev, "couldn't enable clock\n");
-+ return rc;
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "couldn't enable clock\n");
++ return ret;
+ }
+
-+ dev_set_name(dev, DEVICE_NAME);
-+
-+ platform_set_drvdata(pdev, priv);
-+
-+ rc = aspeed_espi_slave_config_irq(pdev);
-+ if (rc) {
-+ platform_set_drvdata(pdev, NULL);
-+ goto err;
++ /*
++ * We check that the regmap works on this very first access, but as this
++ * is an MMIO-backed regmap, subsequent regmap access is not going to
++ * fail and we skip error checks from this point.
++ */
++ ret = regmap_read(priv->map, ASPEED_ESPI_CTRL, &ctrl);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to read ctrl register\n");
++ goto err_clk_disable_out;
++ }
++ regmap_write(priv->map, ASPEED_ESPI_CTRL,
++ ctrl | ASPEED_ESPI_CTRL_OOB_CHRDY);
++
++ priv->pltrstn_miscdev.minor = MISC_DYNAMIC_MINOR;
++ priv->pltrstn_miscdev.name = "espi-pltrstn";
++ priv->pltrstn_miscdev.fops = &aspeed_espi_pltrstn_fops;
++ priv->pltrstn_miscdev.parent = &pdev->dev;
++
++ ret = misc_register(&priv->pltrstn_miscdev);
++ if (ret) {
++ dev_err(&pdev->dev, "Unable to register device\n");
++ goto err_clk_disable_out;
+ }
+
-+ dev_info(dev, "aspeed,ast2500-espi-slave probe complete\n");
++ dev_info(&pdev->dev, "eSPI registered, irq %d\n", priv->irq);
++
+ return 0;
+
-+err:
++err_clk_disable_out:
+ clk_disable_unprepare(priv->clk);
-+ return rc;
-+}
+
++ return ret;
++}
+
-+static int aspeed_espi_slave_remove(struct platform_device *pdev)
++static int aspeed_espi_remove(struct platform_device *pdev)
+{
-+ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct aspeed_espi *priv = dev_get_drvdata(&pdev->dev);
+
++ misc_deregister(&priv->pltrstn_miscdev);
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
-+static const struct of_device_id of_espi_slave_match_table[] = {
++static const struct of_device_id of_espi_match_table[] = {
+ { .compatible = "aspeed,ast2500-espi-slave" },
+ { }
+};
-+MODULE_DEVICE_TABLE(of, of_espi_slave_match_table);
++MODULE_DEVICE_TABLE(of, of_espi_match_table);
+
-+static struct platform_driver aspeed_espi_slave_driver = {
-+ .driver = {
-+ .name = DEVICE_NAME,
-+ .of_match_table = of_match_ptr(of_espi_slave_match_table),
++static struct platform_driver aspeed_espi_driver = {
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = of_match_ptr(of_espi_match_table),
+ },
-+ .probe = aspeed_espi_slave_probe,
-+ .remove = aspeed_espi_slave_remove,
++ .probe = aspeed_espi_probe,
++ .remove = aspeed_espi_remove,
+};
-+module_platform_driver(aspeed_espi_slave_driver);
++module_platform_driver(aspeed_espi_driver);
+
-+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
-+MODULE_DESCRIPTION("Linux device interface to the eSPI slave");
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("Aspeed eSPI driver");
++MODULE_LICENSE("GPL v2");
--
2.7.4