* Re: [PATCH v3 1/5] dt-bindings: dmaengine: Add SpacemiT K3 DMA compatible string
From: Troy Mitchell @ 2026-04-01 6:44 UTC (permalink / raw)
To: Krzysztof Kozlowski, Troy Mitchell
Cc: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Guodong Xu, Michael Turquette,
Stephen Boyd, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, dmaengine, devicetree, linux-riscv, spacemit,
linux-kernel, linux-clk
In-Reply-To: <20260401-divergent-magenta-dalmatian-3c6c3e@quoll>
On Wed Apr 1, 2026 at 2:42 PM CST, Krzysztof Kozlowski wrote:
> On Tue, Mar 31, 2026 at 04:27:04PM +0800, Troy Mitchell wrote:
>> From: Guodong Xu <guodong@riscstar.com>
>> - Memory addressing capabilities: Unlike the K1 SoC, which had memory addressing
>> limitations (e.g., restricted to the 0-4GB space) and required a dedicated
>> dma-bus with dma-ranges to restrict memory allocations, the K3 DMA masters
>> possess full memory addressing capabilities.
>
> Programming interface is still compatible, regardless of memory
> addressing limitations, so that is rather incorrect reason.
I'll remove this item. Thanks.
- Troy
>
> Best regards,
> Krzysztof
^ permalink raw reply
* Re: [PATCH v9 00/21] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers
From: Tomi Valkeinen @ 2026-04-01 6:47 UTC (permalink / raw)
To: Ceclan Dumitru, Sakari Ailus, dumitru.ceclan
Cc: Mauro Carvalho Chehab, Laurent Pinchart, Julien Massot,
Rob Herring, Niklas Söderlund, Greg Kroah-Hartman,
Cosmin Tanislav, linux-media, linux-kernel, devicetree,
linux-staging, linux-gpio, Niklas Söderlund, Martin Hecht,
Tomi Valkeinen, Cosmin Tanislav, Cory Keitz
In-Reply-To: <dd858ec6-7621-45d6-9328-b5b03a4d0cec@gmail.com>
Hi,
On 30/03/2026 10:15, Ceclan Dumitru wrote:
>
>
> On 3/11/26 9:58 AM, Sakari Ailus wrote:
>> Hi Dumitru,
>>
>> On Wed, Mar 11, 2026 at 09:17:12AM +0200, Dumitru Ceclan via B4 Relay wrote:
>
> ...
>
>>
>> ...
>>
>>> The following v4l2-compliance test still fails:
>>> fail: v4l2-test-subdevs.cpp(371): fmt.code == 0 || fmt.code == ~0U
>>> fail: v4l2-test-subdevs.cpp(418): checkMBusFrameFmt(node, fmt.format)
>>> test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
>>
>> Could you post the full report here, please?
>>
So why do these failures happen? It wasn't obvious to me from the full
report either.
Tomi
^ permalink raw reply
* Re: [PATCH v7 2/5] platform: arm64: Add driver for EC found on Qualcomm reference devices
From: Anvesh Jain P @ 2026-04-01 6:47 UTC (permalink / raw)
To: Akhil P Oommen, Sibi Sankar, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Hans de Goede, Ilpo Järvinen,
Bryan O'Donoghue, Bjorn Andersson, Konrad Dybcio,
Randy Dunlap
Cc: linux-arm-msm, devicetree, linux-kernel, platform-driver-x86,
Maya Matuszczyk, Dmitry Baryshkov, Konrad Dybcio
In-Reply-To: <0b7b8415-7039-4bad-8079-ea3280891f68@oss.qualcomm.com>
On 3/31/2026 9:07 PM, Akhil P Oommen wrote:
> On 3/27/2026 3:38 PM, Anvesh Jain P wrote:
>> From: Sibi Sankar <sibi.sankar@oss.qualcomm.com>
>>
>> Add Embedded controller driver support for Hamoa/Purwa/Glymur qualcomm
>> reference boards. It handles fan control, temperature sensors, access
>> to EC state changes and supports reporting suspend entry/exit to the
>> EC.
>>
>> Co-developed-by: Maya Matuszczyk <maccraft123mc@gmail.com>
>> Signed-off-by: Maya Matuszczyk <maccraft123mc@gmail.com>
>> Signed-off-by: Sibi Sankar <sibi.sankar@oss.qualcomm.com>
>> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
>> Acked-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> Co-developed-by: Anvesh Jain P <anvesh.p@oss.qualcomm.com>
>> Signed-off-by: Anvesh Jain P <anvesh.p@oss.qualcomm.com>
>> ---
>> MAINTAINERS | 8 +
>> drivers/platform/arm64/Kconfig | 12 +
>> drivers/platform/arm64/Makefile | 1 +
>> drivers/platform/arm64/qcom-hamoa-ec.c | 451 +++++++++++++++++++++++++++++++++
>> 4 files changed, 472 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 30ca84404976..536dfd9adff4 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -21804,6 +21804,14 @@ F: Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
>> F: drivers/misc/fastrpc.c
>> F: include/uapi/misc/fastrpc.h
>>
>> +QUALCOMM HAMOA EMBEDDED CONTROLLER DRIVER
>> +M: Anvesh Jain P <anvesh.p@oss.qualcomm.com>
>> +M: Sibi Sankar <sibi.sankar@oss.qualcomm.com>
>> +L: linux-arm-msm@vger.kernel.org
>> +S: Maintained
>> +F: Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-ec.yaml
>> +F: drivers/platform/arm64/qcom-hamoa-ec.c
>> +
>> QUALCOMM HEXAGON ARCHITECTURE
>> M: Brian Cain <brian.cain@oss.qualcomm.com>
>> L: linux-hexagon@vger.kernel.org
>> diff --git a/drivers/platform/arm64/Kconfig b/drivers/platform/arm64/Kconfig
>> index 10f905d7d6bf..025cdf091f9e 100644
>> --- a/drivers/platform/arm64/Kconfig
>> +++ b/drivers/platform/arm64/Kconfig
>> @@ -90,4 +90,16 @@ config EC_LENOVO_THINKPAD_T14S
>>
>> Say M or Y here to include this support.
>>
>> +config EC_QCOM_HAMOA
>
> Enable this in arm64 defconfig?
>
> Anyway, for the whole series:
>
> Tested-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>
> Nice work. I have been looking for a way to force fan always ON since
> Hamoa. :)
>
> -Akhil.
>
>
Thanks for Testing this! Will add it in v8.
Regarding enabling in arm64 defconfig — that's a good point. I'll add a
patch to the series enabling EC_QCOM_HAMOA in the arm64 defconfig in
next respin once consensus is achieved.
Glad the fan control is useful!
--
Anvesh
>> + tristate "Embedded Controller driver for Qualcomm Hamoa/Glymur reference devices"
>> + depends on ARCH_QCOM || COMPILE_TEST
>> + depends on I2C
>> + help
>> + Say M or Y here to enable the Embedded Controller driver for Qualcomm
>> + Snapdragon-based Hamoa/Glymur reference devices. The driver handles fan
>> + control, temperature sensors, access to EC state changes and supports
>> + reporting suspend entry/exit to the EC.
>> +
>> + This driver currently supports Hamoa/Purwa/Glymur reference devices.
>> +
>> endif # ARM64_PLATFORM_DEVICES
>> diff --git a/drivers/platform/arm64/Makefile b/drivers/platform/arm64/Makefile
>> index 60c131cff6a1..7681be4a46e9 100644
>> --- a/drivers/platform/arm64/Makefile
>> +++ b/drivers/platform/arm64/Makefile
>> @@ -9,3 +9,4 @@ obj-$(CONFIG_EC_ACER_ASPIRE1) += acer-aspire1-ec.o
>> obj-$(CONFIG_EC_HUAWEI_GAOKUN) += huawei-gaokun-ec.o
>> obj-$(CONFIG_EC_LENOVO_YOGA_C630) += lenovo-yoga-c630.o
>> obj-$(CONFIG_EC_LENOVO_THINKPAD_T14S) += lenovo-thinkpad-t14s.o
>> +obj-$(CONFIG_EC_QCOM_HAMOA) += qcom-hamoa-ec.o
>> diff --git a/drivers/platform/arm64/qcom-hamoa-ec.c b/drivers/platform/arm64/qcom-hamoa-ec.c
>> new file mode 100644
>> index 000000000000..0f883130ac9a
>> --- /dev/null
>> +++ b/drivers/platform/arm64/qcom-hamoa-ec.c
>> @@ -0,0 +1,451 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2024 Maya Matuszczyk <maccraft123mc@gmail.com>
>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>> + */
>> +
>> +#include <linux/bitfield.h>
>> +#include <linux/bits.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/i2c.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pm.h>
>> +#include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +
>> +#define EC_SCI_EVT_READ_CMD 0x05
>> +#define EC_FW_VERSION_CMD 0x0e
>> +#define EC_MODERN_STANDBY_CMD 0x23
>> +#define EC_FAN_DBG_CONTROL_CMD 0x30
>> +#define EC_SCI_EVT_CONTROL_CMD 0x35
>> +#define EC_THERMAL_CAP_CMD 0x42
>> +
>> +#define EC_FW_VERSION_RESP_LEN 4
>> +#define EC_THERMAL_CAP_RESP_LEN 3
>> +#define EC_FAN_DEBUG_CMD_LEN 6
>> +#define EC_FAN_SPEED_DATA_SIZE 4
>> +
>> +#define EC_MODERN_STANDBY_ENTER 0x01
>> +#define EC_MODERN_STANDBY_EXIT 0x00
>> +
>> +#define EC_FAN_DEBUG_MODE_OFF 0
>> +#define EC_FAN_DEBUG_MODE_ON BIT(0)
>> +#define EC_FAN_ON BIT(1)
>> +#define EC_FAN_DEBUG_TYPE_PWM BIT(2)
>> +#define EC_MAX_FAN_CNT 2
>> +#define EC_FAN_NAME_SIZE 20
>> +#define EC_FAN_MAX_PWM 255
>> +
>> +enum qcom_ec_sci_events {
>> + EC_FAN1_STATUS_CHANGE_EVT = 0x30,
>> + EC_FAN2_STATUS_CHANGE_EVT,
>> + EC_FAN1_SPEED_CHANGE_EVT,
>> + EC_FAN2_SPEED_CHANGE_EVT,
>> + EC_NEW_LUT_SET_EVT,
>> + EC_FAN_PROFILE_SWITCH_EVT,
>> + EC_THERMISTOR_1_THRESHOLD_CROSS_EVT,
>> + EC_THERMISTOR_2_THRESHOLD_CROSS_EVT,
>> + EC_THERMISTOR_3_THRESHOLD_CROSS_EVT,
>> + /* Reserved: 0x39 - 0x3c/0x3f */
>> + EC_RECOVERED_FROM_RESET_EVT = 0x3d,
>> +};
>> +
>> +struct qcom_ec_version {
>> + u8 main_version;
>> + u8 sub_version;
>> + u8 test_version;
>> +};
>> +
>> +struct qcom_ec_thermal_cap {
>> +#define EC_THERMAL_FAN_CNT(x) (FIELD_GET(GENMASK(1, 0), (x)))
>> +#define EC_THERMAL_FAN_TYPE(x) (FIELD_GET(GENMASK(4, 2), (x)))
>> +#define EC_THERMAL_THERMISTOR_MASK(x) (FIELD_GET(GENMASK(7, 0), (x)))
>> + u8 fan_cnt;
>> + u8 fan_type;
>> + u8 thermistor_mask;
>> +};
>> +
>> +struct qcom_ec_cooling_dev {
>> + struct thermal_cooling_device *cdev;
>> + struct device *parent_dev;
>> + u8 fan_id;
>> + u8 state;
>> +};
>> +
>> +struct qcom_ec {
>> + struct qcom_ec_cooling_dev *ec_cdev;
>> + struct qcom_ec_thermal_cap thermal_cap;
>> + struct qcom_ec_version version;
>> + struct i2c_client *client;
>> +};
>> +
>> +static int qcom_ec_read(struct qcom_ec *ec, u8 cmd, u8 resp_len, u8 *resp)
>> +{
>> + int ret;
>> +
>> + ret = i2c_smbus_read_i2c_block_data(ec->client, cmd, resp_len, resp);
>> +
>> + if (ret < 0)
>> + return ret;
>> + else if (ret == 0 || ret == 0xff)
>> + return -EOPNOTSUPP;
>> +
>> + if (resp[0] >= resp_len)
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * EC Device Firmware Version:
>> + *
>> + * Read Response:
>> + * ----------------------------------------------------------------------
>> + * | Offset | Name | Description |
>> + * ----------------------------------------------------------------------
>> + * | 0x00 | Byte count | Number of bytes in response |
>> + * | | | (excluding byte count) |
>> + * ----------------------------------------------------------------------
>> + * | 0x01 | Test-version | Test-version of EC firmware |
>> + * ----------------------------------------------------------------------
>> + * | 0x02 | Sub-version | Sub-version of EC firmware |
>> + * ----------------------------------------------------------------------
>> + * | 0x03 | Main-version | Main-version of EC firmware |
>> + * ----------------------------------------------------------------------
>> + *
>> + */
>> +static int qcom_ec_read_fw_version(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct qcom_ec *ec = i2c_get_clientdata(client);
>> + struct qcom_ec_version *version = &ec->version;
>> + u8 resp[EC_FW_VERSION_RESP_LEN];
>> + int ret;
>> +
>> + ret = qcom_ec_read(ec, EC_FW_VERSION_CMD, EC_FW_VERSION_RESP_LEN, resp);
>> + if (ret < 0)
>> + return ret;
>> +
>> + version->main_version = resp[3];
>> + version->sub_version = resp[2];
>> + version->test_version = resp[1];
>> +
>> + dev_dbg(dev, "EC Version %d.%d.%d\n",
>> + version->main_version, version->sub_version, version->test_version);
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * EC Device Thermal Capabilities:
>> + *
>> + * Read Response:
>> + * ------------------------------------------------------------------------------
>> + * | Offset | Name | Description |
>> + * ------------------------------------------------------------------------------
>> + * | 0x00 | Byte count | Number of bytes in response |
>> + * | | | (excluding byte count) |
>> + * ------------------------------------------------------------------------------
>> + * | 0x02 (LSB) | EC Thermal | Bit 0-1: Number of fans |
>> + * | 0x3 | Capabilities | Bit 2-4: Type of fan |
>> + * | | | Bit 5-6: Reserved |
>> + * | | | Bit 7: Data Valid/Invalid |
>> + * | | | (Valid - 1, Invalid - 0) |
>> + * | | | Bit 8-15: Thermistor 0 - 7 presence |
>> + * | | | (1 present, 0 absent) |
>> + * ------------------------------------------------------------------------------
>> + *
>> + */
>> +static int qcom_ec_thermal_capabilities(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct qcom_ec *ec = i2c_get_clientdata(client);
>> + struct qcom_ec_thermal_cap *cap = &ec->thermal_cap;
>> + u8 resp[EC_THERMAL_CAP_RESP_LEN];
>> + int ret;
>> +
>> + ret = qcom_ec_read(ec, EC_THERMAL_CAP_CMD, EC_THERMAL_CAP_RESP_LEN, resp);
>> + if (ret < 0)
>> + return ret;
>> +
>> + cap->fan_cnt = min(EC_MAX_FAN_CNT, EC_THERMAL_FAN_CNT(resp[1]));
>> + cap->fan_type = EC_THERMAL_FAN_TYPE(resp[1]);
>> + cap->thermistor_mask = EC_THERMAL_THERMISTOR_MASK(resp[2]);
>> +
>> + dev_dbg(dev, "Fan count: %d Fan Type: %d Thermistor Mask: %x\n",
>> + cap->fan_cnt, cap->fan_type, cap->thermistor_mask);
>> +
>> + return 0;
>> +}
>> +
>> +static irqreturn_t qcom_ec_irq(int irq, void *data)
>> +{
>> + struct qcom_ec *ec = data;
>> + struct device *dev = &ec->client->dev;
>> + int val;
>> +
>> + val = i2c_smbus_read_byte_data(ec->client, EC_SCI_EVT_READ_CMD);
>> + if (val < 0) {
>> + dev_err_ratelimited(dev, "Failed to read EC SCI Event: %d\n", val);
>> + return IRQ_HANDLED;
>> + }
>> +
>> + switch (val) {
>> + case EC_FAN1_STATUS_CHANGE_EVT:
>> + dev_dbg_ratelimited(dev, "Fan1 status changed\n");
>> + break;
>> + case EC_FAN2_STATUS_CHANGE_EVT:
>> + dev_dbg_ratelimited(dev, "Fan2 status changed\n");
>> + break;
>> + case EC_FAN1_SPEED_CHANGE_EVT:
>> + dev_dbg_ratelimited(dev, "Fan1 speed crossed low/high trip point\n");
>> + break;
>> + case EC_FAN2_SPEED_CHANGE_EVT:
>> + dev_dbg_ratelimited(dev, "Fan2 speed crossed low/high trip point\n");
>> + break;
>> + case EC_NEW_LUT_SET_EVT:
>> + dev_dbg_ratelimited(dev, "New LUT set\n");
>> + break;
>> + case EC_FAN_PROFILE_SWITCH_EVT:
>> + dev_dbg_ratelimited(dev, "FAN Profile switched\n");
>> + break;
>> + case EC_THERMISTOR_1_THRESHOLD_CROSS_EVT:
>> + dev_dbg_ratelimited(dev, "Thermistor 1 threshold crossed\n");
>> + break;
>> + case EC_THERMISTOR_2_THRESHOLD_CROSS_EVT:
>> + dev_dbg_ratelimited(dev, "Thermistor 2 threshold crossed\n");
>> + break;
>> + case EC_THERMISTOR_3_THRESHOLD_CROSS_EVT:
>> + dev_dbg_ratelimited(dev, "Thermistor 3 threshold crossed\n");
>> + break;
>> + case EC_RECOVERED_FROM_RESET_EVT:
>> + dev_dbg_ratelimited(dev, "EC recovered from reset\n");
>> + break;
>> + default:
>> + dev_notice_ratelimited(dev, "Unknown EC event: %d\n", val);
>> + break;
>> + }
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int qcom_ec_sci_evt_control(struct device *dev, bool enable)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> +
>> + return i2c_smbus_write_byte_data(client, EC_SCI_EVT_CONTROL_CMD, !!enable);
>> +}
>> +
>> +static int qcom_ec_fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state)
>> +{
>> + *state = EC_FAN_MAX_PWM;
>> +
>> + return 0;
>> +}
>> +
>> +static int qcom_ec_fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
>> +{
>> + struct qcom_ec_cooling_dev *ec_cdev = cdev->devdata;
>> +
>> + *state = ec_cdev->state;
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * Fan Debug control command:
>> + *
>> + * Command Payload:
>> + * --------------------------------------------------------------------------------------
>> + * | Offset | Name | Description |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x00 | Command | Fan control command |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x01 | Fan ID | 0x1 : Fan 1 |
>> + * | | | 0x2 : Fan 2 |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x02 | Byte count = 4| Size of data to set fan speed |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x03 | Mode | Bit 0: Debug Mode On/Off (0 - OFF, 1 - ON ) |
>> + * | | | Bit 1: Fan On/Off (0 - Off, 1 - ON) |
>> + * | | | Bit 2: Debug Type (0 - RPM, 1 - PWM) |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x04 (LSB) | Speed in RPM | RPM value, if mode selected is RPM |
>> + * | 0x05 | | |
>> + * --------------------------------------------------------------------------------------
>> + * | 0x06 | Speed in PWM | PWM value, if mode selected is PWM (0 - 255) |
>> + * ______________________________________________________________________________________
>> + *
>> + */
>> +static int qcom_ec_fan_debug_mode_off(struct qcom_ec_cooling_dev *ec_cdev)
>> +{
>> + struct device *dev = ec_cdev->parent_dev;
>> + struct i2c_client *client = to_i2c_client(dev);
>> + u8 request[6] = { ec_cdev->fan_id, EC_FAN_SPEED_DATA_SIZE,
>> + EC_FAN_DEBUG_MODE_OFF, 0, 0, 0 };
>> + int ret;
>> +
>> + ret = i2c_smbus_write_i2c_block_data(client, EC_FAN_DBG_CONTROL_CMD,
>> + sizeof(request), request);
>> + if (ret) {
>> + dev_err(dev, "Failed to turn off fan%d debug mode: %d\n",
>> + ec_cdev->fan_id, ret);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int qcom_ec_fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
>> +{
>> + struct qcom_ec_cooling_dev *ec_cdev = cdev->devdata;
>> + struct device *dev = ec_cdev->parent_dev;
>> + struct i2c_client *client = to_i2c_client(dev);
>> + u8 request[6] = { ec_cdev->fan_id, EC_FAN_SPEED_DATA_SIZE,
>> + EC_FAN_DEBUG_MODE_ON | EC_FAN_ON | EC_FAN_DEBUG_TYPE_PWM,
>> + 0, 0, state };
>> + int ret;
>> +
>> + ret = i2c_smbus_write_i2c_block_data(client, EC_FAN_DBG_CONTROL_CMD,
>> + sizeof(request), request);
>> + if (ret) {
>> + dev_err(dev, "Failed to set fan pwm: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + ec_cdev->state = state;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct thermal_cooling_device_ops qcom_ec_thermal_ops = {
>> + .get_max_state = qcom_ec_fan_get_max_state,
>> + .get_cur_state = qcom_ec_fan_get_cur_state,
>> + .set_cur_state = qcom_ec_fan_set_cur_state,
>> +};
>> +
>> +static int qcom_ec_resume(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> +
>> + return i2c_smbus_write_byte_data(client, EC_MODERN_STANDBY_CMD,
>> + EC_MODERN_STANDBY_ENTER);
>> +}
>> +
>> +static int qcom_ec_suspend(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> +
>> + return i2c_smbus_write_byte_data(client, EC_MODERN_STANDBY_CMD,
>> + EC_MODERN_STANDBY_EXIT);
>> +}
>> +
>> +static int qcom_ec_probe(struct i2c_client *client)
>> +{
>> + struct device *dev = &client->dev;
>> + struct qcom_ec *ec;
>> + unsigned int i;
>> + int ret;
>> +
>> + ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
>> + if (!ec)
>> + return -ENOMEM;
>> +
>> + ec->client = client;
>> +
>> + ret = devm_request_threaded_irq(dev, client->irq, NULL, qcom_ec_irq,
>> + IRQF_ONESHOT, "qcom_ec", ec);
>> + if (ret < 0)
>> + return ret;
>> +
>> + i2c_set_clientdata(client, ec);
>> +
>> + ret = qcom_ec_read_fw_version(dev);
>> + if (ret < 0)
>> + return dev_err_probe(dev, ret, "Failed to read EC firmware version\n");
>> +
>> + ret = qcom_ec_sci_evt_control(dev, true);
>> + if (ret < 0)
>> + return dev_err_probe(dev, ret, "Failed to enable SCI events\n");
>> +
>> + ret = qcom_ec_thermal_capabilities(dev);
>> + if (ret < 0)
>> + return dev_err_probe(dev, ret, "Failed to read thermal capabilities\n");
>> +
>> + if (ec->thermal_cap.fan_cnt == 0) {
>> + dev_warn(dev, FW_BUG "Failed to get fan count, firmware update required\n");
>> + return 0;
>> + }
>> +
>> + ec->ec_cdev = devm_kcalloc(dev, ec->thermal_cap.fan_cnt, sizeof(*ec->ec_cdev), GFP_KERNEL);
>> + if (!ec->ec_cdev)
>> + return -ENOMEM;
>> +
>> + for (i = 0; i < ec->thermal_cap.fan_cnt; i++) {
>> + struct qcom_ec_cooling_dev *ec_cdev = &ec->ec_cdev[i];
>> + char name[EC_FAN_NAME_SIZE];
>> +
>> + scnprintf(name, sizeof(name), "qcom_ec_fan_%u", i);
>> + ec_cdev->fan_id = i + 1;
>> + ec_cdev->parent_dev = dev;
>> +
>> + ec_cdev->cdev = devm_thermal_of_cooling_device_register(dev, NULL, name, ec_cdev,
>> + &qcom_ec_thermal_ops);
>> + if (IS_ERR(ec_cdev->cdev)) {
>> + return dev_err_probe(dev, PTR_ERR(ec_cdev->cdev),
>> + "Failed to register fan%d cooling device\n", i);
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void qcom_ec_remove(struct i2c_client *client)
>> +{
>> + struct qcom_ec *ec = i2c_get_clientdata(client);
>> + struct device *dev = &client->dev;
>> + int ret;
>> +
>> + ret = qcom_ec_sci_evt_control(dev, false);
>> + if (ret < 0)
>> + dev_err(dev, "Failed to disable SCI events: %d\n", ret);
>> +
>> + for (int i = 0; i < ec->thermal_cap.fan_cnt; i++) {
>> + struct qcom_ec_cooling_dev *ec_cdev = &ec->ec_cdev[i];
>> +
>> + qcom_ec_fan_debug_mode_off(ec_cdev);
>> + }
>> +}
>> +
>> +static const struct of_device_id qcom_ec_of_match[] = {
>> + { .compatible = "qcom,hamoa-crd-ec" },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, qcom_ec_of_match);
>> +
>> +static const struct i2c_device_id qcom_ec_i2c_id_table[] = {
>> + { "qcom-hamoa-ec", },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(i2c, qcom_ec_i2c_id_table);
>> +
>> +static DEFINE_SIMPLE_DEV_PM_OPS(qcom_ec_pm_ops,
>> + qcom_ec_suspend,
>> + qcom_ec_resume);
>> +
>> +static struct i2c_driver qcom_ec_i2c_driver = {
>> + .driver = {
>> + .name = "qcom-hamoa-ec",
>> + .of_match_table = qcom_ec_of_match,
>> + .pm = &qcom_ec_pm_ops
>> + },
>> + .probe = qcom_ec_probe,
>> + .remove = qcom_ec_remove,
>> + .id_table = qcom_ec_i2c_id_table,
>> +};
>> +module_i2c_driver(qcom_ec_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("QCOM Hamoa Embedded Controller");
>> +MODULE_LICENSE("GPL");
>>
>
^ permalink raw reply
* RE: [PATCH v4 2/4] irqchip/ast2700-intc: Add AST2700-A2 support
From: Ryan Chen @ 2026-04-01 6:49 UTC (permalink / raw)
To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org
In-Reply-To: <87tstw7zfj.ffs@tglx>
> Subject: Re: [PATCH v4 2/4] irqchip/ast2700-intc: Add AST2700-A2 support
>
> On Mon, Mar 30 2026 at 14:32, Ryan Chen wrote:
> > +static int resolve_parent_range_for_output(const struct aspeed_intc0
> *intc0,
> > + const struct fwnode_handle *parent,
> > + u32 output,
> > + struct aspeed_intc_interrupt_range *resolved)
>
> Please reduce the number of line breaks. You still have 100 characters.
Will update
static int resolve_parent_range_for_output(const struct aspeed_intc0 *intc0,
const struct fwnode_handle *parent, u32 output,
struct aspeed_intc_interrupt_range *resolved)
>
> > +{
> > + for (size_t i = 0; i < intc0->ranges.nranges; i++) {
> > + struct aspeed_intc_interrupt_range range =
> > + intc0->ranges.ranges[i];
>
> No line break required.
Will update
struct aspeed_intc_interrupt_range range = intc0->ranges.ranges[i];
>
> > +static int aspeed_intc1_irq_domain_activate(struct irq_domain *domain,
> > + struct irq_data *data, bool reserve) {
> > + struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data);
> > + struct aspeed_intc_interrupt_range resolved;
> > + int rc, bank, bit;
> > + u32 mask;
> > +
> > + if (WARN_ON_ONCE((data->hwirq >> INTC1_ROUTE_SHIFT) >=
> ARRAY_SIZE(aspeed_intc1_routes)))
> > + return -EINVAL;
> > +
> > + /*
> > + * outpin may be an error if the upstream is the BootMCU APLIC node, or
> > + * anything except a valid intc0 driver instance
> > + */
> > + rc = aspeed_intc0_resolve_route(intc1->upstream, INTC1_ROUTE_NUM,
> > + aspeed_intc1_routes[data->hwirq >>
> INTC1_ROUTE_SHIFT],
> > + intc1->ranges.nranges,
> > + intc1->ranges.ranges, &resolved);
>
> Please test your code with CONFIG_PROVE_LOCKING=y, which is mandatory
> for submission according to documentation.
>
> This is invoked with the interrupt descriptor lock held and interrupts disabled.
>
> aspeed_intc0_resolve_route()
> ....
> irq_find_matching_fwspec()
> mutex_lock(&irq_domain_mutex); <---- FAIL
>
Thank you point out the issue.
I plan to cache the irq_domain pointer in each aspeed_intc_interrupt_range
entry at populate time.
Add a domain field to struct aspeed_intc_interrupt_range in irq-ast2700.h
In aspeed_intc_populate_ranges() (irq-ast2700.c), call irq_find_matching_fwspec()
once per range entry and store the result in r->domain.
This runs in probe context, so taking irq_domain_mutex is safe.
In aspeed_intc0_resolve_route() (irq-ast2700-intc0.c), replace the
irq_find_matching_fwspec() call with a direct comparison against c1r.domain.
In aspeed_intc1_request_interrupts() (irq-ast2700-intc1.c),
likewise replace irq_find_matching_fwspec() with a comparison against r->domain.
^ permalink raw reply
* [PATCH net-next v2 00/11] net: airoha: Support multiple net_devices connected to the same GDM port
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
manages the traffic in a TDM manner. As a result multiple net_devices can
connect to the same GDM{3,4} port and there is a theoretical "1:n"
relation between GDM ports and net_devices.
┌─────────────────────────────────┐
│ │ ┌──────┐
│ P1 GDM1 ├────►MT7530│
│ │ └──────┘
│ │ ETH0 (DSA conduit)
│ │
│ PSE/FE │
│ │
│ │
│ │ ┌─────┐
│ P0 CDM1 ├────►QDMA0│
│ P4 P9 GDM4 │ └─────┘
└──┬─────────────────────────┬────┘
│ │
┌──▼──┐ ┌────▼────┐
│ PPE │ │ ARB │
└─────┘ └─┬─────┬─┘
│ │
┌──▼──┐┌─▼───┐
│ ETH ││ USB │
└─────┘└─────┘
ETH1 ETH2
This series introduces support for multiple net_devices connected to the
same Frame Engine (FE) GDM port (GDM3 or GDM4) via an external hw
arbiter. Please note GDM1 or GDM2 does not support the connection with
the external arbiter.
---
Changes in v2:
- Rename multiplexer in arbiter in the commit logs.
- Rebase on top of net-next main branch.
- Add missing PPE cpu port configuration for GDM2 when loopback is
enabled.
- Link to v1: https://lore.kernel.org/r/20260329-airoha-eth-multi-serdes-v1-0-00f52dc360ca@kernel.org
---
Lorenzo Bianconi (11):
dt-bindings: net: airoha: Add EN7581 ethernet-ports properties
net: airoha: Set PPE cpu port for GDM2 if loopback is enabled
net: airoha: Rely on net_device pointer in airoha_dev_setup_tc_block signature
net: airoha: Rely on net_device pointer in HTB callbacks
net: airoha: Rely on net_device pointer in ETS callbacks
net: airoha: Introduce airoha_gdm_dev struct
net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct
net: airoha: Rely on airoha_gdm_dev pointer in airhoa_is_lan_gdm_port()
net: airoha: Support multiple net_devices for a single FE GDM port
net: airoha: Do not stop GDM port if it is shared
net: airoha: Rename get_src_port_id callback in get_sport
.../devicetree/bindings/net/airoha,en7581-eth.yaml | 44 +-
drivers/net/ethernet/airoha/airoha_eth.c | 631 +++++++++++++--------
drivers/net/ethernet/airoha/airoha_eth.h | 30 +-
drivers/net/ethernet/airoha/airoha_ppe.c | 43 +-
4 files changed, 502 insertions(+), 246 deletions(-)
---
base-commit: f1359c240191e686614847905fc861cbda480b47
change-id: 20260324-airoha-eth-multi-serdes-fb4b556ee756
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply
* [PATCH net-next v2 01/11] dt-bindings: net: airoha: Add EN7581 ethernet-ports properties
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3
or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner.
As a result multiple net_devices can connect to the same GDM{3,4} port
and there is a theoretical "1:n" relation between GDM ports and
net_devices.
Introduce the ethernet-port property in order to model a given net_device
that is connected via the external arbiter to the GDM{3,4} port (that
is represented by the ethernet property. Please note GDM1 or GDM2 does not
support the connection with the external arbiter and are represented
by ethernet property.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../devicetree/bindings/net/airoha,en7581-eth.yaml | 44 +++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml b/Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
index fbe2ddcdd909cb3d853a4ab9e9fec4af1d096c52..ebbd433e9c9fbfaefd8d07c3678cabc91574d125 100644
--- a/Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
+++ b/Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
@@ -130,6 +130,30 @@ patternProperties:
maximum: 4
description: GMAC port identifier
+ '#address-cells':
+ const: 1
+ '#size-cells':
+ const: 0
+
+ patternProperties:
+ "^ethernet-port@[0-5]$":
+ type: object
+ unevaluatedProperties: false
+ $ref: ethernet-controller.yaml#
+ description: External ethernet port ID available on the GDM port
+
+ properties:
+ compatible:
+ const: airoha,eth-port
+
+ reg:
+ maxItems: 1
+ description: External ethernet port identifier
+
+ required:
+ - compatible
+ - reg
+
required:
- reg
- compatible
@@ -191,9 +215,27 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
- mac: ethernet@1 {
+ mac1: ethernet@1 {
compatible = "airoha,eth-mac";
reg = <1>;
};
+
+ mac4: ethernet@4 {
+ compatible = "airoha,eth-mac";
+ reg = <4>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-port@0 {
+ compatible = "airoha,eth-port";
+ reg = <0>;
+ };
+
+ ethernet-port@1 {
+ compatible = "airoha,eth-port";
+ reg = <1>;
+ };
+ };
};
};
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 02/11] net: airoha: Set PPE cpu port for GDM2 if loopback is enabled
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Add missing PPE cpu port configuration for GDM2 if QoS loopback is enabled
for GDM3 or GDM4 ports. Similar to commit 'f44218cd5e6a ("net: airoha:
Reset PPE cpu port configuration in airoha_ppe_hw_init()"), this patch is
fixing an issue not visible to the user (so we do not need to backport it)
since airoha_eth driver currently supports just the internal phy available
via the MT7530 DSA switch and there are no WAN interfaces officially
supported since PCS/external phy is not merged mainline yet (it will be
posted with following patches).
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++++--
drivers/net/ethernet/airoha/airoha_eth.h | 3 ++-
drivers/net/ethernet/airoha/airoha_ppe.c | 6 +++---
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 2beba017e791d20f142e754edafcd402d8cc496f..ff5fc852d7dc3960fdcf6ae7465896340c3f43a0 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1713,7 +1713,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
{
struct airoha_eth *eth = port->qdma->eth;
u32 val, pse_port, chan, nbq;
- int src_port;
+ int i, src_port;
/* Forward the traffic to the proper GDM port */
pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
@@ -1757,6 +1757,9 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
SP_CPORT_MASK(val),
__field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2));
+ for (i = 0; i < eth->soc->num_ppe; i++)
+ airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX);
+
if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) {
u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq);
@@ -1795,7 +1798,8 @@ static int airoha_dev_init(struct net_device *dev)
}
for (i = 0; i < eth->soc->num_ppe; i++)
- airoha_ppe_set_cpu_port(port, i);
+ airoha_ppe_set_cpu_port(port, i,
+ airoha_get_fe_port(port));
return 0;
}
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 7df4dbcd8861856c54c2a38bc89c69180ac2f6dc..f04b8d8cfc09f74f288c347d03e18b4f4f3aa893 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -650,7 +650,8 @@ int airoha_get_fe_port(struct airoha_gdm_port *port);
bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
struct airoha_gdm_port *port);
-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id);
+void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id,
+ u8 fport);
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
u16 hash, bool rx_wlan);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 58b14aea7c2f33ebce11c51d892eefff692378ca..0f42247a2ef3d67b7dadb6201079ff2c2defbf0d 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -85,10 +85,9 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp);
}
-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id)
+void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, u8 fport)
{
struct airoha_qdma *qdma = port->qdma;
- u8 fport = airoha_get_fe_port(port);
struct airoha_eth *eth = qdma->eth;
u8 qdma_id = qdma - ð->qdma[0];
u32 fe_cpu_port;
@@ -174,7 +173,8 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
if (!port)
continue;
- airoha_ppe_set_cpu_port(port, i);
+ airoha_ppe_set_cpu_port(port, i,
+ airoha_get_fe_port(port));
}
}
}
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 03/11] net: airoha: Rely on net_device pointer in airoha_dev_setup_tc_block signature
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Remove airoha_gdm_port dependency in airoha_dev_setup_tc_block routine
signature and rely on net_device pointer instead. Please note this patch
does not introduce any logical change and it is a preliminary patch to
support multiple net_devices connected to the GDM3 or GDM4 ports via an
external hw arbiter.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index ff5fc852d7dc3960fdcf6ae7465896340c3f43a0..e1448e01dd69b7d46f0efd8ad4e8531bca0ae1eb 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2675,7 +2675,7 @@ static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,
}
}
-static int airoha_dev_setup_tc_block(struct airoha_gdm_port *port,
+static int airoha_dev_setup_tc_block(struct net_device *dev,
struct flow_block_offload *f)
{
flow_setup_cb_t *cb = airoha_dev_setup_tc_block_cb;
@@ -2688,12 +2688,12 @@ static int airoha_dev_setup_tc_block(struct airoha_gdm_port *port,
f->driver_block_list = &block_cb_list;
switch (f->command) {
case FLOW_BLOCK_BIND:
- block_cb = flow_block_cb_lookup(f->block, cb, port->dev);
+ block_cb = flow_block_cb_lookup(f->block, cb, dev);
if (block_cb) {
flow_block_cb_incref(block_cb);
return 0;
}
- block_cb = flow_block_cb_alloc(cb, port->dev, port->dev, NULL);
+ block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
@@ -2702,7 +2702,7 @@ static int airoha_dev_setup_tc_block(struct airoha_gdm_port *port,
list_add_tail(&block_cb->driver_list, &block_cb_list);
return 0;
case FLOW_BLOCK_UNBIND:
- block_cb = flow_block_cb_lookup(f->block, cb, port->dev);
+ block_cb = flow_block_cb_lookup(f->block, cb, dev);
if (!block_cb)
return -ENOENT;
@@ -2801,7 +2801,7 @@ static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
return airoha_tc_setup_qdisc_htb(port, type_data);
case TC_SETUP_BLOCK:
case TC_SETUP_FT:
- return airoha_dev_setup_tc_block(port, type_data);
+ return airoha_dev_setup_tc_block(dev, type_data);
default:
return -EOPNOTSUPP;
}
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 04/11] net: airoha: Rely on net_device pointer in HTB callbacks
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Remove airoha_gdm_port dependency in HTB tc callback signatures and rely
on net_device pointer instead. Please note this patch does not introduce
any logical change and it is a preliminary patch in order to support
multiple net_devices connected to the same GDM3 or GDM4 port via an
external hw arbiter.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 51 ++++++++++++++++++--------------
1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index e1448e01dd69b7d46f0efd8ad4e8531bca0ae1eb..52599ebe85e6a74002c290edb82c55ba9fdfcc69 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2480,10 +2480,11 @@ static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma,
mode, val);
}
-static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port,
+static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
int channel, u32 rate,
u32 bucket_size)
{
+ struct airoha_gdm_port *port = netdev_priv(netdev);
int i, err;
for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
@@ -2503,21 +2504,21 @@ static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port,
return 0;
}
-static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port,
+static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */
- struct net_device *dev = port->dev;
- int num_tx_queues = dev->real_num_tx_queues;
- int err;
+ int err, num_tx_queues = netdev->real_num_tx_queues;
+ struct airoha_gdm_port *port = netdev_priv(netdev);
if (opt->parent_classid != TC_HTB_CLASSID_ROOT) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid");
return -EINVAL;
}
- err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum);
+ err = airoha_qdma_set_tx_rate_limit(netdev, channel, rate,
+ opt->quantum);
if (err) {
NL_SET_ERR_MSG_MOD(opt->extack,
"failed configuring htb offload");
@@ -2527,9 +2528,10 @@ static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port,
if (opt->command == TC_HTB_NODE_MODIFY)
return 0;
- err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1);
+ err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1);
if (err) {
- airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum);
+ airoha_qdma_set_tx_rate_limit(netdev, channel, 0,
+ opt->quantum);
NL_SET_ERR_MSG_MOD(opt->extack,
"failed setting real_num_tx_queues");
return err;
@@ -2716,44 +2718,47 @@ static int airoha_dev_setup_tc_block(struct net_device *dev,
}
}
-static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue)
+static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
{
- struct net_device *dev = port->dev;
+ struct airoha_gdm_port *port = netdev_priv(netdev);
- netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1);
- airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0);
+ netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1);
+ airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0);
clear_bit(queue, port->qos_sq_bmap);
}
-static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port,
+static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
+ struct airoha_gdm_port *port = netdev_priv(netdev);
if (!test_bit(channel, port->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
return -EINVAL;
}
- airoha_tc_remove_htb_queue(port, channel);
+ airoha_tc_remove_htb_queue(netdev, channel);
return 0;
}
-static int airoha_tc_htb_destroy(struct airoha_gdm_port *port)
+static int airoha_tc_htb_destroy(struct net_device *netdev)
{
+ struct airoha_gdm_port *port = netdev_priv(netdev);
int q;
for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
- airoha_tc_remove_htb_queue(port, q);
+ airoha_tc_remove_htb_queue(netdev, q);
return 0;
}
-static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port,
+static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
+ struct airoha_gdm_port *port = netdev_priv(netdev);
if (!test_bit(channel, port->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
@@ -2765,23 +2770,23 @@ static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port,
return 0;
}
-static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port,
+static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
struct tc_htb_qopt_offload *opt)
{
switch (opt->command) {
case TC_HTB_CREATE:
break;
case TC_HTB_DESTROY:
- return airoha_tc_htb_destroy(port);
+ return airoha_tc_htb_destroy(dev);
case TC_HTB_NODE_MODIFY:
case TC_HTB_LEAF_ALLOC_QUEUE:
- return airoha_tc_htb_alloc_leaf_queue(port, opt);
+ return airoha_tc_htb_alloc_leaf_queue(dev, opt);
case TC_HTB_LEAF_DEL:
case TC_HTB_LEAF_DEL_LAST:
case TC_HTB_LEAF_DEL_LAST_FORCE:
- return airoha_tc_htb_delete_leaf_queue(port, opt);
+ return airoha_tc_htb_delete_leaf_queue(dev, opt);
case TC_HTB_LEAF_QUERY_QUEUE:
- return airoha_tc_get_htb_get_leaf_queue(port, opt);
+ return airoha_tc_get_htb_get_leaf_queue(dev, opt);
default:
return -EOPNOTSUPP;
}
@@ -2798,7 +2803,7 @@ static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_ETS:
return airoha_tc_setup_qdisc_ets(port, type_data);
case TC_SETUP_QDISC_HTB:
- return airoha_tc_setup_qdisc_htb(port, type_data);
+ return airoha_tc_setup_qdisc_htb(dev, type_data);
case TC_SETUP_BLOCK:
case TC_SETUP_FT:
return airoha_dev_setup_tc_block(dev, type_data);
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 05/11] net: airoha: Rely on net_device pointer in ETS callbacks
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Remove airoha_gdm_port dependency in ETS tc callback signatures and rely
on net_device pointer instead. Please note this patch does not introduce
any logical change and it is a preliminary patch in order to support
multiple net_devices connected to the same GDM3 or GDM4 port via an
external hw arbiter.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 52599ebe85e6a74002c290edb82c55ba9fdfcc69..268f4e34f38d2df128f0be52ae00fec07e46b1bf 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2126,10 +2126,11 @@ airoha_ethtool_get_rmon_stats(struct net_device *dev,
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
}
-static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port,
+static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
int channel, enum tx_sched_mode mode,
const u16 *weights, u8 n_weights)
{
+ struct airoha_gdm_port *port = netdev_priv(netdev);
int i;
for (i = 0; i < AIROHA_NUM_TX_RING; i++)
@@ -2161,17 +2162,15 @@ static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port,
return 0;
}
-static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port,
- int channel)
+static int airoha_qdma_set_tx_prio_sched(struct net_device *dev, int channel)
{
static const u16 w[AIROHA_NUM_QOS_QUEUES] = {};
- return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w,
+ return airoha_qdma_set_chan_tx_sched(dev, channel, TC_SCH_SP, w,
ARRAY_SIZE(w));
}
-static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
- int channel,
+static int airoha_qdma_set_tx_ets_sched(struct net_device *dev, int channel,
struct tc_ets_qopt_offload *opt)
{
struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
@@ -2212,14 +2211,15 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1)
mode = nstrict + 1;
- return airoha_qdma_set_chan_tx_sched(port, channel, mode, w,
+ return airoha_qdma_set_chan_tx_sched(dev, channel, mode, w,
ARRAY_SIZE(w));
}
-static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port,
- int channel,
+static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
struct tc_ets_qopt_offload *opt)
{
+ struct airoha_gdm_port *port = netdev_priv(netdev);
+
u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
REG_CNTR_VAL(channel << 1));
u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
@@ -2234,7 +2234,7 @@ static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port,
return 0;
}
-static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
+static int airoha_tc_setup_qdisc_ets(struct net_device *dev,
struct tc_ets_qopt_offload *opt)
{
int channel;
@@ -2247,12 +2247,12 @@ static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
switch (opt->command) {
case TC_ETS_REPLACE:
- return airoha_qdma_set_tx_ets_sched(port, channel, opt);
+ return airoha_qdma_set_tx_ets_sched(dev, channel, opt);
case TC_ETS_DESTROY:
/* PRIO is default qdisc scheduler */
- return airoha_qdma_set_tx_prio_sched(port, channel);
+ return airoha_qdma_set_tx_prio_sched(dev, channel);
case TC_ETS_STATS:
- return airoha_qdma_get_tx_ets_stats(port, channel, opt);
+ return airoha_qdma_get_tx_ets_stats(dev, channel, opt);
default:
return -EOPNOTSUPP;
}
@@ -2797,11 +2797,9 @@ static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
-
switch (type) {
case TC_SETUP_QDISC_ETS:
- return airoha_tc_setup_qdisc_ets(port, type_data);
+ return airoha_tc_setup_qdisc_ets(dev, type_data);
case TC_SETUP_QDISC_HTB:
return airoha_tc_setup_qdisc_htb(dev, type_data);
case TC_SETUP_BLOCK:
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 06/11] net: airoha: Introduce airoha_gdm_dev struct
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3
or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner.
As a result multiple net_devices can connect to the same GDM{3,4} port
and there is a theoretical "1:n" relation between GDM port and
net_devices.
Introduce airoha_gdm_dev struct to collect net_device related info (e.g.
net_device and external phy pointer). Please note this is just a
preliminary patch and we are still supporting a single net_device for
each GDM port. Subsequent patches will add support for multiple net_devices
connected to the same GDM port.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 268 +++++++++++++++++++------------
drivers/net/ethernet/airoha/airoha_eth.h | 13 +-
drivers/net/ethernet/airoha/airoha_ppe.c | 17 +-
3 files changed, 180 insertions(+), 118 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 268f4e34f38d2df128f0be52ae00fec07e46b1bf..99f19edb993b8143973f2ed91c41dfa975eab6ef 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -616,6 +616,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
struct page *page = virt_to_head_page(e->buf);
u32 desc_ctrl = le32_to_cpu(desc->ctrl);
struct airoha_gdm_port *port;
+ struct net_device *netdev;
int data_len, len, p;
if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
@@ -638,6 +639,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
goto free_frag;
port = eth->ports[p];
+ netdev = port->dev->dev;
if (!q->skb) { /* first buffer */
q->skb = napi_build_skb(e->buf, q->buf_size);
if (!q->skb)
@@ -645,8 +647,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
__skb_put(q->skb, len);
skb_mark_for_recycle(q->skb);
- q->skb->dev = port->dev;
- q->skb->protocol = eth_type_trans(q->skb, port->dev);
+ q->skb->dev = netdev;
+ q->skb->protocol = eth_type_trans(q->skb, netdev);
q->skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(q->skb, qid);
} else { /* scattered frame */
@@ -664,7 +666,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl))
continue;
- if (netdev_uses_dsa(port->dev)) {
+ if (netdev_uses_dsa(netdev)) {
/* PPE module requires untagged packets to work
* properly and it provides DSA port index via the
* DMA descriptor. Report DSA tag to the DSA stack
@@ -1622,19 +1624,20 @@ static void airoha_update_hw_stats(struct airoha_gdm_port *port)
spin_unlock(&port->stats.lock);
}
-static int airoha_dev_open(struct net_device *dev)
+static int airoha_dev_open(struct net_device *netdev)
{
- int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN;
- struct airoha_gdm_port *port = netdev_priv(dev);
+ int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_qdma *qdma = port->qdma;
u32 pse_port = FE_PSE_PORT_PPE1;
- netif_tx_start_all_queues(dev);
+ netif_tx_start_all_queues(netdev);
err = airoha_set_vip_for_gdm_port(port, true);
if (err)
return err;
- if (netdev_uses_dsa(dev))
+ if (netdev_uses_dsa(netdev))
airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
GDM_STAG_EN_MASK);
else
@@ -1662,19 +1665,20 @@ static int airoha_dev_open(struct net_device *dev)
return 0;
}
-static int airoha_dev_stop(struct net_device *dev)
+static int airoha_dev_stop(struct net_device *netdev)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_qdma *qdma = port->qdma;
int i, err;
- netif_tx_disable(dev);
+ netif_tx_disable(netdev);
err = airoha_set_vip_for_gdm_port(port, false);
if (err)
return err;
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
- netdev_tx_reset_subqueue(dev, i);
+ netdev_tx_reset_subqueue(netdev, i);
airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
@@ -1695,16 +1699,17 @@ static int airoha_dev_stop(struct net_device *dev)
return 0;
}
-static int airoha_dev_set_macaddr(struct net_device *dev, void *p)
+static int airoha_dev_set_macaddr(struct net_device *netdev, void *p)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
int err;
- err = eth_mac_addr(dev, p);
+ err = eth_mac_addr(netdev, p);
if (err)
return err;
- airoha_set_macaddr(port, dev->dev_addr);
+ airoha_set_macaddr(port, netdev->dev_addr);
return 0;
}
@@ -1770,16 +1775,17 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
return 0;
}
-static int airoha_dev_init(struct net_device *dev)
+static int airoha_dev_init(struct net_device *netdev)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
- struct airoha_eth *eth = port->eth;
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
int i;
/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
- port->dev->irq = port->qdma->irq_banks[0].irq;
- airoha_set_macaddr(port, dev->dev_addr);
+ dev->dev->irq = port->qdma->irq_banks[0].irq;
+ airoha_set_macaddr(port, netdev->dev_addr);
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -1804,10 +1810,11 @@ static int airoha_dev_init(struct net_device *dev)
return 0;
}
-static void airoha_dev_get_stats64(struct net_device *dev,
+static void airoha_dev_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *storage)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
unsigned int start;
airoha_update_hw_stats(port);
@@ -1826,36 +1833,39 @@ static void airoha_dev_get_stats64(struct net_device *dev,
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
}
-static int airoha_dev_change_mtu(struct net_device *dev, int mtu)
+static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_eth *eth = port->qdma->eth;
u32 len = ETH_HLEN + mtu + ETH_FCS_LEN;
airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
GDM_LONG_LEN_MASK,
FIELD_PREP(GDM_LONG_LEN_MASK, len));
- WRITE_ONCE(dev->mtu, mtu);
+ WRITE_ONCE(netdev->mtu, mtu);
return 0;
}
-static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
+static u16 airoha_dev_select_queue(struct net_device *netdev,
+ struct sk_buff *skb,
struct net_device *sb_dev)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
int queue, channel;
/* For dsa device select QoS channel according to the dsa user port
* index, rely on port id otherwise. Select QoS queue based on the
* skb priority.
*/
- channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
+ channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id;
channel = channel % AIROHA_NUM_QOS_CHANNELS;
queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
- return queue < dev->num_tx_queues ? queue : 0;
+ return queue < netdev->num_tx_queues ? queue : 0;
}
static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
@@ -1919,9 +1929,10 @@ int airoha_get_fe_port(struct airoha_gdm_port *port)
}
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
- struct net_device *dev)
+ struct net_device *netdev)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_qdma *qdma = port->qdma;
u32 nr_frags, tag, msg0, msg1, len;
struct airoha_queue_entry *e;
@@ -1934,7 +1945,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
u8 fport;
qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx);
- tag = airoha_get_dsa_tag(skb, dev);
+ tag = airoha_get_dsa_tag(skb, netdev);
msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK,
qid / AIROHA_NUM_QOS_QUEUES) |
@@ -1970,7 +1981,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
spin_lock_bh(&q->lock);
- txq = netdev_get_tx_queue(dev, qid);
+ txq = netdev_get_tx_queue(netdev, qid);
nr_frags = 1 + skb_shinfo(skb)->nr_frags;
if (q->queued + nr_frags >= q->ndesc) {
@@ -1993,9 +2004,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
dma_addr_t addr;
u32 val;
- addr = dma_map_single(dev->dev.parent, data, len,
+ addr = dma_map_single(netdev->dev.parent, data, len,
DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev.parent, addr)))
+ if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
goto error_unmap;
list_move_tail(&e->list, &tx_list);
@@ -2042,8 +2053,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
while (!list_empty(&tx_list)) {
e = list_first_entry(&tx_list, struct airoha_queue_entry,
list);
- dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len,
- DMA_TO_DEVICE);
+ dma_unmap_single(netdev->dev.parent, e->dma_addr,
+ e->dma_len, DMA_TO_DEVICE);
e->dma_addr = 0;
list_move_tail(&e->list, &q->tx_list);
}
@@ -2051,25 +2062,27 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
spin_unlock_bh(&q->lock);
error:
dev_kfree_skb_any(skb);
- dev->stats.tx_dropped++;
+ netdev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
-static void airoha_ethtool_get_drvinfo(struct net_device *dev,
+static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_eth *eth = port->qdma->eth;
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
}
-static void airoha_ethtool_get_mac_stats(struct net_device *dev,
+static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
struct ethtool_eth_mac_stats *stats)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
unsigned int start;
airoha_update_hw_stats(port);
@@ -2097,11 +2110,12 @@ static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = {
};
static void
-airoha_ethtool_get_rmon_stats(struct net_device *dev,
+airoha_ethtool_get_rmon_stats(struct net_device *netdev,
struct ethtool_rmon_stats *stats,
const struct ethtool_rmon_hist_range **ranges)
{
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_hw_stats *hw_stats = &port->stats;
unsigned int start;
@@ -2130,7 +2144,8 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
int channel, enum tx_sched_mode mode,
const u16 *weights, u8 n_weights)
{
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
int i;
for (i = 0; i < AIROHA_NUM_TX_RING; i++)
@@ -2218,7 +2233,8 @@ static int airoha_qdma_set_tx_ets_sched(struct net_device *dev, int channel,
static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
struct tc_ets_qopt_offload *opt)
{
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
REG_CNTR_VAL(channel << 1));
@@ -2484,7 +2500,8 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
int channel, u32 rate,
u32 bucket_size)
{
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
int i, err;
for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
@@ -2510,7 +2527,8 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */
int err, num_tx_queues = netdev->real_num_tx_queues;
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
if (opt->parent_classid != TC_HTB_CLASSID_ROOT) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid");
@@ -2621,11 +2639,12 @@ static int airoha_tc_matchall_act_validate(struct tc_cls_matchall_offload *f)
return 0;
}
-static int airoha_dev_tc_matchall(struct net_device *dev,
+static int airoha_dev_tc_matchall(struct net_device *netdev,
struct tc_cls_matchall_offload *f)
{
enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT;
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
u32 rate = 0, bucket_size = 0;
switch (f->command) {
@@ -2660,18 +2679,19 @@ static int airoha_dev_tc_matchall(struct net_device *dev,
static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,
void *type_data, void *cb_priv)
{
- struct net_device *dev = cb_priv;
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct net_device *netdev = cb_priv;
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
struct airoha_eth *eth = port->qdma->eth;
- if (!tc_can_offload(dev))
+ if (!tc_can_offload(netdev))
return -EOPNOTSUPP;
switch (type) {
case TC_SETUP_CLSFLOWER:
return airoha_ppe_setup_tc_block_cb(ð->ppe->dev, type_data);
case TC_SETUP_CLSMATCHALL:
- return airoha_dev_tc_matchall(dev, type_data);
+ return airoha_dev_tc_matchall(netdev, type_data);
default:
return -EOPNOTSUPP;
}
@@ -2720,7 +2740,8 @@ static int airoha_dev_setup_tc_block(struct net_device *dev,
static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
{
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1);
airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0);
@@ -2731,7 +2752,8 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
if (!test_bit(channel, port->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
@@ -2745,7 +2767,8 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
static int airoha_tc_htb_destroy(struct net_device *netdev)
{
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
int q;
for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
@@ -2758,7 +2781,8 @@ static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
struct tc_htb_qopt_offload *opt)
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
- struct airoha_gdm_port *port = netdev_priv(netdev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
if (!test_bit(channel, port->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
@@ -2794,8 +2818,8 @@ static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
return 0;
}
-static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
- void *type_data)
+static int airoha_dev_tc_setup(struct net_device *dev,
+ enum tc_setup_type type, void *type_data)
{
switch (type) {
case TC_SETUP_QDISC_ETS:
@@ -2861,25 +2885,81 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
}
}
-bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
- struct airoha_gdm_port *port)
+bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
+ struct airoha_gdm_dev *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
- if (eth->ports[i] == port)
+ struct airoha_gdm_port *port = eth->ports[i];
+
+ if (!port)
+ continue;
+
+ if (port->dev == dev)
return true;
}
return false;
}
+static int airoha_alloc_gdm_device(struct airoha_eth *eth,
+ struct airoha_gdm_port *port,
+ struct device_node *np)
+{
+ struct airoha_gdm_dev *dev;
+ struct net_device *netdev;
+ int err;
+
+ netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev),
+ AIROHA_NUM_NETDEV_TX_RINGS,
+ AIROHA_NUM_RX_RING);
+ if (!netdev) {
+ dev_err(eth->dev, "alloc_etherdev failed\n");
+ return -ENOMEM;
+ }
+
+ netdev->netdev_ops = &airoha_netdev_ops;
+ netdev->ethtool_ops = &airoha_ethtool_ops;
+ netdev->max_mtu = AIROHA_MAX_MTU;
+ netdev->watchdog_timeo = 5 * HZ;
+ netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 |
+ NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO |
+ NETIF_F_HW_TC;
+ netdev->features |= netdev->hw_features;
+ netdev->vlan_features = netdev->hw_features;
+ netdev->dev.of_node = np;
+ SET_NETDEV_DEV(netdev, eth->dev);
+
+ /* reserve hw queues for HTB offloading */
+ err = netif_set_real_num_tx_queues(netdev, AIROHA_NUM_TX_RING);
+ if (err)
+ return err;
+
+ err = of_get_ethdev_address(np, netdev);
+ if (err) {
+ if (err == -EPROBE_DEFER)
+ return err;
+
+ eth_hw_addr_random(netdev);
+ dev_info(eth->dev, "generated random MAC address %pM\n",
+ netdev->dev_addr);
+ }
+
+ dev = netdev_priv(netdev);
+ dev->dev = netdev;
+ dev->port = port;
+ port->dev = dev;
+ dev->eth = eth;
+
+ return 0;
+}
+
static int airoha_alloc_gdm_port(struct airoha_eth *eth,
struct device_node *np)
{
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
struct airoha_gdm_port *port;
- struct net_device *dev;
int err, p;
u32 id;
@@ -2901,51 +2981,20 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
return -EINVAL;
}
- dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port),
- AIROHA_NUM_NETDEV_TX_RINGS,
- AIROHA_NUM_RX_RING);
- if (!dev) {
- dev_err(eth->dev, "alloc_etherdev failed\n");
+ port = devm_kzalloc(eth->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
return -ENOMEM;
- }
-
- dev->netdev_ops = &airoha_netdev_ops;
- dev->ethtool_ops = &airoha_ethtool_ops;
- dev->max_mtu = AIROHA_MAX_MTU;
- dev->watchdog_timeo = 5 * HZ;
- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM |
- NETIF_F_SG | NETIF_F_TSO |
- NETIF_F_HW_TC;
- dev->features |= dev->hw_features;
- dev->vlan_features = dev->hw_features;
- dev->dev.of_node = np;
- SET_NETDEV_DEV(dev, eth->dev);
-
- /* reserve hw queues for HTB offloading */
- err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING);
- if (err)
- return err;
-
- err = of_get_ethdev_address(np, dev);
- if (err) {
- if (err == -EPROBE_DEFER)
- return err;
-
- eth_hw_addr_random(dev);
- dev_info(eth->dev, "generated random MAC address %pM\n",
- dev->dev_addr);
- }
- port = netdev_priv(dev);
u64_stats_init(&port->stats.syncp);
spin_lock_init(&port->stats.lock);
- port->eth = eth;
- port->dev = dev;
port->id = id;
eth->ports[p] = port;
- return airoha_metadata_dst_alloc(port);
+ err = airoha_metadata_dst_alloc(port);
+ if (err)
+ return err;
+
+ return airoha_alloc_gdm_device(eth, port, np);
}
static int airoha_register_gdm_devices(struct airoha_eth *eth)
@@ -2959,7 +3008,7 @@ static int airoha_register_gdm_devices(struct airoha_eth *eth)
if (!port)
continue;
- err = register_netdev(port->dev);
+ err = register_netdev(port->dev->dev);
if (err)
return err;
}
@@ -3066,12 +3115,14 @@ static int airoha_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
+ struct airoha_gdm_dev *dev;
if (!port)
continue;
- if (port->dev->reg_state == NETREG_REGISTERED)
- unregister_netdev(port->dev);
+ dev = port->dev;
+ if (dev && dev->dev->reg_state == NETREG_REGISTERED)
+ unregister_netdev(dev->dev);
airoha_metadata_dst_free(port);
}
airoha_hw_cleanup(eth);
@@ -3092,11 +3143,14 @@ static void airoha_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
+ struct airoha_gdm_dev *dev;
if (!port)
continue;
- unregister_netdev(port->dev);
+ dev = port->dev;
+ if (dev)
+ unregister_netdev(dev->dev);
airoha_metadata_dst_free(port);
}
airoha_hw_cleanup(eth);
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index f04b8d8cfc09f74f288c347d03e18b4f4f3aa893..0700d6b76e4685c3047d3604f843781af312c7b6 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -531,10 +531,15 @@ struct airoha_qdma {
struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
};
+struct airoha_gdm_dev {
+ struct airoha_gdm_port *port;
+ struct net_device *dev;
+ struct airoha_eth *eth;
+};
+
struct airoha_gdm_port {
struct airoha_qdma *qdma;
- struct airoha_eth *eth;
- struct net_device *dev;
+ struct airoha_gdm_dev *dev;
int id;
struct airoha_hw_stats stats;
@@ -647,8 +652,8 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
}
int airoha_get_fe_port(struct airoha_gdm_port *port);
-bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
- struct airoha_gdm_port *port);
+bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
+ struct airoha_gdm_dev *dev);
void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id,
u8 fport);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 0f42247a2ef3d67b7dadb6201079ff2c2defbf0d..a8c1a5adce30f0af416c0660abad67ea6240513e 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -291,12 +291,12 @@ static void airoha_ppe_foe_set_bridge_addrs(struct airoha_foe_bridge *br,
static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
struct airoha_foe_entry *hwe,
- struct net_device *dev, int type,
+ struct net_device *netdev, int type,
struct airoha_flow_data *data,
int l4proto)
{
u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val;
- int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev);
+ int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev);
struct airoha_foe_mac_info_common *l2;
u8 smac_id = 0xf;
@@ -312,10 +312,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
hwe->ib1 = val;
val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f);
- if (dev) {
+ if (netdev) {
struct airoha_wdma_info info = {};
- if (!airoha_ppe_get_wdma_info(dev, data->eth.h_dest, &info)) {
+ if (!airoha_ppe_get_wdma_info(netdev, data->eth.h_dest,
+ &info)) {
val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) |
FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT,
FE_PSE_PORT_CDM4);
@@ -325,12 +326,14 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID,
info.wcid);
} else {
- struct airoha_gdm_port *port = netdev_priv(dev);
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port;
u8 pse_port;
- if (!airoha_is_valid_gdm_port(eth, port))
+ if (!airoha_is_valid_gdm_dev(eth, dev))
return -EINVAL;
+ port = dev->port;
if (dsa_port >= 0 || eth->ports[1])
pse_port = port->id == 4 ? FE_PSE_PORT_GDM4
: port->id;
@@ -1423,7 +1426,7 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port)
{
struct airoha_eth *eth = port->qdma->eth;
- struct net_device *dev = port->dev;
+ struct net_device *dev = port->dev->dev;
const u8 *addr = dev->dev_addr;
u32 val;
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 07/11] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Move airoha_qdma pointer from airoha_gdm_port struct to airoha_gdm_dev
one since the QDMA block used depends on the particular net_device
WAN/LAN configuration and in the current codebase net_device pointer is
associated to airoha_gdm_dev struct.
This is a preliminary patch to support multiple net_devices connected
to the same GDM{3,4} port via an external hw arbiter.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 98 +++++++++++++++-----------------
drivers/net/ethernet/airoha/airoha_eth.h | 9 ++-
drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++---
3 files changed, 59 insertions(+), 65 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 99f19edb993b8143973f2ed91c41dfa975eab6ef..8a9d79afe48d636e17168d43ed152620ed661435 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -71,9 +71,10 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
}
-static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
+static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
{
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
u32 val, reg;
reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
@@ -85,7 +86,7 @@ static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
- airoha_ppe_init_upd_mem(port);
+ airoha_ppe_init_upd_mem(dev);
}
static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
@@ -101,10 +102,10 @@ static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
FIELD_PREP(GDM_UCFQ_MASK, val));
}
-static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port,
- bool enable)
+static int airoha_set_vip_for_gdm_port(struct airoha_gdm_dev *dev, bool enable)
{
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
u32 vip_port;
switch (port->id) {
@@ -1480,9 +1481,10 @@ static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
}
}
-static void airoha_update_hw_stats(struct airoha_gdm_port *port)
+static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
{
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
u32 val, i = 0;
spin_lock(&port->stats.lock);
@@ -1629,11 +1631,11 @@ static int airoha_dev_open(struct net_device *netdev)
int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- struct airoha_qdma *qdma = port->qdma;
+ struct airoha_qdma *qdma = dev->qdma;
u32 pse_port = FE_PSE_PORT_PPE1;
netif_tx_start_all_queues(netdev);
- err = airoha_set_vip_for_gdm_port(port, true);
+ err = airoha_set_vip_for_gdm_port(dev, true);
if (err)
return err;
@@ -1669,11 +1671,11 @@ static int airoha_dev_stop(struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- struct airoha_qdma *qdma = port->qdma;
+ struct airoha_qdma *qdma = dev->qdma;
int i, err;
netif_tx_disable(netdev);
- err = airoha_set_vip_for_gdm_port(port, false);
+ err = airoha_set_vip_for_gdm_port(dev, false);
if (err)
return err;
@@ -1702,21 +1704,21 @@ static int airoha_dev_stop(struct net_device *netdev)
static int airoha_dev_set_macaddr(struct net_device *netdev, void *p)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
int err;
err = eth_mac_addr(netdev, p);
if (err)
return err;
- airoha_set_macaddr(port, netdev->dev_addr);
+ airoha_set_macaddr(dev, netdev->dev_addr);
return 0;
}
-static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
+static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
{
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
u32 val, pse_port, chan, nbq;
int i, src_port;
@@ -1763,7 +1765,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
__field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2));
for (i = 0; i < eth->soc->num_ppe; i++)
- airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX);
+ airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX);
if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) {
u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq);
@@ -1783,9 +1785,9 @@ static int airoha_dev_init(struct net_device *netdev)
int i;
/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
- port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
- dev->dev->irq = port->qdma->irq_banks[0].irq;
- airoha_set_macaddr(port, netdev->dev_addr);
+ dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
+ dev->dev->irq = dev->qdma->irq_banks[0].irq;
+ airoha_set_macaddr(dev, netdev->dev_addr);
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -1794,7 +1796,7 @@ static int airoha_dev_init(struct net_device *netdev)
if (!eth->ports[1]) {
int err;
- err = airoha_set_gdm2_loopback(port);
+ err = airoha_set_gdm2_loopback(dev);
if (err)
return err;
}
@@ -1804,8 +1806,7 @@ static int airoha_dev_init(struct net_device *netdev)
}
for (i = 0; i < eth->soc->num_ppe; i++)
- airoha_ppe_set_cpu_port(port, i,
- airoha_get_fe_port(port));
+ airoha_ppe_set_cpu_port(dev, i, airoha_get_fe_port(dev));
return 0;
}
@@ -1817,7 +1818,7 @@ static void airoha_dev_get_stats64(struct net_device *netdev,
struct airoha_gdm_port *port = dev->port;
unsigned int start;
- airoha_update_hw_stats(port);
+ airoha_update_hw_stats(dev);
do {
start = u64_stats_fetch_begin(&port->stats.syncp);
storage->rx_packets = port->stats.rx_ok_pkts;
@@ -1837,8 +1838,8 @@ static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- struct airoha_eth *eth = port->qdma->eth;
u32 len = ETH_HLEN + mtu + ETH_FCS_LEN;
+ struct airoha_eth *eth = dev->eth;
airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
GDM_LONG_LEN_MASK,
@@ -1912,10 +1913,10 @@ static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
#endif
}
-int airoha_get_fe_port(struct airoha_gdm_port *port)
+int airoha_get_fe_port(struct airoha_gdm_dev *dev)
{
- struct airoha_qdma *qdma = port->qdma;
- struct airoha_eth *eth = qdma->eth;
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
switch (eth->soc->version) {
case 0x7583:
@@ -1932,8 +1933,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
- struct airoha_qdma *qdma = port->qdma;
+ struct airoha_qdma *qdma = dev->qdma;
u32 nr_frags, tag, msg0, msg1, len;
struct airoha_queue_entry *e;
struct netdev_queue *txq;
@@ -1971,7 +1971,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
}
}
- fport = airoha_get_fe_port(port);
+ fport = airoha_get_fe_port(dev);
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
@@ -2071,8 +2071,7 @@ static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_eth *eth = dev->eth;
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
@@ -2085,7 +2084,7 @@ static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
struct airoha_gdm_port *port = dev->port;
unsigned int start;
- airoha_update_hw_stats(port);
+ airoha_update_hw_stats(dev);
do {
start = u64_stats_fetch_begin(&port->stats.syncp);
stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
@@ -2125,7 +2124,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
ARRAY_SIZE(hw_stats->rx_len) + 1);
*ranges = airoha_ethtool_rmon_ranges;
- airoha_update_hw_stats(port);
+ airoha_update_hw_stats(dev);
do {
int i;
@@ -2145,18 +2144,17 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
const u16 *weights, u8 n_weights)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
int i;
for (i = 0; i < AIROHA_NUM_TX_RING; i++)
- airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel),
+ airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel),
TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
for (i = 0; i < n_weights; i++) {
u32 status;
int err;
- airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG,
+ airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG,
TWRR_RW_CMD_MASK |
FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
@@ -2164,13 +2162,12 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
err = read_poll_timeout(airoha_qdma_rr, status,
status & TWRR_RW_CMD_DONE,
USEC_PER_MSEC, 10 * USEC_PER_MSEC,
- true, port->qdma,
- REG_TXWRR_WEIGHT_CFG);
+ true, dev->qdma, REG_TXWRR_WEIGHT_CFG);
if (err)
return err;
}
- airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3),
+ airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3),
CHAN_QOS_MODE_MASK(channel),
__field_prep(CHAN_QOS_MODE_MASK(channel), mode));
@@ -2236,9 +2233,9 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
+ u64 cpu_tx_packets = airoha_qdma_rr(dev->qdma,
REG_CNTR_VAL(channel << 1));
- u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
+ u64 fwd_tx_packets = airoha_qdma_rr(dev->qdma,
REG_CNTR_VAL((channel << 1) + 1));
u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) +
(fwd_tx_packets - port->fwd_tx_packets);
@@ -2501,17 +2498,16 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
u32 bucket_size)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
int i, err;
for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
- err = airoha_qdma_set_trtcm_config(port->qdma, channel,
+ err = airoha_qdma_set_trtcm_config(dev->qdma, channel,
REG_EGRESS_TRTCM_CFG, i,
!!rate, TRTCM_METER_MODE);
if (err)
return err;
- err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel,
+ err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel,
REG_EGRESS_TRTCM_CFG,
i, rate, bucket_size);
if (err)
@@ -2561,11 +2557,11 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
return 0;
}
-static int airoha_qdma_set_rx_meter(struct airoha_gdm_port *port,
+static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,
u32 rate, u32 bucket_size,
enum trtcm_unit_type unit_type)
{
- struct airoha_qdma *qdma = port->qdma;
+ struct airoha_qdma *qdma = dev->qdma;
int i;
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
@@ -2644,7 +2640,6 @@ static int airoha_dev_tc_matchall(struct net_device *netdev,
{
enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
u32 rate = 0, bucket_size = 0;
switch (f->command) {
@@ -2669,7 +2664,7 @@ static int airoha_dev_tc_matchall(struct net_device *netdev,
fallthrough;
}
case TC_CLSMATCHALL_DESTROY:
- return airoha_qdma_set_rx_meter(port, rate, bucket_size,
+ return airoha_qdma_set_rx_meter(dev, rate, bucket_size,
unit_type);
default:
return -EOPNOTSUPP;
@@ -2681,8 +2676,7 @@ static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,
{
struct net_device *netdev = cb_priv;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
- struct airoha_eth *eth = port->qdma->eth;
+ struct airoha_eth *eth = dev->eth;
if (!tc_can_offload(netdev))
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 0700d6b76e4685c3047d3604f843781af312c7b6..b1e05cb67ce93640b25355106947ca2ab31f7235 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -533,12 +533,12 @@ struct airoha_qdma {
struct airoha_gdm_dev {
struct airoha_gdm_port *port;
+ struct airoha_qdma *qdma;
struct net_device *dev;
struct airoha_eth *eth;
};
struct airoha_gdm_port {
- struct airoha_qdma *qdma;
struct airoha_gdm_dev *dev;
int id;
@@ -651,19 +651,18 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
return eth->soc->version == 0x7583;
}
-int airoha_get_fe_port(struct airoha_gdm_port *port);
+int airoha_get_fe_port(struct airoha_gdm_dev *dev);
bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
struct airoha_gdm_dev *dev);
-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id,
- u8 fport);
+void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
u16 hash, bool rx_wlan);
int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);
int airoha_ppe_init(struct airoha_eth *eth);
void airoha_ppe_deinit(struct airoha_eth *eth);
-void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port);
+void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev);
u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);
struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
u32 hash);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index a8c1a5adce30f0af416c0660abad67ea6240513e..6c55ffa40edad63ec135cd0c987b3bcac0b0fbf6 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -85,9 +85,9 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp);
}
-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, u8 fport)
+void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
{
- struct airoha_qdma *qdma = port->qdma;
+ struct airoha_qdma *qdma = dev->qdma;
struct airoha_eth *eth = qdma->eth;
u8 qdma_id = qdma - ð->qdma[0];
u32 fe_cpu_port;
@@ -173,8 +173,8 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
if (!port)
continue;
- airoha_ppe_set_cpu_port(port, i,
- airoha_get_fe_port(port));
+ airoha_ppe_set_cpu_port(port->dev, i,
+ airoha_get_fe_port(port->dev));
}
}
}
@@ -1423,11 +1423,12 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan);
}
-void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port)
+void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev)
{
- struct airoha_eth *eth = port->qdma->eth;
- struct net_device *dev = port->dev->dev;
- const u8 *addr = dev->dev_addr;
+ struct airoha_gdm_port *port = dev->port;
+ struct net_device *netdev = dev->dev;
+ struct airoha_eth *eth = dev->eth;
+ const u8 *addr = netdev->dev_addr;
u32 val;
val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 08/11] net: airoha: Rely on airoha_gdm_dev pointer in airhoa_is_lan_gdm_port()
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Rename airhoa_is_lan_gdm_port in airhoa_is_lan_gdm_dev. Moreover, rely
on airoha_gdm_dev pointer in airhoa_is_lan_gdm_dev() instead of
airoha_gdm_port one.
This is a preliminary patch to support multiple net_devices connected to
the same GDM{3,4} port via an external hw arbiter.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 6 ++----
drivers/net/ethernet/airoha/airoha_eth.h | 4 +++-
drivers/net/ethernet/airoha/airoha_ppe.c | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 8a9d79afe48d636e17168d43ed152620ed661435..5e489e8593ba6ad3d5d9f6a383c827919153652e 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -73,12 +73,10 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
{
- struct airoha_gdm_port *port = dev->port;
struct airoha_eth *eth = dev->eth;
u32 val, reg;
- reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
- : REG_FE_WAN_MAC_H;
+ reg = airoha_is_lan_gdm_dev(dev) ? REG_FE_LAN_MAC_H : REG_FE_WAN_MAC_H;
val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
airoha_fe_wr(eth, reg, val);
@@ -1785,7 +1783,7 @@ static int airoha_dev_init(struct net_device *netdev)
int i;
/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
- dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
+ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
dev->dev->irq = dev->qdma->irq_banks[0].irq;
airoha_set_macaddr(dev, netdev->dev_addr);
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index b1e05cb67ce93640b25355106947ca2ab31f7235..c444ba7832dec356286e5dd2166aba792fdd2c5f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -632,8 +632,10 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
#define airoha_qdma_clear(qdma, offset, val) \
airoha_rmw((qdma)->regs, (offset), (val), 0)
-static inline bool airoha_is_lan_gdm_port(struct airoha_gdm_port *port)
+static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev)
{
+ struct airoha_gdm_port *port = dev->port;
+
/* GDM1 port on EN7581 SoC is connected to the lan dsa switch.
* GDM{2,3,4} can be used as wan port connected to an external
* phy module.
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 6c55ffa40edad63ec135cd0c987b3bcac0b0fbf6..c86cbbfacc1e6e049ccac60d703edc8ca53eff9b 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -347,7 +347,7 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
/* For downlink traffic consume SRAM memory for hw
* forwarding descriptors queue.
*/
- if (airoha_is_lan_gdm_port(port))
+ if (airoha_is_lan_gdm_dev(dev))
val |= AIROHA_FOE_IB2_FAST_PATH;
if (dsa_port >= 0)
val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 09/11] net: airoha: Support multiple net_devices for a single FE GDM port
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
manages the traffic in a TDM manner. As a result multiple net_devices can
connect to the same GDM{3,4} port and there is a theoretical "1:n"
relation between GDM ports and net_devices.
┌─────────────────────────────────┐
│ │ ┌──────┐
│ P1 GDM1 ├────►MT7530│
│ │ └──────┘
│ │ ETH0 (DSA conduit)
│ │
│ PSE/FE │
│ │
│ │
│ │ ┌─────┐
│ P0 CDM1 ├────►QDMA0│
│ P4 P9 GDM4 │ └─────┘
└──┬─────────────────────────┬────┘
│ │
┌──▼──┐ ┌────▼────┐
│ PPE │ │ ARB │
└─────┘ └─┬─────┬─┘
│ │
┌──▼──┐┌─▼───┐
│ ETH ││ USB │
└─────┘└─────┘
ETH1 ETH2
Introduce support for multiple net_devices connected to the same Frame
Engine (FE) GDM port (GDM3 or GDM4) via an external hw arbiter.
Please note GDM1 or GDM2 does not support the connection with the external
arbiter.
Add get_dev_from_sport callback since EN7581 and AN7583 have different
logics for the net_device type connected to GDM3 or GDM4.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 229 ++++++++++++++++++++++++-------
drivers/net/ethernet/airoha/airoha_eth.h | 9 +-
drivers/net/ethernet/airoha/airoha_ppe.c | 13 +-
3 files changed, 198 insertions(+), 53 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 5e489e8593ba6ad3d5d9f6a383c827919153652e..0780fb8aacfbc51fdd896de7be70fb34ee49e864 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -580,24 +580,26 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
return nframes;
}
-static int airoha_qdma_get_gdm_port(struct airoha_eth *eth,
- struct airoha_qdma_desc *desc)
+static struct airoha_gdm_dev *
+airoha_qdma_get_gdm_dev(struct airoha_eth *eth, struct airoha_qdma_desc *desc)
{
- u32 port, sport, msg1 = le32_to_cpu(desc->msg1);
+ struct airoha_gdm_port *port;
+ u16 p, d;
- sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1);
- switch (sport) {
- case 0x10 ... 0x14:
- port = 0;
- break;
- case 0x2 ... 0x4:
- port = sport - 1;
- break;
- default:
- return -EINVAL;
- }
+ if (eth->soc->ops.get_dev_from_sport(desc, &p, &d))
+ return ERR_PTR(-ENODEV);
+
+ if (p >= ARRAY_SIZE(eth->ports))
+ return ERR_PTR(-ENODEV);
+
+ port = eth->ports[p];
+ if (!port)
+ return ERR_PTR(-ENODEV);
+
+ if (d >= ARRAY_SIZE(port->devs))
+ return ERR_PTR(-ENODEV);
- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port;
+ return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV);
}
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
@@ -614,9 +616,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
u32 hash, reason, msg1 = le32_to_cpu(desc->msg1);
struct page *page = virt_to_head_page(e->buf);
u32 desc_ctrl = le32_to_cpu(desc->ctrl);
- struct airoha_gdm_port *port;
- struct net_device *netdev;
- int data_len, len, p;
+ struct airoha_gdm_dev *dev;
+ int data_len, len;
if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
break;
@@ -633,12 +634,10 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
if (!len || data_len < len)
goto free_frag;
- p = airoha_qdma_get_gdm_port(eth, desc);
- if (p < 0 || !eth->ports[p])
+ dev = airoha_qdma_get_gdm_dev(eth, desc);
+ if (IS_ERR(dev))
goto free_frag;
- port = eth->ports[p];
- netdev = port->dev->dev;
if (!q->skb) { /* first buffer */
q->skb = napi_build_skb(e->buf, q->buf_size);
if (!q->skb)
@@ -646,8 +645,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
__skb_put(q->skb, len);
skb_mark_for_recycle(q->skb);
- q->skb->dev = netdev;
- q->skb->protocol = eth_type_trans(q->skb, netdev);
+ q->skb->dev = dev->dev;
+ q->skb->protocol = eth_type_trans(q->skb, dev->dev);
q->skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(q->skb, qid);
} else { /* scattered frame */
@@ -665,7 +664,9 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl))
continue;
- if (netdev_uses_dsa(netdev)) {
+ if (netdev_uses_dsa(dev->dev)) {
+ struct airoha_gdm_port *port = dev->port;
+
/* PPE module requires untagged packets to work
* properly and it provides DSA port index via the
* DMA descriptor. Report DSA tag to the DSA stack
@@ -1717,7 +1718,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
{
struct airoha_gdm_port *port = dev->port;
struct airoha_eth *eth = dev->eth;
- u32 val, pse_port, chan, nbq;
+ u32 val, pse_port, chan;
int i, src_port;
/* Forward the traffic to the proper GDM port */
@@ -1747,9 +1748,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
- /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
- nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
- src_port = eth->soc->ops.get_src_port_id(port, nbq);
+ src_port = eth->soc->ops.get_src_port_id(port, dev->nbq);
if (src_port < 0)
return src_port;
@@ -1766,7 +1765,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX);
if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) {
- u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq);
+ u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq);
airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask,
__field_prep(mask, AIROHA_GDM2_IDX));
@@ -1970,7 +1969,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
}
fport = airoha_get_fe_port(dev);
- msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
+ msg1 = FIELD_PREP(QDMA_ETH_TXMSG_NBOQ_MASK, dev->nbq) |
+ FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
q = &qdma->q_tx[qid];
@@ -2884,12 +2884,15 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
+ int j;
if (!port)
continue;
- if (port->dev == dev)
- return true;
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
+ if (port->devs[j] == dev)
+ return true;
+ }
}
return false;
@@ -2897,10 +2900,11 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
static int airoha_alloc_gdm_device(struct airoha_eth *eth,
struct airoha_gdm_port *port,
- struct device_node *np)
+ int nbq, struct device_node *np)
{
- struct airoha_gdm_dev *dev;
struct net_device *netdev;
+ struct airoha_gdm_dev *dev;
+ u8 index;
int err;
netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev),
@@ -2938,11 +2942,24 @@ static int airoha_alloc_gdm_device(struct airoha_eth *eth,
netdev->dev_addr);
}
+ /* Allowed nbq for EN7581 on GDM3 port are 4 and 5 for PCIE0
+ * and PCIE1 respectively.
+ */
+ index = nbq;
+ if (airoha_is_7581(eth) && port->id == AIROHA_GDM3_IDX)
+ index -= 4;
+
+ if (index >= ARRAY_SIZE(port->devs) || port->devs[index]) {
+ dev_err(eth->dev, "invalid nbq id: %d\n", nbq);
+ return -EINVAL;
+ }
+
dev = netdev_priv(netdev);
dev->dev = netdev;
dev->port = port;
- port->dev = dev;
dev->eth = eth;
+ dev->nbq = nbq;
+ port->devs[index] = dev;
return 0;
}
@@ -2952,7 +2969,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
{
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
struct airoha_gdm_port *port;
- int err, p;
+ struct device_node *node;
+ int err, p, d = 0;
u32 id;
if (!id_ptr) {
@@ -2986,7 +3004,36 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
if (err)
return err;
- return airoha_alloc_gdm_device(eth, port, np);
+ for_each_child_of_node(np, node) {
+ /* Multiple external serdes connected to the FE GDM port via an
+ * external arbiter.
+ */
+ const __be32 *nbq_ptr;
+
+ if (!of_device_is_compatible(node, "airoha,eth-port"))
+ continue;
+
+ d++;
+ if (!of_device_is_available(node))
+ continue;
+
+ nbq_ptr = of_get_property(node, "reg", NULL);
+ if (!nbq_ptr) {
+ dev_err(eth->dev, "missing nbq id\n");
+ err = -EINVAL;
+ of_node_put(node);
+ break;
+ }
+
+ err = airoha_alloc_gdm_device(eth, port, be32_to_cpup(nbq_ptr),
+ node);
+ if (err) {
+ of_node_put(node);
+ return err;
+ }
+ }
+
+ return !d ? airoha_alloc_gdm_device(eth, port, 0, np) : 0;
}
static int airoha_register_gdm_devices(struct airoha_eth *eth)
@@ -2995,14 +3042,22 @@ static int airoha_register_gdm_devices(struct airoha_eth *eth)
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
- int err;
+ int j;
if (!port)
continue;
- err = register_netdev(port->dev->dev);
- if (err)
- return err;
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
+ struct airoha_gdm_dev *dev = port->devs[j];
+ int err;
+
+ if (!dev)
+ continue;
+
+ err = register_netdev(dev->dev);
+ if (err)
+ return err;
+ }
}
return 0;
@@ -3107,14 +3162,20 @@ static int airoha_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
- struct airoha_gdm_dev *dev;
+ int j;
if (!port)
continue;
- dev = port->dev;
- if (dev && dev->dev->reg_state == NETREG_REGISTERED)
- unregister_netdev(dev->dev);
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
+ struct airoha_gdm_dev *dev = port->devs[j];
+
+ if (!dev)
+ continue;
+
+ if (dev->dev->reg_state == NETREG_REGISTERED)
+ unregister_netdev(dev->dev);
+ }
airoha_metadata_dst_free(port);
}
airoha_hw_cleanup(eth);
@@ -3135,14 +3196,19 @@ static void airoha_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
- struct airoha_gdm_dev *dev;
+ int j;
if (!port)
continue;
- dev = port->dev;
- if (dev)
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
+ struct airoha_gdm_dev *dev = port->devs[j];
+
+ if (!dev)
+ continue;
+
unregister_netdev(dev->dev);
+ }
airoha_metadata_dst_free(port);
}
airoha_hw_cleanup(eth);
@@ -3183,6 +3249,39 @@ static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)
return -EINVAL;
}
+static int airoha_en7581_get_dev_from_sport(struct airoha_qdma_desc *desc,
+ u16 *port, u16 *dev)
+{
+ u32 sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK,
+ le32_to_cpu(desc->msg1));
+
+ *dev = 0;
+ switch (sport) {
+ case 0x10 ... 0x14:
+ *port = 0; /* GDM1 */
+ break;
+ case 0x2:
+ *port = 1; /* GDM2 */
+ break;
+ case HSGMII_LAN_7581_PCIE1_SRCPORT:
+ *dev = 1;
+ fallthrough;
+ case HSGMII_LAN_7581_PCIE0_SRCPORT:
+ *port = 2; /* GDM3 */
+ break;
+ case HSGMII_LAN_7581_USB_SRCPORT:
+ *dev = 1;
+ fallthrough;
+ case HSGMII_LAN_7581_ETH_SRCPORT:
+ *port = 3; /* GDM4 */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const char * const an7583_xsi_rsts_names[] = {
"xsi-mac",
"hsi0-mac",
@@ -3212,6 +3311,36 @@ static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)
return -EINVAL;
}
+static int airoha_an7583_get_dev_from_sport(struct airoha_qdma_desc *desc,
+ u16 *port, u16 *dev)
+{
+ u32 sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK,
+ le32_to_cpu(desc->msg1));
+
+ *dev = 0;
+ switch (sport) {
+ case 0x10 ... 0x14:
+ *port = 0; /* GDM1 */
+ break;
+ case 0x2:
+ *port = 1; /* GDM2 */
+ break;
+ case HSGMII_LAN_7583_ETH_SRCPORT:
+ *port = 2; /* GDM3 */
+ break;
+ case HSGMII_LAN_7583_USB_SRCPORT:
+ *dev = 1;
+ fallthrough;
+ case HSGMII_LAN_7583_PCIE_SRCPORT:
+ *port = 3; /* GDM4 */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct airoha_eth_soc_data en7581_soc_data = {
.version = 0x7581,
.xsi_rsts_names = en7581_xsi_rsts_names,
@@ -3219,6 +3348,7 @@ static const struct airoha_eth_soc_data en7581_soc_data = {
.num_ppe = 2,
.ops = {
.get_src_port_id = airoha_en7581_get_src_port_id,
+ .get_dev_from_sport = airoha_en7581_get_dev_from_sport,
},
};
@@ -3229,6 +3359,7 @@ static const struct airoha_eth_soc_data an7583_soc_data = {
.num_ppe = 1,
.ops = {
.get_src_port_id = airoha_an7583_get_src_port_id,
+ .get_dev_from_sport = airoha_an7583_get_dev_from_sport,
},
};
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index c444ba7832dec356286e5dd2166aba792fdd2c5f..d641b648b7974db2d8f203639b987db03af1a603 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -17,6 +17,7 @@
#include <net/dsa.h>
#define AIROHA_MAX_NUM_GDM_PORTS 4
+#define AIROHA_MAX_NUM_GDM_DEVS 2
#define AIROHA_MAX_NUM_QDMA 2
#define AIROHA_MAX_NUM_IRQ_BANKS 4
#define AIROHA_MAX_DSA_PORTS 7
@@ -534,12 +535,14 @@ struct airoha_qdma {
struct airoha_gdm_dev {
struct airoha_gdm_port *port;
struct airoha_qdma *qdma;
- struct net_device *dev;
struct airoha_eth *eth;
+ struct net_device *dev;
+
+ int nbq;
};
struct airoha_gdm_port {
- struct airoha_gdm_dev *dev;
+ struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS];
int id;
struct airoha_hw_stats stats;
@@ -581,6 +584,8 @@ struct airoha_eth_soc_data {
int num_ppe;
struct {
int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq);
+ int (*get_dev_from_sport)(struct airoha_qdma_desc *desc,
+ u16 *port, u16 *dev);
} ops;
};
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index c86cbbfacc1e6e049ccac60d703edc8ca53eff9b..9e02e7b6bd0a27130130361d5b3f8730b033409b 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -162,6 +162,7 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
for (p = 0; p < ARRAY_SIZE(eth->ports); p++) {
struct airoha_gdm_port *port = eth->ports[p];
+ int j;
airoha_fe_rmw(eth, REG_PPE_MTU(i, p),
FP0_EGRESS_MTU_MASK |
@@ -173,8 +174,16 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
if (!port)
continue;
- airoha_ppe_set_cpu_port(port->dev, i,
- airoha_get_fe_port(port->dev));
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
+ struct airoha_gdm_dev *dev = port->devs[j];
+ u8 fport;
+
+ if (!dev)
+ continue;
+
+ fport = airoha_get_fe_port(dev);
+ airoha_ppe_set_cpu_port(dev, i, fport);
+ }
}
}
}
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 10/11] net: airoha: Do not stop GDM port if it is shared
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
Theoretically, in the current codebase, two independent net_devices can
be connected to the same GDM port so we need to check the GDM port is not
used by any other running net_device before setting the forward
configuration to FE_PSE_PORT_DROP.
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++++---
drivers/net/ethernet/airoha/airoha_eth.h | 2 ++
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 0780fb8aacfbc51fdd896de7be70fb34ee49e864..3f9bce8c537081756aff276009c77670ec5915f4 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1662,6 +1662,7 @@ static int airoha_dev_open(struct net_device *netdev)
}
airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
pse_port);
+ atomic_inc(&port->users);
return 0;
}
@@ -1681,9 +1682,6 @@ static int airoha_dev_stop(struct net_device *netdev)
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
netdev_tx_reset_subqueue(netdev, i);
- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
- FE_PSE_PORT_DROP);
-
if (atomic_dec_and_test(&qdma->users)) {
airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
GLOBAL_CFG_TX_DMA_EN_MASK |
@@ -1697,6 +1695,11 @@ static int airoha_dev_stop(struct net_device *netdev)
}
}
+ if (atomic_dec_and_test(&port->users))
+ airoha_set_gdm_port_fwd_cfg(qdma->eth,
+ REG_GDM_FWD_CFG(port->id),
+ FE_PSE_PORT_DROP);
+
return 0;
}
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index d641b648b7974db2d8f203639b987db03af1a603..337bb2d1b59fac6d7bed216e7d7dbbe1ca89d3c5 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -545,6 +545,8 @@ struct airoha_gdm_port {
struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS];
int id;
+ atomic_t users;
+
struct airoha_hw_stats stats;
DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v2 11/11] net: airoha: Rename get_src_port_id callback in get_sport
From: Lorenzo Bianconi @ 2026-04-01 6:59 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lorenzo Bianconi
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-0-ac427ae4beeb@kernel.org>
For code consistency, rename get_src_port_id callback in get_sport.
Please note this patch does not introduce any logical change and it is
just a cosmetic patch.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++-----
drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 3f9bce8c537081756aff276009c77670ec5915f4..5fe48601bb623f9dba9d3a4d2c1fd6c8276aba88 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1751,7 +1751,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
- src_port = eth->soc->ops.get_src_port_id(port, dev->nbq);
+ src_port = eth->soc->ops.get_sport(port, dev->nbq);
if (src_port < 0)
return src_port;
@@ -3228,7 +3228,7 @@ static const char * const en7581_xsi_rsts_names[] = {
"xfp-mac",
};
-static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)
+static int airoha_en7581_get_sport(struct airoha_gdm_port *port, int nbq)
{
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -3292,7 +3292,7 @@ static const char * const an7583_xsi_rsts_names[] = {
"xfp-mac",
};
-static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)
+static int airoha_an7583_get_sport(struct airoha_gdm_port *port, int nbq)
{
switch (port->id) {
case AIROHA_GDM3_IDX:
@@ -3350,7 +3350,7 @@ static const struct airoha_eth_soc_data en7581_soc_data = {
.num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
.num_ppe = 2,
.ops = {
- .get_src_port_id = airoha_en7581_get_src_port_id,
+ .get_sport = airoha_en7581_get_sport,
.get_dev_from_sport = airoha_en7581_get_dev_from_sport,
},
};
@@ -3361,7 +3361,7 @@ static const struct airoha_eth_soc_data an7583_soc_data = {
.num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names),
.num_ppe = 1,
.ops = {
- .get_src_port_id = airoha_an7583_get_src_port_id,
+ .get_sport = airoha_an7583_get_sport,
.get_dev_from_sport = airoha_an7583_get_dev_from_sport,
},
};
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 337bb2d1b59fac6d7bed216e7d7dbbe1ca89d3c5..bbd83d7b6453ae5e45b2e324bbee47883978675f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -585,7 +585,7 @@ struct airoha_eth_soc_data {
int num_xsi_rsts;
int num_ppe;
struct {
- int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq);
+ int (*get_sport)(struct airoha_gdm_port *port, int nbq);
int (*get_dev_from_sport)(struct airoha_qdma_desc *desc,
u16 *port, u16 *dev);
} ops;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] arm64: dts: imx8x-colibri: Correct SODIMM PAD settings
From: Alexander Stein @ 2026-04-01 7:05 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Philippe Schenker, Ernest Van Hoecke, linux-arm-kernel
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Peng Fan,
Peng Fan (OSS)
In-Reply-To: <20260401-imx8-fix-v1-1-cb27398a6aaf@nxp.com>
Am Mittwoch, 1. April 2026, 08:40:56 CEST schrieb Peng Fan (OSS):
> From: Peng Fan <peng.fan@nxp.com>
>
> SION is BIT(30), not BIT(26). Correct it.
>
> Fixes: 7ece3cbc8b1ef ("arm64: dts: colibri-imx8x: Add atmel pinctrl groups")
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>
> ---
> arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
> index 47895ff8cb244e9bbebe228eb554c2b3f0dded1d..2415487d3a5dea92f9084cd1b312a07f6a09f3cf 100644
> --- a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
> @@ -631,12 +631,12 @@ pinctrl_adc0: adc0grp {
> */
> pinctrl_atmel_adap: atmeladaptergrp {
> fsl,pins = <IMX8QXP_UART1_RX_LSIO_GPIO0_IO22 0x21>, /* SODIMM 30 */
> - <IMX8QXP_UART1_TX_LSIO_GPIO0_IO21 0x4000021>; /* SODIMM 28 */
> + <IMX8QXP_UART1_TX_LSIO_GPIO0_IO21 0x40000021>; /* SODIMM 28 */
> };
>
> /* Atmel MXT touchsceen + boards with built-in Capacitive Touch Connector */
> pinctrl_atmel_conn: atmelconnectorgrp {
> - fsl,pins = <IMX8QXP_QSPI0B_DATA2_LSIO_GPIO3_IO20 0x4000021>, /* SODIMM 107 */
> + fsl,pins = <IMX8QXP_QSPI0B_DATA2_LSIO_GPIO3_IO20 0x40000021>, /* SODIMM 107 */
> <IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 0x21>; /* SODIMM 106 */
> };
>
>
> ---
> base-commit: 36ece9697e89016181e5ae87510e40fb31d86f2b
> change-id: 20260401-imx8-fix-10369e895b8a
>
> Best regards,
>
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/
^ permalink raw reply
* Re: [PATCH RFC 1/4] dt-bindings: clock: qcom,sm8550-tcsr: Add QREF regulator supplies for glymur
From: Krzysztof Kozlowski @ 2026-04-01 7:18 UTC (permalink / raw)
To: Qiang Yu, Bjorn Andersson, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Taniya Das,
Konrad Dybcio, johan
Cc: linux-arm-msm, linux-clk, devicetree, linux-kernel
In-Reply-To: <20260331-qref_vote-v1-1-3fd7fbf87864@oss.qualcomm.com>
On 01/04/2026 08:35, Qiang Yu wrote:
> The glymur TCSR PCIe clkref clocks require regulator supplies for the
> QREF block and its refgen reference voltage generator. Add the optional
> supply properties restricted to qcom,glymur-tcsr via an allOf/if/then
> conditional schema.
>
> Switch from additionalProperties to unevaluatedProperties so that
> properties defined inside the if/then block are correctly recognised as
> evaluated and not rejected by the schema validator.
Sorry, but no. There is a reason for that why additionalProperties fail
and writing-bindings explain that.
>
> Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
> ---
> .../bindings/clock/qcom,sm8550-tcsr.yaml | 26 +++++++++++++++++++++-
> 1 file changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
> index ae9aef0e54e8b8b85bc70e6096d524447091f39e..88db650e69ef2388a5bfb6783a57c1d48c0e780f 100644
> --- a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
> +++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
> @@ -49,11 +49,35 @@ properties:
> '#reset-cells':
> const: 1
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: qcom,glymur-tcsr
> + then:
> + properties:
> + vdda-refgen-0p9-supply: true
> + vdda-refgen-1p2-supply: true
> + vdda-qrefrx0-0p9-supply: true
> + vdda-qrefrx1-0p9-supply: true
> + vdda-qrefrx2-0p9-supply: true
> + vdda-qrefrx4-0p9-supply: true
> + vdda-qrefrx5-0p9-supply: true
> + vdda-qreftx0-0p9-supply: true
> + vdda-qreftx0-1p2-supply: true
> + vdda-qreftx1-0p9-supply: true
> + vdda-qrefrpt0-0p9-supply: true
> + vdda-qrefrpt1-0p9-supply: true
> + vdda-qrefrpt2-0p9-supply: true
> + vdda-qrefrpt3-0p9-supply: true
> + vdda-qrefrpt4-0p9-supply: true
I really doubt that TCSR, which is a small, tiny tiny block the in SoC
have this ~15 pin supplies.
Anyway, if it has, then device is quite different and should live in its
own schema.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH] arm64: dts: imx8x-colibri: Correct SODIMM PAD settings
From: Daniel Baluta @ 2026-04-01 7:26 UTC (permalink / raw)
To: Peng Fan (OSS), Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Philippe Schenker, Ernest Van Hoecke
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <20260401-imx8-fix-v1-1-cb27398a6aaf@nxp.com>
On 4/1/26 09:40, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> SION is BIT(30), not BIT(26). Correct it.
>
> Fixes: 7ece3cbc8b1ef ("arm64: dts: colibri-imx8x: Add atmel pinctrl groups")
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
What is the general attitude around using symbolic macros for pin config?
Like here: https://www.spinics.net/lists/kernel/msg6072866.html
I think there are useful to avoid this kind of bugs.
If I get enough Ack's I can move forward and replace all magic numbers from imx dtses.
thanks,
Daniel
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: arm: qcom: Add monaco-evk-ac support
From: Krzysztof Kozlowski @ 2026-04-01 7:25 UTC (permalink / raw)
To: Umang Chheda
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, linux-arm-msm, devicetree,
linux-kernel, netdev
In-Reply-To: <20260401-monaco-evk-ac-sku-v2-1-27b5f702cfba@oss.qualcomm.com>
On Wed, Apr 01, 2026 at 12:14:42AM +0530, Umang Chheda wrote:
> Introduce bindings for the monaco-evk-ac IoT board, which is
> based on the monaco-ac (QCS8300-AC) SoC variant.
>
> Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
> ---
> Documentation/devicetree/bindings/arm/qcom.yaml | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 00/19] drm/panel: support Waveshare DSI TOUCH kits
From: Dmitry Baryshkov @ 2026-04-01 7:26 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
The Waveshare DSI TOUCH family of DSI panel kits feature different DSI
video-mode panels, bundled with the separate controlling circuit,
produing necessary voltages from the 3.3V and 5V supplies. Extend panel
drivers to support those Waveshare panels and also add GPIO driver for
the onboard control circuitry.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Dmitry Baryshkov (19):
dt-bindings: display/panel: himax,hx83102: describe Waveshare panel
dt-bindings: display/panel: himax,hx8394: describe Waveshare panel
dt-bindings: display/panel: jadard,jd9365da-h3: describe Waveshare panel
dt-bindings: display/panel: ilitek,ili9881c: describe Waveshare panel
dt-bindings: dipslay/panel: describe panels using Focaltech OTA7290B
drm/of: add helper to count data-lanes on a remote endpoint
drm/panel: himax-hx83102: support Waveshare 12.3" DSI panel
drm/panel: himax-hx8394: set prepare_prev_first
drm/panel: himax-hx8394: simplify hx8394_enable()
drm/panel: himax-hx8394: support Waveshare DSI panels
drm/panel: jadard-jd9365da-h3: use drm_connector_helper_get_modes_fixed
drm/panel: jadard-jd9365da-h3: support variable DSI configuration
drm/panel: jadard-jd9365da-h3: set prepare_prev_first
drm/panel: jadard-jd9365da-h3: support Waveshare DSI panels
drm/panel: ilitek-ili9881c: support Waveshare 7.0" DSI panel
drm/panel: add devm_drm_panel_add() helper
drm/panel: add driver for Waveshare 8.8" DSI TOUCH-A panel
dt-bindings: gpio: describe Waveshare GPIO controller
gpio: add GPIO controller found on Waveshare DSI TOUCH panels
.../bindings/display/panel/focaltech,ota7290b.yaml | 70 +
.../bindings/display/panel/himax,hx83102.yaml | 2 +
.../bindings/display/panel/himax,hx8394.yaml | 2 +
.../bindings/display/panel/ilitek,ili9881c.yaml | 2 +
.../bindings/display/panel/jadard,jd9365da-h3.yaml | 6 +
.../bindings/gpio/waveshare,dsi-touch-gpio.yaml | 100 ++
drivers/gpio/Kconfig | 10 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-waveshare-dsi.c | 220 +++
drivers/gpu/drm/drm_of.c | 34 +
drivers/gpu/drm/drm_panel.c | 23 +
drivers/gpu/drm/panel/Kconfig | 13 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-focaltech-ota7290b.c | 208 +++
drivers/gpu/drm/panel/panel-himax-hx83102.c | 144 +-
drivers/gpu/drm/panel/panel-himax-hx8394.c | 279 +++-
drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 251 +++-
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 1563 ++++++++++++++++++--
include/drm/drm_of.h | 13 +
include/drm/drm_panel.h | 1 +
20 files changed, 2813 insertions(+), 130 deletions(-)
---
base-commit: 3b058d1aeeeff27a7289529c4944291613b364e9
change-id: 20260401-waveshare-dsi-touch-e1717a1ffc40
Best regards,
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH 01/19] dt-bindings: display/panel: himax,hx83102: describe Waveshare panel
From: Dmitry Baryshkov @ 2026-04-01 7:26 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
In-Reply-To: <20260401-waveshare-dsi-touch-v1-0-5e9119b5a014@oss.qualcomm.com>
Describe Waveshare 12.3-DSI-TOUCH-A panel which allegedly uses HX83102
as a panel controller.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
index 66404b425af3..7667428bf9a8 100644
--- a/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
+++ b/Documentation/devicetree/bindings/display/panel/himax,hx83102.yaml
@@ -30,6 +30,8 @@ properties:
- starry,2082109qfh040022-50e
# STARRY himax83102-j02 10.51" WUXGA TFT LCD panel
- starry,himax83102-j02
+ # Waveshare 12.3-DSI-TOUCH-A panel
+ - waveshare,12.3-dsi-touch-a
- const: himax,hx83102
reg:
--
2.47.3
^ permalink raw reply related
* [PATCH 02/19] dt-bindings: display/panel: himax,hx8394: describe Waveshare panel
From: Dmitry Baryshkov @ 2026-04-01 7:26 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
In-Reply-To: <20260401-waveshare-dsi-touch-v1-0-5e9119b5a014@oss.qualcomm.com>
Describe Waveshare 5" and 5" DSI panels which use HX9365-E as a panel
controller.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
index 84e840e0224f..83c343b02835 100644
--- a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
+++ b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
@@ -23,6 +23,8 @@ properties:
- hannstar,hsd060bhw4
- microchip,ac40t08a-mipi-panel
- powkiddy,x55-panel
+ - waveshare,5.0-dsi-touch-a
+ - waveshare,5.5-dsi-touch-a
- const: himax,hx8394
- items:
- enum:
--
2.47.3
^ permalink raw reply related
* [PATCH 03/19] dt-bindings: display/panel: jadard,jd9365da-h3: describe Waveshare panel
From: Dmitry Baryshkov @ 2026-04-01 7:26 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
In-Reply-To: <20260401-waveshare-dsi-touch-v1-0-5e9119b5a014@oss.qualcomm.com>
Describe Waveshare DSI panels which use JD9365 as a panel controller.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
index e39efb44ed42..4eae802de9fd 100644
--- a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
+++ b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
@@ -24,6 +24,12 @@ properties:
- radxa,display-10hd-ad001
- radxa,display-8hd-ad002
- taiguanck,xti05101-01a
+ - waveshare,3.4-dsi-touch-c
+ - waveshare,4.0-dsi-touch-c
+ - waveshare,8.0-dsi-touch-a
+ - waveshare,9.0-dsi-touch-b
+ - waveshare,10.1-dsi-touch-a
+ - waveshare,10.1-dsi-touch-b
- const: jadard,jd9365da-h3
reg:
--
2.47.3
^ permalink raw reply related
* [PATCH 04/19] dt-bindings: display/panel: ilitek,ili9881c: describe Waveshare panel
From: Dmitry Baryshkov @ 2026-04-01 7:26 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski
Cc: dri-devel, devicetree, linux-kernel, linux-gpio
In-Reply-To: <20260401-waveshare-dsi-touch-v1-0-5e9119b5a014@oss.qualcomm.com>
Describe Waveshare 7" DSI panel which uses ILI9881 as a panel
controller. This panel requires two voltags supplies, so add separate
iovcc supply.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml
index d979701a00a8..42e35986fbf6 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml
@@ -24,6 +24,7 @@ properties:
- raspberrypi,dsi-7inch
- startek,kd050hdfia020
- tdo,tl050hdv35
+ - waveshare,7.0-dsi-touch-a
- wanchanglong,w552946aaa
- wanchanglong,w552946aba
- const: ilitek,ili9881c
@@ -34,6 +35,7 @@ properties:
backlight: true
port: true
power-supply: true
+ iovcc-supply: true
reset-gpios: true
rotation: true
--
2.47.3
^ permalink raw reply related
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