1057e7797SBaihan Li /* SPDX-License-Identifier: GPL-2.0-or-later */ 2057e7797SBaihan Li /* Copyright (c) 2024 Hisilicon Limited. */ 3057e7797SBaihan Li 4057e7797SBaihan Li #ifndef DP_COMM_H 5057e7797SBaihan Li #define DP_COMM_H 6057e7797SBaihan Li 7057e7797SBaihan Li #include <linux/types.h> 8057e7797SBaihan Li #include <linux/bitops.h> 9057e7797SBaihan Li #include <linux/errno.h> 10057e7797SBaihan Li #include <linux/mutex.h> 11057e7797SBaihan Li #include <linux/kernel.h> 12057e7797SBaihan Li #include <linux/bitfield.h> 13057e7797SBaihan Li #include <linux/io.h> 14057e7797SBaihan Li #include <drm/display/drm_dp_helper.h> 15057e7797SBaihan Li 16*1e7f3551SBaihan Li #include "dp_hw.h" 17*1e7f3551SBaihan Li 1854063d86SBaihan Li #define HIBMC_DP_LANE_NUM_MAX 2 1954063d86SBaihan Li 2054063d86SBaihan Li struct hibmc_link_status { 2154063d86SBaihan Li bool clock_recovered; 2254063d86SBaihan Li bool channel_equalized; 2354063d86SBaihan Li }; 2454063d86SBaihan Li 2554063d86SBaihan Li struct hibmc_link_cap { 2654063d86SBaihan Li u8 link_rate; 2754063d86SBaihan Li u8 lanes; 2854063d86SBaihan Li }; 2954063d86SBaihan Li 3054063d86SBaihan Li struct hibmc_dp_link { 3154063d86SBaihan Li struct hibmc_link_status status; 3254063d86SBaihan Li u8 train_set[HIBMC_DP_LANE_NUM_MAX]; 3354063d86SBaihan Li struct hibmc_link_cap cap; 3454063d86SBaihan Li }; 3554063d86SBaihan Li 36057e7797SBaihan Li struct hibmc_dp_dev { 37*1e7f3551SBaihan Li struct drm_dp_aux *aux; 38057e7797SBaihan Li struct drm_device *dev; 39057e7797SBaihan Li void __iomem *base; 40057e7797SBaihan Li struct mutex lock; /* protects concurrent RW in hibmc_dp_reg_write_field() */ 4154063d86SBaihan Li struct hibmc_dp_link link; 4254063d86SBaihan Li u8 dpcd[DP_RECEIVER_CAP_SIZE]; 439e736cd4SBaihan Li void __iomem *serdes_base; 44057e7797SBaihan Li }; 45057e7797SBaihan Li 46057e7797SBaihan Li #define dp_field_modify(reg_value, mask, val) \ 47057e7797SBaihan Li do { \ 48057e7797SBaihan Li (reg_value) &= ~(mask); \ 49057e7797SBaihan Li (reg_value) |= FIELD_PREP(mask, val); \ 50057e7797SBaihan Li } while (0) \ 51057e7797SBaihan Li 52057e7797SBaihan Li #define hibmc_dp_reg_write_field(dp, offset, mask, val) \ 53057e7797SBaihan Li do { \ 54057e7797SBaihan Li typeof(dp) _dp = dp; \ 55057e7797SBaihan Li typeof(_dp->base) addr = (_dp->base + (offset)); \ 56057e7797SBaihan Li mutex_lock(&_dp->lock); \ 57057e7797SBaihan Li u32 reg_value = readl(addr); \ 58057e7797SBaihan Li dp_field_modify(reg_value, mask, val); \ 59057e7797SBaihan Li writel(reg_value, addr); \ 60057e7797SBaihan Li mutex_unlock(&_dp->lock); \ 61057e7797SBaihan Li } while (0) 62057e7797SBaihan Li 63*1e7f3551SBaihan Li void hibmc_dp_aux_init(struct hibmc_dp *dp); 6454063d86SBaihan Li int hibmc_dp_link_training(struct hibmc_dp_dev *dp); 659e736cd4SBaihan Li int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp); 669e736cd4SBaihan Li int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp); 679e736cd4SBaihan Li int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]); 68057e7797SBaihan Li 69057e7797SBaihan Li #endif 70