DF-4966 / mask_check.c
/* * DF-4966 mask_check โ dce110 id_to_offset I2C-pad SDA wrong-bit * * hw_translate_dce110.c:189-190 assigns * info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; (0x100) * to EVERY GPIO_ID_DDC_DATA line, and en=GPIO_DDC_LINE_I2C_PAD * only swaps the offset to mmDC_GPIO_I2CPAD_A (0x4899). But the DCE11 * register DC_GPIO_I2CPAD_A defines SCL at bit 0 (0x1) and SDA at bit 1 * (0x2), unlike the DDCx_A/VGA registers where CLK=bit0/DATA=bit8. * The DDC_DATA (SDA) translation for the I2C pad therefore carries a * mask for a bit that does not exist in the target register. */ #include <stdio.h> #include <stdbool.h> #include <stdint.h> #define mmDC_GPIO_DDC1_A 0x4869 #define mmDC_GPIO_I2CPAD_A 0x4899 #define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK 0x100 #define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK 0x1 #define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK 0x1 #define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK 0x2 #define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK 0x100 int main(void) { uint32_t ddc_data_i2cpad_mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; uint32_t ddc_clk_i2cpad_mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; uint32_t ddc_data_ddc1_mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; printf("register DC_GPIO_I2CPAD_A (0x%x) real fields: SCL=0x%x SDA=0x%x\n", mmDC_GPIO_I2CPAD_A, DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK, DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK); printf("id_to_offset(DDC_DATA, I2C_PAD) mask = 0x%x -> %s\n", ddc_data_i2cpad_mask, ddc_data_i2cpad_mask == DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK ? "correct" : "WRONG: selects bit 8; SDA is bit 1 โ reserved-bit write / dead-bit read"); printf("id_to_offset(DDC_CLOCK, I2C_PAD) mask = 0x%x -> %s\n", ddc_clk_i2cpad_mask, ddc_clk_i2cpad_mask == DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK ? "correct (by coincidence: DDC CLK bit == SCL bit)" : "wrong"); printf("control: id_to_offset(DDC_DATA, DDC1) mask = 0x%x vs DC_GPIO_DDC1DATA_A_MASK=0x%x -> %s\n", ddc_data_ddc1_mask, DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK, ddc_data_ddc1_mask == DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK ? "correct (shared mask valid for real DDC lines)" : "wrong"); /* * Consequence: hw_gpio/hw_ddc program the pad via * REG_UPDATE(DC_GPIO_DDC1_A.. / DC_GPIO_I2CPAD_A, mask, ...) * i.e. read-modify-write of 0x4899 with mask 0x100 โ sets/reads an * undefined bit while never touching the real SDA bit (0x2). */ return 0; } |