[PATCH 4/4] ipmi: bt-bmc: Read LPC address and SerIRQ from device tree
From: Yu-Che Hsieh via B4 Relay
Date: Mon Jun 29 2026 - 02:53:37 EST
From: Yu-Che Hsieh <yc_hsieh@xxxxxxxxxxxxxx>
The BT interface currently programs a fixed host LPC IO address and
SerIRQ number. This works for the existing single-channel setup, but
does not allow the host interface parameters to be described by firmware.
Read the LPC IO address from aspeed,lpc-io-reg and the SerIRQ number
and interrupt type from aspeed,lpc-interrupts. Keep the existing IO
address, SerIRQ number, and level-low interrupt type as defaults when
the properties are not present.
Signed-off-by: Yu-Che Hsieh <yc_hsieh@xxxxxxxxxxxxxx>
---
drivers/char/ipmi/bt-bmc.c | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 486ecc0b6815..6e1f941e63db 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -65,6 +65,12 @@ struct bt_bmc {
struct timer_list poll_timer;
struct mutex mutex;
atomic_t open_count;
+ u32 io_addr;
+
+ struct {
+ u32 id;
+ u32 type;
+ } sirq;
};
static u8 bt_inb(struct bt_bmc *bt_bmc, int reg)
@@ -429,6 +435,33 @@ static int bt_bmc_probe(struct platform_device *pdev)
mutex_init(&bt_bmc->mutex);
init_waitqueue_head(&bt_bmc->queue);
+ rc = of_property_read_u32(dev->of_node, "aspeed,lpc-io-reg",
+ &bt_bmc->io_addr);
+ if (rc) {
+ bt_bmc->io_addr = BT_IO_BASE;
+ } else if (bt_bmc->io_addr > FIELD_MAX(BT_CR0_IO_BASE)) {
+ dev_err(dev, "invalid LPC IO address\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(dev->of_node, "aspeed,lpc-interrupts",
+ (u32 *)&bt_bmc->sirq, 2);
+ if (rc) {
+ bt_bmc->sirq.id = BT_IRQ;
+ bt_bmc->sirq.type = IRQ_TYPE_LEVEL_LOW;
+ } else {
+ if (bt_bmc->sirq.id > FIELD_MAX(BT_CR0_SIRQ)) {
+ dev_err(dev, "invalid SerIRQ number\n");
+ return -EINVAL;
+ }
+
+ if (bt_bmc->sirq.type != IRQ_TYPE_LEVEL_HIGH &&
+ bt_bmc->sirq.type != IRQ_TYPE_LEVEL_LOW) {
+ dev_err(dev, "invalid SerIRQ type\n");
+ return -EINVAL;
+ }
+ }
+
bt_bmc->miscdev.minor = MISC_DYNAMIC_MINOR;
bt_bmc->miscdev.name = DEVICE_NAME;
bt_bmc->miscdev.fops = &bt_bmc_fops;
@@ -450,8 +483,10 @@ static int bt_bmc_probe(struct platform_device *pdev)
add_timer(&bt_bmc->poll_timer);
}
- writel(FIELD_PREP(BT_CR0_IO_BASE, BT_IO_BASE) |
- FIELD_PREP(BT_CR0_SIRQ, BT_IRQ) |
+ writel(FIELD_PREP(BT_CR0_IO_BASE, bt_bmc->io_addr) |
+ FIELD_PREP(BT_CR0_SIRQ, bt_bmc->sirq.id) |
+ FIELD_PREP(BT_CR0_SIRQ_TYPE,
+ bt_bmc->sirq.type == IRQ_TYPE_LEVEL_LOW ? 0 : 1) |
BT_CR0_EN_CLR_SLV_RDP |
BT_CR0_EN_CLR_SLV_WRP |
BT_CR0_ENABLE_IBT,
--
2.34.1