Files
BPI-M2C/MPI_DSI/0001-uboot-fix-mipi-panel-probe-reboot.patch
2026-09-22 09:38:26 +08:00

196 lines
4.8 KiB
Diff

From 9f2a9e624b59f50ad0f4a47a63c659d3af31f30a Mon Sep 17 00:00:00 2001
From: BPI-M2C <bpi-m2c@local>
Date: Sun, 20 Sep 2026 12:00:00 +0800
Subject: [PATCH] uboot: sprd: fix MIPI panel probe failure reboot
When multiple panel nodes are probed, release IOVDD together with the
other panel GPIOs. Otherwise the next candidate fails with -EBUSY.
Handle power-on errors without attempting an ID read, and never continue
initializing the last candidate after all panel ID probes have failed.
Continuing after panel_slave_if_uinit() caused an access to the powered-off
DSI1 register block at 0x31400000 and a synchronous abort.
Also unwind GPIOs acquired by a partially failed power-on sequence and
check the selected init callback before invoking it.
---
drivers/video/sprd/panel-if/panel_ops_mipi.c | 31 ++++++++++++++++++++++++----
drivers/video/sprd/sprd_panel.c | 38 +++++++++++++++++---------
2 files changed, 52 insertions(+), 17 deletions(-)
--- a/drivers/video/sprd/panel-if/panel_ops_mipi.c
+++ b/drivers/video/sprd/panel-if/panel_ops_mipi.c
@@ -378,6 +378,10 @@
struct panel_info *info = &panel_device;
struct power_gpio *io = &info->power_pin;
int ret;
+ bool iovdd_requested = false;
+ bool avdd_requested = false;
+ bool avee_requested = false;
+ bool reset_requested = false;
if (!io->gpio_reset) {
pr_err("gpio_reset is NULL\n");
@@ -390,8 +394,9 @@
&power_iovdd, GPIOD_IS_OUT);
if (ret) {
pr_err("request sprd,lcd-iovdd-gpio fail:%d\n", ret);
- return ret;
+ goto power_on_failed;
}
+ iovdd_requested = true;
dm_gpio_set_value(&power_iovdd, 1);
mdelay(10);
}
@@ -401,8 +406,9 @@
&power_avdd, GPIOD_IS_OUT);
if (ret) {
pr_err("request sprd,lcd-avdd-gpio fail:%d\n", ret);
- return ret;
+ goto power_on_failed;
}
+ avdd_requested = true;
dm_gpio_set_value(&power_avdd, 1);
mdelay(info->power_gpio_delay);
}
@@ -412,8 +418,9 @@
&power_avee, GPIOD_IS_OUT);
if (ret) {
pr_err("request sprd,lcd-avee-gpio fail:%d\n", ret);
- return ret;
+ goto power_on_failed;
}
+ avee_requested = true;
dm_gpio_set_value(&power_avee, 1);
mdelay(20);
}
@@ -435,8 +442,9 @@
&power_reset, GPIOD_IS_OUT);
if (ret) {
pr_err("request sprd,lcd-reset-gpio fail:%d\n", ret);
- return ret;
+ goto power_on_failed;
}
+ reset_requested = true;
timing = info->power_on_seq.timing;
for (i = 0; i < info->power_on_seq.items; i++) {
@@ -463,10 +471,25 @@
dm_gpio_free(dev, &power_avdd);
dm_gpio_free(dev, &power_avee);
+ dm_gpio_free(dev, &power_iovdd);
dm_gpio_free(dev, &power_off);
}
#endif
return 0;
+
+#ifndef CONFIG_FPGA
+power_on_failed:
+ if (reset_requested)
+ dm_gpio_free(dev, &power_reset);
+ if (avee_requested)
+ dm_gpio_free(dev, &power_avee);
+ if (avdd_requested)
+ dm_gpio_free(dev, &power_avdd);
+ if (iovdd_requested)
+ dm_gpio_free(dev, &power_iovdd);
+
+ return ret;
+#endif
}
static int panel_set_brightness(int level)
--- a/drivers/video/sprd/sprd_panel.c
+++ b/drivers/video/sprd/sprd_panel.c
@@ -821,12 +821,13 @@
static int sprd_panel_probe(struct udevice *dev)
{
struct panel_info *info;
- struct sprd_panel_ops *ops;
+ struct sprd_panel_ops *ops = NULL;
u8 *info_addr;
int lcd_offset, offset;
int ret = -1;
int lcd_panel_offset = 0;
int info_size;
+ bool panel_powered;
struct udevice *panel_dev = NULL;
const void *fdt = gd->fdt_blob;
@@ -877,6 +878,7 @@
for (offset = fdt_first_subnode(fdt, lcd_offset);
offset >= 0; offset = fdt_next_subnode(fdt, offset)) {
+ panel_powered = false;
if (info) {
memset((uint8_t *)info_addr, 0, info_size);
of_parse_panel(fdt, offset, info);
@@ -890,7 +892,13 @@
ops = panel_drv->ops;
if (ops && ops->power) {
printf("enter power panel\n");
- ops->power(dev, true);
+ ret = ops->power(dev, true);
+ if (ret) {
+ pr_err("power on panel 0x%x failed: %d\n",
+ info->lcd_id, ret);
+ goto panel_probe_failed;
+ }
+ panel_powered = true;
}
if (ops && ops->read_id) {
@@ -903,7 +911,8 @@
}
}
- if (ops && ops->power) {
+panel_probe_failed:
+ if (panel_powered && ops && ops->power) {
ops->power(dev, false);
}
@@ -919,7 +928,7 @@
if (ret) {
pr_err("No Panel Attached!\n");
- //return -1;
+ return ret;
}
if (info->dual_dsi_en){
@@ -929,18 +938,21 @@
panel_if_init();
}
- if (ops && ops->init){
- if(info->mipi_port == 0){
+ if (info->mipi_port == 0) {
+ if (ops && ops->init)
ops->init();
- }
- else
+ } else {
+ if (ops && ops->slave_init)
ops->slave_init();
}
- if (info->dual_dsi_en){
- if(info->mipi_port == 0)
- ops->slave_init();
- else
- ops->init();
+ if (info->dual_dsi_en) {
+ if (info->mipi_port == 0) {
+ if (ops && ops->slave_init)
+ ops->slave_init();
+ } else {
+ if (ops && ops->init)
+ ops->init();
+ }
}
--
2.34.1