From 77d47dc85c8b1d33e7aaa9659b557889740722e0 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Mon, 1 Jun 2026 14:32:17 -0700 Subject: [PATCH 01/10] extcon: Add STM32 SPI IPC driver Add a custom SPI client driver that functions as an extcon event provider. This driver communicates with an external STM32 co-processor over SPI using an attention line (interrupt) to propagate USB cable events. It registers separate virtual extcon sub-devices for each connector, allowing ChipIdea OTG controllers to switch between Host/Peripheral roles. A debugfs simulation interface is also exposed for runtime testing. --- drivers/extcon/Kconfig | 7 + drivers/extcon/Makefile | 1 + drivers/extcon/extcon-stm32-ipc.c | 292 ++++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 drivers/extcon/extcon-stm32-ipc.c diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index cf472e44c5ff9..8852425b68fba 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -176,6 +176,13 @@ config EXTCON_USB_GPIO Say Y here to enable GPIO based USB cable detection extcon support. Used typically if GPIO is used for USB ID pin detection. +config EXTCON_STM32_SPI_IPC + tristate "STM32 SPI IPC and Virtual Extcon support" + depends on SPI + help + Say Y here to enable the STM32 to i.MX8MM SPI IPC and Virtual Extcon + driver, which handles USB connection/cable event notifications over SPI. + config EXTCON_USBC_CROS_EC tristate "ChromeOS Embedded Controller EXTCON support" depends on CROS_EC diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 1b390d934ca92..b962d043fd804 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -23,5 +23,6 @@ obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o +obj-$(CONFIG_EXTCON_STM32_SPI_IPC) += extcon-stm32-ipc.o obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c new file mode 100644 index 0000000000000..ad70407cbb0c7 --- /dev/null +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * drivers/extcon/extcon-stm32-ipc.c - STM32 SPI IPC and Virtual Extcon Driver + * + * Copyright (C) 2026 MultiTracks + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "stm-spi-ipc" + +/* Protocol constants */ +#define STM_IPC_MSG_MAGIC 0x5A +#define MSG_TYPE_USB_EVENT 0x01 + +struct stm_ipc_packet { + u8 magic; + u8 type; + u8 length; + u8 port; + u8 state; /* 0 = disconnected, 1 = peripheral (VBUS), 2 = host (ID) */ + u8 crc; +} __packed; + +/* Parent SPI controller private structure */ +struct stm_ipc_priv { + struct spi_device *spi; + struct mutex lock; + struct dentry *debugfs_root; +}; + +/* Child connector platform device private structure */ +struct stm_connector_priv { + struct extcon_dev *edev; + u32 port_id; +}; + +static const unsigned int stm_usb_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +/* Helper to update extcon state based on STM32 reporting */ +static void stm_ipc_update_state(struct extcon_dev *edev, u8 state) +{ + switch (state) { + case 0: /* Disconnected */ + extcon_set_state_sync(edev, EXTCON_USB, false); + extcon_set_state_sync(edev, EXTCON_USB_HOST, false); + break; + case 1: /* Peripheral Mode (VBUS present) */ + extcon_set_state_sync(edev, EXTCON_USB_HOST, false); + extcon_set_state_sync(edev, EXTCON_USB, true); + break; + case 2: /* Host Mode (ID ground) */ + extcon_set_state_sync(edev, EXTCON_USB, false); + extcon_set_state_sync(edev, EXTCON_USB_HOST, true); + break; + default: + break; + } +} + +/* Callback used to find and update state of correct child platform device */ +static int match_and_update_state(struct device *dev, void *data) +{ + struct stm_connector_priv *priv = dev_get_drvdata(dev); + u8 *port_info = data; + u8 port_id = port_info[0]; + u8 state = port_info[1]; + + if (priv && priv->port_id == port_id) { + stm_ipc_update_state(priv->edev, state); + return 1; /* Found and processed, stop iteration */ + } + return 0; +} + +/* Threaded IRQ Handler (safe to perform sleeping SPI transfers) */ +static irqreturn_t stm_ipc_threaded_irq(int irq, void *dev_id) +{ + struct stm_ipc_priv *priv = dev_id; + struct stm_ipc_packet tx_buf = {0}; + struct stm_ipc_packet rx_buf = {0}; + struct spi_transfer t = { + .tx_buf = &tx_buf, + .rx_buf = &rx_buf, + .len = sizeof(struct stm_ipc_packet), + }; + struct spi_message m; + int ret; + + mutex_lock(&priv->lock); + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(priv->spi, &m); + if (ret < 0) { + dev_err(&priv->spi->dev, "SPI sync transfer failed: %d\n", ret); + goto out; + } + + /* Validate packet */ + if (rx_buf.magic != STM_IPC_MSG_MAGIC) { + dev_warn_ratelimited(&priv->spi->dev, "Invalid magic byte: 0x%02x\n", rx_buf.magic); + goto out; + } + + /* Process USB event */ + if (rx_buf.type == MSG_TYPE_USB_EVENT) { + u8 port_info[2] = { rx_buf.port, rx_buf.state }; + + dev_info(&priv->spi->dev, "USB Event from STM32 on Port %d: State %d\n", rx_buf.port, rx_buf.state); + device_for_each_child(&priv->spi->dev, port_info, match_and_update_state); + } + +out: + mutex_unlock(&priv->lock); + return IRQ_HANDLED; +} + +/* Debugfs Simulation Entry (for mocking events) */ +static int stm_ipc_sim_write(void *data, u64 val) +{ + struct stm_connector_priv *priv = data; + + if (val > 2) + return -EINVAL; + + stm_ipc_update_state(priv->edev, (u8)val); + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(stm_ipc_sim_fops, NULL, stm_ipc_sim_write, "%llu\n"); + +/* Child Connector Platform Device Probe */ +static int stm_usb_connector_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct stm_connector_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = of_property_read_u32(dev->of_node, "port-id", &priv->port_id); + if (ret) { + dev_err(dev, "Missing 'port-id' property\n"); + return ret; + } + + priv->edev = devm_extcon_dev_allocate(dev, stm_usb_cable); + if (IS_ERR(priv->edev)) + return PTR_ERR(priv->edev); + + ret = devm_extcon_dev_register(dev, priv->edev); + if (ret) { + dev_err(dev, "Failed to register extcon device: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, priv); + + /* Set up DebugFS for this virtual connector for runtime simulation */ + struct stm_ipc_priv *parent_priv = dev_get_drvdata(dev->parent); + if (parent_priv && parent_priv->debugfs_root) { + char name[32]; + snprintf(name, sizeof(name), "usb%d_sim", priv->port_id + 1); + debugfs_create_file(name, 0200, parent_priv->debugfs_root, priv, &stm_ipc_sim_fops); + } + + dev_info(dev, "Registered virtual USB connector on Port %d\n", priv->port_id); + return 0; +} + +static const struct of_device_id stm_usb_connector_of_match[] = { + { .compatible = "multitracks,stm32-usb-connector" }, + { } +}; +MODULE_DEVICE_TABLE(of, stm_usb_connector_of_match); + +static struct platform_driver stm_usb_connector_driver = { + .probe = stm_usb_connector_probe, + .driver = { + .name = "stm32-usb-connector", + .of_match_table = stm_usb_connector_of_match, + }, +}; + +/* Parent SPI Driver Probe */ +static int stm_ipc_probe(struct spi_device *spi) +{ + struct stm_ipc_priv *priv; + int ret; + + priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->spi = spi; + mutex_init(&priv->lock); + spi_set_drvdata(spi, priv); + + /* Initialize DebugFS root directory under /sys/kernel/debug/stm_ipc */ + priv->debugfs_root = debugfs_create_dir("stm_ipc", NULL); + + /* Populate subnodes as platform devices (this probes the connector sub-drivers) */ + ret = devm_of_platform_populate(&spi->dev); + if (ret) { + dev_err(&spi->dev, "Failed to populate child connectors: %d\n", ret); + goto err_debugfs; + } + + /* Request Attention Pin Interrupt */ + if (spi->irq > 0) { + ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, + stm_ipc_threaded_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + DRIVER_NAME, priv); + if (ret) { + dev_err(&spi->dev, "Failed to request threaded IRQ: %d\n", ret); + goto err_debugfs; + } + } + + dev_info(&spi->dev, "STM32 SPI IPC Core initialized\n"); + return 0; + +err_debugfs: + debugfs_remove_recursive(priv->debugfs_root); + return ret; +} + +static void stm_ipc_remove(struct spi_device *spi) +{ + struct stm_ipc_priv *priv = spi_get_drvdata(spi); + debugfs_remove_recursive(priv->debugfs_root); +} + +static const struct of_device_id stm_ipc_of_match[] = { + { .compatible = "multitracks,stm32-spi-ipc" }, + { } +}; +MODULE_DEVICE_TABLE(of, stm_ipc_of_match); + +static struct spi_driver stm_ipc_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = stm_ipc_of_match, + }, + .probe = stm_ipc_probe, + .remove = stm_ipc_remove, +}; + +static int __init stm_ipc_init(void) +{ + int ret; + + ret = spi_register_driver(&stm_ipc_driver); + if (ret) + return ret; + + ret = platform_driver_register(&stm_usb_connector_driver); + if (ret) { + spi_unregister_driver(&stm_ipc_driver); + return ret; + } + + return 0; +} +static void __exit stm_ipc_exit(void) +{ + spi_unregister_driver(&stm_ipc_driver); + platform_driver_unregister(&stm_usb_connector_driver); +} + +module_init(stm_ipc_init); +module_exit(stm_ipc_exit); + +MODULE_AUTHOR("Samuel Morris "); +MODULE_DESCRIPTION("STM32 SPI IPC and virtual Extcon Driver"); +MODULE_LICENSE("GPL v2"); From a56401417f4c65a26d32900a932c52cb14888b26 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Mon, 1 Jun 2026 14:32:29 -0700 Subject: [PATCH 02/10] arm64: configs: Enable STM32 SPI IPC extcon driver Enable CONFIG_EXTCON_STM32_SPI_IPC in mt_connect_defconfig to compile the custom stm-spi-ipc extcon driver directly into the kernel. --- arch/arm64/configs/mt_connect_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mt_connect_defconfig b/arch/arm64/configs/mt_connect_defconfig index d8d9f9f621c08..6414223cf288a 100644 --- a/arch/arm64/configs/mt_connect_defconfig +++ b/arch/arm64/configs/mt_connect_defconfig @@ -652,6 +652,7 @@ CONFIG_FSL_QIXIS=y CONFIG_SOC_TI=y CONFIG_EXTCON_PTN5150=m CONFIG_EXTCON_USB_GPIO=y +CONFIG_EXTCON_STM32_SPI_IPC=y CONFIG_IIO=y CONFIG_FXLS8962AF_I2C=m CONFIG_IIO_ST_ACCEL_3AXIS=m From f2093d19b964b01f35f1a89589ca6cf22709e959 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Mon, 1 Jun 2026 14:32:39 -0700 Subject: [PATCH 03/10] arm64: dts: freescale: Add STM32 SPI IPC and extcon nodes Configure the ECSPI2 controller on mt-connect to support the STM32 SPI IPC slave node and its virtual USB connector child nodes. Bind &usbotg1 and &usbotg2 to their respective virtual extcon connectors and enable role switching. Set up pin control and active-low interrupt for GPIO2_IO11. --- arch/arm64/boot/dts/freescale/mt-connect.dts | 28 +++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/mt-connect.dts b/arch/arm64/boot/dts/freescale/mt-connect.dts index 49b02c88cba9d..949475cda4227 100644 --- a/arch/arm64/boot/dts/freescale/mt-connect.dts +++ b/arch/arm64/boot/dts/freescale/mt-connect.dts @@ -495,15 +495,29 @@ }; &ecspi2 { - status = "okay"; + #address-cells = <1>; + #size-cells = <0>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ecspi2>; + pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_stm_ipc>; cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + status = "okay"; - spidev1: spi@0 { + stm_ipc: stm32-ipc@0 { + compatible = "multitracks,stm32-spi-ipc"; reg = <0>; - compatible = "rohm,dh2228fv"; - spi-max-frequency = <500000>; + spi-max-frequency = <10000000>; + interrupt-parent = <&gpio2>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + + usb1_connector: connector-usb1 { + compatible = "multitracks,stm32-usb-connector"; + port-id = <0>; + }; + + usb2_connector: connector-usb2 { + compatible = "multitracks,stm32-usb-connector"; + port-id = <1>; + }; }; }; @@ -520,6 +534,7 @@ }; &usbotg1 { + extcon = <&usb1_connector>; hnp-disable; srp-disable; adp-disable; @@ -533,6 +548,7 @@ }; &usbotg2 { + extcon = <&usb2_connector>; hnp-disable; srp-disable; adp-disable; @@ -710,7 +726,7 @@ >; }; - pinctrl_typec1: typec1grp { + pinctrl_stm_ipc: stmipcgrp { fsl,pins = < MX8MM_IOMUXC_SD1_STROBE_GPIO2_IO11 0x159 >; From 4aec1db04c9833910642652f812069de3a45a9cb Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:34:42 -0700 Subject: [PATCH 04/10] extcon: Kconfig: select CRC8 and improve stm32-ipc help description --- drivers/extcon/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 8852425b68fba..910f1eb15b121 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -179,9 +179,11 @@ config EXTCON_USB_GPIO config EXTCON_STM32_SPI_IPC tristate "STM32 SPI IPC and Virtual Extcon support" depends on SPI + select CRC8 help - Say Y here to enable the STM32 to i.MX8MM SPI IPC and Virtual Extcon - driver, which handles USB connection/cable event notifications over SPI. + Say Y here to enable the STM32 SPI IPC and Virtual Extcon driver, + which handles USB connection/cable event notifications reported + by an external STM32 co-processor over SPI. config EXTCON_USBC_CROS_EC tristate "ChromeOS Embedded Controller EXTCON support" From ed4c8612d6de2bd57bbaea90c66b89e4ebc97600 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:35:26 -0700 Subject: [PATCH 05/10] extcon: stm32-ipc: remove unused GPIO header --- drivers/extcon/extcon-stm32-ipc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index ad70407cbb0c7..f899d5824230e 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include From 24dc94a0d1fda6e9f93e6ecf58f944e51c8ce6fa Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:35:27 -0700 Subject: [PATCH 06/10] extcon: stm32-ipc: fallback to safe disconnected state error --- drivers/extcon/extcon-stm32-ipc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index f899d5824230e..8df0c09fee12c 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -66,6 +66,10 @@ static void stm_ipc_update_state(struct extcon_dev *edev, u8 state) extcon_set_state_sync(edev, EXTCON_USB_HOST, true); break; default: + /* Fallback to safe disconnected state on protocol error */ + extcon_set_state_sync(edev, EXTCON_USB, false); + extcon_set_state_sync(edev, EXTCON_USB_HOST, false); + pr_warn_ratelimited("stm-spi-ipc: Invalid USB connector state: %u\n", state); break; } } From 764a575e2ae5c406d6930e35a715a07f2272b2b0 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:35:27 -0700 Subject: [PATCH 07/10] extcon: stm32-ipc: Use dev_dbg in threaded IRQ to avoid log flooding --- drivers/extcon/extcon-stm32-ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index 8df0c09fee12c..01c31f82d84a7 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -123,7 +123,7 @@ static irqreturn_t stm_ipc_threaded_irq(int irq, void *dev_id) if (rx_buf.type == MSG_TYPE_USB_EVENT) { u8 port_info[2] = { rx_buf.port, rx_buf.state }; - dev_info(&priv->spi->dev, "USB Event from STM32 on Port %d: State %d\n", rx_buf.port, rx_buf.state); + dev_dbg(&priv->spi->dev, "USB Event from STM32 on Port %d: State %d\n", rx_buf.port, rx_buf.state); device_for_each_child(&priv->spi->dev, port_info, match_and_update_state); } From 0c4f1715dceb6ed4cea7555ea0bbdb43261cce79 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:35:27 -0700 Subject: [PATCH 08/10] extcon: stm32-ipc: create per-device debugfs to avoid collisions --- drivers/extcon/extcon-stm32-ipc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index 01c31f82d84a7..6366d3a85dde9 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -214,8 +214,20 @@ static int stm_ipc_probe(struct spi_device *spi) mutex_init(&priv->lock); spi_set_drvdata(spi, priv); - /* Initialize DebugFS root directory under /sys/kernel/debug/stm_ipc */ - priv->debugfs_root = debugfs_create_dir("stm_ipc", NULL); + struct dentry *parent; + + /* Initialize DebugFS subdirectory under /sys/kernel/debug/stm_ipc/ */ + parent = debugfs_create_dir("stm_ipc", NULL); + if (IS_ERR_OR_NULL(parent)) { + dev_warn(&spi->dev, "Failed to create debugfs parent directory\n"); + priv->debugfs_root = NULL; + } else { + priv->debugfs_root = debugfs_create_dir(dev_name(&spi->dev), parent); + if (IS_ERR_OR_NULL(priv->debugfs_root)) { + dev_warn(&spi->dev, "Failed to create debugfs root directory\n"); + priv->debugfs_root = NULL; + } + } /* Populate subnodes as platform devices (this probes the connector sub-drivers) */ ret = devm_of_platform_populate(&spi->dev); From 887f1577be770f4df32529dfa278dea565c2538a Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:35:27 -0700 Subject: [PATCH 09/10] extcon: stm32-ipc: implement CRC-8/length validation on SPI packets --- drivers/extcon/extcon-stm32-ipc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index 6366d3a85dde9..2ba47f957db1b 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -14,6 +14,7 @@ #include #include #include +#include #define DRIVER_NAME "stm-spi-ipc" @@ -31,6 +32,8 @@ struct stm_ipc_packet { } __packed; /* Parent SPI controller private structure */ +DECLARE_CRC8_TABLE(stm_crc8_table); + struct stm_ipc_priv { struct spi_device *spi; struct mutex lock; @@ -102,6 +105,7 @@ static irqreturn_t stm_ipc_threaded_irq(int irq, void *dev_id) }; struct spi_message m; int ret; + u8 calc_crc; mutex_lock(&priv->lock); @@ -113,12 +117,27 @@ static irqreturn_t stm_ipc_threaded_irq(int irq, void *dev_id) goto out; } - /* Validate packet */ + /* Validate magic byte */ if (rx_buf.magic != STM_IPC_MSG_MAGIC) { dev_warn_ratelimited(&priv->spi->dev, "Invalid magic byte: 0x%02x\n", rx_buf.magic); goto out; } + /* Validate packet CRC */ + calc_crc = crc8(stm_crc8_table, (const u8 *)&rx_buf, offsetof(struct stm_ipc_packet, crc), 0); + if (calc_crc != rx_buf.crc) { + dev_warn_ratelimited(&priv->spi->dev, "CRC mismatch: read 0x%02x, calculated 0x%02x\n", + rx_buf.crc, calc_crc); + goto out; + } + + /* Validate packet payload length for USB events */ + if (rx_buf.type == MSG_TYPE_USB_EVENT && rx_buf.length != 2) { + dev_warn_ratelimited(&priv->spi->dev, "Invalid packet length: %u (expected 2)\n", + rx_buf.length); + goto out; + } + /* Process USB event */ if (rx_buf.type == MSG_TYPE_USB_EVENT) { u8 port_info[2] = { rx_buf.port, rx_buf.state }; @@ -216,6 +235,9 @@ static int stm_ipc_probe(struct spi_device *spi) struct dentry *parent; + /* Setup CRC8 lookup table (polynomial 0x07) */ + crc8_populate_msb(stm_crc8_table, 0x07); + /* Initialize DebugFS subdirectory under /sys/kernel/debug/stm_ipc/ */ parent = debugfs_create_dir("stm_ipc", NULL); if (IS_ERR_OR_NULL(parent)) { From 225b1c2c9e2d4777624749c95cf4a38f3bc1b048 Mon Sep 17 00:00:00 2001 From: Samuel Morris Date: Wed, 3 Jun 2026 15:51:19 -0700 Subject: [PATCH 10/10] extcon: stm32-ipc: replace magic numbers with enum and defines --- drivers/extcon/extcon-stm32-ipc.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/extcon/extcon-stm32-ipc.c b/drivers/extcon/extcon-stm32-ipc.c index 2ba47f957db1b..79298b811fad3 100644 --- a/drivers/extcon/extcon-stm32-ipc.c +++ b/drivers/extcon/extcon-stm32-ipc.c @@ -19,15 +19,23 @@ #define DRIVER_NAME "stm-spi-ipc" /* Protocol constants */ -#define STM_IPC_MSG_MAGIC 0x5A -#define MSG_TYPE_USB_EVENT 0x01 +#define STM_IPC_MSG_MAGIC 0x5A +#define MSG_TYPE_USB_EVENT 0x01 +#define STM_IPC_MSG_LEN_USB_EVENT 2 +#define STM_IPC_CRC8_POLYNOMIAL 0x07 + +enum stm_ipc_usb_state { + STM_IPC_USB_STATE_DISCONNECTED = 0, + STM_IPC_USB_STATE_PERIPHERAL = 1, + STM_IPC_USB_STATE_HOST = 2, +}; struct stm_ipc_packet { u8 magic; u8 type; u8 length; u8 port; - u8 state; /* 0 = disconnected, 1 = peripheral (VBUS), 2 = host (ID) */ + u8 state; /* enum stm_ipc_usb_state */ u8 crc; } __packed; @@ -56,15 +64,15 @@ static const unsigned int stm_usb_cable[] = { static void stm_ipc_update_state(struct extcon_dev *edev, u8 state) { switch (state) { - case 0: /* Disconnected */ + case STM_IPC_USB_STATE_DISCONNECTED: extcon_set_state_sync(edev, EXTCON_USB, false); extcon_set_state_sync(edev, EXTCON_USB_HOST, false); break; - case 1: /* Peripheral Mode (VBUS present) */ + case STM_IPC_USB_STATE_PERIPHERAL: extcon_set_state_sync(edev, EXTCON_USB_HOST, false); extcon_set_state_sync(edev, EXTCON_USB, true); break; - case 2: /* Host Mode (ID ground) */ + case STM_IPC_USB_STATE_HOST: extcon_set_state_sync(edev, EXTCON_USB, false); extcon_set_state_sync(edev, EXTCON_USB_HOST, true); break; @@ -132,9 +140,9 @@ static irqreturn_t stm_ipc_threaded_irq(int irq, void *dev_id) } /* Validate packet payload length for USB events */ - if (rx_buf.type == MSG_TYPE_USB_EVENT && rx_buf.length != 2) { - dev_warn_ratelimited(&priv->spi->dev, "Invalid packet length: %u (expected 2)\n", - rx_buf.length); + if (rx_buf.type == MSG_TYPE_USB_EVENT && rx_buf.length != STM_IPC_MSG_LEN_USB_EVENT) { + dev_warn_ratelimited(&priv->spi->dev, "Invalid packet length: %u (expected %d)\n", + rx_buf.length, STM_IPC_MSG_LEN_USB_EVENT); goto out; } @@ -156,7 +164,7 @@ static int stm_ipc_sim_write(void *data, u64 val) { struct stm_connector_priv *priv = data; - if (val > 2) + if (val > STM_IPC_USB_STATE_HOST) return -EINVAL; stm_ipc_update_state(priv->edev, (u8)val); @@ -236,7 +244,7 @@ static int stm_ipc_probe(struct spi_device *spi) struct dentry *parent; /* Setup CRC8 lookup table (polynomial 0x07) */ - crc8_populate_msb(stm_crc8_table, 0x07); + crc8_populate_msb(stm_crc8_table, STM_IPC_CRC8_POLYNOMIAL); /* Initialize DebugFS subdirectory under /sys/kernel/debug/stm_ipc/ */ parent = debugfs_create_dir("stm_ipc", NULL);