From 67c0472297b2c7baf87f84ed8c4572f60421d736 Mon Sep 17 00:00:00 2001 From: Peter Galka Date: Wed, 22 Oct 2025 08:10:16 +0200 Subject: [PATCH] drivers: spi: kbus: split interrupt handling Signed-off-by: Peter Galka --- arch/arm64/boot/dts/ti/k3-am62x-pfc.dtsi | 1 + drivers/spi/spi-kbus.c | 47 +++++++++++++++++++----- include/linux/spi/kbus.h | 1 + 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/ti/k3-am62x-pfc.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-pfc.dtsi index e81e78ce25fa..ec0fb9c27485 100644 --- a/arch/arm64/boot/dts/ti/k3-am62x-pfc.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62x-pfc.dtsi @@ -743,6 +743,7 @@ spi-max-frequency = <10000000>; kbus,reset-on-boot; + kbus,renesas; /* * kbus,cmdsel-gpio is used to signal the need for an update diff --git a/drivers/spi/spi-kbus.c b/drivers/spi/spi-kbus.c index 2f1a1bbc3c6c..f2f41de82d8b 100644 --- a/drivers/spi/spi-kbus.c +++ b/drivers/spi/spi-kbus.c @@ -37,6 +37,8 @@ #define KBUS_DUMMY_BIT_PER_WORD 8 #define KBUS_DUMMY_SPEED 1000000 +#define KBUS_CMD_UPDATE 0xa3 + #if KBUS_TESTING struct wago_trace_data wago_ktest; #endif @@ -107,7 +109,21 @@ int kbus_wait_for_event(int *event) return 0; } -static irqreturn_t kbus_isr(int irq, void *dev) +static irqreturn_t kbus_infineon_isr(int irq, void *dev) +{ + struct kbus_drv_data *kdrvdata = dev_get_drvdata(kbus_device); + + trace_pxc_kbus(__func__, "kbus-irq:in"); + kdrvdata->kbus_irq_state = 0; /* attention: changed polarisation */ + + /* wake_up_interruptible(&kdrvdata->kbus_irq_wq); */ + wake_up(&kdrvdata->kbus_irq_wq); + + trace_pxc_kbus(__func__, "kbus-irq:out"); + return IRQ_HANDLED; +} + +static irqreturn_t kbus_renesas_isr(int irq, void *dev) { struct kbus_drv_data *kdrvdata = dev_get_drvdata(kbus_device); @@ -664,7 +680,7 @@ static long kbus_ioctl(struct file *file, uint cmd, ulong arg) case KBUS_IOC_CMD: /* FIXME */ { struct kbus_cmd kcmd; - struct kbus_cmd __user *kcmd_user; + struct kbus_cmd __user *kcmd_user = (struct kbus_cmd __user *)arg; trace_pxc_kbus(__func__, "KCMD: Enter: Set kbus_irq_state to 1."); @@ -679,19 +695,21 @@ static long kbus_ioctl(struct file *file, uint cmd, ulong arg) /* Indicate Transfer Start */ gpiod_set_value(kdrvdata->gpio_nirq, 0); - kcmd_user = (struct kbus_cmd __user *)arg; - - if ((int)*kcmd_user->tx_buf == 0xA3) { - kdrvdata->kbus_ign_irq = 1; - trace_pxc_kbus(__func__, "KCMD: A3: Update cmd"); - } - if (copy_from_user(&kcmd, kcmd_user, sizeof(kcmd))) { /* release the irq pin */ gpiod_set_value(kdrvdata->gpio_nirq, 1); return -EFAULT; } + u8 tx_byte; + if (!copy_from_user(&tx_byte, kcmd.tx_buf, sizeof(tx_byte))) { + if ((int)tx_byte == KBUS_CMD_UPDATE) { + kdrvdata->kbus_ign_irq = 1; + trace_pxc_kbus(__func__, "KCMD: Update cmd (0xa3)"); + pr_info("%s: KCMD: Update cmd (0xa3)\n", __func__); + } + } + ret = kbus_cmd_txrx(&kcmd); if (ret < 0) { /* release the irq pin */ @@ -1100,6 +1118,8 @@ static struct kbus_drv_data *kbus_probe_dt(struct spi_device *spi) } } + kdrvdata->kbus_renesas = of_property_read_bool(np, "kbus,renesas"); + kdrvdata->kbus_irq = gpiod_to_irq(kdrvdata->gpio_nrdy); kdrvdata->spi = spi; @@ -1127,6 +1147,7 @@ static int kbus_probe(struct spi_device *spi) int ret = 0; u8 save = 0; struct kbus_drv_data *kdrvdata; + irqreturn_t (*kbus_isr)(int, void *); if (!spi->dev.of_node) { pr_err("WAGO KBUS Driver: No DT node found!\n"); @@ -1139,6 +1160,14 @@ static int kbus_probe(struct spi_device *spi) init_waitqueue_head(&kdrvdata->kbus_irq_wq); + if (kdrvdata->kbus_renesas) + kbus_isr = kbus_renesas_isr; + else + kbus_isr = kbus_infineon_isr; + + pr_info("%s: %s is used\n", __func__, kdrvdata->kbus_renesas? + "renesas" : "infineon"); + ret = request_irq(kdrvdata->kbus_irq, kbus_isr, IRQF_SHARED | IRQ_TYPE_EDGE_BOTH, "kbus", &kbus_dev); diff --git a/include/linux/spi/kbus.h b/include/linux/spi/kbus.h index 4b3612d858f2..6a05735ad454 100644 --- a/include/linux/spi/kbus.h +++ b/include/linux/spi/kbus.h @@ -98,6 +98,7 @@ struct kbus_drv_data { wait_queue_head_t kbus_irq_wq; struct spi_device *spi; const char *kbus_tty_device_name; + bool kbus_renesas; }; /* For userspace ioctl communication */