Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/ltphy: Program the P2P Transaction flow for LT Phy

Program the LT PHY P2P transaction which uses P2M cycle to get
get data fro Phy when it is ready and then go read the MAC register
from the MAC address space.

Bspec: 68966, 74497, 74483, 74500
Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>
Link: https://patch.msgid.link/20251101032513.4171255-14-suraj.kandpal@intel.com

+143 -5
+5 -5
drivers/gpu/drm/i915/display/intel_cx0_phy.c
··· 125 125 intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref); 126 126 } 127 127 128 - static void intel_clear_response_ready_flag(struct intel_encoder *encoder, 129 - int lane) 128 + void intel_clear_response_ready_flag(struct intel_encoder *encoder, 129 + int lane) 130 130 { 131 131 struct intel_display *display = to_intel_display(encoder); 132 132 ··· 135 135 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET); 136 136 } 137 137 138 - static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) 138 + void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) 139 139 { 140 140 struct intel_display *display = to_intel_display(encoder); 141 141 enum port port = encoder->port; ··· 156 156 intel_clear_response_ready_flag(encoder, lane); 157 157 } 158 158 159 - static int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 160 - int command, int lane, u32 *val) 159 + int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 160 + int command, int lane, u32 *val) 161 161 { 162 162 struct intel_display *display = to_intel_display(encoder); 163 163 enum port port = encoder->port;
+5
drivers/gpu/drm/i915/display/intel_cx0_phy.h
··· 22 22 struct intel_encoder; 23 23 struct intel_hdmi; 24 24 25 + void intel_clear_response_ready_flag(struct intel_encoder *encoder, 26 + int lane); 25 27 bool intel_encoder_is_c10phy(struct intel_encoder *encoder); 26 28 void intel_mtl_pll_enable(struct intel_encoder *encoder, 27 29 const struct intel_crtc_state *crtc_state); ··· 54 52 u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr); 55 53 void intel_cx0_write(struct intel_encoder *encoder, 56 54 u8 lane_mask, u16 addr, u8 data, bool committed); 55 + int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 56 + int command, int lane, u32 *val); 57 + void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane); 57 58 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); 58 59 void intel_cx0_pll_power_save_wa(struct intel_display *display); 59 60 void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
+1
drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
··· 50 50 #define XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1) 51 51 #define XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2) 52 52 #define XELPDP_PORT_M2P_COMMAND_READ REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3) 53 + #define XELPDP_PORT_P2P_TRANSACTION_PENDING REG_BIT(24) 53 54 #define XELPDP_PORT_M2P_DATA_MASK REG_GENMASK(23, 16) 54 55 #define XELPDP_PORT_M2P_DATA(val) REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val) 55 56 #define XELPDP_PORT_M2P_TRANSACTION_RESET REG_BIT(15)
+117
drivers/gpu/drm/i915/display/intel_lt_phy.c
··· 20 20 #include "intel_psr.h" 21 21 #include "intel_tc.h" 22 22 23 + #define for_each_lt_phy_lane_in_mask(__lane_mask, __lane) \ 24 + for ((__lane) = 0; (__lane) < 2; (__lane)++) \ 25 + for_each_if((__lane_mask) & BIT(__lane)) 26 + 23 27 #define INTEL_LT_PHY_LANE0 BIT(0) 24 28 #define INTEL_LT_PHY_LANE1 BIT(1) 25 29 #define INTEL_LT_PHY_BOTH_LANES (INTEL_LT_PHY_LANE1 |\ ··· 1003 999 intel_cx0_write(encoder, lane_mask, addr, data, committed); 1004 1000 } 1005 1001 1002 + static void intel_lt_phy_clear_status_p2p(struct intel_encoder *encoder, 1003 + int lane) 1004 + { 1005 + struct intel_display *display = to_intel_display(encoder); 1006 + 1007 + intel_de_rmw(display, 1008 + XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(encoder->port, lane), 1009 + XELPDP_PORT_P2M_RESPONSE_READY, 0); 1010 + } 1011 + 1012 + static void 1013 + assert_dc_off(struct intel_display *display) 1014 + { 1015 + bool enabled; 1016 + 1017 + enabled = intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF); 1018 + drm_WARN_ON(display->drm, !enabled); 1019 + } 1020 + 1021 + static int __intel_lt_phy_p2p_write_once(struct intel_encoder *encoder, 1022 + int lane, u16 addr, u8 data, 1023 + i915_reg_t mac_reg_addr, 1024 + u8 expected_mac_val) 1025 + { 1026 + struct intel_display *display = to_intel_display(encoder); 1027 + enum port port = encoder->port; 1028 + enum phy phy = intel_encoder_to_phy(encoder); 1029 + int ack; 1030 + u32 val; 1031 + 1032 + if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 1033 + XELPDP_PORT_P2P_TRANSACTION_PENDING, 1034 + XELPDP_MSGBUS_TIMEOUT_SLOW)) { 1035 + drm_dbg_kms(display->drm, 1036 + "PHY %c Timeout waiting for previous transaction to complete. Resetting bus.\n", 1037 + phy_name(phy)); 1038 + intel_cx0_bus_reset(encoder, lane); 1039 + return -ETIMEDOUT; 1040 + } 1041 + 1042 + intel_de_rmw(display, XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane), 0, 0); 1043 + 1044 + intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 1045 + XELPDP_PORT_P2P_TRANSACTION_PENDING | 1046 + XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED | 1047 + XELPDP_PORT_M2P_DATA(data) | 1048 + XELPDP_PORT_M2P_ADDRESS(addr)); 1049 + 1050 + ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); 1051 + if (ack < 0) 1052 + return ack; 1053 + 1054 + if (val & XELPDP_PORT_P2M_ERROR_SET) { 1055 + drm_dbg_kms(display->drm, 1056 + "PHY %c Error occurred during P2P write command. Status: 0x%x\n", 1057 + phy_name(phy), val); 1058 + intel_lt_phy_clear_status_p2p(encoder, lane); 1059 + intel_cx0_bus_reset(encoder, lane); 1060 + return -EINVAL; 1061 + } 1062 + 1063 + /* 1064 + * RE-VISIT: 1065 + * This needs to be added to give PHY time to set everything up this was a requirement 1066 + * to get the display up and running 1067 + * This is the time PHY takes to settle down after programming the PHY. 1068 + */ 1069 + udelay(150); 1070 + intel_clear_response_ready_flag(encoder, lane); 1071 + intel_lt_phy_clear_status_p2p(encoder, lane); 1072 + 1073 + return 0; 1074 + } 1075 + 1076 + static void __intel_lt_phy_p2p_write(struct intel_encoder *encoder, 1077 + int lane, u16 addr, u8 data, 1078 + i915_reg_t mac_reg_addr, 1079 + u8 expected_mac_val) 1080 + { 1081 + struct intel_display *display = to_intel_display(encoder); 1082 + enum phy phy = intel_encoder_to_phy(encoder); 1083 + int i, status; 1084 + 1085 + assert_dc_off(display); 1086 + 1087 + /* 3 tries is assumed to be enough to write successfully */ 1088 + for (i = 0; i < 3; i++) { 1089 + status = __intel_lt_phy_p2p_write_once(encoder, lane, addr, data, mac_reg_addr, 1090 + expected_mac_val); 1091 + 1092 + if (status == 0) 1093 + return; 1094 + } 1095 + 1096 + drm_err_once(display->drm, 1097 + "PHY %c P2P Write %04x failed after %d retries.\n", phy_name(phy), addr, i); 1098 + } 1099 + 1100 + static void intel_lt_phy_p2p_write(struct intel_encoder *encoder, 1101 + u8 lane_mask, u16 addr, u8 data, 1102 + i915_reg_t mac_reg_addr, 1103 + u8 expected_mac_val) 1104 + { 1105 + int lane; 1106 + 1107 + for_each_lt_phy_lane_in_mask(lane_mask, lane) 1108 + __intel_lt_phy_p2p_write(encoder, lane, addr, data, mac_reg_addr, expected_mac_val); 1109 + } 1110 + 1006 1111 static void 1007 1112 intel_lt_phy_setup_powerdown(struct intel_encoder *encoder, u8 lane_count) 1008 1113 { ··· 1541 1428 * register at offset 0xC00 for Owned PHY Lanes*. 1542 1429 */ 1543 1430 /* 6.3. Clear P2P transaction Ready bit. */ 1431 + intel_lt_phy_p2p_write(encoder, owned_lane_mask, LT_PHY_RATE_UPDATE, 1432 + LT_PHY_RATE_CONTROL_VDR_UPDATE, LT_PHY_MAC_VDR, 1433 + LT_PHY_PCLKIN_GATE); 1434 + 1544 1435 /* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */ 1545 1436 /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */ 1546 1437 /*
+15
drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
··· 6 6 #ifndef __INTEL_LT_PHY_REGS_H__ 7 7 #define __INTEL_LT_PHY_REGS_H__ 8 8 9 + #define XE3PLPD_MSGBUS_TIMEOUT_FAST_US 500 9 10 #define XE3PLPD_MACCLK_TURNON_LATENCY_MS 1 10 11 #define XE3PLPD_MACCLK_TURNON_LATENCY_US 21 11 12 #define XE3PLPD_RATE_CALIB_DONE_LATENCY_US 50 12 13 #define XE3PLPD_RESET_START_LATENCY_US 10 13 14 #define XE3PLPD_RESET_END_LATENCY_US 200 15 + 16 + /* LT Phy MAC Register */ 17 + #define LT_PHY_MAC_VDR _MMIO(0xC00) 18 + #define LT_PHY_PCLKIN_GATE REG_BIT8(0) 14 19 15 20 /* LT Phy Vendor Register */ 16 21 #define LT_PHY_VDR_0_CONFIG 0xC02 ··· 31 26 #define LT_PHY_VDR_X_DATAY(idx, y) ((0xC06 + (3 - (y))) + 0x6 * (idx)) 32 27 33 28 #define LT_PHY_RATE_UPDATE 0xCC4 29 + #define LT_PHY_RATE_CONTROL_VDR_UPDATE REG_BIT8(0) 34 30 35 31 #define _XE3PLPD_PORT_BUF_CTL5(idx) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \ 36 32 _XELPDP_PORT_BUF_CTL1_LN0_A, \ ··· 44 38 #define XE3PLPD_MACCLK_RATE_MASK REG_GENMASK(4, 0) 45 39 #define XE3PLPD_MACCLK_RATE_DEF REG_FIELD_PREP(XE3PLPD_MACCLK_RATE_MASK, 0x1F) 46 40 41 + #define _XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(idx, lane) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \ 42 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \ 43 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \ 44 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \ 45 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) \ 46 + + 0x60 + (lane) * 0x4) 47 + #define XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(port, lane) _XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(__xe2lpd_port_idx(port), \ 48 + lane) 49 + #define XE3LPD_PORT_P2M_ADDR_MASK REG_GENMASK(11, 0) 47 50 #endif /* __INTEL_LT_PHY_REGS_H__ */