hdmirx: i2c monitor [1/1]

PD#SWPL-132152

Problem:
support to dump i2c data

Solution:
support to dump i2c data

Verify:
t3x

Change-Id: I127e91f84297daddee6b720eba2bff17f53104e2
Signed-off-by: Gaowei Zhao <gaowei.zhao@amlogic.com>
This commit is contained in:
Gaowei Zhao
2023-10-24 14:01:51 +08:00
committed by gerrit autosubmit
parent 2bab1d3389
commit c19d943134
7 changed files with 281 additions and 2 deletions
@@ -628,7 +628,7 @@
0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0
0x0 0xfe390000 0x0 0x20000
0x0 0xfe000000 0x0 0x1fff
0x0 0xfe000000 0x0 0x15000
0x0 0xfe008000 0x280 0x334>;
};
@@ -770,6 +770,11 @@ struct emp_info_s {
u8 data_ver;
};
struct i2c_info_s {
phys_addr_t phy_addr;
struct page *pg_addr;
};
struct spkts_rcvd_sts {
u32 pkt_vsi_rcvd:1;
u32 pkt_drm_rcvd:1;
@@ -840,6 +845,7 @@ struct rx_info_s {
struct rx_aml_phy aml_phy_21;
struct emp_info_s emp_buff_a; //for vid0
struct emp_info_s emp_buff_b; //for vid1
struct i2c_info_s i2c_buff;
struct edid_capacity edid_cap;
bool suspend_flag;
};
@@ -6026,6 +6026,9 @@ int rx_debug_wr_reg(const char *buf, char *tmpbuf, int i, u8 port)
} else if (buf[2] == 'A') {
hdmirx_wr_amlphy_t3x(adr, value, port);
rx_pr("write %x to port%d [%x]\n", value, port, adr);
} else if (buf[2] == 'c') {
wr_reg_clk_ctl(adr, value);
rx_pr("write %x to [%x]\n", value, adr);
}
}
return 0;
@@ -6072,6 +6075,9 @@ int rx_debug_rd_reg(const char *buf, char *tmpbuf, u8 port)
} else if (buf[2] == 'A') {
value = hdmirx_rd_amlphy_t3x(adr, port);
rx_pr("port%d, amlphy [%x]=%x\n", port, adr, value);
} else if (buf[2] == 'c') {
value = rd_reg_clk_ctl(adr);
rx_pr("amlphy [%x]=%x\n", adr, value);
}
}
return 0;
@@ -3430,6 +3430,7 @@ unsigned int hdmirx_rd_amlphy(unsigned int addr);
unsigned int hdmirx_rd_amlphy_t3x(unsigned int addr, u8 port);
void hdmirx_irq_hdcp_enable(bool enable, u8 port);
u8 rx_get_avmute_sts(u8 port);
void wr_reg_ana_ctl(u32 offset, u32 val);
u8 hdmirx_rd_cor(u32 addr, u8 port);
void hdmirx_wr_cor(u32 addr, u8 data, u8 port);
bool hdmirx_poll_cor(u32 addr, u8 exp_data, u8 mask, u32 max_try, u8 port);
+204 -1
View File
@@ -60,7 +60,8 @@ int vga_tuning_min = 0x21;
int vga_tuning_max = 0x26;
int cal_phy_time;
enum frl_train_sts_e frl_train_sts = E_FRL_TRAIN_START;
/* i2c monitor */
#define I2C_BUFF_SIZE 0x1000
/* for T3X 2.0 */
static const u32 phy_misc_t3x_20[][2] = {
/* 0x18 0x1c */
@@ -4825,6 +4826,208 @@ bool is_frl_train_finished(void)
return ret;
}
void rx_i2c_dbg_monitor(void)
{
u32 data32;
if (rx_info.chip_id != CHIP_ID_T3X)
return;
data32 = rd_reg_clk_ctl(T3X_I2C_MONITOR_INTR_STATUS);
if (data32 > 3) { //ignore start abnormal
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_START, 0x0);
rx_i2c_dump();
wr_reg_clk_ctl(T3X_I2C_MONITOR_INTR_STATUS, data32);
}
}
static void rx_parse_i2c_data(u8 *buf, int size)
{
static const char * const ack_print[] = {"ACK", "NAK"};
static const char * const wr_print[] = {"Write", "Read"};
u8 type, data, ack, wr;
int i;
if (!buf || size < 4)
return;
for (i = 0; i < size; i += 4) {
/*
* |31..29|28.......9|8..1| 0|
* |type |delta time|data|ack|
*/
if (!buf[i] && !buf[i + 1] && !buf[i + 2] && !buf[i + 3])
break;
type = (buf[i + 3] & MSK(3, 5)) >> 5;
data = (buf[i] & MSK(7, 1)) >> 1 | (buf[i + 1] & 0x1) << 7;
ack = buf[i] & 0x1;
wr = data & 0x1;
switch (type) {
case E_DATA:
rx_pr("0x%x + %s\n", data, ack_print[ack]);
break;
case E_START_DATA:
rx_pr("%s to [0x%x] + %s\n", wr_print[wr], data, ack_print[ack]);
break;
case E_STOP_DATA:
rx_pr("0x%x + %s + Stop\n", data, ack_print[ack]);
break;
case E_START_DATA_STOP:
rx_pr("%s to [0x%x] + %s + Stop\n", wr_print[wr], data, ack_print[ack]);
break;
case E_STOP_ABNORMAL:
rx_pr("!!STOP Abnormal(incomplete data)\n");
break;
case E_START_ABNORMAL:
if (ack) {
rx_pr("!!Start Abnormal: %s to [0x%x] + %s\n",
wr_print[wr], data, ack_print[ack]);
} else {
rx_pr("!!Start Abnormal(incomplete data)\n");
}
break;
case E_TIME_OUT:
if (ack)
rx_pr("!!time out(no data)\n");
else
rx_pr("!!time out + 0x%x\n", data);
break;
default:
if ((data >> 5) == 0) {
if (ack)
rx_pr("HPD rise\n");
else
rx_pr("HPD fall\n");
} else {
rx_pr("!!other type:0x%x\n", data);
}
break;
}
}
rx_pr("i:0x%x\n", i);
}
void rx_i2c_monitor(u8 sel, u8 smp_mod, u8 trig_mod, u8 dump_mod)
{
u8 *src = NULL;
u32 data32;
data32 = 0;
data32 |= (smp_mod == 3 ? 1 : 0) << 31; //[31] bist_mode exist bug, can't use
data32 |= (dump_mod & 0x1f) << 16; //[20-16]dump mode
data32 |= 0x0 << 4; //[4] clk_free
data32 |= (smp_mod & 0x3) << 2; //[3:2] smp_mode
data32 |= 0x1 << 1; //[1] hpd_en
data32 |= (trig_mod & 0x1) << 0; //[0] trig_mode
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_CNTL, data32);
data32 = 0;
data32 |= (sel >= 6 ? 1 << (sel - 6) : 0) << 24; //[31:24] sel input hpd to monitor
data32 |= (1 << sel) << 0; //[23:0] sel input scl to monitor
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_SEL, data32);
data32 = 0;
data32 |= 0x2008 << 16; //[31:16] scl filter control
data32 |= 0x2008 << 0; //[15: 0] sda filter control
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_FLT, data32);
data32 = 0;
data32 |= 0x7 << 0; //[15: 0] sda filter control
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_FLT_HPD, data32);
data32 = 0;
data32 |= 0xa << 16; //[31:16] time tick in smp_clk
data32 |= 0x1 << 8; //[ 8] smp_clk enable
data32 |= 0x5 << 0; //[ 7: 0] smp_clk div, cec sample:0x48
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_CLK, data32);
data32 = 0;
data32 |= 0x3ff << 0; //[10:0]
wr_reg_clk_ctl(T3X_I2C_MONITOR_INTR_MASK, data32);
rx_info.i2c_buff.pg_addr = alloc_pages(GFP_KERNEL, 0);
src = (u8 *)kmap_atomic(rx_info.i2c_buff.pg_addr);
memset(src, 0x0, I2C_BUFF_SIZE);
kunmap_atomic(src);
rx_info.i2c_buff.phy_addr = page_to_phys(rx_info.i2c_buff.pg_addr);
if (rx_info.i2c_buff.phy_addr) {
wr_reg_clk_ctl(T3X_I2C_MONITOR_DDR_START_ADDR,
rx_info.i2c_buff.phy_addr >> 4);
wr_reg_clk_ctl(T3X_I2C_MONITOR_DDR_END_ADDR,
(rx_info.i2c_buff.phy_addr + I2C_BUFF_SIZE) >> 4);
}
data32 = 0;
data32 |= 0x1 << 4; //[ 4] endian in 32 bit
data32 |= 0x0 << 0; //[3:0] burst length
wr_reg_clk_ctl(T3X_I2C_MONITOR_DDR_CNTL, data32);
//smp start,config this bit after all the other reg has been ready
wr_reg_clk_ctl(T3X_I2C_MONITOR_SMP_START, 0x1);
}
static void rx_i2c_reg_dump(void)
{
rx_pr("T3X_I2C_MONITOR_SMP_CNTL: 0x%x-0x%x\n", T3X_I2C_MONITOR_SMP_CNTL,
rd_reg_clk_ctl(T3X_I2C_MONITOR_SMP_CNTL));
rx_pr("T3X_I2C_MONITOR_SMP_SEL: 0x%x-0x%x\n", T3X_I2C_MONITOR_SMP_SEL,
rd_reg_clk_ctl(T3X_I2C_MONITOR_SMP_SEL));
rx_pr("T3X_I2C_MONITOR_SMP_FLT: 0x%x-0x%x\n", T3X_I2C_MONITOR_SMP_FLT,
rd_reg_clk_ctl(T3X_I2C_MONITOR_SMP_FLT));
rx_pr("T3X_I2C_MONITOR_SMP_FLT_HPD: 0x%x-0x%x\n", T3X_I2C_MONITOR_SMP_FLT_HPD,
rd_reg_clk_ctl(T3X_I2C_MONITOR_SMP_FLT_HPD));
rx_pr("T3X_I2C_MONITOR_SMP_CLK: 0x%x-0x%x\n", T3X_I2C_MONITOR_SMP_CLK,
rd_reg_clk_ctl(T3X_I2C_MONITOR_SMP_CLK));
rx_pr("T3X_I2C_MONITOR_INTR_MASK: 0x%x-0x%x\n", T3X_I2C_MONITOR_INTR_MASK,
rd_reg_clk_ctl(T3X_I2C_MONITOR_INTR_MASK));
rx_pr("T3X_I2C_MONITOR_DDR_START_ADDR: 0x%x-0x%x\n", T3X_I2C_MONITOR_DDR_START_ADDR,
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_START_ADDR));
rx_pr("T3X_I2C_MONITOR_DDR_END_ADDR: 0x%x-0x%x\n", T3X_I2C_MONITOR_DDR_END_ADDR,
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_END_ADDR));
rx_pr("T3X_I2C_MONITOR_DDR_CNTL: 0x%x-0x%x\n", T3X_I2C_MONITOR_DDR_CNTL,
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_CNTL));
}
void rx_i2c_dump(void)
{
//int i, j;
u8 *i2c_buff = NULL;
u8 *src_buf = NULL;
int buf_cnt;
if (log_level & REG_LOG)
rx_i2c_reg_dump();
i2c_buff = kmalloc(I2C_BUFF_SIZE, GFP_KERNEL);
if (!i2c_buff)
return;
memset(i2c_buff, 0, I2C_BUFF_SIZE);
src_buf = (u8 *)kmap_atomic(rx_info.i2c_buff.pg_addr);
if (!src_buf) {
kfree(i2c_buff);
return;
}
memcpy(i2c_buff, src_buf, I2C_BUFF_SIZE);
/*
*for (i = 0; i < 128; i++) {
* for (j = 0; j < 32; j++)
* pr_cont("%02X ", i2c_buff[i * 32 + j]);
* rx_pr("\n");
*}
*/
kunmap_atomic(src_buf);
buf_cnt = (rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_WPTR) -
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_START_ADDR)) << 4;
rx_pr("buf_cnt:wptr:0x%x-start:0x%x=0x%x\n",
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_WPTR) << 4,
rd_reg_clk_ctl(T3X_I2C_MONITOR_DDR_START_ADDR) << 4,
buf_cnt);
rx_parse_i2c_data(i2c_buff, I2C_BUFF_SIZE);
kfree(i2c_buff);
}
void rx_frl_train_handler(struct work_struct *work)
{
hdmi_tx_rx_frl_training_main(E_PORT2);
@@ -134,6 +134,59 @@
#define T3X_CLKCTRL_AUD21_PLL_CTRL3 (0x02ed << 2)
#define T3X_CLKCTRL_AUD21_PLL_STS (0x02ee << 2)
/* i2c monitor reg */
#define T3X_I2C_MONITOR_BASE 0xfe014000
#define T3X_I2C_MONITOR_SMP_START (0x14000 + (0x000 << 2))
#define T3X_I2C_MONITOR_SMP_SEL (0x14000 + (0x001 << 2))
#define T3X_I2C_MONITOR_SMP_CNTL (0x14000 + (0x002 << 2))
#define T3X_I2C_MONITOR_SMP_FLT (0x14000 + (0x003 << 2))
#define T3X_I2C_MONITOR_SMP_FLT_HPD (0x14000 + (0x004 << 2))
#define T3X_I2C_MONITOR_SMP_I2C_TIMEOUT_TH (0x14000 + (0x005 << 2))
#define T3X_I2C_MONITOR_SMP_CLK (0x14000 + (0x006 << 2))
#define T3X_I2C_MONITOR_DDR_START_ADDR (0x14000 + (0x007 << 2))
#define T3X_I2C_MONITOR_DDR_END_ADDR (0x14000 + (0x008 << 2))
#define T3X_I2C_MONITOR_DDR_CNTL (0x14000 + (0x009 << 2))
#define T3X_I2C_MONITOR_INTR_MASK (0x14000 + (0x00a << 2))
#define T3X_I2C_MONITOR_DDR_WPTR (0x14000 + (0x00b << 2))
#define T3X_I2C_MONITOR_DDR_BOUND_CNT (0x14000 + (0x00c << 2))
#define T3X_I2C_MONITOR_AXI_CMD_PENDING (0x14000 + (0x00d << 2))
#define T3X_I2C_MONITOR_SMP_STATUS (0x14000 + (0x00e << 2))
#define T3X_I2C_MONITOR_SMP_I2C_BUSY_CNT (0x14000 + (0x00f << 2))
#define T3X_I2C_MONITOR_AXI_STATUS (0x14000 + (0x010 << 2))
#define T3X_I2C_MONITOR_INTR_STATUS (0x14000 + (0x011 << 2))
#define T3X_I2C_MONITOR_AXI_CMD_CNT (0x14000 + (0x012 << 2))
enum i2c_sample_mode_e {
E_FUNC_SAMPLE,
E_I2C_WAVE_SAMPLE,
E_CEC_WAVE_SAMPLE,
E_BIST_MODE
};
enum i2c_trigger_mode_e {
E_HW_TRIGGER,
E_SW_TRIGGER
};
enum i2c_dump_mode_e {
E_ABNORMAL_START0 = 0x1,
E_ABNORMAL_START1 = 0x2,
E_ABNORMAL_STOP = 0x4,
E_I2C_TIMEOUT = 0x8,
E_HPD_CHANGE = 0x10,
E_DUMP_ALL = 0x1f
};
enum i2c_data_type_e {
E_DATA,
E_START_DATA,
E_STOP_DATA,
E_START_DATA_STOP,
E_STOP_ABNORMAL,
E_START_ABNORMAL,
E_TIME_OUT
};
enum frl_train_sts_e {
E_FRL_TRAIN_START,
E_FRL_TRAIN_FINISH,
@@ -230,6 +283,9 @@ bool is_fsm_ready_t3x(void);
bool rx_get_clkready_sts(u8 port);
bool rx_get_valid_m_sts(u8 port);
void rx_i2c_dbg_monitor(void);
void rx_i2c_monitor(u8 sel, u8 smp_mod, u8 trig_mod, u8 dump_mod);
void rx_i2c_dump(void);
//void reset_pcs(void);
/*function declare end*/
@@ -8413,6 +8413,12 @@ int hdmirx_debug(const char *buf, int size)
rx_pr("phy_addr = 0x%x, size = 0x%x, maped:%px\n",
rx_reg_maps[i].phy_addr, size, rx_reg_maps[i].p);
}
} else if (strncmp(tmpbuf, "i2c_monitor", 10) == 0) {
rx_i2c_monitor(6 + port, E_FUNC_SAMPLE, E_SW_TRIGGER, E_DUMP_ALL);
rx_pr("i2c_monitor start\n");
} else if (strncmp(tmpbuf, "i2c_dump", 7) == 0) {
rx_pr("i2c_dump\n");
rx_i2c_dump();
}
return 0;
}
@@ -8699,6 +8705,7 @@ void hdmirx_timer_handler(struct timer_list *t)
rx_clkmsr_monitor();
rx_hpd_monitor();
rx_edid_monitor();
rx_i2c_dbg_monitor();
if (rx_info.chip_id == CHIP_ID_T3X)
hdmirx_timer_t3x();
else