summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Gynther <pgynther@google.com>2024-02-09 12:23:04 -0800
committerPetri Gynther <pgynther@google.com>2024-02-09 13:55:15 -0800
commit5fde3d56bd7507ea84affdf41b172f086faadc70 (patch)
tree956c7cbf16e18281d27154ec2ded3f0e8e28165d
parent2fad53a51fea745f744a22d0ef53cae2245a0df3 (diff)
downloaddisplay-5fde3d56bd7507ea84affdf41b172f086faadc70.tar.gz
drm: samsung: handle USBDP PHY init failures
Handle unexpected timeout failures in: dpphytca_reg_wait_mode_change() dp_reg_wait_phy_pll_lock() properly in dp_hw_init() and dp_hw_reinit(). Bug: 306144368 Signed-off-by: Petri Gynther <pgynther@google.com> Change-Id: Ia69c2ac92df3320947806f99a54633dbec676fe0
-rw-r--r--samsung/cal_9855/dp_reg.c8
-rw-r--r--samsung/cal_9865/dp_reg.c51
-rw-r--r--samsung/cal_common/dp_cal.h4
-rw-r--r--samsung/exynos_drm_dp.c31
4 files changed, 69 insertions, 25 deletions
diff --git a/samsung/cal_9855/dp_reg.c b/samsung/cal_9855/dp_reg.c
index b940c61..fffbe3d 100644
--- a/samsung/cal_9855/dp_reg.c
+++ b/samsung/cal_9855/dp_reg.c
@@ -1530,7 +1530,7 @@ int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data)
}
/* DP Hardware Control Interfaces */
-void dp_hw_init(struct dp_hw_config *hw_config)
+int dp_hw_init(struct dp_hw_config *hw_config)
{
cal_log_info(0, "DP Link Version = 0x%X\n", dp_reg_get_version());
@@ -1583,9 +1583,11 @@ void dp_hw_init(struct dp_hw_config *hw_config)
/* Set Interrupts */
dp_hw_set_common_interrupt(1);
cal_log_debug(0, "set interrupts\n");
+
+ return 0;
}
-void dp_hw_reinit(struct dp_hw_config *hw_config)
+int dp_hw_reinit(struct dp_hw_config *hw_config)
{
/* Set system clock to OSC */
dp_reg_set_txclk_osc();
@@ -1619,6 +1621,8 @@ void dp_hw_reinit(struct dp_hw_config *hw_config)
dp_reg_set_enhanced_mode(hw_config->enhanced_mode ? 1 : 0);
dp_reg_set_sst1_video_func_en(1);
cal_log_debug(0, "set sst function\n");
+
+ return 0;
}
void dp_hw_deinit(struct dp_hw_config *hw_config)
diff --git a/samsung/cal_9865/dp_reg.c b/samsung/cal_9865/dp_reg.c
index 8f179dd..0182370 100644
--- a/samsung/cal_9865/dp_reg.c
+++ b/samsung/cal_9865/dp_reg.c
@@ -179,7 +179,7 @@ static u32 audio_sync_m_n[2][4][7] = {
*/
/* USBDP PHY TCA Registers */
-static void dpphytca_reg_wait_mode_change(enum lane_usage lane)
+static int dpphytca_reg_wait_mode_change(enum lane_usage lane)
{
unsigned int cnt = 0;
unsigned int val = 0;
@@ -202,9 +202,11 @@ static void dpphytca_reg_wait_mode_change(enum lane_usage lane)
TCA_REG_TCA_INTR_STS));
cal_log_err(0, "Fail to change mode from USB to DP%d\n", lane);
- } else
- cal_log_debug(0, "Success to change mode from USB to DP%d\n",
- lane);
+ return -ETIME;
+ }
+
+ cal_log_debug(0, "Success to change mode from USB to DP%d\n", lane);
+ return 0;
}
static void dpphytca_reg_set_tcpc(u32 mux_control, u32 orientation,
@@ -886,7 +888,7 @@ static enum lane_usage dp_get_and_inform_lanes(struct dp_hw_config *hw_config)
return num_lane;
}
-static void dpphy_reg_switch_to_dp(enum lane_usage num_lane)
+static int dpphy_reg_switch_to_dp(enum lane_usage num_lane)
{
u32 tcpc_mux_con = NO_CONNECTION, tcpc_orientation = NORMAL;
u32 tcpc_low_pwr_en = STANDARD_OPERATION, tcpc_valid = VALID_I;
@@ -908,7 +910,7 @@ static void dpphy_reg_switch_to_dp(enum lane_usage num_lane)
cal_log_debug(0, "Start USB to DP%d\n", num_lane);
dpphytca_reg_set_tcpc(tcpc_mux_con, tcpc_orientation, tcpc_low_pwr_en,
tcpc_valid);
- dpphytca_reg_wait_mode_change(num_lane);
+ return dpphytca_reg_wait_mode_change(num_lane);
}
static void dpphy_reg_set_lanes(struct dp_hw_config *hw_config, enum lane_usage num_lane)
@@ -933,8 +935,9 @@ static void dpphy_reg_set_lanes(struct dp_hw_config *hw_config, enum lane_usage
cal_log_debug(0, "enable %d lanes.\n", num_lane);
}
-static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig)
+static int dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig)
{
+ int ret;
enum lane_usage num_lane = DP_USE_0_LANES;
//dpphy_reg_usbdrd_qch_en(1);
@@ -963,7 +966,9 @@ static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig)
num_lane = dp_get_and_inform_lanes(hw_config);
/* Switch from USB to DP */
- dpphy_reg_switch_to_dp(num_lane);
+ ret = dpphy_reg_switch_to_dp(num_lane);
+ if (ret)
+ return ret;
cal_log_debug(0, "switch from USB to DP.\n");
/* Set DP TX lanes */
@@ -972,6 +977,8 @@ static void dpphy_reg_init(struct dp_hw_config *hw_config, bool reconfig)
/* De-assert DP Alt-mode Disable ACK */
dpphy_reg_set_config19_dpalt_disable_ack(0);
+
+ return 0;
}
/*
@@ -2355,8 +2362,10 @@ int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data)
}
/* DP Hardware Control Interfaces */
-void dp_hw_init(struct dp_hw_config *hw_config)
+int dp_hw_init(struct dp_hw_config *hw_config)
{
+ int ret;
+
cal_log_debug(0, "DP Link Version = 0x%X\n", dp_reg_get_version());
/* Apply Soft Reset */
@@ -2376,11 +2385,15 @@ void dp_hw_init(struct dp_hw_config *hw_config)
dwc3_exynos_phy_enable(1, 1);
atomic_inc(&hw_config->usbdp_phy_en_cnt);
- dpphy_reg_init(hw_config, false);
+ ret = dpphy_reg_init(hw_config, false);
+ if (ret)
+ return ret;
cal_log_debug(0, "init USBDP Combo PHY\n");
/* Wait for PHY PLL Lock */
- dp_reg_wait_phy_pll_lock();
+ ret = dp_reg_wait_phy_pll_lock();
+ if (ret)
+ return ret;
cal_log_debug(0, "locked PHY PLL\n");
/* Set system clock to TXCLK */
@@ -2412,21 +2425,29 @@ void dp_hw_init(struct dp_hw_config *hw_config)
/* Set Interrupts */
dp_hw_set_common_interrupt(1);
cal_log_debug(0, "set interrupts\n");
+
+ return 0;
}
-void dp_hw_reinit(struct dp_hw_config *hw_config)
+int dp_hw_reinit(struct dp_hw_config *hw_config)
{
+ int ret;
+
/* Set system clock to OSC */
dp_reg_set_txclk_osc();
cal_log_debug(0, "set system clk to OSC: Mux(%u)\n",
dp_reg_get_gfmux_status());
/* USBDP PHY Re-initialization */
- dpphy_reg_init(hw_config, true);
+ ret = dpphy_reg_init(hw_config, true);
+ if (ret)
+ return ret;
cal_log_debug(0, "reconfig USBDP Combo PHY\n");
/* Wait for PHY PLL Lock */
- dp_reg_wait_phy_pll_lock();
+ ret = dp_reg_wait_phy_pll_lock();
+ if (ret)
+ return ret;
cal_log_debug(0, "locked PHY PLL\n");
/* Set system clock to TXCLK */
@@ -2448,6 +2469,8 @@ void dp_hw_reinit(struct dp_hw_config *hw_config)
dp_reg_set_enhanced_mode(hw_config->enhanced_mode ? 1 : 0);
dp_reg_set_sst1_video_func_en(1);
cal_log_debug(0, "set sst function\n");
+
+ return 0;
}
void dp_hw_deinit(struct dp_hw_config *hw_config)
diff --git a/samsung/cal_common/dp_cal.h b/samsung/cal_common/dp_cal.h
index 225616e..37f82f6 100644
--- a/samsung/cal_common/dp_cal.h
+++ b/samsung/cal_common/dp_cal.h
@@ -317,8 +317,8 @@ int dp_hw_read_dpcd_burst(u32 address, u32 length, u8 *data);
int dp_hw_read_edid(u8 block_cnt, u32 length, u8 *data);
/* DP Hardware Control Interfaces */
-void dp_hw_init(struct dp_hw_config *hw_config);
-void dp_hw_reinit(struct dp_hw_config *hw_config);
+int dp_hw_init(struct dp_hw_config *hw_config);
+int dp_hw_reinit(struct dp_hw_config *hw_config);
void dp_hw_deinit(struct dp_hw_config *hw_config);
void dp_hw_start(void);
void dp_hw_stop(void);
diff --git a/samsung/exynos_drm_dp.c b/samsung/exynos_drm_dp.c
index 1ff6623..02d5e01 100644
--- a/samsung/exynos_drm_dp.c
+++ b/samsung/exynos_drm_dp.c
@@ -571,8 +571,10 @@ static int dp_link_configure(struct dp_device *dp)
return 0;
}
-static void dp_init_link_training_cr(struct dp_device *dp)
+static int dp_init_link_training_cr(struct dp_device *dp)
{
+ int ret;
+
/* Disable DP Training Pattern */
drm_dp_dpcd_writeb(&dp->dp_aux, DP_TRAINING_PATTERN_SET,
DP_TRAINING_PATTERN_DISABLE);
@@ -580,7 +582,12 @@ static void dp_init_link_training_cr(struct dp_device *dp)
/* Reconfigure DP HW */
dp_set_hwconfig_dplink(dp);
dp_set_hwconfig_video(dp);
- dp_hw_reinit(&dp->hw_config);
+ ret = dp_hw_reinit(&dp->hw_config);
+ if (ret) {
+ dp_err(dp, "dp_hw_reinit() failed\n");
+ return ret;
+ }
+
dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n",
dp->hw_config.link_rate, dp->hw_config.num_lanes);
@@ -597,6 +604,8 @@ static void dp_init_link_training_cr(struct dp_device *dp)
/* Enable DP Training Pattern */
drm_dp_dpcd_writeb(&dp->dp_aux, DP_TRAINING_PATTERN_SET,
DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE);
+
+ return 0;
}
static bool dp_do_link_training_cr(struct dp_device *dp, u32 interval_us)
@@ -621,7 +630,8 @@ static bool dp_do_link_training_cr(struct dp_device *dp, u32 interval_us)
max_reach_value[i] = 0;
}
- dp_init_link_training_cr(dp);
+ if (dp_init_link_training_cr(dp))
+ goto err;
// Voltage Swing
do {
@@ -914,9 +924,12 @@ static int dp_link_up(struct dp_device *dp)
dp_set_hwconfig_video(dp);
dp->hw_config.dp_emul = true;
- dp_hw_reinit(&dp->hw_config);
- dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n",
- dp->hw_config.link_rate, dp->hw_config.num_lanes);
+ if (!dp_hw_reinit(&dp->hw_config)) {
+ dp_info(dp, "HW configured with Rate(%d) and Lanes(%u)\n",
+ dp->hw_config.link_rate, dp->hw_config.num_lanes);
+ } else {
+ dp_err(dp, "dp_hw_reinit() failed\n");
+ }
mutex_unlock(&dp->training_lock);
return 0;
@@ -1724,7 +1737,11 @@ static void dp_work_hpd(struct work_struct *work)
/* PHY power on */
usleep_range(10000, 10030);
- dp_hw_init(&dp->hw_config); /* for AUX ch read/write. */
+ ret = dp_hw_init(&dp->hw_config); /* for AUX ch read/write. */
+ if (ret) {
+ dp_err(dp, "dp_hw_init() failed\n");
+ goto HPD_FAIL;
+ }
usleep_range(10000, 11000);
ret = dp_link_up(dp);