From 3042fbdfcf526caef4928450b30255a7c13a577c Mon Sep 17 00:00:00 2001 From: Zitong Cai Date: Sun, 7 Sep 2025 15:14:55 +0800 Subject: [PATCH] mfd: display-serdes: Fix system crash caused by serdes_init_seq being a null pointer When the serdes-init-sequence is not configured, serdes_init_seq is a null pointer. However, some serdes initializations do not require the serdes_init_seq configuration, so the driver needs to execute normally even when the serdes-init-sequence is not configured. Change-Id: Id01f0921c9050db5c20f6ad075ddd47891f68bcb Signed-off-by: Zitong Cai --- drivers/mfd/display-serdes/serdes-i2c.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index dfe709332adb..8639633ff20d 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -17,6 +17,9 @@ int serdes_i2c_set_sequence(struct serdes *serdes) int i, num = 0, ret = 0; unsigned int def = 0; + if (!serdes->serdes_init_seq) + return 0; + for (i = 0; i < serdes->serdes_init_seq->reg_seq_cnt; i++) { if (serdes->serdes_init_seq->reg_sequence[i].reg == 0xffff) { SERDES_DBG_MFD("%s: delay 0x%04x us\n", __func__, @@ -195,10 +198,13 @@ static void serdes_reg_check_work(struct kthread_work *work) } serdes_i2c_check_register(serdes, &flag); + if (flag) { + if (serdes->chip_data->chip_init) serdes->chip_data->chip_init(serdes); serdes_i2c_set_sequence_backup(serdes); + msleep(500); SERDES_DBG_MFD("%s %s\n", __func__, serdes->chip_data->name); } @@ -208,6 +214,9 @@ static void serdes_reg_check_work(struct kthread_work *work) static int serdes_reg_check_work_setup(struct serdes *serdes) { + if (!serdes->serdes_backup_seq || !serdes->serdes_backup_seq->reg_seq_cnt) + return 0; + kthread_init_delayed_work(&serdes->reg_check_work, serdes_reg_check_work); @@ -220,6 +229,8 @@ static int serdes_reg_check_work_setup(struct serdes *serdes) kthread_queue_delayed_work(serdes->kworker, &serdes->reg_check_work, msecs_to_jiffies(20000)); + SERDES_DBG_MFD("serdes %s use_reg_check_work\n", serdes->chip_data->name); + return 0; } @@ -285,7 +296,7 @@ static int serdes_get_init_seq(struct serdes *serdes) data = of_get_property(np, "serdes-init-sequence", &len); if (!data) { dev_err(dev, "failed to get serdes-init-sequence\n"); - return -EINVAL; + return 0; } serdes->serdes_init_seq = devm_kzalloc(dev, sizeof(*serdes->serdes_init_seq), @@ -310,8 +321,6 @@ static int serdes_get_init_seq(struct serdes *serdes) return err; } - serdes->dual_link = of_property_read_bool(dev->of_node, "dual-link"); - /* init ser register(not des register) more early if uboot logo disabled */ serdes->route_enable = of_property_read_bool(dev->of_node, "route-enable"); if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER)) { @@ -374,6 +383,8 @@ static int serdes_i2c_probe(struct i2c_client *client, } } + serdes->dual_link = of_property_read_bool(dev->of_node, "dual-link"); + serdes->extcon = devm_extcon_dev_allocate(dev, serdes_cable); if (IS_ERR(serdes->extcon)) return dev_err_probe(dev, PTR_ERR(serdes->extcon), @@ -442,12 +453,9 @@ static int serdes_i2c_probe(struct i2c_client *client, } serdes->use_reg_check_work = of_property_read_bool(dev->of_node, "use-reg-check-work"); - if (serdes->use_reg_check_work) { + if (serdes->use_reg_check_work) serdes_reg_check_work_setup(serdes); - SERDES_DBG_MFD("%s: use_reg_check_work=%d\n", __func__, serdes->use_reg_check_work); - } - serdes_create_debugfs(serdes); dev_info(dev, "serdes %s serdes_i2c_probe successful version %s\n", @@ -469,7 +477,7 @@ static void serdes_i2c_remove(struct i2c_client *client) struct device *dev = &client->dev; struct serdes *serdes = dev_get_drvdata(dev); - if (serdes->use_reg_check_work) + if (!IS_ERR_OR_NULL(serdes->kworker)) serdes_reg_check_work_free(serdes); if (serdes->use_delay_work) {