[RFC 1/5] ipmi:bt-bmc: Separate out ASPEED specific bits

Subsystems: ipmi subsystem, the rest

10 messages, 3 authors, 2021-10-06 · open the first message on its own page

[RFC 1/5] ipmi:bt-bmc: Separate out ASPEED specific bits

From: Anton Blanchard <hidden>
Date: 2021-10-06 02:12:52

Most of the IPMI BT BMC driver is architecture agnostic - it deals with
architected registers and behaviour in the IPMI specification.

Separate out the few ASPEED specific bits into their own functions
so we can use this driver on other architectures.

Signed-off-by: Anton Blanchard <redacted>
---
 drivers/char/ipmi/bt-bmc.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 6e3d247b55d1..f85fafc96ef6 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -39,6 +39,7 @@
 #define   BT_CR2_IRQ_H2B	0x01
 #define   BT_CR2_IRQ_HBUSY	0x40
 #define BT_CR3		0xc
+
 #define BT_CTRL		0x10
 #define   BT_CTRL_B_BUSY		0x80
 #define   BT_CTRL_H_BUSY		0x40
@@ -372,7 +373,7 @@ static void poll_timer(struct timer_list *t)
 	add_timer(&bt_bmc->poll_timer);
 }
 
-static irqreturn_t bt_bmc_irq(int irq, void *arg)
+static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
 {
 	struct bt_bmc *bt_bmc = arg;
 	u32 reg;
@@ -393,7 +394,7 @@ static irqreturn_t bt_bmc_irq(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
-static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 			     struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -403,7 +404,7 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 	if (bt_bmc->irq < 0)
 		return bt_bmc->irq;
 
-	rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
+	rc = devm_request_irq(dev, bt_bmc->irq, aspeed_bt_bmc_irq, IRQF_SHARED,
 			      DEVICE_NAME, bt_bmc);
 	if (rc < 0) {
 		dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
@@ -424,6 +425,16 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 	return rc;
 }
 
+static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
+{
+	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
+		     (BT_IO_BASE << BT_CR0_IO_BASE) |
+		     (BT_IRQ << BT_CR0_IRQ) |
+		     BT_CR0_EN_CLR_SLV_RDP |
+		     BT_CR0_EN_CLR_SLV_WRP |
+		     BT_CR0_ENABLE_IBT);
+}
+
 static int bt_bmc_probe(struct platform_device *pdev)
 {
 	struct bt_bmc *bt_bmc;
@@ -472,7 +483,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
 		return rc;
 	}
 
-	bt_bmc_config_irq(bt_bmc, pdev);
+	aspeed_bt_bmc_config_irq(bt_bmc, pdev);
 
 	if (bt_bmc->irq >= 0) {
 		dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -483,12 +494,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
 		add_timer(&bt_bmc->poll_timer);
 	}
 
-	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
-		     (BT_IO_BASE << BT_CR0_IO_BASE) |
-		     (BT_IRQ << BT_CR0_IRQ) |
-		     BT_CR0_EN_CLR_SLV_RDP |
-		     BT_CR0_EN_CLR_SLV_WRP |
-		     BT_CR0_ENABLE_IBT);
+	aspeed_enable_bt(bt_bmc);
 
 	clr_b_busy(bt_bmc);
 
-- 
2.31.1

[RFC 2/5] ipmi:bt-bmc: Prefix ASPEED specific registers with ASPEED_

From: Anton Blanchard <hidden>
Date: 2021-10-06 02:13:29

Signed-off-by: Anton Blanchard <redacted>
---
 drivers/char/ipmi/bt-bmc.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index f85fafc96ef6..2b0fe1255026 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -26,19 +26,19 @@
 #define BT_IO_BASE	0xe4
 #define BT_IRQ		10
 
-#define BT_CR0		0x0
+#define ASPEED_BT_CR0	0x0
 #define   BT_CR0_IO_BASE		16
 #define   BT_CR0_IRQ			12
 #define   BT_CR0_EN_CLR_SLV_RDP		0x8
 #define   BT_CR0_EN_CLR_SLV_WRP		0x4
 #define   BT_CR0_ENABLE_IBT		0x1
-#define BT_CR1		0x4
+#define ASPEED_BT_CR1	0x4
 #define   BT_CR1_IRQ_H2B	0x01
 #define   BT_CR1_IRQ_HBUSY	0x40
-#define BT_CR2		0x8
+#define ASPEED_BT_CR2	0x8
 #define   BT_CR2_IRQ_H2B	0x01
 #define   BT_CR2_IRQ_HBUSY	0x40
-#define BT_CR3		0xc
+#define ASPEED_BT_CR3	0xc
 
 #define BT_CTRL		0x10
 #define   BT_CTRL_B_BUSY		0x80
@@ -379,7 +379,7 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
 	u32 reg;
 	int rc;
 
-	rc = regmap_read(bt_bmc->map, bt_bmc->offset + BT_CR2, &reg);
+	rc = regmap_read(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR2, &reg);
 	if (rc)
 		return IRQ_NONE;
 
@@ -388,7 +388,7 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
 		return IRQ_NONE;
 
 	/* ack pending IRQs */
-	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR2, reg);
+	regmap_write(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR2, reg);
 
 	wake_up(&bt_bmc->queue);
 	return IRQ_HANDLED;
@@ -418,7 +418,7 @@ static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 	 * will be cleared (along with B2H) when we can write the next
 	 * message to the BT buffer
 	 */
-	rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + BT_CR1,
+	rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR1,
 				(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY),
 				(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY));
 
@@ -427,7 +427,7 @@ static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 
 static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
 {
-	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
+	regmap_write(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR0,
 		     (BT_IO_BASE << BT_CR0_IO_BASE) |
 		     (BT_IRQ << BT_CR0_IRQ) |
 		     BT_CR0_EN_CLR_SLV_RDP |
-- 
2.31.1

[RFC 3/5] ipmi:bt-bmc: Put arch specific function into bt_bmc_ops

From: Anton Blanchard <hidden>
Date: 2021-10-06 02:14:05

While most of the driver is arch agnostic, setting up and handling
interrupts, and enabling the hardware is not. Create bt_bmc_ops to
handle these functions.

Signed-off-by: Anton Blanchard <redacted>
---
 drivers/char/ipmi/bt-bmc.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 2b0fe1255026..b48e04405ac4 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -17,6 +17,7 @@
 #include <linux/regmap.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/of_device.h>
 
 /*
  * This is a BMC device used to communicate to the host
@@ -435,15 +436,30 @@ static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
 		     BT_CR0_ENABLE_IBT);
 }
 
+struct bt_bmc_ops {
+	int (*config_irq)(struct bt_bmc *bt_bmc, struct platform_device *pdev);
+	void (*enable_bt)(struct bt_bmc *bt_bmc);
+};
+
+static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
+	.config_irq = aspeed_bt_bmc_config_irq,
+	.enable_bt = aspeed_enable_bt,
+};
+
 static int bt_bmc_probe(struct platform_device *pdev)
 {
 	struct bt_bmc *bt_bmc;
 	struct device *dev;
 	int rc;
+	const struct bt_bmc_ops *ops;
 
 	dev = &pdev->dev;
 	dev_info(dev, "Found bt bmc device\n");
 
+	ops = of_device_get_match_data(&pdev->dev);
+	if (!ops)
+		return -ENODEV;
+
 	bt_bmc = devm_kzalloc(dev, sizeof(*bt_bmc), GFP_KERNEL);
 	if (!bt_bmc)
 		return -ENOMEM;
@@ -483,7 +499,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
 		return rc;
 	}
 
-	aspeed_bt_bmc_config_irq(bt_bmc, pdev);
+	ops->config_irq(bt_bmc, pdev);
 
 	if (bt_bmc->irq >= 0) {
 		dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -494,7 +510,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
 		add_timer(&bt_bmc->poll_timer);
 	}
 
-	aspeed_enable_bt(bt_bmc);
+	ops->enable_bt(bt_bmc);
 
 	clr_b_busy(bt_bmc);
 
@@ -512,8 +528,8 @@ static int bt_bmc_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id bt_bmc_match[] = {
-	{ .compatible = "aspeed,ast2400-ibt-bmc" },
-	{ .compatible = "aspeed,ast2500-ibt-bmc" },
+	{ .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+	{ .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
 	{ },
 };
 
-- 
2.31.1

[RFC 4/5] ipmi:bt-bmc: No longer ASPEED specific

From: Anton Blanchard <hidden>
Date: 2021-10-06 02:14:42

The driver is no longer specific to ASPEED, so rename the config option
and remove the dependency on ARCH_ASPEED.

Signed-off-by: Anton Blanchard <redacted>
---
 .../bindings/ipmi/{aspeed,ast2400-ibt-bmc.txt => ibt-bmc.txt}   | 2 +-
 arch/arm/configs/aspeed_g4_defconfig                            | 2 +-
 arch/arm/configs/aspeed_g5_defconfig                            | 2 +-
 arch/arm/configs/multi_v5_defconfig                             | 2 +-
 arch/arm/configs/multi_v7_defconfig                             | 2 +-
 drivers/char/ipmi/Kconfig                                       | 2 +-
 drivers/char/ipmi/Makefile                                      | 2 +-
 7 files changed, 7 insertions(+), 7 deletions(-)
 rename Documentation/devicetree/bindings/ipmi/{aspeed,ast2400-ibt-bmc.txt => ibt-bmc.txt} (93%)
diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
similarity index 93%
rename from Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
rename to Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 028268fd99ee..78ee716a950e 100644
--- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -1,4 +1,4 @@
-* Aspeed BT (Block Transfer) IPMI interface
+* BT (Block Transfer) IPMI interface
 
 The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs
 (BaseBoard Management Controllers) and the BT interface can be used to
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index acaafa351d08..51696ba49c80 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -124,7 +124,7 @@ CONFIG_SERIAL_8250_ASPEED_VUART=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_ASPEED_KCS_IPMI_BMC=y
-CONFIG_ASPEED_BT_IPMI_BMC=y
+CONFIG_BT_IPMI_BMC=y
 CONFIG_HW_RANDOM_TIMERIOMEM=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 480dbbb4ff91..758dac62f34f 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -141,7 +141,7 @@ CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_ASPEED_KCS_IPMI_BMC=y
 CONFIG_IPMI_KCS_BMC_SERIO=y
-CONFIG_ASPEED_BT_IPMI_BMC=y
+CONFIG_BT_IPMI_BMC=y
 CONFIG_HW_RANDOM_TIMERIOMEM=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
index 80a3ae02d759..f3ed5da74dfa 100644
--- a/arch/arm/configs/multi_v5_defconfig
+++ b/arch/arm/configs/multi_v5_defconfig
@@ -150,7 +150,7 @@ CONFIG_SERIAL_ATMEL_TTYAT=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_ASPEED_KCS_IPMI_BMC=m
-CONFIG_ASPEED_BT_IPMI_BMC=m
+CONFIG_BT_IPMI_BMC=m
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_TIMERIOMEM=m
 # CONFIG_I2C_COMPAT is not set
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index ba67c4717dcc..03e97d95c251 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -384,7 +384,7 @@ CONFIG_SERIAL_OWL_CONSOLE=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_ASPEED_KCS_IPMI_BMC=m
-CONFIG_ASPEED_BT_IPMI_BMC=m
+CONFIG_BT_IPMI_BMC=m
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ST=y
 CONFIG_TCG_TPM=m
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 249b31197eea..8b2f0f675e5f 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -151,7 +151,7 @@ config IPMI_KCS_BMC_SERIO
 	  This support is also available as a module. The module will be
 	  called kcs_bmc_serio.
 
-config ASPEED_BT_IPMI_BMC
+config BT_IPMI_BMC
 	depends on ARCH_ASPEED || COMPILE_TEST
 	depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
 	tristate "BT IPMI bmc driver"
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index 84f47d18007f..75c71cbd568b 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
 obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o
 obj-$(CONFIG_IPMI_KCS_BMC_SERIO) += kcs_bmc_serio.o
 obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o
-obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
+obj-$(CONFIG_BT_IPMI_BMC) += bt-bmc.o
 obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
 obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
 obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
-- 
2.31.1

[RFC 5/5] ipmi:bt-bmc: Add Microwatt

From: Anton Blanchard <hidden>
Date: 2021-10-06 02:15:17

This adds the Microwatt specific bits, including interrupt support.

Signed-off-by: Anton Blanchard <redacted>
---
 .../devicetree/bindings/ipmi/ibt-bmc.txt      |  1 +
 drivers/char/ipmi/Kconfig                     |  8 ++-
 drivers/char/ipmi/bt-bmc.c                    | 69 +++++++++++++++++++
 3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 78ee716a950e..1b661daf0193 100644
--- a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -9,6 +9,7 @@ Required properties:
 - compatible : should be one of
 	"aspeed,ast2400-ibt-bmc"
 	"aspeed,ast2500-ibt-bmc"
+	"ibm,microwatt-ibt-bmc"
 - reg: physical address and size of the registers
 
 Optional properties:
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 8b2f0f675e5f..079302f4eef2 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
 	  called kcs_bmc_serio.
 
 config BT_IPMI_BMC
-	depends on ARCH_ASPEED || COMPILE_TEST
+	depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
 	depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
 	tristate "BT IPMI bmc driver"
 	help
 	  Provides a driver for the BT (Block Transfer) IPMI interface
-	  found on Aspeed SOCs (AST2400 and AST2500). The driver
-	  implements the BMC side of the BT interface.
+	  found on Aspeed SOCs (AST2400 and AST2500) as well as the OpenPOWER
+	  LPC peripheral macro at
+	  <https://github.com/OpenPOWERFoundation/lpcperipheral>
+	  The driver implements the BMC side of the BT interface.
 
 config IPMB_DEVICE_INTERFACE
 	tristate 'IPMB Interface handler'
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b48e04405ac4..24327b57c60b 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -41,6 +41,11 @@
 #define   BT_CR2_IRQ_HBUSY	0x40
 #define ASPEED_BT_CR3	0xc
 
+#define MICROWATT_IRQ_MASK	0x0
+#define MICROWATT_IRQ_STATUS	0x4
+#define   IRQ_HOST_TO_BMC_ATTN	0x1
+#define   IRQ_HOST_NOT_BUSY	0x2
+
 #define BT_CTRL		0x10
 #define   BT_CTRL_B_BUSY		0x80
 #define   BT_CTRL_H_BUSY		0x40
@@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
+{
+	struct bt_bmc *bt_bmc = arg;
+	u32 reg;
+	int rc;
+
+	rc = regmap_read(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, &reg);
+	if (rc)
+		return IRQ_NONE;
+
+	/* Interrupt wasn't something we knew about */
+	if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
+		return IRQ_NONE;
+
+	/* ack all pending IRQs */
+	regmap_write(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, 0);
+
+	wake_up(&bt_bmc->queue);
+	return IRQ_HANDLED;
+}
+
 static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
 			     struct platform_device *pdev)
 {
@@ -446,6 +472,48 @@ static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
 	.enable_bt = aspeed_enable_bt,
 };
 
+static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+			     struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int rc;
+
+	bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+	if (bt_bmc->irq < 0)
+		return bt_bmc->irq;
+
+	rc = devm_request_irq(dev, bt_bmc->irq, microwatt_bt_bmc_irq, IRQF_SHARED,
+			      DEVICE_NAME, bt_bmc);
+	if (rc < 0) {
+		dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
+		bt_bmc->irq = rc;
+		return rc;
+	}
+
+	/*
+	 * Configure the hardware to give us an interrupt whenever the H2B
+	 * bit is set or the HBUSY bit is cleared.
+	 *
+	 * H2B will be asserted when the bmc has data for us; HBUSY
+	 * will be cleared (along with B2H) when we can write the next
+	 * message to the BT buffer
+	 */
+	rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_MASK,
+				(IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY),
+				(IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY));
+
+	return rc;
+}
+
+static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
+{
+}
+
+static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
+	.config_irq = microwatt_bt_bmc_config_irq,
+	.enable_bt = microwatt_enable_bt,
+};
+
 static int bt_bmc_probe(struct platform_device *pdev)
 {
 	struct bt_bmc *bt_bmc;
@@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
 static const struct of_device_id bt_bmc_match[] = {
 	{ .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
 	{ .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+	{ .compatible = "ibm,microwatt-ibt-bmc", .data = &microwatt_bt_bmc_ops },
 	{ },
 };
 
-- 
2.31.1

Re: [RFC 5/5] ipmi:bt-bmc: Add Microwatt

From: Joel Stanley <joel@jms.id.au>
Date: 2021-10-06 02:36:49

Hi Anton,

On Wed, 6 Oct 2021 at 02:12, Anton Blanchard [off-list ref] wrote:
This adds the Microwatt specific bits, including interrupt support.
The series looks good.

I've got a couple of patches on the ipmi list that this will conflict with:

 https://sourceforge.net/p/openipmi/mailman/message/37345391/
 https://lore.kernel.org/all/20210903015314.177987-1-joel@jms.id.au/

If there's no feedback from others I suggest basing your series on top
of those, and sending them to Corey on the ipmi list to merge.

Cheers,

Joel
quoted hunk
Signed-off-by: Anton Blanchard <redacted>
---
 .../devicetree/bindings/ipmi/ibt-bmc.txt      |  1 +
 drivers/char/ipmi/Kconfig                     |  8 ++-
 drivers/char/ipmi/bt-bmc.c                    | 69 +++++++++++++++++++
 3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 78ee716a950e..1b661daf0193 100644
--- a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -9,6 +9,7 @@ Required properties:
 - compatible : should be one of
        "aspeed,ast2400-ibt-bmc"
        "aspeed,ast2500-ibt-bmc"
+       "ibm,microwatt-ibt-bmc"
 - reg: physical address and size of the registers

 Optional properties:
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 8b2f0f675e5f..079302f4eef2 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
          called kcs_bmc_serio.

 config BT_IPMI_BMC
-       depends on ARCH_ASPEED || COMPILE_TEST
+       depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
        depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
        tristate "BT IPMI bmc driver"
        help
          Provides a driver for the BT (Block Transfer) IPMI interface
-         found on Aspeed SOCs (AST2400 and AST2500). The driver
-         implements the BMC side of the BT interface.
+         found on Aspeed SOCs (AST2400 and AST2500) as well as the OpenPOWER
+         LPC peripheral macro at
+         <https://github.com/OpenPOWERFoundation/lpcperipheral>
+         The driver implements the BMC side of the BT interface.

 config IPMB_DEVICE_INTERFACE
        tristate 'IPMB Interface handler'
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b48e04405ac4..24327b57c60b 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -41,6 +41,11 @@
 #define   BT_CR2_IRQ_HBUSY     0x40
 #define ASPEED_BT_CR3  0xc

+#define MICROWATT_IRQ_MASK     0x0
+#define MICROWATT_IRQ_STATUS   0x4
+#define   IRQ_HOST_TO_BMC_ATTN 0x1
+#define   IRQ_HOST_NOT_BUSY    0x2
+
 #define BT_CTRL                0x10
 #define   BT_CTRL_B_BUSY               0x80
 #define   BT_CTRL_H_BUSY               0x40
@@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }

+static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
+{
+       struct bt_bmc *bt_bmc = arg;
+       u32 reg;
+       int rc;
+
+       rc = regmap_read(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, &reg);
+       if (rc)
+               return IRQ_NONE;
+
+       /* Interrupt wasn't something we knew about */
+       if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
+               return IRQ_NONE;
+
+       /* ack all pending IRQs */
+       regmap_write(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, 0);
+
+       wake_up(&bt_bmc->queue);
+       return IRQ_HANDLED;
+}
+
 static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
                             struct platform_device *pdev)
 {
@@ -446,6 +472,48 @@ static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
        .enable_bt = aspeed_enable_bt,
 };

+static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+                            struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       int rc;
+
+       bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+       if (bt_bmc->irq < 0)
+               return bt_bmc->irq;
+
+       rc = devm_request_irq(dev, bt_bmc->irq, microwatt_bt_bmc_irq, IRQF_SHARED,
+                             DEVICE_NAME, bt_bmc);
+       if (rc < 0) {
+               dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
+               bt_bmc->irq = rc;
+               return rc;
+       }
+
+       /*
+        * Configure the hardware to give us an interrupt whenever the H2B
+        * bit is set or the HBUSY bit is cleared.
+        *
+        * H2B will be asserted when the bmc has data for us; HBUSY
+        * will be cleared (along with B2H) when we can write the next
+        * message to the BT buffer
+        */
+       rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_MASK,
+                               (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY),
+                               (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY));
+
+       return rc;
+}
+
+static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
+{
+}
+
+static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
+       .config_irq = microwatt_bt_bmc_config_irq,
+       .enable_bt = microwatt_enable_bt,
+};
+
 static int bt_bmc_probe(struct platform_device *pdev)
 {
        struct bt_bmc *bt_bmc;
@@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
 static const struct of_device_id bt_bmc_match[] = {
        { .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
        { .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+       { .compatible = "ibm,microwatt-ibt-bmc", .data = &microwatt_bt_bmc_ops },
        { },
 };

--
2.31.1

Re: [RFC 5/5] ipmi:bt-bmc: Add Microwatt

From: Anton Blanchard <hidden>
Date: 2021-10-06 03:07:33

Hi Joel,
The series looks good.

I've got a couple of patches on the ipmi list that this will conflict
with:

 https://sourceforge.net/p/openipmi/mailman/message/37345391/
 https://lore.kernel.org/all/20210903015314.177987-1-joel@jms.id.au/

If there's no feedback from others I suggest basing your series on top
of those, and sending them to Corey on the ipmi list to merge.
Looks good, will do.

Thanks,
Anton
Cheers,

Joel
quoted
Signed-off-by: Anton Blanchard <redacted>
---
 .../devicetree/bindings/ipmi/ibt-bmc.txt      |  1 +
 drivers/char/ipmi/Kconfig                     |  8 ++-
 drivers/char/ipmi/bt-bmc.c                    | 69
+++++++++++++++++++ 3 files changed, 75 insertions(+), 3
deletions(-)
diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt index
78ee716a950e..1b661daf0193 100644 ---
a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt +++
b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt @@ -9,6 +9,7
@@ Required properties:
 - compatible : should be one of
        "aspeed,ast2400-ibt-bmc"
        "aspeed,ast2500-ibt-bmc"
+       "ibm,microwatt-ibt-bmc"
 - reg: physical address and size of the registers

 Optional properties:
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 8b2f0f675e5f..079302f4eef2 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
          called kcs_bmc_serio.

 config BT_IPMI_BMC
-       depends on ARCH_ASPEED || COMPILE_TEST
+       depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
        depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
        tristate "BT IPMI bmc driver"
        help
          Provides a driver for the BT (Block Transfer) IPMI
interface
-         found on Aspeed SOCs (AST2400 and AST2500). The driver
-         implements the BMC side of the BT interface.
+         found on Aspeed SOCs (AST2400 and AST2500) as well as the
OpenPOWER
+         LPC peripheral macro at
+         <https://github.com/OpenPOWERFoundation/lpcperipheral>
+         The driver implements the BMC side of the BT interface.

 config IPMB_DEVICE_INTERFACE
        tristate 'IPMB Interface handler'
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b48e04405ac4..24327b57c60b 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -41,6 +41,11 @@
 #define   BT_CR2_IRQ_HBUSY     0x40
 #define ASPEED_BT_CR3  0xc

+#define MICROWATT_IRQ_MASK     0x0
+#define MICROWATT_IRQ_STATUS   0x4
+#define   IRQ_HOST_TO_BMC_ATTN 0x1
+#define   IRQ_HOST_NOT_BUSY    0x2
+
 #define BT_CTRL                0x10
 #define   BT_CTRL_B_BUSY               0x80
 #define   BT_CTRL_H_BUSY               0x40
@@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq,
void *arg) return IRQ_HANDLED;
 }

+static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
+{
+       struct bt_bmc *bt_bmc = arg;
+       u32 reg;
+       int rc;
+
+       rc = regmap_read(bt_bmc->map, bt_bmc->offset +
MICROWATT_IRQ_STATUS, &reg);
+       if (rc)
+               return IRQ_NONE;
+
+       /* Interrupt wasn't something we knew about */
+       if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
+               return IRQ_NONE;
+
+       /* ack all pending IRQs */
+       regmap_write(bt_bmc->map, bt_bmc->offset +
MICROWATT_IRQ_STATUS, 0); +
+       wake_up(&bt_bmc->queue);
+       return IRQ_HANDLED;
+}
+
 static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
                             struct platform_device *pdev)
 {
@@ -446,6 +472,48 @@ static const struct bt_bmc_ops
aspeed_bt_bmc_ops = { .enable_bt = aspeed_enable_bt,
 };

+static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+                            struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       int rc;
+
+       bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+       if (bt_bmc->irq < 0)
+               return bt_bmc->irq;
+
+       rc = devm_request_irq(dev, bt_bmc->irq,
microwatt_bt_bmc_irq, IRQF_SHARED,
+                             DEVICE_NAME, bt_bmc);
+       if (rc < 0) {
+               dev_warn(dev, "Unable to request IRQ %d\n",
bt_bmc->irq);
+               bt_bmc->irq = rc;
+               return rc;
+       }
+
+       /*
+        * Configure the hardware to give us an interrupt whenever
the H2B
+        * bit is set or the HBUSY bit is cleared.
+        *
+        * H2B will be asserted when the bmc has data for us; HBUSY
+        * will be cleared (along with B2H) when we can write the
next
+        * message to the BT buffer
+        */
+       rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset +
MICROWATT_IRQ_MASK,
+                               (IRQ_HOST_TO_BMC_ATTN |
IRQ_HOST_NOT_BUSY),
+                               (IRQ_HOST_TO_BMC_ATTN |
IRQ_HOST_NOT_BUSY)); +
+       return rc;
+}
+
+static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
+{
+}
+
+static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
+       .config_irq = microwatt_bt_bmc_config_irq,
+       .enable_bt = microwatt_enable_bt,
+};
+
 static int bt_bmc_probe(struct platform_device *pdev)
 {
        struct bt_bmc *bt_bmc;
@@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device
*pdev) static const struct of_device_id bt_bmc_match[] = {
        { .compatible = "aspeed,ast2400-ibt-bmc", .data =
&aspeed_bt_bmc_ops }, { .compatible = "aspeed,ast2500-ibt-bmc",
.data = &aspeed_bt_bmc_ops },
+       { .compatible = "ibm,microwatt-ibt-bmc", .data =
&microwatt_bt_bmc_ops }, { },
 };

--
2.31.1
 

Re: [RFC 3/5] ipmi:bt-bmc: Put arch specific function into bt_bmc_ops

From: Cédric Le Goater <clg@kaod.org>
Date: 2021-10-06 06:02:33

On 10/6/21 04:12, Anton Blanchard wrote:
While most of the driver is arch agnostic, setting up and handling
interrupts, and enabling the hardware is not. Create bt_bmc_ops to
handle these functions.

Signed-off-by: Anton Blanchard <redacted>
See comment on patch 5. Any how,

Reviewed-by: Cédric Le Goater <clg@kaod.org>

Thanks

C.
quoted hunk
---
  drivers/char/ipmi/bt-bmc.c | 24 ++++++++++++++++++++----
  1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 2b0fe1255026..b48e04405ac4 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -17,6 +17,7 @@
  #include <linux/regmap.h>
  #include <linux/sched.h>
  #include <linux/timer.h>
+#include <linux/of_device.h>
  
  /*
   * This is a BMC device used to communicate to the host
@@ -435,15 +436,30 @@ static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
  		     BT_CR0_ENABLE_IBT);
  }
  
+struct bt_bmc_ops {
+	int (*config_irq)(struct bt_bmc *bt_bmc, struct platform_device *pdev);
+	void (*enable_bt)(struct bt_bmc *bt_bmc);
+};
+
+static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
+	.config_irq = aspeed_bt_bmc_config_irq,
+	.enable_bt = aspeed_enable_bt,
+};
+
  static int bt_bmc_probe(struct platform_device *pdev)
  {
  	struct bt_bmc *bt_bmc;
  	struct device *dev;
  	int rc;
+	const struct bt_bmc_ops *ops;
  
  	dev = &pdev->dev;
  	dev_info(dev, "Found bt bmc device\n");
  
+	ops = of_device_get_match_data(&pdev->dev);
+	if (!ops)
+		return -ENODEV;
+
  	bt_bmc = devm_kzalloc(dev, sizeof(*bt_bmc), GFP_KERNEL);
  	if (!bt_bmc)
  		return -ENOMEM;
@@ -483,7 +499,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
  		return rc;
  	}
  
-	aspeed_bt_bmc_config_irq(bt_bmc, pdev);
+	ops->config_irq(bt_bmc, pdev);
  
  	if (bt_bmc->irq >= 0) {
  		dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -494,7 +510,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
  		add_timer(&bt_bmc->poll_timer);
  	}
  
-	aspeed_enable_bt(bt_bmc);
+	ops->enable_bt(bt_bmc);
  
  	clr_b_busy(bt_bmc);
  
@@ -512,8 +528,8 @@ static int bt_bmc_remove(struct platform_device *pdev)
  }
  
  static const struct of_device_id bt_bmc_match[] = {
-	{ .compatible = "aspeed,ast2400-ibt-bmc" },
-	{ .compatible = "aspeed,ast2500-ibt-bmc" },
+	{ .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+	{ .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
  	{ },
  };
  

Re: [RFC 5/5] ipmi:bt-bmc: Add Microwatt

From: Cédric Le Goater <clg@kaod.org>
Date: 2021-10-06 06:08:29

On 10/6/21 04:12, Anton Blanchard wrote:
quoted hunk
This adds the Microwatt specific bits, including interrupt support.

Signed-off-by: Anton Blanchard <redacted>
---
  .../devicetree/bindings/ipmi/ibt-bmc.txt      |  1 +
  drivers/char/ipmi/Kconfig                     |  8 ++-
  drivers/char/ipmi/bt-bmc.c                    | 69 +++++++++++++++++++
  3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 78ee716a950e..1b661daf0193 100644
--- a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -9,6 +9,7 @@ Required properties:
  - compatible : should be one of
  	"aspeed,ast2400-ibt-bmc"
  	"aspeed,ast2500-ibt-bmc"
+	"ibm,microwatt-ibt-bmc"
  - reg: physical address and size of the registers
  
  Optional properties:
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 8b2f0f675e5f..079302f4eef2 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
  	  called kcs_bmc_serio.
  
  config BT_IPMI_BMC
-	depends on ARCH_ASPEED || COMPILE_TEST
+	depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
  	depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
  	tristate "BT IPMI bmc driver"
  	help
  	  Provides a driver for the BT (Block Transfer) IPMI interface
-	  found on Aspeed SOCs (AST2400 and AST2500). The driver
-	  implements the BMC side of the BT interface.
+	  found on Aspeed SOCs (AST2400 and AST2500) as well as the OpenPOWER
+	  LPC peripheral macro at
+	  <https://github.com/OpenPOWERFoundation/lpcperipheral>
+	  The driver implements the BMC side of the BT interface.
  
  config IPMB_DEVICE_INTERFACE
  	tristate 'IPMB Interface handler'
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b48e04405ac4..24327b57c60b 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -41,6 +41,11 @@
  #define   BT_CR2_IRQ_HBUSY	0x40
  #define ASPEED_BT_CR3	0xc
  
+#define MICROWATT_IRQ_MASK	0x0
+#define MICROWATT_IRQ_STATUS	0x4
+#define   IRQ_HOST_TO_BMC_ATTN	0x1
+#define   IRQ_HOST_NOT_BUSY	0x2
+
  #define BT_CTRL		0x10
  #define   BT_CTRL_B_BUSY		0x80
  #define   BT_CTRL_H_BUSY		0x40
@@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
  	return IRQ_HANDLED;
  }
  
+static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
+{
+	struct bt_bmc *bt_bmc = arg;
+	u32 reg;
+	int rc;
+
+	rc = regmap_read(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, &reg);
+	if (rc)
+		return IRQ_NONE;
+
+	/* Interrupt wasn't something we knew about */
+	if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
+		return IRQ_NONE;
+
+	/* ack all pending IRQs */
+	regmap_write(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, 0);
+
+	wake_up(&bt_bmc->queue);
+	return IRQ_HANDLED;
+}
+
  static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
  			     struct platform_device *pdev)
  {
@@ -446,6 +472,48 @@ static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
  	.enable_bt = aspeed_enable_bt,
  };
  
+static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+			     struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int rc;
+
+	bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+	if (bt_bmc->irq < 0)
+		return bt_bmc->irq;
+
+	rc = devm_request_irq(dev, bt_bmc->irq, microwatt_bt_bmc_irq, IRQF_SHARED,
+			      DEVICE_NAME, bt_bmc);
+	if (rc < 0) {
+		dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
+		bt_bmc->irq = rc;
+		return rc;
+	}
+
+	/*
+	 * Configure the hardware to give us an interrupt whenever the H2B
+	 * bit is set or the HBUSY bit is cleared.
+	 *
+	 * H2B will be asserted when the bmc has data for us; HBUSY
+	 * will be cleared (along with B2H) when we can write the next
+	 * message to the BT buffer
+	 */
+	rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_MASK,
+				(IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY),
+				(IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY));
This is the only difference. May be we could introduce a ->config_irq_hw()
handler to keep a larger part common. No big deal.

Reviewed-by: Cédric Le Goater <clg@kaod.org>

C.

quoted hunk
+	return rc;
+}
+
+static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
+{
+}
+
+static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
+	.config_irq = microwatt_bt_bmc_config_irq,
+	.enable_bt = microwatt_enable_bt,
+};
+
  static int bt_bmc_probe(struct platform_device *pdev)
  {
  	struct bt_bmc *bt_bmc;
@@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
  static const struct of_device_id bt_bmc_match[] = {
  	{ .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
  	{ .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+	{ .compatible = "ibm,microwatt-ibt-bmc", .data = &microwatt_bt_bmc_ops },
  	{ },
  };
  

Re: [RFC 1/5] ipmi:bt-bmc: Separate out ASPEED specific bits

From: Cédric Le Goater <clg@kaod.org>
Date: 2021-10-06 06:28:44

On 10/6/21 04:12, Anton Blanchard wrote:
Most of the IPMI BT BMC driver is architecture agnostic - it deals with
architected registers and behaviour in the IPMI specification.

Separate out the few ASPEED specific bits into their own functions
so we can use this driver on other architectures.

Signed-off-by: Anton Blanchard <redacted>
Reviewed-by: Cédric Le Goater <clg@kaod.org>

Thanks,

C.
quoted hunk
---
  drivers/char/ipmi/bt-bmc.c | 26 ++++++++++++++++----------
  1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 6e3d247b55d1..f85fafc96ef6 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -39,6 +39,7 @@
  #define   BT_CR2_IRQ_H2B	0x01
  #define   BT_CR2_IRQ_HBUSY	0x40
  #define BT_CR3		0xc
+
  #define BT_CTRL		0x10
  #define   BT_CTRL_B_BUSY		0x80
  #define   BT_CTRL_H_BUSY		0x40
@@ -372,7 +373,7 @@ static void poll_timer(struct timer_list *t)
  	add_timer(&bt_bmc->poll_timer);
  }
  
-static irqreturn_t bt_bmc_irq(int irq, void *arg)
+static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
  {
  	struct bt_bmc *bt_bmc = arg;
  	u32 reg;
@@ -393,7 +394,7 @@ static irqreturn_t bt_bmc_irq(int irq, void *arg)
  	return IRQ_HANDLED;
  }
  
-static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
  			     struct platform_device *pdev)
  {
  	struct device *dev = &pdev->dev;
@@ -403,7 +404,7 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
  	if (bt_bmc->irq < 0)
  		return bt_bmc->irq;
  
-	rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
+	rc = devm_request_irq(dev, bt_bmc->irq, aspeed_bt_bmc_irq, IRQF_SHARED,
  			      DEVICE_NAME, bt_bmc);
  	if (rc < 0) {
  		dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
@@ -424,6 +425,16 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
  	return rc;
  }
  
+static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
+{
+	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
+		     (BT_IO_BASE << BT_CR0_IO_BASE) |
+		     (BT_IRQ << BT_CR0_IRQ) |
+		     BT_CR0_EN_CLR_SLV_RDP |
+		     BT_CR0_EN_CLR_SLV_WRP |
+		     BT_CR0_ENABLE_IBT);
+}
+
  static int bt_bmc_probe(struct platform_device *pdev)
  {
  	struct bt_bmc *bt_bmc;
@@ -472,7 +483,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
  		return rc;
  	}
  
-	bt_bmc_config_irq(bt_bmc, pdev);
+	aspeed_bt_bmc_config_irq(bt_bmc, pdev);
  
  	if (bt_bmc->irq >= 0) {
  		dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -483,12 +494,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
  		add_timer(&bt_bmc->poll_timer);
  	}
  
-	regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
-		     (BT_IO_BASE << BT_CR0_IO_BASE) |
-		     (BT_IRQ << BT_CR0_IRQ) |
-		     BT_CR0_EN_CLR_SLV_RDP |
-		     BT_CR0_EN_CLR_SLV_WRP |
-		     BT_CR0_ENABLE_IBT);
+	aspeed_enable_bt(bt_bmc);
  
  	clr_b_busy(bt_bmc);
  

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help