diff --git a/drivers/mfd/display-serdes/core.h b/drivers/mfd/display-serdes/core.h index cba8716ea7ba..44a5cbda9505 100644 --- a/drivers/mfd/display-serdes/core.h +++ b/drivers/mfd/display-serdes/core.h @@ -106,7 +106,7 @@ #define SERDES_DBG_CHIP(x...) no_printk(x) #endif -#define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-240815" +#define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-241025" #define MAX_NUM_SERDES_SPLIT 8 struct serdes; enum ser_link_mode { @@ -116,6 +116,11 @@ enum ser_link_mode { SER_SPLITTER_MODE, }; +struct check_reg_data { + char name[30]; + struct reg_sequence seq; +}; + struct serdes_chip_pinctrl_info { struct pinctrl_pin_desc *pins; unsigned int num_pins; @@ -181,6 +186,10 @@ struct serdes_chip_split_ops { int (*set_i2c_addr)(struct serdes *serdes, int address, int link); }; +struct serdes_check_reg_ops { + int (*check_reg)(struct serdes *serdes); +}; + struct serdes_chip_pm_ops { /* serdes chip function for suspend and resume */ int (*suspend)(struct serdes *serdes); @@ -217,6 +226,7 @@ struct serdes_chip_data { struct serdes_chip_pinctrl_ops *pinctrl_ops; struct serdes_chip_gpio_ops *gpio_ops; struct serdes_chip_split_ops *split_ops; + struct serdes_check_reg_ops *check_ops; struct serdes_chip_pm_ops *pm_ops; struct serdes_chip_irq_ops *irq_ops; }; @@ -373,6 +383,7 @@ struct serdes { int lock_irq_trig; int err_irq_trig; atomic_t flag_ser_init; + atomic_t flag_early_suspend; struct workqueue_struct *mfd_wq; struct delayed_work mfd_delay_work; diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96745.c b/drivers/mfd/display-serdes/maxim/maxim-max96745.c index 296098223fc8..0bc38852fb32 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96745.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96745.c @@ -856,6 +856,49 @@ static struct serdes_chip_split_ops max96745_split_ops = { .deselect = max96745_deselect, }; +static const struct check_reg_data max96745_improtant_reg[10] = { + { + "MAX96745 LINK LOCK", + { 0x0013, (1 << 3) }, + }, { + "MAX96745 LINKA LOCK", + { 0x002A, (1 << 0) }, + }, { + "MAX96745 LINKB LOCK", + { 0x0034, (1 << 0) }, + }, { + "MAX96745 X PCLK DET", + { 0x0102, (1 << 7) }, + }, { + "MAX96745 Y PCLK DET", + { 0x0112, (1 << 7) }, + }, +}; + +static int max96745_check_reg(struct serdes *serdes) +{ + int i = 0, ret = 0; + unsigned int val = 0; + + for (i = 0; i < ARRAY_SIZE(max96745_improtant_reg); i++) { + if (!max96745_improtant_reg[i].seq.reg) + break; + + ret = serdes_reg_read(serdes, max96745_improtant_reg[i].seq.reg, &val); + if (!ret && !(val & max96745_improtant_reg[i].seq.def) + && (!atomic_read(&serdes->flag_early_suspend))) + dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__, + max96745_improtant_reg[i].name, + max96745_improtant_reg[i].seq.reg, val); + } + + return 0; +} + +static struct serdes_check_reg_ops max96745_check_reg_ops = { + .check_reg = max96745_check_reg, +}; + static int max96745_pm_suspend(struct serdes *serdes) { return 0; @@ -897,6 +940,7 @@ struct serdes_chip_data serdes_max96745_data = { .pinctrl_ops = &max96745_pinctrl_ops, .gpio_ops = &max96745_gpio_ops, .split_ops = &max96745_split_ops, + .check_ops = &max96745_check_reg_ops, .pm_ops = &max96745_pm_ops, .irq_ops = &max96745_irq_ops, }; diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96752.c b/drivers/mfd/display-serdes/maxim/maxim-max96752.c index e39649d9972c..ae8cdb4ccce4 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96752.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96752.c @@ -601,6 +601,40 @@ static struct serdes_chip_split_ops max96752_split_ops = { .set_i2c_addr = max96752_set_i2c_addr, }; +static const struct check_reg_data max96752_improtant_reg[10] = { + { + "MAX96752 VIDEO LOCK", + { 0x0003, (1 << 0) }, + }, { + "MAX96752 VIDEO LOCK", + { 0x0108, (1 << 6) }, + }, +}; + +static int max96752_check_reg(struct serdes *serdes) +{ + int i = 0, ret = 0; + unsigned int val = 0; + + for (i = 0; i < ARRAY_SIZE(max96752_improtant_reg); i++) { + if (!max96752_improtant_reg[i].seq.reg) + break; + + ret = serdes_reg_read(serdes, max96752_improtant_reg[i].seq.reg, &val); + if (!ret && !(val & max96752_improtant_reg[i].seq.def) + && (!atomic_read(&serdes->flag_early_suspend))) + dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__, + max96752_improtant_reg[i].name, + max96752_improtant_reg[i].seq.reg, val); + } + + return 0; +} + +static struct serdes_check_reg_ops max96752_check_reg_ops = { + .check_reg = max96752_check_reg, +}; + static int max96752_pm_suspend(struct serdes *serdes) { return 0; @@ -642,6 +676,7 @@ struct serdes_chip_data serdes_max96752_data = { .bridge_ops = &max96752_bridge_ops, .pinctrl_ops = &max96752_pinctrl_ops, .split_ops = &max96752_split_ops, + .check_ops = &max96752_check_reg_ops, .gpio_ops = &max96752_gpio_ops, .pm_ops = &max96752_pm_ops, .irq_ops = &max96752_irq_ops, diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96789.c b/drivers/mfd/display-serdes/maxim/maxim-max96789.c index 7b4789259e29..30bfe27857df 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96789.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96789.c @@ -772,6 +772,43 @@ static struct serdes_chip_split_ops max96789_split_ops = { .deselect = max96789_deselect, }; +static const struct check_reg_data max96789_improtant_reg[10] = { + { + "MAX96789 LINK LOCK", + { 0x0013, (1 << 3) }, + }, { + "MAX96789 X PCLK DET", + { 0x0102, (1 << 7) }, + }, { + "MAX96789 Y PCLK DET", + { 0x0112, (1 << 7) }, + }, +}; + +static int max96789_check_reg(struct serdes *serdes) +{ + int i = 0, ret = 0; + unsigned int val = 0; + + for (i = 0; i < ARRAY_SIZE(max96789_improtant_reg); i++) { + if (!max96789_improtant_reg[i].seq.reg) + break; + + ret = serdes_reg_read(serdes, max96789_improtant_reg[i].seq.reg, &val); + if (!ret && !(val & max96789_improtant_reg[i].seq.def) + && (!atomic_read(&serdes->flag_early_suspend))) + dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__, + max96789_improtant_reg[i].name, + max96789_improtant_reg[i].seq.reg, val); + } + + return 0; +} + +static struct serdes_check_reg_ops max96789_check_reg_ops = { + .check_reg = max96789_check_reg, +}; + static int max96789_pm_suspend(struct serdes *serdes) { return 0; @@ -813,6 +850,7 @@ struct serdes_chip_data serdes_max96789_data = { .pinctrl_ops = &max96789_pinctrl_ops, .gpio_ops = &max96789_gpio_ops, .split_ops = &max96789_split_ops, + .check_ops = &max96789_check_reg_ops, .pm_ops = &max96789_pm_ops, .irq_ops = &max96789_irq_ops, }; diff --git a/drivers/mfd/display-serdes/serdes-bridge-split.c b/drivers/mfd/display-serdes/serdes-bridge-split.c index a129377bcabc..f76201ad7665 100644 --- a/drivers/mfd/display-serdes/serdes-bridge-split.c +++ b/drivers/mfd/display-serdes/serdes-bridge-split.c @@ -238,7 +238,7 @@ static int serdes_bridge_split_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct serdes_bridge_split *serdes_bridge_split; - if (!serdes->dev) + if (!serdes->dev || !serdes->chip_data) return -1; serdes_bridge_split = devm_kzalloc(dev, sizeof(*serdes_bridge_split), GFP_KERNEL); diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 17198da83e58..617710c67f4b 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -243,7 +243,7 @@ static int serdes_bridge_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct serdes_bridge *serdes_bridge; - if (!serdes->dev) + if (!serdes->dev || !serdes->chip_data) return -1; serdes_bridge = devm_kzalloc(dev, sizeof(*serdes_bridge), GFP_KERNEL); diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index 55f7d1d69e1f..249210873ceb 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -171,6 +171,9 @@ static int serdes_i2c_check_register(struct serdes *serdes, int *flag) return ret; } + if (serdes->chip_data->check_ops->check_reg) + ret = serdes->chip_data->check_ops->check_reg(serdes); + return ret; } @@ -207,6 +210,7 @@ static int serdes_reg_check_work_setup(struct serdes *serdes) return PTR_ERR(serdes->kworker); mutex_init(&serdes->reg_check_lock); atomic_set(&serdes->flag_ser_init, 1); + atomic_set(&serdes->flag_early_suspend, 0); kthread_queue_delayed_work(serdes->kworker, &serdes->reg_check_work, msecs_to_jiffies(20000)); @@ -463,6 +467,11 @@ static void serdes_i2c_remove(struct i2c_client *client) static int serdes_i2c_prepare(struct device *dev) { + struct serdes *serdes = dev_get_drvdata(dev); + + atomic_set(&serdes->flag_early_suspend, 1); + + SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev)); return 0; } @@ -473,6 +482,7 @@ static void serdes_i2c_complete(struct device *dev) if (serdes->chip_data->serdes_type == TYPE_SER) serdes_i2c_set_sequence(serdes); + atomic_set(&serdes->flag_early_suspend, 0); SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev)); } diff --git a/drivers/mfd/display-serdes/serdes-irq.c b/drivers/mfd/display-serdes/serdes-irq.c index 5aa685a20075..c99202825d84 100644 --- a/drivers/mfd/display-serdes/serdes-irq.c +++ b/drivers/mfd/display-serdes/serdes-irq.c @@ -44,6 +44,9 @@ int serdes_irq_init(struct serdes *serdes) { int ret = 0; + if (!serdes->dev || !serdes->chip_data) + return -1; + mutex_init(&serdes->irq_lock); /* lock irq */ @@ -53,6 +56,9 @@ int serdes_irq_init(struct serdes *serdes) "failed to get serdes lock GPIO\n"); if (serdes->lock_gpio) { + serdes->lock_gpio->label = devm_kasprintf(serdes->dev, GFP_KERNEL, + "lock-%s-%s", dev_name(serdes->dev), + serdes->chip_data->name); serdes->lock_irq = gpiod_to_irq(serdes->lock_gpio); if (serdes->lock_irq < 0) return serdes->lock_irq; @@ -64,7 +70,7 @@ int serdes_irq_init(struct serdes *serdes) ret = devm_request_threaded_irq(serdes->dev, serdes->lock_irq, NULL, serdes_bridge_lock_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, - dev_name(serdes->dev), serdes); + serdes->lock_gpio->label, serdes); if (ret) return dev_err_probe(serdes->dev, ret, "failed to request serdes lock IRQ\n"); @@ -77,6 +83,9 @@ int serdes_irq_init(struct serdes *serdes) "failed to get serdes err GPIO\n"); if (serdes->err_gpio) { + serdes->err_gpio->label = devm_kasprintf(serdes->dev, GFP_KERNEL, + "err-%s-%s", dev_name(serdes->dev), + serdes->chip_data->name); serdes->err_irq = gpiod_to_irq(serdes->err_gpio); if (serdes->err_irq < 0) return serdes->err_irq; @@ -87,7 +96,7 @@ int serdes_irq_init(struct serdes *serdes) ret = devm_request_threaded_irq(serdes->dev, serdes->err_irq, NULL, serdes_bridge_err_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, - dev_name(serdes->dev), serdes); + serdes->err_gpio->label, serdes); if (ret) return dev_err_probe(serdes->dev, ret, "failed to request err IRQ\n"); } diff --git a/drivers/mfd/display-serdes/serdes-panel-split.c b/drivers/mfd/display-serdes/serdes-panel-split.c index 233fbf4c421b..f165bc8bc563 100644 --- a/drivers/mfd/display-serdes/serdes-panel-split.c +++ b/drivers/mfd/display-serdes/serdes-panel-split.c @@ -29,6 +29,7 @@ static int serdes_panel_split_prepare(struct drm_panel *panel) if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->prepare) ret = serdes->chip_data->panel_ops->prepare(serdes); + serdes_set_pinctrl_sleep(serdes); serdes_set_pinctrl_default(serdes); SERDES_DBG_MFD("%s: %s\n", __func__, serdes->chip_data->name); diff --git a/drivers/mfd/display-serdes/serdes-panel.c b/drivers/mfd/display-serdes/serdes-panel.c index c4dc033e1326..508a7f5bbb77 100644 --- a/drivers/mfd/display-serdes/serdes-panel.c +++ b/drivers/mfd/display-serdes/serdes-panel.c @@ -29,6 +29,7 @@ static int serdes_panel_prepare(struct drm_panel *panel) if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->prepare) ret = serdes->chip_data->panel_ops->prepare(serdes); + serdes_set_pinctrl_sleep(serdes); serdes_set_pinctrl_default(serdes); SERDES_DBG_MFD("%s: %s\n", __func__, serdes->chip_data->name); diff --git a/drivers/mfd/display-serdes/serdes-pinctrl.c b/drivers/mfd/display-serdes/serdes-pinctrl.c index d6bc9009a87d..72d3518e8d6d 100644 --- a/drivers/mfd/display-serdes/serdes-pinctrl.c +++ b/drivers/mfd/display-serdes/serdes-pinctrl.c @@ -229,7 +229,7 @@ static int serdes_pinctrl_probe(struct platform_device *pdev) int pin_base = 0; int i, j, ret; - if (!serdes->dev) + if (!serdes->dev || !serdes->chip_data) return -1; pinctrl_info = chip_data->pinctrl_info;