Re: [PATCH v4 2/5] platform: arm64: Add driver for EC found on Qualcomm reference devices
From: Krzysztof Kozlowski
Date: Fri Mar 13 2026 - 15:05:35 EST
On 13/03/2026 11:29, Anvesh Jain P wrote:
> +
> +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(dev, "Failed to read EC SCI Event: %d\n", val);
ratelimit
> + return IRQ_HANDLED;
> + }
> +
> + switch (val) {
> + case EC_FAN1_STATUS_CHANGE_EVT:
> + dev_dbg(dev, "Fan1 status changed\n");
ratelimit everywhere further. You are in interrupt handler so imagine
same interrupt keep happening because of constant overheat.
> + break;
> + case EC_FAN2_STATUS_CHANGE_EVT:
> + dev_dbg(dev, "Fan2 status changed\n");
> + break;
> + case EC_FAN1_SPEED_CHANGE_EVT:
> + dev_dbg(dev, "Fan1 speed crossed low/high trip point\n");
> + break;
> + case EC_FAN2_SPEED_CHANGE_EVT:
> + dev_dbg(dev, "Fan2 speed crossed low/high trip point\n");
> + break;
> + case EC_NEW_LUT_SET_EVT:
> + dev_dbg(dev, "New LUT set\n");
> + break;
> + case EC_FAN_PROFILE_SWITCH_EVT:
> + dev_dbg(dev, "FAN Profile switched\n");
> + break;
> + case EC_THERMISTOR_1_THRESHOLD_CROSS_EVT:
> + dev_dbg(dev, "Thermistor 1 threshold crossed\n");
> + break;
> + case EC_THERMISTOR_2_THRESHOLD_CROSS_EVT:
> + dev_dbg(dev, "Thermistor 2 threshold crossed\n");
> + break;
> + case EC_THERMISTOR_3_THRESHOLD_CROSS_EVT:
> + dev_dbg(dev, "Thermistor 3 threshold crossed\n");
> + break;
> + case EC_RECOVERED_FROM_RESET_EVT:
> + dev_dbg(dev, "EC recovered from reset\n");
> + break;
> + default:
> + dev_dbg(dev, "Unknown EC event: %d\n", val);
> + break;
> + }
> +
...
> +
> + ret = devm_request_threaded_irq(dev, client->irq, NULL, qcom_ec_irq,
> + IRQF_ONESHOT, "qcom_ec", ec);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to get irq\n");
No need for message, just 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_thermal_capabilities(dev);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to read thermal capabilities\n");
> +
> + ret = qcom_ec_sci_evt_control(dev, true);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to enable SCI events\n");
> +
> + 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];
> +
> + snprintf(name, EC_FAN_NAME_SIZE, "qcom_ec_fan_%d", i);
> + ec_cdev->fan_id = i + 1;
> + ec_cdev->parent_dev = dev;
> +
> + ec_cdev->cdev = thermal_cooling_device_register(name, ec_cdev,
> + &qcom_ec_thermal_ops);
> + if (IS_ERR(ec_cdev->cdev)) {
> + dev_err_probe(dev, PTR_ERR(cdev),
> + "Thermal cooling device registration failed\n");
> + ret = -EINVAL;
Why do you override actual return code?
> + goto unroll_cooling_dev;
> + }
> + }
> +
> + return 0;
> +
> +unroll_cooling_dev:
> + for (i--; i >= 0; i--) {
> + struct qcom_ec_cooling_dev *ec_cdev = &ec->ec_cdev[i];
> +
> + if (ec_cdev->cdev) {
> + thermal_cooling_device_unregister(ec_cdev->cdev);
> + ec_cdev->cdev = NULL;
> + }
> + }
> +
> + return ret;
> +}
Best regards,
Krzysztof