* [PATCH WIP v3 07/11] dt-bindings: input: touchscreen: st,stmfts: Introduce reset GPIO
From: David Heidelberg via B4 Relay @ 2026-04-03 17:08 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260403-stmfts5-v3-0-5da768cfd201@ixit.cz>
From: David Heidelberg <david@ixit.cz>
FTS has associated reset GPIO, document it.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
index 12256ae7df90d..64c4f24ea3dd0 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
@@ -40,6 +40,10 @@ properties:
vdd-supply:
description: Power supply
+ reset-gpios:
+ description: Reset GPIO (active-low)
+ maxItems: 1
+
required:
- compatible
- reg
--
2.53.0
^ permalink raw reply related
* [PATCH WIP v3 08/11] Input: stmfts - add optional reset GPIO support
From: David Heidelberg via B4 Relay @ 2026-04-03 17:08 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260403-stmfts5-v3-0-5da768cfd201@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Add support for an optional "reset-gpios" property. If present, the
driver drives the reset line high at probe time and releases it during
power-on, after the regulators have been enabled.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 5f7de5e687da2..04110006f54a0 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -77,6 +77,7 @@ static const struct regulator_bulk_data stmfts_supplies[] = {
struct stmfts_data {
struct i2c_client *client;
struct input_dev *input;
+ struct gpio_desc *reset_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
@@ -539,6 +540,15 @@ static int stmfts_read_system_info(struct stmfts_data *sdata)
return 0;
}
+static void stmfts_reset(struct stmfts_data *sdata)
+{
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(sdata->reset_gpio, 0);
+ msleep(50);
+}
+
static int stmfts_power_on(struct stmfts_data *sdata)
{
int err;
@@ -548,6 +558,9 @@ static int stmfts_power_on(struct stmfts_data *sdata)
if (err)
return err;
+ if (sdata->reset_gpio)
+ stmfts_reset(sdata);
+
/*
* The datasheet does not specify the power on time, but considering
* that the reset time is < 10ms, I sleep 20ms to be sure
@@ -606,6 +619,10 @@ static void stmfts_power_off(void *data)
struct stmfts_data *sdata = data;
disable_irq(sdata->client->irq);
+
+ if (sdata->reset_gpio)
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
sdata->supplies);
}
@@ -662,6 +679,12 @@ static int stmfts_probe(struct i2c_client *client)
if (err)
return err;
+ sdata->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->reset_gpio),
+ "Failed to get GPIO 'reset'\n");
+
sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related
* [PATCH WIP v3 09/11] dt-bindings: input: touchscreen: st,stmfts: Introduce STM FTS5
From: David Heidelberg via B4 Relay @ 2026-04-03 17:08 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260403-stmfts5-v3-0-5da768cfd201@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Introduce more recent STM FTS5 touchscreen support.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
.../devicetree/bindings/input/touchscreen/st,stmfts.yaml | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
index 64c4f24ea3dd0..441fc92b9a4ed 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
@@ -16,10 +16,19 @@ description:
allOf:
- $ref: touchscreen.yaml#
+ - if:
+ properties:
+ compatible:
+ const: st,stmfts5
+ then:
+ required:
+ - mode-switch-gpios
properties:
compatible:
- const: st,stmfts
+ enum:
+ - st,stmfts
+ - st,stmfts5
reg:
maxItems: 1
@@ -40,6 +49,10 @@ properties:
vdd-supply:
description: Power supply
+ mode-switch-gpios:
+ description: Switch between touchscreen SLPI and AP mode.
+ maxItems: 1
+
reset-gpios:
description: Reset GPIO (active-low)
maxItems: 1
--
2.53.0
^ permalink raw reply related
* [PATCH WIP v3 10/11] Input: stmfts - support FTS5
From: David Heidelberg via B4 Relay @ 2026-04-03 17:08 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260403-stmfts5-v3-0-5da768cfd201@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Introduce basic FTS5 support.
FTS support SLPI and AP mode, introduce mode-switch GPIO to switch between
those two. Currently we can handle only full power AP mode, so we just
keep the AP on.
Useful for devices like Pixel 3 (blueline) and many others.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 481 +++++++++++++++++++++++++++++++++++--
1 file changed, 460 insertions(+), 21 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 04110006f54a0..e0fa1c4af1987 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-// STMicroelectronics FTS Touchscreen device driver
-//
-// Copyright (c) 2017 Samsung Electronics Co., Ltd.
-// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
+/* STMicroelectronics FTS Touchscreen device driver
+ *
+ * Copyright 2017 Samsung Electronics Co., Ltd.
+ * Copyright 2017 Andi Shyti <andi@etezian.org>
+ * Copyright David Heidelberg <david@ixit.cz>
+ * Copyright Petr Hodina <petr.hodina@protonmail.com>
+ */
#include <linux/delay.h>
#include <linux/i2c.h>
@@ -12,6 +15,7 @@
#include <linux/irq.h>
#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -34,6 +38,7 @@
#define STMFTS_FULL_FORCE_CALIBRATION 0xa2
#define STMFTS_MS_CX_TUNING 0xa3
#define STMFTS_SS_CX_TUNING 0xa4
+#define STMFTS5_SET_SCAN_MODE 0xa0
/* events */
#define STMFTS_EV_NO_EVENT 0x00
@@ -51,12 +56,32 @@
#define STMFTS_EV_STATUS 0x16
#define STMFTS_EV_DEBUG 0xdb
+/* events FTS5 */
+#define STMFTS5_EV_CONTROLLER_READY 0x03
+/* FTM5 event IDs (full byte, not masked) */
+#define STMFTS5_EV_MULTI_TOUCH_ENTER 0x13
+#define STMFTS5_EV_MULTI_TOUCH_MOTION 0x23
+#define STMFTS5_EV_MULTI_TOUCH_LEAVE 0x33
+#define STMFTS5_EV_STATUS_UPDATE 0x43
+#define STMFTS5_EV_USER_REPORT 0x53
+#define STMFTS5_EV_DEBUG 0xe3
+#define STMFTS5_EV_ERROR 0xf3
+
/* multi touch related event masks */
#define STMFTS_MASK_EVENT_ID 0x0f
#define STMFTS_MASK_TOUCH_ID 0xf0
#define STMFTS_MASK_LEFT_EVENT 0x0f
#define STMFTS_MASK_X_MSB 0x0f
#define STMFTS_MASK_Y_LSB 0xf0
+#define STMFTS5_MASK_TOUCH_TYPE 0x0f
+
+/* touch type classifications */
+#define STMFTS_TOUCH_TYPE_INVALID 0x00
+#define STMFTS_TOUCH_TYPE_FINGER 0x01
+#define STMFTS_TOUCH_TYPE_GLOVE 0x02
+#define STMFTS_TOUCH_TYPE_STYLUS 0x03
+#define STMFTS_TOUCH_TYPE_PALM 0x04
+#define STMFTS_TOUCH_TYPE_HOVER 0x05
/* key related event masks */
#define STMFTS_MASK_KEY_NO_TOUCH 0x00
@@ -75,9 +100,12 @@ static const struct regulator_bulk_data stmfts_supplies[] = {
};
struct stmfts_data {
+ const struct stmfts_chip_ops *ops;
+
struct i2c_client *client;
struct input_dev *input;
struct gpio_desc *reset_gpio;
+ struct gpio_desc *mode_switch_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
@@ -101,12 +129,24 @@ struct stmfts_data {
struct completion cmd_done;
+ unsigned long touch_id;
+ unsigned long stylus_id;
+
+ bool is_fts5;
bool use_key;
bool led_status;
bool hover_enabled;
+ bool stylus_enabled;
bool running;
};
+struct stmfts_chip_ops {
+ int (*power_on)(struct stmfts_data *sdata);
+ int (*input_open)(struct input_dev *dev);
+ void (*input_close)(struct input_dev *dev);
+ void (*parse_events)(struct stmfts_data *sdata);
+};
+
static int stmfts_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
@@ -169,6 +209,7 @@ static int stmfts_read_events(struct stmfts_data *sdata)
return ret == ARRAY_SIZE(msgs) ? 0 : -EIO;
}
+/* FTS4 event handling functions */
static void stmfts_report_contact_event(struct stmfts_data *sdata,
const u8 event[])
{
@@ -204,6 +245,157 @@ static void stmfts_report_contact_release(struct stmfts_data *sdata,
input_sync(sdata->input);
}
+/* FTS5 event handling functions */
+static void stmfts5_report_contact_event(struct stmfts_data *sdata,
+ const u8 event[])
+{
+ u8 area;
+ u8 maj;
+ u8 min;
+ /* FTM5 event format:
+ * event[0] = event ID (0x13/0x23)
+ * event[1] = touch type (low 4 bits) | touch ID (high 4 bits)
+ * event[2] = X LSB
+ * event[3] = X MSB (low 4 bits) | Y MSB (high 4 bits)
+ * event[4] = Y LSB
+ * event[5] = pressure
+ * event[6] = major (low 4 bits) | minor (high 4 bits)
+ * event[7] = minor (high 2 bits)
+ */
+ u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+ u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+ int x, y, distance;
+ unsigned int tool = MT_TOOL_FINGER;
+ bool touch_condition = true;
+
+ /* Parse coordinates with better precision */
+ x = (((int)event[3] & STMFTS_MASK_X_MSB) << 8) | event[2];
+ y = ((int)event[4] << 4) | ((event[3] & STMFTS_MASK_Y_LSB) >> 4);
+
+ /* Parse pressure - ensure non-zero for active touch */
+ area = event[5];
+ if (area <= 0 && touch_type != STMFTS_TOUCH_TYPE_HOVER) {
+ /* Should not happen for contact events. Set minimum pressure
+ * to prevent touch from being dropped
+ */
+ dev_warn_once(&sdata->client->dev,
+ "zero pressure on contact event, slot %d\n", touch_id);
+ area = 1;
+ }
+
+ /* Parse touch area with improved bit extraction */
+ maj = (((event[0] & 0x0C) << 2) | ((event[6] & 0xF0) >> 4));
+ min = (((event[7] & 0xC0) >> 2) | (event[6] & 0x0F));
+
+ /* Distance is 0 for touching, max for hovering */
+ distance = 0;
+
+ /* Classify touch type and set appropriate tool and parameters */
+ switch (touch_type) {
+ case STMFTS_TOUCH_TYPE_STYLUS:
+ if (sdata->stylus_enabled) {
+ tool = MT_TOOL_PEN;
+ __set_bit(touch_id, &sdata->stylus_id);
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+ }
+ fallthrough; /* Report as finger if stylus not enabled */
+
+ case STMFTS_TOUCH_TYPE_FINGER:
+ case STMFTS_TOUCH_TYPE_GLOVE:
+ tool = MT_TOOL_FINGER;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_PALM:
+ /* Palm touch - report but can be filtered by userspace */
+ tool = MT_TOOL_PALM;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_HOVER:
+ tool = MT_TOOL_FINGER;
+ touch_condition = false;
+ area = 0;
+ distance = 255;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_INVALID:
+ default:
+ dev_warn(&sdata->client->dev,
+ "invalid touch type %d for slot %d\n",
+ touch_type, touch_id);
+ return;
+ }
+
+ /* Boundary check - some devices report max value, adjust */
+ if (x >= sdata->prop.max_x)
+ x = sdata->prop.max_x - 1;
+ if (y >= sdata->prop.max_y)
+ y = sdata->prop.max_y - 1;
+
+ input_mt_slot(sdata->input, touch_id);
+ input_report_key(sdata->input, BTN_TOUCH, touch_condition);
+ input_mt_report_slot_state(sdata->input, tool, true);
+
+ input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
+ input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, maj);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, min);
+ input_report_abs(sdata->input, ABS_MT_PRESSURE, area);
+ input_report_abs(sdata->input, ABS_MT_DISTANCE, distance);
+
+ input_sync(sdata->input);
+}
+
+static void stmfts5_report_contact_release(struct stmfts_data *sdata,
+ const u8 event[])
+{
+ /* FTM5 format: touch ID is in high 4 bits of event[1] */
+ u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+ u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+ unsigned int tool = MT_TOOL_FINGER;
+
+ /* Determine tool type based on touch classification */
+ switch (touch_type) {
+ case STMFTS_TOUCH_TYPE_STYLUS:
+ if (sdata->stylus_enabled) {
+ tool = MT_TOOL_PEN;
+ __clear_bit(touch_id, &sdata->stylus_id);
+ } else {
+ __clear_bit(touch_id, &sdata->touch_id);
+ }
+ break;
+
+ case STMFTS_TOUCH_TYPE_PALM:
+ tool = MT_TOOL_PALM;
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_FINGER:
+ case STMFTS_TOUCH_TYPE_GLOVE:
+ case STMFTS_TOUCH_TYPE_HOVER:
+ default:
+ tool = MT_TOOL_FINGER;
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+ }
+
+ input_mt_slot(sdata->input, touch_id);
+ input_report_abs(sdata->input, ABS_MT_PRESSURE, 0);
+ input_mt_report_slot_state(sdata->input, tool, false);
+
+ /* Report BTN_TOUCH only if no touches remain */
+ if (!sdata->touch_id && !sdata->stylus_id)
+ input_report_key(sdata->input, BTN_TOUCH, 0);
+
+ input_sync(sdata->input);
+}
+
static void stmfts_report_hover_event(struct stmfts_data *sdata,
const u8 event[])
{
@@ -251,7 +443,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
switch (event[0]) {
-
case STMFTS_EV_CONTROLLER_READY:
case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
case STMFTS_EV_STATUS:
@@ -264,7 +455,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
switch (event[0] & STMFTS_MASK_EVENT_ID) {
-
case STMFTS_EV_MULTI_TOUCH_ENTER:
case STMFTS_EV_MULTI_TOUCH_MOTION:
stmfts_report_contact_event(sdata, event);
@@ -298,6 +488,45 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
}
+static void stmfts5_parse_events(struct stmfts_data *sdata)
+{
+ for (int i = 0; i < STMFTS_STACK_DEPTH; i++) {
+ u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
+
+ switch (event[0]) {
+ case STMFTS5_EV_CONTROLLER_READY:
+ complete(&sdata->cmd_done);
+ fallthrough;
+
+ case STMFTS_EV_NO_EVENT:
+ case STMFTS5_EV_STATUS_UPDATE:
+ case STMFTS5_EV_USER_REPORT:
+ case STMFTS5_EV_DEBUG:
+ return;
+
+ case STMFTS5_EV_MULTI_TOUCH_ENTER:
+ case STMFTS5_EV_MULTI_TOUCH_MOTION:
+ stmfts5_report_contact_event(sdata, event);
+ break;
+
+ case STMFTS5_EV_MULTI_TOUCH_LEAVE:
+ stmfts5_report_contact_release(sdata, event);
+ break;
+
+ case STMFTS5_EV_ERROR:
+ dev_warn(&sdata->client->dev,
+ "error code: 0x%x%x%x%x%x%x",
+ event[6], event[5], event[4],
+ event[3], event[2], event[1]);
+ break;
+
+ default:
+ dev_err(&sdata->client->dev,
+ "unknown FTS5 event %#02x\n", event[0]);
+ }
+ }
+}
+
static irqreturn_t stmfts_irq_handler(int irq, void *dev)
{
struct stmfts_data *sdata = dev;
@@ -310,7 +539,7 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
dev_err(&sdata->client->dev,
"failed to read events: %d\n", err);
else
- stmfts_parse_events(sdata);
+ sdata->ops->parse_events(sdata);
return IRQ_HANDLED;
}
@@ -332,6 +561,25 @@ static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
return 0;
}
+static int stmfts5_set_scan_mode(struct stmfts_data *sdata, const u8 val)
+{
+ int err;
+
+ u8 scan_mode_cmd[3] = { STMFTS5_SET_SCAN_MODE, 0x00, val };
+ struct i2c_msg msg = {
+ .addr = sdata->client->addr,
+ .len = sizeof(scan_mode_cmd),
+ .buf = scan_mode_cmd,
+ };
+
+ err = i2c_transfer(sdata->client->adapter, &msg, 1);
+ if (err != 1)
+ return err < 0 ? err : -EIO;
+
+ return 0;
+
+}
+
static int stmfts_input_open(struct input_dev *dev)
{
struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -371,6 +619,28 @@ static int stmfts_input_open(struct input_dev *dev)
return 0;
}
+static int stmfts5_input_open(struct input_dev *dev)
+{
+ struct stmfts_data *sdata = input_get_drvdata(dev);
+ int err;
+
+ err = pm_runtime_resume_and_get(&sdata->client->dev);
+ if (err)
+ return err;
+
+ mutex_lock(&sdata->mutex);
+ sdata->running = true;
+ mutex_unlock(&sdata->mutex);
+
+ err = stmfts5_set_scan_mode(sdata, 0xff);
+ if (err) {
+ pm_runtime_put_sync(&sdata->client->dev);
+ return err;
+ }
+
+ return 0;
+}
+
static void stmfts_input_close(struct input_dev *dev)
{
struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -404,6 +674,23 @@ static void stmfts_input_close(struct input_dev *dev)
pm_runtime_put_sync(&sdata->client->dev);
}
+static void stmfts5_input_close(struct input_dev *dev)
+{
+ struct stmfts_data *sdata = input_get_drvdata(dev);
+ int err;
+
+ err = stmfts5_set_scan_mode(sdata, 0x00);
+ if (err)
+ dev_warn(&sdata->client->dev,
+ "failed to disable touchscreen: %d\n", err);
+
+ mutex_lock(&sdata->mutex);
+ sdata->running = false;
+ mutex_unlock(&sdata->mutex);
+
+ pm_runtime_put_sync(&sdata->client->dev);
+}
+
static ssize_t stmfts_sysfs_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -484,7 +771,7 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
guard(mutex)(&sdata->mutex);
if (hover != sdata->hover_enabled) {
- if (sdata->running) {
+ if (sdata->running && !sdata->is_fts5) {
err = i2c_smbus_write_byte(sdata->client,
value ? STMFTS_SS_HOVER_SENSE_ON :
STMFTS_SS_HOVER_SENSE_OFF);
@@ -614,6 +901,41 @@ static int stmfts_power_on(struct stmfts_data *sdata)
return err;
}
+static int stmfts5_power_on(struct stmfts_data *sdata)
+{
+ int err, ret;
+ u8 event[STMFTS_EVENT_SIZE];
+
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ if (err)
+ return err;
+
+ /* Power stabilization delay */
+ msleep(20);
+
+ if (sdata->reset_gpio)
+ stmfts_reset(sdata);
+
+ /* Verify I2C communication */
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ STMFTS_READ_ALL_EVENT,
+ sizeof(event), event);
+ if (ret < 0) {
+ err = ret;
+ goto power_off;
+ }
+
+ enable_irq(sdata->client->irq);
+
+ return 0;
+
+power_off:
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ return err;
+}
+
static void stmfts_power_off(void *data)
{
struct stmfts_data *sdata = data;
@@ -623,6 +945,11 @@ static void stmfts_power_off(void *data)
if (sdata->reset_gpio)
gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ if (sdata->is_fts5) {
+ i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
+ msleep(20);
+ }
+
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
sdata->supplies);
}
@@ -656,6 +983,7 @@ static int stmfts_probe(struct i2c_client *client)
struct device *dev = &client->dev;
int err;
struct stmfts_data *sdata;
+ const struct of_device_id *match;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_BYTE_DATA |
@@ -672,6 +1000,13 @@ static int stmfts_probe(struct i2c_client *client)
mutex_init(&sdata->mutex);
init_completion(&sdata->cmd_done);
+ match = of_match_device(dev->driver->of_match_table, dev);
+ sdata->ops = of_device_get_match_data(dev);
+ if (match && of_device_is_compatible(dev->of_node, "st,stmfts5"))
+ sdata->is_fts5 = true;
+ else
+ sdata->is_fts5 = false;
+
err = devm_regulator_bulk_get_const(dev,
ARRAY_SIZE(stmfts_supplies),
stmfts_supplies,
@@ -685,34 +1020,80 @@ static int stmfts_probe(struct i2c_client *client)
return dev_err_probe(dev, PTR_ERR(sdata->reset_gpio),
"Failed to get GPIO 'reset'\n");
+ if (sdata->is_fts5) {
+ sdata->mode_switch_gpio = devm_gpiod_get_optional(&client->dev,
+ "mode-switch",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->mode_switch_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->mode_switch_gpio),
+ "Failed to get GPIO 'switch'\n");
+
+ }
+
sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
sdata->input->name = STMFTS_DEV_NAME;
sdata->input->id.bustype = BUS_I2C;
- sdata->input->open = stmfts_input_open;
- sdata->input->close = stmfts_input_close;
+ sdata->input->open = sdata->ops->input_open;
+ sdata->input->close = sdata->ops->input_close;
+
+ /* FTS5-specific input properties */
+ if (sdata->is_fts5) {
+ /* Mark as direct input device for calibration support */
+ __set_bit(INPUT_PROP_DIRECT, sdata->input->propbit);
+
+ /* Set up basic touch capabilities */
+ input_set_capability(sdata->input, EV_KEY, BTN_TOUCH);
+ }
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y);
touchscreen_parse_properties(sdata->input, true, &sdata->prop);
+ /* Set resolution for accurate calibration (FTS5) */
+ if (sdata->is_fts5 && !input_abs_get_res(sdata->input, ABS_MT_POSITION_X)) {
+ input_abs_set_res(sdata->input, ABS_MT_POSITION_X, 10);
+ input_abs_set_res(sdata->input, ABS_MT_POSITION_Y, 10);
+ }
+
+ /* Enhanced MT parameters */
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
- input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
- input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
+
+ if (sdata->is_fts5) {
+ input_set_abs_params(sdata->input, ABS_MT_DISTANCE, 0, 255, 0, 0);
+
+ /* Enable stylus support if requested */
+ sdata->stylus_enabled = device_property_read_bool(dev,
+ "stylus-enabled");
+ } else {
+ input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
+ }
sdata->use_key = device_property_read_bool(dev,
"touch-key-connected");
- if (sdata->use_key) {
+ if (sdata->use_key && !sdata->is_fts5) {
input_set_capability(sdata->input, EV_KEY, KEY_MENU);
input_set_capability(sdata->input, EV_KEY, KEY_BACK);
}
- err = input_mt_init_slots(sdata->input,
- STMFTS_MAX_FINGERS, INPUT_MT_DIRECT);
+ /* Initialize touch tracking bitmaps (FTS5) */
+ if (sdata->is_fts5) {
+ sdata->touch_id = 0;
+ sdata->stylus_id = 0;
+
+ /* Initialize MT slots with support for pen tool type */
+ err = input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ } else {
+ err = input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+ INPUT_MT_DIRECT);
+ }
+
if (err)
return err;
@@ -732,9 +1113,11 @@ static int stmfts_probe(struct i2c_client *client)
if (err)
return err;
- dev_dbg(dev, "initializing ST-Microelectronics FTS...\n");
+ dev_dbg(dev, "initializing ST-Microelectronics FTS%s...\n",
+ sdata->is_fts5 ? "5" : "");
+
- err = stmfts_power_on(sdata);
+ err = sdata->ops->power_on(sdata);
if (err)
return err;
@@ -746,7 +1129,7 @@ static int stmfts_probe(struct i2c_client *client)
if (err)
return err;
- if (sdata->use_key) {
+ if (sdata->use_key && !sdata->is_fts5) {
err = stmfts_enable_led(sdata);
if (err) {
/*
@@ -790,8 +1173,47 @@ static int stmfts_runtime_resume(struct device *dev)
int ret;
ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
- if (ret)
+ if (ret) {
dev_err(dev, "failed to resume device: %d\n", ret);
+ return ret;
+ }
+
+ if (sdata->is_fts5) {
+ msleep(20);
+
+ /* Perform capacitance tuning after wakeup */
+ ret = i2c_smbus_write_byte(client, STMFTS_MS_CX_TUNING);
+ if (ret)
+ dev_warn(dev, "MS_CX_TUNING failed: %d\n", ret);
+ msleep(20);
+
+ ret = i2c_smbus_write_byte(client, STMFTS_SS_CX_TUNING);
+ if (ret)
+ dev_warn(dev, "SS_CX_TUNING failed: %d\n", ret);
+ msleep(20);
+
+ /* Force calibration */
+ ret = i2c_smbus_write_byte(client, STMFTS_FULL_FORCE_CALIBRATION);
+ if (ret)
+ dev_warn(dev, "FORCE_CALIBRATION failed: %d\n", ret);
+ msleep(50);
+
+ /* Enable controller interrupts */
+ u8 int_enable_cmd[4] = {0xB6, 0x00, 0x2C, 0x01};
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .len = 4,
+ .buf = int_enable_cmd,
+ };
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1)
+ return ret < 0 ? ret : -EIO;
+
+ msleep(20);
+
+ return 0;
+ }
return ret;
}
@@ -809,7 +1231,7 @@ static int stmfts_resume(struct device *dev)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
- return stmfts_power_on(sdata);
+ return sdata->ops->power_on(sdata);
}
static const struct dev_pm_ops stmfts_pm_ops = {
@@ -818,8 +1240,23 @@ static const struct dev_pm_ops stmfts_pm_ops = {
};
#ifdef CONFIG_OF
+static const struct stmfts_chip_ops stmfts4_ops = {
+ .power_on = stmfts_power_on,
+ .input_open = stmfts_input_open,
+ .input_close = stmfts_input_close,
+ .parse_events = stmfts_parse_events,
+};
+
+static const struct stmfts_chip_ops stmfts5_ops = {
+ .power_on = stmfts5_power_on,
+ .input_open = stmfts5_input_open,
+ .input_close = stmfts5_input_close,
+ .parse_events = stmfts5_parse_events,
+};
+
static const struct of_device_id stmfts_of_match[] = {
- { .compatible = "st,stmfts", },
+ { .compatible = "st,stmfts", .data = &stmfts4_ops },
+ { .compatible = "st,stmfts5", .data = &stmfts5_ops },
{ },
};
MODULE_DEVICE_TABLE(of, stmfts_of_match);
@@ -847,5 +1284,7 @@ static struct i2c_driver stmfts_driver = {
module_i2c_driver(stmfts_driver);
MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
+MODULE_AUTHOR("David Heidelberg <david@ixit.cz>");
+MODULE_AUTHOR("Petr Hodina <petr.hodina@protonmail.com>");
MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH WIP v3 11/11] arm64: dts: qcom: sdm845-google: Add STM FTS touchscreen support
From: David Heidelberg via B4 Relay @ 2026-04-03 17:08 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260403-stmfts5-v3-0-5da768cfd201@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Basic touchscreen connected to second i2c bus.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts | 19 ++++++++++++++++++-
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 2 +-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
index fa89be500fb85..8fb988130b551 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
@@ -26,7 +26,24 @@ &i2c2 {
status = "okay";
- /* ST,FTS @ 49 */
+ touchscreen@49 {
+ compatible = "st,stmfts5";
+ reg = <0x49>;
+
+ pinctrl-0 = <&touchscreen_irq_n>, <&touchscreen_reset>;
+ pinctrl-names = "default";
+
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
+
+ mode-switch-gpios = <&tlmm 136 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
+
+ avdd-supply = <&vreg_l14a_1p8>;
+ vdd-supply = <&vreg_l19a_3p3>;
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2160>;
+ };
};
&mdss_dsi0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index 6930066857768..4653c63ec26d2 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -466,7 +466,7 @@ touchscreen_reset: ts-reset-state {
bias-pull-up;
};
- touchscreen_pins: ts-pins-gpio-state {
+ touchscreen_irq_n: ts-irq-n-gpio-state {
pins = "gpio125";
function = "gpio";
drive-strength = <2>;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v7 1/3] soc: qcom: ice: Add OPP-based clock scaling support for ICE
From: Harshal Dev @ 2026-04-03 17:20 UTC (permalink / raw)
To: Abhinaba Rakshit
Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
Neeraj Soni, linux-arm-msm, linux-crypto, devicetree,
linux-kernel, linux-scsi
In-Reply-To: <ac/L6y5B+6SyTNuE@hu-arakshit-hyd.qualcomm.com>
On 4/3/2026 7:47 PM, Abhinaba Rakshit wrote:
> On Mon, Mar 30, 2026 at 08:09:35PM +0530, Harshal Dev wrote:
>>> +/**
>>> + * qcom_ice_scale_clk() - Scale ICE clock for DVFS-aware operations
>>> + * @ice: ICE driver data
>>> + * @target_freq: requested frequency in Hz
>>> + * @round_ceil: when true, selects nearest freq >= @target_freq;
>>> + * otherwise, selects nearest freq <= @target_freq
>>> + *
>>> + * Selects an OPP frequency based on @target_freq and the rounding direction
>>> + * specified by @round_ceil, then programs it using dev_pm_opp_set_rate(),
>>> + * including any voltage or power-domain transitions handled by the OPP
>>> + * framework. Updates ice->core_clk_freq on success.
>>> + *
>>> + * Return: 0 on success; -EOPNOTSUPP if no OPP table; -EINVAL in-case of
>>> + * incorrect flags; or error from dev_pm_opp_set_rate()/OPP lookup.
>>> + */
>>> +int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
>>> + bool round_ceil)
>>
>> Any particular reason for choosing round_ceil? Using round_floor would have
>> saved the need for caller to pass negation of scale_up.
>
> There isn’t a strong technical reason for choosing round_ceil specifically.
> The choice was mainly influenced by the earlier discussion here:
> https://lore.kernel.org/all/15495f8a-37b0-4768-9ee1-05fd6c70034e@oss.qualcomm.com/
>
> Also, this helper isn’t necessarily limited to the current caller.
> We might see additional users in the future where the semantics align more
> naturally with flags like scale_down, which map cleanly to a round_ceil‑style selection.
> That said, I agree that using round_floor could simplify the current callsite by
> avoiding the negation of scale_up.
>
> I don’t have a strong objection to switching it if you feel that would be
> more cleaner for now.
>
No issues, you can choose to do it if you spin a v8 of this patch series.
>>> +{
>>> + unsigned long ice_freq = target_freq;
>>> + struct dev_pm_opp *opp;
>>> + int ret;
>>> +
>>> + if (!ice->has_opp)
>>> + return -EOPNOTSUPP;
>>> +
[...]
>>> +
>>> static struct qcom_ice *qcom_ice_create(struct device *dev,
>>> - void __iomem *base)
>>> + void __iomem *base,
>>> + bool is_legacy_binding)
>>
>> You don't need to introduce is_legacy_binding.
>>
>> Since you only need to add the OPP table when this function gets called from ICE probe,
>> you should not touch this function. Instead, you should call devm_pm_opp_of_add_table()
>> in ICE probe before calling qcom_ice_create() then once qcom_ice_create() is success, you
>> can store the clk rate in the returned qcom_ice *engine ptr by calling clk_get_rate().
>
> This was added as part of the review comment from Krzysztof:
> https://lore.kernel.org/all/20260128-daft-seriema-of-promotion-c50eb5@quoll/
>
> While I agree moving this to qcom_ice_probe would be more cleaner without needing
> to change the API, most of our initializing code for driver by parsing the DT node
> happens through qcom_ice_create, which keeps qcom_ice_probe much simpler.
> Please let me know, if you think otherwise.
>
Seems like a suggestion from Krzysztof and not something based on strong opinion. Again,
you can choose to do this if you spin a v8, I feel it's cleaner.
> Also, I don't see any reason for moving the clk_get_rate() logic to qcom_ice_probe
> though as it will not be set on legacy targets in that case.
I thought only new DT nodes will be specifying the OPP table requiring us to store the
clk rate and restore later. If legacy DT nodes also possess the OPP table, then ignore
this comment.
>
>>> {
>>> struct qcom_ice *engine;
>>> + int err;
>>>
>>> if (!qcom_scm_is_available())
>>> return ERR_PTR(-EPROBE_DEFER);
>>> @@ -584,6 +640,26 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
>>> if (IS_ERR(engine->core_clk))
>>> return ERR_CAST(engine->core_clk);
>>>
>>> + /*
>>> + * Register the OPP table only when ICE is described as a standalone
>>> + * device node. Older platforms place ICE inside the storage controller
>>> + * node, so they don't need an OPP table here, as they are handled in
>>> + * storage controller.
>>> + */
>>> + if (!is_legacy_binding) {
>>> + /* OPP table is optional */
>>> + err = devm_pm_opp_of_add_table(dev);
>>> + if (err && err != -ENODEV) {
>>> + dev_err(dev, "Invalid OPP table in Device tree\n");
>>> + return ERR_PTR(err);
>>> + }
>>> + engine->has_opp = (err == 0);
>>
>> Let's keep it readable and simple. engine->has_opps = true; here and false in error handle above.
>
> Well there are 3 cases to it:
>
> 1. err == 0 which implies devm_pm_opp_of_add_table is successful and we can set engine->has_opp =true.
> 2. err == -ENODEV which implies there is no opp table in the DT node.
> In that case, we don't fail the driver simply go ahead and log in the check below.
> This is done since OPP-table is optional.
> 3. err == any other error code. Something very wrong happened with devm_pm_opp_of_add_table
> and driver should fail.
>
> Hence, we have the condition (err == 0) for setting has_opp flag.
My suggestion is you either explain this in concise comments or simplify the assignment of has_opp
to make it obvious.
Regards,
Harshal
>
> Abhinaba Rakshit
^ permalink raw reply
* [PATCH v9 0/3] PCI: Add support for PCIe WAKE# interrupt
From: Krishna Chaitanya Chundru @ 2026-04-03 17:33 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru,
Manivannan Sadhasivam, Bartosz Golaszewski
PCIe WAKE# interrupt is needed for bringing back PCIe device state from
D3cold to D0.
This is pending from long time, there was two attempts done previously to
add WAKE# support[1], [2]. Those series tried to add support for legacy
interrupts along with WAKE#. Legacy interrupts are already available in
the latest kernel and we can ignore them. For the wake IRQ the series is
trying to use interrupts property define in the device tree.
This series is using gpio property instead of interrupts, from
gpio desc driver will allocate the dedicate IRQ.
Bjorn,
Can you take this series through PCI branch, once other subsystem
maintainers give us ACK.
WAKE# is added in dts schema and merged based on this patch.
https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
[1]: https://lore.kernel.org/all/b2b91240-95fe-145d-502c-d52225497a34@nvidia.com/T/
[2]: https://lore.kernel.org/all/20171226023646.17722-1-jeffy.chen@rock-chips.com/
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
Changes in v9:
- Call device_init_wakeup() only if
dev_pm_set_dedicated_shared_wake_irq() succeeds (Mani).
- Change the IRQ_TYPE from IRQ_TYPE_EDGE_FALLING to IRQ_TYPE_LEVEL_LOW (Mani).
- Link to v8: https://lore.kernel.org/r/20260313-wakeirq_support-v8-0-48a0a702518a@oss.qualcomm.com
Changes in v8:
- Moved the stub functions under CONFIG_OF_IRQ(mani).
- Added the description of how dev_pm_set_dedicated_shared_wake_irq()
works.
- Link to v7: https://lore.kernel.org/r/20260218-wakeirq_support-v7-0-0d4689830207@oss.qualcomm.com
Changes in v7:
- Updated the commit text (Mani).
- Couple of nits like using pci_err instead of dev_err,
use platform_pci_configure_wake(), platform_pci_remove_wake() instead
of calling directly calling pci_configure_of_wake_gpio() & pci_remove_of_wake_gpio() etc (Mani).
- Add a new fwnode_gpiod_get() API that wraps fwnode_gpiod_get_index(..0..), similar to
devm_fwnode_gpiod_get() (Mani).
- Link to v6: https://lore.kernel.org/r/20251127-wakeirq_support-v6-0-60f581f94205@oss.qualcomm.com
Changes in v6:
- Change the name to dev_pm_set_dedicated_shared_wake_irq() and make the
changes pointed by (Rafael).
- Link to v5: https://lore.kernel.org/r/20251107-wakeirq_support-v5-0-464e17f2c20c@oss.qualcomm.com
Changes in v5:
- Enable WAKE# irq only when there is wake -gpios defined in its device
tree node (Bjorn).
- For legacy bindings for direct atach check in root port if we haven't
find the wake in the endpoint node.
- Instead of hooking wake in driver bound case, do it in the framework
irrespective of the driver state (Bjorn).
- Link to v4: https://lore.kernel.org/r/20250801-wake_irq_support-v4-0-6b6639013a1a@oss.qualcomm.com
Changes in v4:
- Move wake from portdrv to core framework to endpoint (Bjorn).
- Added support for multiple WAKE# case (Bjorn). But traverse from
endpoint upstream port to root port till you get WAKE#. And use
IRQF_SHARED flag for requesting interrupts.
- Link to v3: https://lore.kernel.org/r/20250605-wake_irq_support-v3-0-7ba56dc909a5@oss.qualcomm.com
Changes in v3:
- Update the commit messages, function names etc as suggested by Mani.
- return wake_irq if returns error (Neil).
- Link to v2: https://lore.kernel.org/r/20250419-wake_irq_support-v2-0-06baed9a87a1@oss.qualcomm.com
Changes in v2:
- Move the wake irq teardown after pcie_port_device_remove
and move of_pci_setup_wake_irq before pcie_link_rcec (Lukas)
- teardown wake irq in shutdown also.
- Link to v1: https://lore.kernel.org/r/20250401-wake_irq_support-v1-0-d2e22f4a0efd@oss.qualcomm.com
---
Krishna Chaitanya Chundru (3):
PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup
gpio: Add fwnode_gpiod_get() helper
PCI: Add support for PCIe WAKE# interrupt
drivers/base/power/wakeirq.c | 39 ++++++++++++++++++++---
drivers/pci/of.c | 74 +++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.c | 10 ++++++
drivers/pci/pci.h | 2 ++
drivers/pci/probe.c | 2 ++
drivers/pci/remove.c | 1 +
include/linux/gpio/consumer.h | 9 ++++++
include/linux/of_pci.h | 4 +++
include/linux/pci.h | 2 ++
include/linux/pm_wakeirq.h | 6 ++++
10 files changed, 144 insertions(+), 5 deletions(-)
---
base-commit: d8a9a4b11a137909e306e50346148fc5c3b63f9d
change-id: 20251104-wakeirq_support-f54c4baa18c5
Best regards,
--
Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v9 1/3] PM: sleep: wakeirq: Add support for dedicated shared wake IRQ setup
From: Krishna Chaitanya Chundru @ 2026-04-03 17:33 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru
In-Reply-To: <20260403-wakeirq_support-v9-0-1cbecf3b58d7@oss.qualcomm.com>
Some devices require more flexibility when configuring their dedicated
wake-up interrupts, such as support for IRQF_SHARED or other IRQ flags.
This is particularly useful in PCIe systems where multiple endpoints
(e.g., Wi-Fi and Bluetooth controllers) share a common WAKE# signal
line which requests platform to re-establish power and reference clocks
to the components. In such cases, drivers can use this new API
dev_pm_set_dedicated_shared_wake_irq() to register a shared wake IRQ.
Update the internal helper __dev_pm_set_dedicated_wake_irq() to accept an
irq_flags argument. Modify the existing dev_pm_set_dedicated_wake_irq()
and dev_pm_set_dedicated_wake_irq_reverse() to preserve current behavior.
When IRQ registered with IRQF_SHARED we can't use IRQF_NO_AUTOEN flag,
so after registering for irq, disable it explicitly.
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
---
drivers/base/power/wakeirq.c | 39 ++++++++++++++++++++++++++++++++++-----
include/linux/pm_wakeirq.h | 6 ++++++
2 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index ad23f0fa5d1a5a9eb49b1af2288ee4908082b13e..b7b106f55559a7c85cb35d9e5ed22fe37970662d 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -171,7 +171,8 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
return IRQ_HANDLED;
}
-static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
+static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag,
+ unsigned int irq_flags)
{
struct wake_irq *wirq;
int err;
@@ -200,8 +201,7 @@ static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned
* so we use a threaded irq.
*/
err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
- IRQF_ONESHOT | IRQF_NO_AUTOEN,
- wirq->name, wirq);
+ IRQF_ONESHOT | irq_flags, wirq->name, wirq);
if (err)
goto err_free_name;
@@ -237,7 +237,7 @@ static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned
*/
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
{
- return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
+ return __dev_pm_set_dedicated_wake_irq(dev, irq, 0, IRQF_NO_AUTOEN);
}
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
@@ -258,10 +258,39 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
*/
int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
{
- return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
+ return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE,
+ IRQF_NO_AUTOEN);
}
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
+/**
+ * dev_pm_set_dedicated_shared_wake_irq - Request a dedicated shared wake-up interrupt
+ * @dev: Device entry
+ * @irq: Device wake-up interrupt
+ * @flags: Custom IRQ flags (e.g., IRQ_TYPE_EDGE_FALLING)
+ *
+ * This API sets up a threaded interrupt handler for a device that has
+ * a shared wake-up interrupt in addition to the device IO interrupt. It also
+ * sets IRQ flags like IRQ_TYPE_EDGE_FALLING passed by the caller.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int dev_pm_set_dedicated_shared_wake_irq(struct device *dev, int irq, unsigned long flags)
+{
+ struct wake_irq *wirq;
+ int ret;
+
+ ret = __dev_pm_set_dedicated_wake_irq(dev, irq, 0, IRQF_SHARED | flags);
+ if (ret)
+ return ret;
+
+ wirq = dev->power.wakeirq;
+ disable_irq_nosync(wirq->irq);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_shared_wake_irq);
+
/**
* dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
* @dev: Device
diff --git a/include/linux/pm_wakeirq.h b/include/linux/pm_wakeirq.h
index 25b63ed51b765c2c6919f259668a12675330835e..61f1e840745b56baa57db37563e450cb2d757a85 100644
--- a/include/linux/pm_wakeirq.h
+++ b/include/linux/pm_wakeirq.h
@@ -11,6 +11,7 @@ extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq);
extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq);
extern void dev_pm_clear_wake_irq(struct device *dev);
extern int devm_pm_set_wake_irq(struct device *dev, int irq);
+extern int dev_pm_set_dedicated_shared_wake_irq(struct device *dev, int irq, unsigned long flags);
#else /* !CONFIG_PM */
@@ -38,5 +39,10 @@ static inline int devm_pm_set_wake_irq(struct device *dev, int irq)
return 0;
}
+static inline int dev_pm_set_dedicated_shared_wake_irq(struct device *dev,
+ int irq, unsigned long flags)
+{
+ return 0;
+}
#endif /* CONFIG_PM */
#endif /* _LINUX_PM_WAKEIRQ_H */
--
2.34.1
^ permalink raw reply related
* [PATCH v9 2/3] gpio: Add fwnode_gpiod_get() helper
From: Krishna Chaitanya Chundru @ 2026-04-03 17:33 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru,
Manivannan Sadhasivam, Bartosz Golaszewski
In-Reply-To: <20260403-wakeirq_support-v9-0-1cbecf3b58d7@oss.qualcomm.com>
Add fwnode_gpiod_get() as a convenience wrapper around
fwnode_gpiod_get_index() for the common case where only the
first GPIO is required.
This mirrors existing gpiod_get() and devm_gpiod_get() helpers
and avoids open-coding index 0 at call sites.
Suggested-by: Manivannan Sadhasivam <mani@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
include/linux/gpio/consumer.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 0d8408582918680bfea6a04ccedfc0c75211907a..fee926c0262ce9dc4b9a3c151e74f2cf37470a49 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -596,6 +596,15 @@ static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc,
}
#endif /* CONFIG_GPIOLIB && CONFIG_HTE */
+static inline
+struct gpio_desc *fwnode_gpiod_get(struct fwnode_handle *fwnode,
+ const char *con_id,
+ enum gpiod_flags flags,
+ const char *label)
+{
+ return fwnode_gpiod_get_index(fwnode, con_id, 0, flags, label);
+}
+
static inline
struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
struct fwnode_handle *fwnode,
--
2.34.1
^ permalink raw reply related
* [PATCH v9 3/3] PCI: Add support for PCIe WAKE# interrupt
From: Krishna Chaitanya Chundru @ 2026-04-03 17:33 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek, Greg Kroah-Hartman,
Danilo Krummrich, Bjorn Helgaas, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Linus Walleij
Cc: linux-pm, linux-kernel, linux-pci, linux-gpio, quic_vbadigan,
sherry.sun, driver-core, devicetree, Krishna Chaitanya Chundru
In-Reply-To: <20260403-wakeirq_support-v9-0-1cbecf3b58d7@oss.qualcomm.com>
According to the PCI Express specification (PCIe r7.0, Section 5.3.3.2),
two link wakeup mechanisms are defined: Beacon and WAKE#. Beacon is a
hardware-only mechanism and is invisible to software (PCIe r7.0,
Section 4.2.7.8.1). This change adds support for the WAKE# mechanism in
the PCI core.
According to the PCIe specification, multiple WAKE# signals can exist in
a system or each component in the hierarchy could share a single WAKE#
signal. In configurations involving a PCIe switch, each downstream port
(DSP) of the switch may be connected to a separate WAKE# line, allowing
each endpoint to signal WAKE# independently. From figure 5.4 in sec
5.3.3.2, WAKE# can also be terminated at the switch itself. To support
this, the WAKE# should be described in the device tree node of the
endpoint/bridge. If all endpoints share a single WAKE# line, then each
endpoint node should describe the same WAKE# signal or a single WAKE# in
the Root Port node.
In pci_device_add(), PCI framework will search for the WAKE# in device
node, If not found, it searches in its upstream port only if upstream port
is Root Port. Once found, register for the wake IRQ in shared mode, as the
WAKE# may be shared among multiple endpoints.
dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with a
device and requests it, but the PM core keeps the IRQ disabled by default.
The IRQ is enabled only when the device is permitted to wake the system,
i.e. during system suspend and after runtime suspend, and only when device
wakeup is enabled.
When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume() to
bring the device back to an active power state, such as transitioning from
D3cold to D0. Once the device is active and the link is usable, the
endpoint may generate a PME, which is then handled by the PCI core through
PME polling or the PCIe PME service driver to complete the wakeup of the
endpoint.
WAKE# is added in dts schema and merged based on below links.
Link: https://lore.kernel.org/all/20250515090517.3506772-1-krishna.chundru@oss.qualcomm.com/
Link: https://github.com/devicetree-org/dt-schema/pull/170
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
drivers/pci/of.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pci.c | 10 +++++++
drivers/pci/pci.h | 2 ++
drivers/pci/probe.c | 2 ++
drivers/pci/remove.c | 1 +
include/linux/of_pci.h | 4 +++
include/linux/pci.h | 2 ++
7 files changed, 95 insertions(+)
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 9f8eb5df279ed28db7a3b2fd29c65da9975c2efa..1678e82962b78ac206829a3a1fc121b0142b993b 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -7,6 +7,7 @@
#define pr_fmt(fmt) "PCI: OF: " fmt
#include <linux/cleanup.h>
+#include <linux/gpio/consumer.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -15,6 +16,7 @@
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include "pci.h"
#ifdef CONFIG_PCI
@@ -586,6 +588,78 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
return irq_create_of_mapping(&oirq);
}
EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
+
+static void pci_configure_wake_irq(struct pci_dev *pdev, struct gpio_desc *wake)
+{
+ int ret, wake_irq;
+
+ wake_irq = gpiod_to_irq(wake);
+ if (wake_irq < 0) {
+ pci_err(pdev, "Failed to get wake irq: %d\n", wake_irq);
+ return;
+ }
+
+ /*
+ * dev_pm_set_dedicated_shared_wake_irq() associates a wakeup IRQ with the
+ * device and requests it, but the PM core keeps it disabled by default.
+ * The IRQ is enabled only when the device is allowed to wake the system
+ * (during system suspend and after runtime suspend), and only if device
+ * wakeup is enabled.
+ *
+ * When the wake IRQ fires, the wakeirq handler invokes pm_runtime_resume()
+ * to bring the device back to an active power state (e.g. from D3cold to D0).
+ * Once the device is active and the link is usable, the endpoint may signal
+ * a PME, which is then handled by the PCI core (either via PME polling or the
+ * PCIe PME service driver) to wakeup particular endpoint.
+ */
+ ret = dev_pm_set_dedicated_shared_wake_irq(&pdev->dev, wake_irq,
+ IRQ_TYPE_LEVEL_LOW);
+ if (ret < 0) {
+ pci_err(pdev, "Failed to set WAKE# IRQ: %d\n", ret);
+ return;
+ }
+
+ device_init_wakeup(&pdev->dev, true);
+}
+
+void pci_configure_of_wake_gpio(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ struct pci_dev *upstream;
+ struct gpio_desc *gpio;
+
+ if (!dn)
+ return;
+
+ /*
+ * The devices in a hierarchy expose wakeup capability through the 'wake-gpios'
+ * property defined either in the device node or in the Slot node. So first check
+ * for the property in device node and if not available, check in the Slot node.
+ */
+ gpio = fwnode_gpiod_get(of_fwnode_handle(dn), "wake",
+ GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE, NULL);
+ if (IS_ERR(gpio)) {
+ upstream = pci_upstream_bridge(dev);
+ if (upstream && pci_is_root_bus(upstream->bus) && upstream->wake)
+ pci_configure_wake_irq(dev, upstream->wake);
+ } else {
+ dev->wake = gpio;
+ pci_configure_wake_irq(dev, gpio);
+ }
+}
+
+void pci_remove_of_wake_gpio(struct pci_dev *dev)
+{
+ struct device_node *dn = pci_device_to_OF_node(dev);
+
+ if (!dn)
+ return;
+
+ dev_pm_clear_wake_irq(&dev->dev);
+ device_init_wakeup(&dev->dev, false);
+ gpiod_put(dev->wake);
+ dev->wake = NULL;
+}
#endif /* CONFIG_OF_IRQ */
static int pci_parse_request_of_pci_ranges(struct device *dev,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8479c2e1f74f1044416281aba11bf071ea89488a..3d858f36ab48a6daec645574ca9027d9d6f071de 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -17,6 +17,7 @@
#include <linux/lockdep.h>
#include <linux/msi.h>
#include <linux/of.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -1123,6 +1124,15 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
return acpi_pci_bridge_d3(dev);
}
+void platform_pci_configure_wake(struct pci_dev *dev)
+{
+ return pci_configure_of_wake_gpio(dev);
+}
+
+void platform_pci_remove_wake(struct pci_dev *dev)
+{
+ return pci_remove_of_wake_gpio(dev);
+}
/**
* pci_update_current_state - Read power state of given device and cache it
* @dev: PCI device to handle.
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 13d998fbacce6698514d92500dfea03cc562cdc2..65ca9551e558d2e3331fab0a968620d6b2a2522a 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -282,6 +282,8 @@ void pci_msix_init(struct pci_dev *dev);
bool pci_bridge_d3_possible(struct pci_dev *dev);
void pci_bridge_d3_update(struct pci_dev *dev);
int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type);
+void platform_pci_configure_wake(struct pci_dev *dev);
+void platform_pci_remove_wake(struct pci_dev *dev);
static inline bool pci_bus_rrs_vendor_id(u32 l)
{
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bccc7a4bdd794384b7877d453c7989941471c999..372b0d2f4531ea53c0570608306a547101d59e7b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2771,6 +2771,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Establish pdev->tsm for newly added (e.g. new SR-IOV VFs) */
pci_tsm_init(dev);
+ platform_pci_configure_wake(dev);
+
pci_npem_create(dev);
pci_doe_sysfs_init(dev);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index e9d519993853f92f1810d3eff9f44ca7e3e1abd9..d781b41e57c4444077075690cec926a9fe15334f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -35,6 +35,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
if (pci_dev_test_and_set_removed(dev))
return;
+ platform_pci_remove_wake(dev);
pci_doe_sysfs_teardown(dev);
pci_npem_remove(dev);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 29658c0ee71ff10122760214d04ee2bab01709fd..0efd6e9cb4d3d3beaafb42ea411303139f1150d5 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -30,12 +30,16 @@ static inline void of_pci_check_probe_only(void) { }
#if IS_ENABLED(CONFIG_OF_IRQ)
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
+void pci_configure_of_wake_gpio(struct pci_dev *dev);
+void pci_remove_of_wake_gpio(struct pci_dev *dev);
#else
static inline int
of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
{
return 0;
}
+static inline void pci_configure_of_wake_gpio(struct pci_dev *dev) { }
+static inline void pci_remove_of_wake_gpio(struct pci_dev *dev) { }
#endif
#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1c270f1d512301de4d462fe7e5097c32af5c6f8d..d1e08df8a8deaa87780589f23242767fdcdba541 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -586,6 +586,8 @@ struct pci_dev {
/* These methods index pci_reset_fn_methods[] */
u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */
+ struct gpio_desc *wake; /* Holds WAKE# gpio */
+
#ifdef CONFIG_PCIE_TPH
u16 tph_cap; /* TPH capability offset */
u8 tph_mode; /* TPH mode */
--
2.34.1
^ permalink raw reply related
* RE: [PATCh v3 05/14] ASoC: rsnd: Add audmacpp clock and reset support for RZ/G3E
From: John Madieu @ 2026-04-03 17:39 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <87o6k0g8e3.wl-kuninori.morimoto.gx@renesas.com>
Hi Kuninori,
Thanks for your review.
> -----Original Message-----
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Sent: Friday, April 3, 2026 3:06 AM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 05/14] ASoC: rsnd: Add audmacpp clock and reset
> support for RZ/G3E
>
>
> Hi John
>
> Thank you for your patch
>
> > RZ/G3E requires additional audmapp clock and reset lines for Audio
> > DMA-PP operation.
> >
> > Add global audmacpp clock/reset management in rsnd_dma_probe() using
> > optional APIs to remain transparent to other platforms.
> >
> > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> > ---
> (snip)
> > --- a/sound/soc/renesas/rcar/rsnd.h
> > +++ b/sound/soc/renesas/rcar/rsnd.h
> > @@ -623,6 +623,13 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv
> > *priv, struct seq_file *m); struct rsnd_priv {
> >
> > struct platform_device *pdev;
> > +
> > + /*
> > + * below value will be filled on rsnd_dma_probe()
> > + */
> > + struct clk *audmapp_clk;
> > + struct reset_control *audmapp_rstc;
>
> I think it is DMA specific.
> I think we can move it to struct rsnd_dma, instead of in rsnd_priv ?
Agreed. I'll move audmapp_clk and audmapp_rstc into struct rsnd_dma_ctrl
in dma.c since they are used only there.
Regards,
John
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply
* Re: [PATCH v20 06/10] power: reset: Add psci-reboot-mode driver
From: Shivendra Pratap @ 2026-04-03 17:45 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Arnd Bergmann, Bjorn Andersson, Sebastian Reichel, Rob Herring,
Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
John Stultz, Moritz Fischer, Bartosz Golaszewski, Sudeep Holla,
Florian Fainelli, Krzysztof Kozlowski, Dmitry Baryshkov,
Mukesh Ojha, Andre Draszik, Kathiravan Thirumoorthy, linux-pm,
linux-kernel, linux-arm-kernel, linux-arm-msm, devicetree,
Srinivas Kandagatla
In-Reply-To: <ac/hru3IIiU0+Lp9@lpieralisi>
On 03-04-2026 21:20, Lorenzo Pieralisi wrote:
> On Fri, Apr 03, 2026 at 12:05:27AM +0530, Shivendra Pratap wrote:
>>
>>
>> On 01-04-2026 20:07, Lorenzo Pieralisi wrote:
>>> On Tue, Mar 31, 2026 at 11:30:09PM +0530, Shivendra Pratap wrote:
>>>>
>>>>
>>>> On 27-03-2026 19:25, Lorenzo Pieralisi wrote:
>>>>> On Wed, Mar 04, 2026 at 11:33:06PM +0530, Shivendra Pratap wrote:
>>>>>> PSCI supports different types of resets like COLD reset, ARCH WARM
>>
>> [snip..]
>>
>>>>>> + * Predefined reboot-modes are defined as per the values
>>>>>> + * of enum reboot_mode defined in the kernel: reboot.c.
>>>>>> + */
>>>>>> +static struct mode_info psci_resets[] = {
>>>>>> + { .mode = "warm", .magic = REBOOT_WARM},
>>>>>> + { .mode = "soft", .magic = REBOOT_SOFT},
>>>>>> + { .mode = "cold", .magic = REBOOT_COLD},
>>>
>>> These strings match the command userspace issue right ? I think that we
>>> should make them match the corresponding PSCI reset types, the list above
>>> maps command to reboot_mode values and those can belong to any reboot
>>> mode driver to be honest they don't make much sense in a PSCI reboot
>>> mode driver only.
>>>
>>> It is a question for everyone here: would it make sense to make these
>>> predefined resets a set of strings, eg:
>>>
>>> psci-system-reset
>>> psci-system-reset2-arch-warm-reset
>>>
>>> and then vendor resets:
>>>
>>> psci-system-reset2-vendor-reset
>>
>> Can you share bit more details on this? We are already defining the string
>> from userspace in the struct - eg: ".mode = "warm".
>
> "warm","soft","cold" are not strictly speaking PSCI concepts and mean nothing
> well defined to user space and even if they did, they would not belong in
> the PSCI reboot mode driver but in generic code.
>
> Spelling out what a reset is might help instead, again, this is just my
> opinion, I don't know how the semantics of resets have been handled thus
> far.
>
> If userspace issues a LINUX_REBOOT_CMD_RESTART2 with arg, say,
> "psci-system-reset2-arch-warm-reset" it is pretty clear what it wants
> to do in PSCI.
ok. got it.
so it predef-modes.
reboot psci-system-reset2-arch-warm-reset =>goes for => ARCH WARM RESET.
etc..
>
> Again, it is a suggestion, comments welcome.
>
>> yes we can move away from enum reboot_mode and use custom psci defines one -
>> Ack.
>>
>>>
>>
>> [snip ..]
>>
>>>>>> +
>>>>>> +/*
>>>>>> + * arg1 is reset_type(Low 32 bit of magic).
>>>>>> + * arg2 is cookie(High 32 bit of magic).
>>>>>> + * If reset_type is 0, cookie will be used to decide the reset command.
>>>>>> + */
>>>>>> +static int psci_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic)
>>>>>> +{
>>>>>> + u32 reset_type = REBOOT_MODE_ARG1(magic);
>>>>>> + u32 cookie = REBOOT_MODE_ARG2(magic);
>>>>>> +
>>>>>> + if (reset_type == 0) {
>>>>>> + if (cookie == REBOOT_WARM || cookie == REBOOT_SOFT)
>>>>>> + psci_set_reset_cmd(true, 0, 0);
>>>>>> + else
>>>>>> + psci_set_reset_cmd(false, 0, 0);
>>>>>> + } else {
>>>>>> + psci_set_reset_cmd(true, reset_type, cookie);
>>>>>> + }
>>>>>
>>>>> I don't think that psci_set_reset_cmd() has the right interface (and this
>>>>> nested if is too complicated for my taste). All we need to pass is reset-type
>>>>> and cookie (and if the reset is one of the predefined ones, reset-type is 0
>>>>> and cookie is the REBOOT_* cookie).
>>>>>
>>>>> Then the PSCI firmware driver will take the action according to what
>>>>> resets are available.
>>>>>
>>>>> How does it sound ?
>>>>
>>>> So we mean these checks will move to the psci driver? Sorry for re-iterating
>>>> the question.
>>>
>>> Given what I say above, I believe that something we can do is mapping the magic
>>> to an enum like:
>>>
>>> PSCI_SYSTEM_RESET
>>> PSCI_SYSTEM_RESET2_ARCH_SYSTEM_WARM_RESET
>>> PSCI_SYSTEM_RESET2_VENDOR_RESET
>>>
>>> and can add a probe function into PSCI driver similar to psci_has_osi_support() but
>>> to probe for SYSTEM_RESET2 and initialize the predefined strings accordingly,
>>> depending on its presence.
>>
>> Not able to get it cleanly.
>>
>> 1. Will move away from reboot_mode enum for pre-defined modes and define new
>> enum defining these modes- fine.
>> 2. get SYSTEM_RESET2 is supported from psci exported function -- fine, but
>> how we use it here now, as we do not want to send the reset_cmd from
>> psci_set_reset_cmd now?
>
> You do keep psci_set_reset_cmd() but all it is used for is setting a struct
> shared with the PSCI driver where you initialize the enum above, possibly
> with a cookie if it is a vendor reset.
>
>> 3. For pre-defined modes, warm/soft or cold - reset_type and cookie, both
>> are zero, sys_reset2 or sys_reset2 decides the ARCH reset vs cold reset.
>> 4. For vendor-rest , we use sys_reset2 with reset_type and cookie.
>
> Yes.
Ack.
>> All above is done in reboot_notifier call at psci-reboot-mode.
>> --
>>
>> Now in the final restart_notifier->psci_sys_reset --
>>
>> If panic is in progress, we do not use any of the cmd based reset params and
>> go with the legacy reset. So we need to preserve the values that were set
>> from psci-reboot-mode.
>>
>> Did not understand the proposed suggestion in above usecase. Need more input
>> on this.
>
> I explained above. The reboot mode driver sets the command to carry out
> depending on the string coming from user space and whether PSCI supports
> SYSTEM_RESET2 or not.
got it. working on it. thanks.
>> --
>>
>> One other option is to have a restart_notifier in psci-reboot-mode, with
>> lesser priority than psci_sys_rest and then handle all the case including
>> panic and sys_reset2.
>
> No.
Ack.
thanks,
Shivendra
^ permalink raw reply
* RE: [PATCh v3 06/14] ASoC: rsnd: Add RZ/G3E DMA address calculation support
From: John Madieu @ 2026-04-03 18:10 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <87mrzkg89l.wl-kuninori.morimoto.gx@renesas.com>
Hi Kuninori,
Thanks for your review.
> -----Original Message-----
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Sent: Friday, April 3, 2026 3:09 AM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 06/14] ASoC: rsnd: Add RZ/G3E DMA address
> calculation support
>
>
> Hi John
>
> Thank you for your patch
>
> > RZ/G3E has different DMA register base addresses and offset
> > calculations compared to R-Car platforms.
> >
> > Add dedicated rsnd_rzg3e_dma_addr() function with dispatch from
> > rsnd_dma_addr(), following the existing per-generation pattern.
> >
> > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> > ---
> (snip)
> > diff --git a/sound/soc/renesas/rcar/dma.c
> > b/sound/soc/renesas/rcar/dma.c index 0afe4636b005..5b63206361ef 100644
> > --- a/sound/soc/renesas/rcar/dma.c
> > +++ b/sound/soc/renesas/rcar/dma.c
> > @@ -496,7 +496,35 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
> > * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
> > * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
> > * CMD : 0xec500000 / / 0xec008000 0xec308000
> > + *
> > + * ex) G3E case
> > + * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp
> out
> > + * SSI : 0x13C31000 / 0x13C40000 / 0x13C40000
> > + * SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000
> > + * SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000
> > + * CMD : 0x13C00000 / / 0x13C18000 0xEC308000
> > */
> > +
> > +/* RZ/G3E DMA address macros */
> > +#define RDMA_SSI_I_N_G3E(addr, i) (addr ##_reg + 0x0000F000 +
> (0x1000 * i))
> > +#define RDMA_SSI_O_N_G3E(addr, i) (addr ##_reg + 0x0000F000 +
> (0x1000 * i))
> > +
> > +#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 +
> (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 *
> ((i) / 9) * ((j) / 4)))
> > +#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j)
> > +
> > +#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 +
> (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 *
> ((i) / 9) * ((j) / 4)))
> > +#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j)
> > +
> > +#define RDMA_SRC_I_N_G3E(addr, i) (addr ##_reg + 0x00010000 +
> (0x400 * i))
> > +#define RDMA_SRC_O_N_G3E(addr, i) (addr ##_reg + 0x00014000 +
> (0x400 * i))
> > +
> > +#define RDMA_SRC_I_P_G3E(addr, i) (addr ##_reg + 0xD8700000 +
> (0x400 * i))
> > +#define RDMA_SRC_O_P_G3E(addr, i) (addr ##_reg + 0xD8704000 +
> (0x400 * i))
> > +
> > +#define RDMA_CMD_O_N_G3E(addr, i) (addr ##_reg + 0x00018000 +
> (0x400 * i))
> > +#define RDMA_CMD_O_P_G3E(addr, i) (addr ##_reg + 0xD8708000 +
> (0x400 * i))
>
> Please add RZ/G3E info on top of rzg3e_dma_addr()
>
> > +/* R-Car DMA address macros */
> > #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i)
> + 0x8)
> > #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i)
> + 0xc)
>
> And R-Car Gen2 info to gen2_dma_addr()
>
> > +rsnd_dma_addr_lookup(struct rsnd_dai_stream *io,
> > + struct rsnd_mod *mod,
> > + const struct rsnd_dma_addr tbl[3][2][3],
> > + int is_play, int is_from)
> > {
> > - struct rsnd_priv *priv = rsnd_io_to_priv(io);
> > - struct device *dev = rsnd_priv_to_dev(priv);
> > - phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
> > - phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
> > + struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
>
> Creating lookup() is nice idea.
> Very nitpick, but do we need to remove priv, and remake dev ?
>
> > @@ -574,20 +671,10 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
> > * out of calculation rule
> > */
> > if ((id == 9) && (busif >= 4))
> > - dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
> > - id, busif);
> > -
> > - /* it shouldn't happen */
> > - if (use_cmd && !use_src)
> > - dev_err(dev, "DVC is selected without SRC\n");
> > -
> > - /* use SSIU or SSI ? */
> > - if (is_ssi && rsnd_ssi_use_busif(io))
> > - is_ssi++;
> > + dev_err(rsnd_priv_to_dev(priv),
> > + "This driver doesn't support SSI%d-%d, so far", id,
> busif);
>
> Very nitpick, but please keep dev on top.
>
I'll address your comments in v4, moving each macro on top of the
appropriate function and keep dev, avoiding remaking it, and also
pass priv as parameter to rsnd_dma_addr_lookup.
Regards,
John
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply
* Re: [PATCH v7 2/3] ufs: host: Add ICE clock scaling during UFS clock changes
From: Abhinaba Rakshit @ 2026-04-03 18:11 UTC (permalink / raw)
To: Harshal Dev
Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
Neeraj Soni, linux-arm-msm, linux-crypto, devicetree,
linux-kernel, linux-scsi
In-Reply-To: <7fbd9d3f-a313-40dd-9335-799aea5a077a@oss.qualcomm.com>
On Mon, Mar 30, 2026 at 08:09:51PM +0530, Harshal Dev wrote:
> > drivers/ufs/host/ufs-qcom.c | 19 ++++++++++++++++++-
> > 1 file changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
> > index 8d119b3223cbdaa3297d2beabced0962a1a847d5..776444f46fe5f00f947e4b0b4dfe6d64e2ad2150 100644
> > --- a/drivers/ufs/host/ufs-qcom.c
> > +++ b/drivers/ufs/host/ufs-qcom.c
> > @@ -305,6 +305,15 @@ static int ufs_qcom_ice_prepare_key(struct blk_crypto_profile *profile,
> > return qcom_ice_prepare_key(host->ice, lt_key, lt_key_size, eph_key);
> > }
> >
> > +static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
> > + bool round_ceil)
> > +{
> > + if (host->hba->caps & UFSHCD_CAP_CRYPTO)
> > + return qcom_ice_scale_clk(host->ice, target_freq, round_ceil);
> > +
> > + return 0;
> > +}
> > +
> > static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops = {
> > .keyslot_program = ufs_qcom_ice_keyslot_program,
> > .keyslot_evict = ufs_qcom_ice_keyslot_evict,
> > @@ -339,6 +348,12 @@ static void ufs_qcom_config_ice_allocator(struct ufs_qcom_host *host)
> > {
> > }
> >
> > +static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
> > + bool round_ceil)
> > +{
> > + return 0;
> > +}
> > +
> > #endif
> >
> > static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
> > @@ -1646,8 +1661,10 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
> > else
> > err = ufs_qcom_clk_scale_down_post_change(hba, target_freq);
> >
> > + if (!err)
> > + err = ufs_qcom_ice_scale_clk(host, target_freq, !scale_up);
> >
> > - if (err) {
> > + if (err && err != -EOPNOTSUPP) {
>
> Using -EOPNOTSUPP here works fine for now. But anyone touching any of the lower APIs called by
> ufs_qcom_clk_scale_up/down_post_change() needs to ensure they don't return -EOPNOTSUPP, otherwise
> hibernate exit will be skipped. So this carries a minor risk of breaking.
>
> Since regardless of whether ufs_qcom_clk_scale_up/down_post_change() fails or ufs_qcom_ice_scale_clk()
> fails, we exit from hibernate and return from this function, I suggest you handle the error for ice_scale
> separately.
>
> > ufshcd_uic_hibern8_exit(hba);
> > return err;
> > }
> >
>
> Add the call to ufs_qcom_ice_scale_clk() along with error handle here, and let the above error handle
> remain untouched.
>
> err = ufs_qcom_ice_scale_clk(host, target_freq, !scale_up);
> if (err && err != -EOPNOTSUPP) {
> ufshcd_uic_hibern8_exit(hba);
> return err;
> }
>
Right, I did think of this later.
Yes, this needs change.
Ack will update in the v8 patchset.
Thanks.
Abhinaba Rakshit
^ permalink raw reply
* Re: [PATCH v7 3/3] soc: qcom: ice: Set ICE clk to TURBO on probe
From: Abhinaba Rakshit @ 2026-04-03 18:14 UTC (permalink / raw)
To: Harshal Dev
Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Manivannan Sadhasivam, James E.J. Bottomley, Martin K. Petersen,
Neeraj Soni, linux-arm-msm, linux-crypto, devicetree,
linux-kernel, linux-scsi, Konrad Dybcio
In-Reply-To: <90375d37-0440-48d9-a3d3-b0b442839d89@oss.qualcomm.com>
On Mon, Mar 30, 2026 at 08:14:13PM +0530, Harshal Dev wrote:
> >> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> >> index 7976a18d9a4cda1ad6b62b66ce011e244d0f6856..e8ee02a709574afa4ebb8e4395a8d899bf1d4976 100644
> >> --- a/drivers/soc/qcom/ice.c
> >> +++ b/drivers/soc/qcom/ice.c
> >> @@ -659,6 +659,13 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
> >> dev_info(dev, "ICE OPP table is not registered, please update your DT\n");
> >> }
> >>
> >> + if (engine->has_opp) {
> >> + /* Vote for maximum clock rate for maximum performance */
> >> + err = dev_pm_opp_set_rate(dev, INT_MAX);
> >> + if (err)
> >> + dev_warn(dev, "Failed boosting the ICE clk to TURBO\n");
> >> + }
> >> +
> >> engine->core_clk_freq = clk_get_rate(engine->core_clk);
> >> if (!qcom_ice_check_supported(engine))
> >> return ERR_PTR(-EOPNOTSUPP);
> >
> > Hi Konrad
> >
> > Since you previously reviewed this change, I wanted to share an improved approach
> > that I recently realized for handling ICE clock scaling in the MMC use‑case.
> >
> > So far, we have been voting for the maximum frequency during the ICE device probe
> > to align with MMC requirements.
> > But because the ICE probe is common across different storage clients, applying
> > the MAX vote at probe time may unintentionally impact other storage paths.
> >
> > Now that we have a generic scaling API exposed, we can make this logic
> > MMC‑specific instead. In particular, within sdhci_msm_ice_init().
> > https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/drivers/mmc/host/sdhci-msm.c#n1966,
> > we can invoke: qcom_ice_scale_clk(ice, INT_MAX, false);
> >
>
> I agree, this is better instead of blindly turning the clk freq to maximum.
>
> I was about to ask you to move this to qcom_ice_probe() as per comments in previous
> commit. However, since you have mentioned this now, I suggest adding a call in
> sdhci_msm_ice_init() to qcom_ice_clk_scale() immediately after it calls qcom_ice_create().
Sure, thanks.
Will update it in patchset v8.
Abinaba Rakshit
^ permalink raw reply
* [PATCH 0/2] Add USB Ethernet controller (LAN7500) node in VAR-SOM-OM44 devicetree
From: Thomas Richard @ 2026-04-03 19:02 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
Tony Lindgren
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel, linux-omap,
Thomas Richard
The goal of this series is to add the USB Ethernet controller node in the
VAR-SOM-OM44 devicetree in order to allow the bootloader to patch the
devicetree and pass a MAC address to the smsc75xx driver. This was also a
good opportunity to create the schema file for LAN75XX devices.
Signed-off-by: Thomas Richard <thomas.richard@bootlin.com>
---
Thomas Richard (2):
dt-bindings: net: Add schema for LAN75XX compatible USB Ethernet controllers
ARM: dts: ti: var-som-om44: Add USB Ethernet controller node
.../devicetree/bindings/net/microchip,lan75xx.yaml | 52 ++++++++++++++++++++++
arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi | 14 ++++++
2 files changed, 66 insertions(+)
---
base-commit: 6fa0f2cbadc046c57fdd2aa1dad81553cca08963
change-id: 20260330-b4-var-som-om44-lan7500-09dfdc713d39
Best regards,
--
Thomas Richard <thomas.richard@bootlin.com>
^ permalink raw reply
* [PATCH 1/2] dt-bindings: net: Add schema for LAN75XX compatible USB Ethernet controllers
From: Thomas Richard @ 2026-04-03 19:02 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
Tony Lindgren
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel, linux-omap,
Thomas Richard
In-Reply-To: <20260403-b4-var-som-om44-lan7500-v1-0-0dadde850143@bootlin.com>
Create schema for LAN75XX compatible USB Ethernet controllers. The smsc75xx
driver only supports LAN7500 and LAN7505 devices.
Signed-off-by: Thomas Richard <thomas.richard@bootlin.com>
---
.../devicetree/bindings/net/microchip,lan75xx.yaml | 52 ++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/microchip,lan75xx.yaml b/Documentation/devicetree/bindings/net/microchip,lan75xx.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b84022976044ffec2024cff9fc0aa5016723abed
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/microchip,lan75xx.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/microchip,lan75xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip LAN7500/LAN7505 USB Ethernet Controllers
+
+maintainers:
+ - Thomas Richard <thomas.richard@bootlin.com>
+
+description:
+ Device tree properties for LAN75XX compatible USB Ethernet controller.
+
+allOf:
+ - $ref: ethernet-controller.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - usb424,7500
+ - usb424,7505
+
+ reg:
+ maxItems: 1
+
+ local-mac-address: true
+ mac-address: true
+ nvmem-cells: true
+ nvmem-cell-names: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ usb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet@1 {
+ compatible = "usb424,7500";
+ reg = <1>;
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ };
--
2.53.0
^ permalink raw reply related
* [PATCH 2/2] ARM: dts: ti: var-som-om44: Add USB Ethernet controller node
From: Thomas Richard @ 2026-04-03 19:02 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
Tony Lindgren
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel, linux-omap,
Thomas Richard
In-Reply-To: <20260403-b4-var-som-om44-lan7500-v1-0-0dadde850143@bootlin.com>
Add USB tree description, including the Gigabit Ethernet controller
(LAN7500). Adding the LAN7500 node will allow the bootloader to patch the
devicetree and set the MAC address.
Signed-off-by: Thomas Richard <thomas.richard@bootlin.com>
---
arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi
index 37d56b3010cff0f6ea6208289da0aba7328067d5..9e04aa70f98227ac0054fea6cd4521ed1323ecbd 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi
@@ -322,4 +322,18 @@ &usbhshost {
&usbhsehci {
phys = <&hsusb1_phy>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbhub: hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: ethernet@3 {
+ compatible = "usb424,7500";
+ reg = <3>;
+ };
+ };
};
--
2.53.0
^ permalink raw reply related
* RE: [PATCh v3 07/14] ASoC: rsnd: ssui: Add RZ/G3E SSIU BUSIF support
From: John Madieu @ 2026-04-03 19:10 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <87ldf4g893.wl-kuninori.morimoto.gx@renesas.com>
Hi Kuninori,
Thanks for your review.
> -----Original Message-----
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Sent: Friday, April 3, 2026 3:09 AM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 07/14] ASoC: rsnd: ssui: Add RZ/G3E SSIU BUSIF
> support
>
>
> Hi John
>
> Thank you for your patch
>
> > Add support for the SSIU found on the Renesas RZ/G3E SoC, which
> > provides a different BUSIF layout compared to earlier generations:
> >
> > - SSI0-SSI4: 4 BUSIF instances each (BUSIF0-3)
> > - SSI5-SSI8: 1 BUSIF instance each (BUSIF0 only)
> > - SSI9: 4 BUSIF instances (BUSIF0-3)
> > - Total: 28 BUSIFs
> >
> > RZ/G3E also differs from Gen2/Gen3 implementations in that only two
> > pairs of BUSIF error-status registers are available instead of four,
> > and the SSI always operates in BUSIF mode with no PIO fallback.
> >
> > Rather than scattering SoC-specific checks across functional code,
> > introduce an extra capability flags in the match data:
> >
> > - RSND_SSIU_BUSIF_STATUS_COUNT_2: only two BUSIF error-status
> > register pairs are present. Used in rsnd_ssiu_busif_err_irq_ctrl()
> > and rsnd_ssiu_busif_err_status_clear() to limit register iteration.
> >
> > Future SoCs sharing these constraints can set the flags without
> > requiring code changes.
> >
> > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> > ---
> (snip)
> > @@ -72,7 +73,7 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct
> rsnd_mod *mod, int enable)
> > return;
> > }
> >
> > - for (i = 0; i < 4; i++) {
> > + for (unsigned int i = 0; i < priv->ssiu_busif_count; i++) {
> > enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
> > u32 val = 0xf << (shift * 4);
> > u32 sys_int_enable = rsnd_mod_read(mod, reg);
> (snip)
> > @@ -109,7 +110,7 @@ bool rsnd_ssiu_busif_err_status_clear(struct
> rsnd_mod *mod)
> > goto out;
> > }
> >
> > - for (i = 0; i < 4; i++) {
> > + for (unsigned int i = 0; i < priv->ssiu_busif_count; i++) {
> > u32 reg = SSI_SYS_STATUS(i * 2) + offset;
> > u32 status = rsnd_mod_read(mod, reg);
> > u32 val = 0xf << (shift * 4);
>
> ssiu_busif_count is for SSIU specific, no need to have it on priv.
> Please move it on rsnd_ssiu.
Agreed. However, since this is per-SoC, I would rather use a
file-static variable, rather thatn per ssiu instance in rsnd_ssiu.
I hope this is fine for you.
Regards,
John
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply
* RE: [PATCh v3 07/14] ASoC: rsnd: ssui: Add RZ/G3E SSIU BUSIF support
From: John Madieu @ 2026-04-03 19:15 UTC (permalink / raw)
To: Mark Brown
Cc: Kuninori Morimoto, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <a457c427-95bf-43be-84db-02144fcc2bd6@sirena.org.uk>
Hi Mark,
Thanks for your review.
> -----Original Message-----
> From: Mark Brown <broonie@kernel.org>
> Sent: Thursday, April 2, 2026 7:54 PM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 07/14] ASoC: rsnd: ssui: Add RZ/G3E SSIU BUSIF
> support
>
> On Thu, Apr 02, 2026 at 06:24:29PM +0200, John Madieu wrote:
>
> > Rather than scattering SoC-specific checks across functional code,
> > introduce an extra capability flags in the match data:
>
> > bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod) {
> > + struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
>
> There's a priv already in the if (status) check in the loop in this
> function.
Right. I'll remove it in v4.
>
> > @@ -160,7 +161,8 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
> > /*
> > * SSI_MODE0
> > */
> > - rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
> > + if (!rsnd_is_rzg3e(priv))
> > + rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
>
> Perhaps should be a capability flag like the changelog said?
I'll update the changelog to accurately describe things.
>
> > + /* Acquire shared reset once for all SSIU modules */
> > + rstc = devm_reset_control_get_optional_shared(dev, "ssi-all");
> > + if (IS_ERR(rstc))
> > + rstc = NULL;
>
> This just ignores actual errors, including -EPROBE_DEFER. I would expect
> us to report all errors as normal, the reset API will already return NULL
> for genuinely absent resets.
Indeed. I'll properly propagate the error via dev_err_probe() instead.
Regards,
John
^ permalink raw reply
* RE: [PATCh v3 08/14] ASoC: rsnd: Add SSI reset support for RZ/G3E platforms
From: John Madieu @ 2026-04-03 19:23 UTC (permalink / raw)
To: Mark Brown
Cc: Kuninori Morimoto, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <cbd544c2-cfe5-4eb3-b414-7f3fc9b57346@sirena.org.uk>
Hi Mark,
Thanks for the review.
> -----Original Message-----
> From: Mark Brown <broonie@kernel.org>
> Sent: Thursday, April 2, 2026 7:58 PM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 08/14] ASoC: rsnd: Add SSI reset support for RZ/G3E
> platforms
>
> On Thu, Apr 02, 2026 at 06:24:30PM +0200, John Madieu wrote:
> > Add SSI reset support for the Renesas RZ/G3E SoC, which differs from
> > earlier generations in several ways:
> >
> > - The SSI block always operates in BUSIF mode; RZ/G3E does not
> implement
> > the SSITDR/SSIRDR registers used by R-Car Gen2/Gen3/Gen4 for direct
> SSI
> > DMA. Consequently, all audio data must pass through BUSIF.
>
> Does the driver still support PIO mode?
Yes, it does. I'll update the commit message accordingly,
to reflect that.
Regards,
John.
^ permalink raw reply
* Re: [PATCH 5/6] arm64: dts: qcom: milos: Add IPA node
From: Dmitry Baryshkov @ 2026-04-03 19:27 UTC (permalink / raw)
To: Luca Weiss
Cc: Alex Elder, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Alexander Koskovich,
~postmarketos/upstreaming, phone-devel, netdev, linux-kernel,
linux-arm-msm, devicetree
In-Reply-To: <20260403-milos-ipa-v1-5-01e9e4e03d3e@fairphone.com>
On Fri, Apr 03, 2026 at 06:43:51PM +0200, Luca Weiss wrote:
> Add the description of the IPA block in the Milos SoC.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos.dtsi | 44 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 44 insertions(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 6/6] arm64: dts: qcom: milos-fairphone-fp6: Enable IPA
From: Dmitry Baryshkov @ 2026-04-03 19:27 UTC (permalink / raw)
To: Luca Weiss
Cc: Alex Elder, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Alexander Koskovich,
~postmarketos/upstreaming, phone-devel, netdev, linux-kernel,
linux-arm-msm, devicetree
In-Reply-To: <20260403-milos-ipa-v1-6-01e9e4e03d3e@fairphone.com>
On Fri, Apr 03, 2026 at 06:43:52PM +0200, Luca Weiss wrote:
> Configure and enable the node for IPA which enables mobile data on this
> device.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> index c1899db46e71..31c6d6627619 100644
> --- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> +++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> @@ -690,6 +690,15 @@ vreg_l7p: ldo7 {
> /* AW86938FCR vibrator @ 0x5a */
> };
>
> +&ipa {
> + firmware-name = "qcom/milos/fairphone/fp6/ipa_fws.mbn";
> + memory-region = <&ipa_fw_mem>;
> +
> + qcom,gsi-loader = "self";
Are these two common to all Milos devices? Should they be a part of the
milos.dtsi?
> +
> + status = "okay";
> +};
> +
> &pm8550vs_c {
> status = "okay";
> };
>
> --
> 2.53.0
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH 2/2] arm64: dts: qcom: milos: Add IMEM node
From: Dmitry Baryshkov @ 2026-04-03 19:30 UTC (permalink / raw)
To: Luca Weiss
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, ~postmarketos/upstreaming, phone-devel,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260403-milos-imem-v1-2-4244ebb47017@fairphone.com>
On Fri, Apr 03, 2026 at 05:00:24PM +0200, Luca Weiss wrote:
> Add a node for the IMEM found on Milos, which contains pil-reloc-info
> and the modem tables for IPA, among others.
>
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
> arch/arm64/boot/dts/qcom/milos.dtsi | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
> index 4a64a98a434b..1c045743ef77 100644
> --- a/arch/arm64/boot/dts/qcom/milos.dtsi
> +++ b/arch/arm64/boot/dts/qcom/milos.dtsi
> @@ -2289,6 +2289,25 @@ scl-pins {
> };
> };
>
> + sram@14680000 {
> + compatible = "qcom,milos-imem", "syscon", "simple-mfd";
I think, the latest trend is to describe IMEM as a mmio-sram.
> + reg = <0x0 0x14680000 0x0 0x2c000>;
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + ranges = <0 0 0x14680000 0x2c000>;
> +
> + pil-reloc@94c {
> + compatible = "qcom,pil-reloc-info";
> + reg = <0x94c 0xc8>;
> + };
> +
> + ipa_modem_tables: modem-tables@3000 {
> + reg = <0x3000 0x2000>;
> + };
> + };
> +
> apps_smmu: iommu@15000000 {
> compatible = "qcom,milos-smmu-500", "qcom,smmu-500", "arm,mmu-500";
> reg = <0x0 0x15000000 0x0 0x100000>;
>
> --
> 2.53.0
>
--
With best wishes
Dmitry
^ permalink raw reply
* RE: [PATCh v3 09/14] ASoC: rsnd: Add ADG reset support for RZ/G3E
From: John Madieu @ 2026-04-03 19:30 UTC (permalink / raw)
To: geert
Cc: Kuninori Morimoto, Mark Brown, Liam Girdwood, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
magnus.damm, Philipp Zabel, Claudiu.Beznea, Biju Das,
john.madieu@gmail.com, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CAMuHMdUHzcq_f8t0hi-FjiG2FByNmx8k2sz9-QEqzroLSWqXNg@mail.gmail.com>
Hi Geert,
Thanks for the review.
> -----Original Message-----
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> Sent: Friday, April 3, 2026 9:37 AM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCh v3 09/14] ASoC: rsnd: Add ADG reset support for RZ/G3E
>
> Hi John,
>
> On Thu, 2 Apr 2026 at 18:53, John Madieu <john.madieu.xa@bp.renesas.com>
> wrote:
> > RZ/G3E requires the ADG reset line to be deasserted for the audio
> > subsystem to operate. The ADG module clock is already managed via
> > rsnd_adg_clk_enable/disable() through adg->adg, so no additional clock
> > handling is needed.
> >
> > Add support for the optional "adg" reset control on Renesas RZ/G3E SoC.
> >
> > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
>
> Thanks for your patch!
>
> > --- a/sound/soc/renesas/rcar/adg.c
> > +++ b/sound/soc/renesas/rcar/adg.c
> > @@ -771,6 +771,7 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv,
> > struct seq_file *m)
> >
> > int rsnd_adg_probe(struct rsnd_priv *priv) {
> > + struct reset_control *rstc;
> > struct rsnd_adg *adg;
> > struct device *dev = rsnd_priv_to_dev(priv);
> > int ret;
> > @@ -779,8 +780,13 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
> > if (!adg)
> > return -ENOMEM;
> >
> > + rstc = devm_reset_control_get_optional_exclusive(dev, "adg");
> > + if (IS_ERR(rstc))
> > + return dev_err_probe(dev, PTR_ERR(rstc),
> > + "failed to get adg reset\n");
>
> Given this file already uses lines longer than 80 characters, the above
> statement would fit on a single line.
Agreed. I'll collapse both the dev_err_probe() and rsnd_mod_init()
calls to single lines.
Regards,
John.
>
> > +
> > ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
> > - NULL, NULL, 0, 0);
> > + NULL, rstc, 0, 0);
>
> This one fits for sure.
>
> > if (ret)
> > return ret;
> >
>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
>
> In personal conversations with technical people, I call myself a hacker.
> But when I'm talking to journalists I just say "programmer" or something
> like that.
> -- Linus Torvalds
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox