mfd: display-serdes: improve drivers about these case

1.set lcd low level before set high level
2.set label for lock&err gpio and irq
3.add monitor function for serdes important register

Signed-off-by: Luo Wei <lw@rock-chips.com>
Change-Id: I6e0ee19de04dec87fd356a6f5cb046612bec3451
This commit is contained in:
Luo Wei
2024-10-25 14:14:44 +08:00
committed by Tao Huang
parent 872875b540
commit 427cd6dd82
11 changed files with 155 additions and 6 deletions

View File

@@ -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;

View File

@@ -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,
};

View File

@@ -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,

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;