Loading drivers/i2c/busses/i2c-mt65xx.c +278 −51 Original line number Diff line number Diff line Loading @@ -40,12 +40,11 @@ #define I2C_SOFT_RST 0x0001 #define I2C_FIFO_ADDR_CLR 0x0001 #define I2C_DELAY_LEN 0x0002 #define I2C_ST_START_CON 0x8001 #define I2C_FS_START_CON 0x1800 #define I2C_TIME_CLR_VALUE 0x0000 #define I2C_TIME_DEFAULT_VALUE 0x0003 #define I2C_WRRD_TRANAC_VALUE 0x0002 #define I2C_RD_TRANAC_VALUE 0x0001 #define I2C_SCL_MIS_COMP_VALUE 0x0000 #define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_RX 0x0001 Loading @@ -55,10 +54,13 @@ #define I2C_DMA_HARD_RST 0x0002 #define I2C_DMA_4G_MODE 0x0001 #define I2C_DEFAULT_CLK_DIV 5 #define MAX_SAMPLE_CNT_DIV 8 #define MAX_STEP_CNT_DIV 64 #define MAX_CLOCK_DIV 256 #define MAX_HS_STEP_CNT_DIV 8 #define I2C_STANDARD_MODE_BUFFER (1000 / 2) #define I2C_FAST_MODE_BUFFER (300 / 2) #define I2C_FAST_MODE_PLUS_BUFFER (20 / 2) #define I2C_CONTROL_RS (0x1 << 1) #define I2C_CONTROL_DMA_EN (0x1 << 2) Loading Loading @@ -123,6 +125,12 @@ enum I2C_REGS_OFFSET { OFFSET_TRANSFER_LEN_AUX, OFFSET_CLOCK_DIV, OFFSET_LTIMING, OFFSET_SCL_HIGH_LOW_RATIO, OFFSET_HS_SCL_HIGH_LOW_RATIO, OFFSET_SCL_MIS_COMP_POINT, OFFSET_STA_STO_AC_TIMING, OFFSET_HS_STA_STO_AC_TIMING, OFFSET_SDA_TIMING, }; static const u16 mt_i2c_regs_v1[] = { Loading Loading @@ -150,6 +158,12 @@ static const u16 mt_i2c_regs_v1[] = { [OFFSET_DEBUGCTRL] = 0x68, [OFFSET_TRANSFER_LEN_AUX] = 0x6c, [OFFSET_CLOCK_DIV] = 0x70, [OFFSET_SCL_HIGH_LOW_RATIO] = 0x74, [OFFSET_HS_SCL_HIGH_LOW_RATIO] = 0x78, [OFFSET_SCL_MIS_COMP_POINT] = 0x7C, [OFFSET_STA_STO_AC_TIMING] = 0x80, [OFFSET_HS_STA_STO_AC_TIMING] = 0x84, [OFFSET_SDA_TIMING] = 0x88, }; static const u16 mt_i2c_regs_v2[] = { Loading @@ -168,9 +182,11 @@ static const u16 mt_i2c_regs_v2[] = { [OFFSET_HS] = 0x30, [OFFSET_IO_CONFIG] = 0x34, [OFFSET_FIFO_ADDR_CLR] = 0x38, [OFFSET_SDA_TIMING] = 0x3c, [OFFSET_TRANSFER_LEN_AUX] = 0x44, [OFFSET_CLOCK_DIV] = 0x48, [OFFSET_SOFTRESET] = 0x50, [OFFSET_SCL_MIS_COMP_POINT] = 0x90, [OFFSET_DEBUGSTAT] = 0xe0, [OFFSET_DEBUGCTRL] = 0xe8, [OFFSET_FIFO_STAT] = 0xf4, Loading @@ -191,6 +207,19 @@ struct mtk_i2c_compatible { unsigned char ltiming_adjust: 1; }; struct mtk_i2c_ac_timing { u16 htiming; u16 ltiming; u16 hs; u16 ext; u16 inter_clk_div; u16 scl_hl_ratio; u16 hs_scl_hl_ratio; u16 sta_stop; u16 hs_sta_stop; u16 sda_timing; }; struct mtk_i2c { struct i2c_adapter adap; /* i2c host adapter */ struct device *dev; Loading @@ -215,9 +244,46 @@ struct mtk_i2c { u16 ltiming_reg; unsigned char auto_restart; bool ignore_restart_irq; struct mtk_i2c_ac_timing ac_timing; const struct mtk_i2c_compatible *dev_comp; }; /** * struct i2c_spec_values: * min_low_ns: min LOW period of the SCL clock * min_su_sta_ns: min set-up time for a repeated START condition * max_hd_dat_ns: max data hold time * min_su_dat_ns: min data set-up time */ struct i2c_spec_values { unsigned int min_low_ns; unsigned int min_high_ns; unsigned int min_su_sta_ns; unsigned int max_hd_dat_ns; unsigned int min_su_dat_ns; }; static const struct i2c_spec_values standard_mode_spec = { .min_low_ns = 4700 + I2C_STANDARD_MODE_BUFFER, .min_su_sta_ns = 4700 + I2C_STANDARD_MODE_BUFFER, .max_hd_dat_ns = 3450 - I2C_STANDARD_MODE_BUFFER, .min_su_dat_ns = 250 + I2C_STANDARD_MODE_BUFFER, }; static const struct i2c_spec_values fast_mode_spec = { .min_low_ns = 1300 + I2C_FAST_MODE_BUFFER, .min_su_sta_ns = 600 + I2C_FAST_MODE_BUFFER, .max_hd_dat_ns = 900 - I2C_FAST_MODE_BUFFER, .min_su_dat_ns = 100 + I2C_FAST_MODE_BUFFER, }; static const struct i2c_spec_values fast_mode_plus_spec = { .min_low_ns = 500 + I2C_FAST_MODE_PLUS_BUFFER, .min_su_sta_ns = 260 + I2C_FAST_MODE_PLUS_BUFFER, .max_hd_dat_ns = 400 - I2C_FAST_MODE_PLUS_BUFFER, .min_su_dat_ns = 50 + I2C_FAST_MODE_PLUS_BUFFER, }; static const struct i2c_adapter_quirks mt6577_i2c_quirks = { .flags = I2C_AQ_COMB_WRITE_THEN_READ, .max_num_msgs = 1, Loading Loading @@ -397,14 +463,38 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) if (i2c->dev_comp->dcm) mtk_i2c_writew(i2c, I2C_DCM_DISABLE, OFFSET_DCM_EN); if (i2c->dev_comp->timing_adjust) mtk_i2c_writew(i2c, I2C_DEFAULT_CLK_DIV - 1, OFFSET_CLOCK_DIV); mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING); mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS); if (i2c->dev_comp->ltiming_adjust) mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING); if (i2c->dev_comp->timing_adjust) { mtk_i2c_writew(i2c, i2c->ac_timing.ext, OFFSET_EXT_CONF); mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div, OFFSET_CLOCK_DIV); mtk_i2c_writew(i2c, I2C_SCL_MIS_COMP_VALUE, OFFSET_SCL_MIS_COMP_POINT); mtk_i2c_writew(i2c, i2c->ac_timing.sda_timing, OFFSET_SDA_TIMING); if (i2c->dev_comp->ltiming_adjust) { mtk_i2c_writew(i2c, i2c->ac_timing.htiming, OFFSET_TIMING); mtk_i2c_writew(i2c, i2c->ac_timing.hs, OFFSET_HS); mtk_i2c_writew(i2c, i2c->ac_timing.ltiming, OFFSET_LTIMING); } else { mtk_i2c_writew(i2c, i2c->ac_timing.scl_hl_ratio, OFFSET_SCL_HIGH_LOW_RATIO); mtk_i2c_writew(i2c, i2c->ac_timing.hs_scl_hl_ratio, OFFSET_HS_SCL_HIGH_LOW_RATIO); mtk_i2c_writew(i2c, i2c->ac_timing.sta_stop, OFFSET_STA_STO_AC_TIMING); mtk_i2c_writew(i2c, i2c->ac_timing.hs_sta_stop, OFFSET_HS_STA_STO_AC_TIMING); } } /* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */ if (i2c->have_pmic) mtk_i2c_writew(i2c, I2C_CONTROL_WRAPPER, OFFSET_PATH_DIR); Loading @@ -422,6 +512,126 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); } static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed) { if (speed <= I2C_MAX_STANDARD_MODE_FREQ) return &standard_mode_spec; else if (speed <= I2C_MAX_FAST_MODE_FREQ) return &fast_mode_spec; else return &fast_mode_plus_spec; } static int mtk_i2c_max_step_cnt(unsigned int target_speed) { if (target_speed > I2C_MAX_FAST_MODE_FREQ) return MAX_HS_STEP_CNT_DIV; else return MAX_STEP_CNT_DIV; } /* * Check and Calculate i2c ac-timing * * Hardware design: * sample_ns = (1000000000 * (sample_cnt + 1)) / clk_src * xxx_cnt_div = spec->min_xxx_ns / sample_ns * * Sample_ns is rounded down for xxx_cnt_div would be greater * than the smallest spec. * The sda_timing is chosen as the middle value between * the largest and smallest. */ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c, unsigned int clk_src, unsigned int check_speed, unsigned int step_cnt, unsigned int sample_cnt) { const struct i2c_spec_values *spec; unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt; unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f; unsigned int sample_ns = div_u64(1000000000ULL * (sample_cnt + 1), clk_src); if (!i2c->dev_comp->timing_adjust) return 0; if (i2c->dev_comp->ltiming_adjust) max_sta_cnt = 0x100; spec = mtk_i2c_get_spec(check_speed); if (i2c->dev_comp->ltiming_adjust) clk_ns = 1000000000 / clk_src; else clk_ns = sample_ns / 2; su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns); if (su_sta_cnt > max_sta_cnt) return -1; low_cnt = DIV_ROUND_UP(spec->min_low_ns, sample_ns); max_step_cnt = mtk_i2c_max_step_cnt(check_speed); if ((2 * step_cnt) > low_cnt && low_cnt < max_step_cnt) { if (low_cnt > step_cnt) { high_cnt = 2 * step_cnt - low_cnt; } else { high_cnt = step_cnt; low_cnt = step_cnt; } } else { return -2; } sda_max = spec->max_hd_dat_ns / sample_ns; if (sda_max > low_cnt) sda_max = 0; sda_min = DIV_ROUND_UP(spec->min_su_dat_ns, sample_ns); if (sda_min < low_cnt) sda_min = 0; if (sda_min > sda_max) return -3; if (check_speed > I2C_MAX_FAST_MODE_FREQ) { if (i2c->dev_comp->ltiming_adjust) { i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (high_cnt << 8); i2c->ac_timing.ltiming &= ~GENMASK(15, 9); i2c->ac_timing.ltiming |= (sample_cnt << 12) | (low_cnt << 9); i2c->ac_timing.ext &= ~GENMASK(7, 1); i2c->ac_timing.ext |= (su_sta_cnt << 1) | (1 << 0); } else { i2c->ac_timing.hs_scl_hl_ratio = (1 << 12) | (high_cnt << 6) | low_cnt; i2c->ac_timing.hs_sta_stop = (su_sta_cnt << 8) | su_sta_cnt; } i2c->ac_timing.sda_timing &= ~GENMASK(11, 6); i2c->ac_timing.sda_timing |= (1 << 12) | ((sda_max + sda_min) / 2) << 6; } else { if (i2c->dev_comp->ltiming_adjust) { i2c->ac_timing.htiming = (sample_cnt << 8) | (high_cnt); i2c->ac_timing.ltiming = (sample_cnt << 6) | (low_cnt); i2c->ac_timing.ext = (su_sta_cnt << 8) | (1 << 0); } else { i2c->ac_timing.scl_hl_ratio = (1 << 12) | (high_cnt << 6) | low_cnt; i2c->ac_timing.sta_stop = (su_sta_cnt << 8) | su_sta_cnt; } i2c->ac_timing.sda_timing = (1 << 12) | (sda_max + sda_min) / 2; } return 0; } /* * Calculate i2c port speed * Loading @@ -446,15 +656,12 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, unsigned int opt_div; unsigned int best_mul; unsigned int cnt_mul; int ret = -EINVAL; if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ; if (target_speed > I2C_MAX_FAST_MODE_FREQ) max_step_cnt = MAX_HS_STEP_CNT_DIV; else max_step_cnt = MAX_STEP_CNT_DIV; max_step_cnt = mtk_i2c_max_step_cnt(target_speed); base_step_cnt = max_step_cnt; /* Find the best combination */ opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed); Loading @@ -473,6 +680,11 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, continue; if (cnt_mul < best_mul) { ret = mtk_i2c_check_ac_timing(i2c, clk_src, target_speed, step_cnt - 1, sample_cnt - 1); if (ret) continue; best_mul = cnt_mul; base_sample_cnt = sample_cnt; base_step_cnt = step_cnt; Loading @@ -481,6 +693,9 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, } } if (ret) return -EINVAL; sample_cnt = base_sample_cnt; step_cnt = base_step_cnt; Loading @@ -506,47 +721,68 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) unsigned int l_step_cnt; unsigned int l_sample_cnt; unsigned int target_speed; unsigned int clk_div; unsigned int max_clk_div; int ret; clk_src = parent_clk / i2c->clk_src_div; target_speed = i2c->speed_hz; parent_clk /= i2c->clk_src_div; if (i2c->dev_comp->timing_adjust) max_clk_div = MAX_CLOCK_DIV; else max_clk_div = 1; for (clk_div = 1; clk_div <= max_clk_div; clk_div++) { clk_src = parent_clk / clk_div; if (target_speed > I2C_MAX_FAST_MODE_FREQ) { /* Set master code speed register */ ret = mtk_i2c_calculate_speed(i2c, clk_src, I2C_MAX_FAST_MODE_FREQ, &l_step_cnt, &l_sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, I2C_MAX_FAST_MODE_FREQ, &l_step_cnt, &l_sample_cnt); if (ret < 0) return ret; continue; i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; /* Set the high speed mode register */ ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); if (ret < 0) return ret; continue; i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (step_cnt << 8); if (i2c->dev_comp->ltiming_adjust) i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt | i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt | (sample_cnt << 12) | (step_cnt << 9); } else { ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &l_step_cnt, &l_sample_cnt); if (ret < 0) return ret; continue; i2c->timing_reg = (sample_cnt << 8) | step_cnt; i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; /* Disable the high speed transaction */ i2c->high_speed_reg = I2C_TIME_CLR_VALUE; if (i2c->dev_comp->ltiming_adjust) i2c->ltiming_reg = (sample_cnt << 6) | step_cnt; i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt; } break; } i2c->ac_timing.inter_clk_div = clk_div - 1; return 0; } Loading Loading @@ -586,12 +822,6 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL); /* set start condition */ if (i2c->speed_hz <= I2C_MAX_STANDARD_MODE_FREQ) mtk_i2c_writew(i2c, I2C_ST_START_CON, OFFSET_EXT_CONF); else mtk_i2c_writew(i2c, I2C_FS_START_CON, OFFSET_EXT_CONF); addr_reg = i2c_8bit_addr_from_msg(msgs); mtk_i2c_writew(i2c, addr_reg, OFFSET_SLAVE_ADDR); Loading Loading @@ -948,9 +1178,6 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (ret) return -EINVAL; if (i2c->dev_comp->timing_adjust) i2c->clk_src_div *= I2C_DEFAULT_CLK_DIV; if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c) return -EINVAL; Loading Loading
drivers/i2c/busses/i2c-mt65xx.c +278 −51 Original line number Diff line number Diff line Loading @@ -40,12 +40,11 @@ #define I2C_SOFT_RST 0x0001 #define I2C_FIFO_ADDR_CLR 0x0001 #define I2C_DELAY_LEN 0x0002 #define I2C_ST_START_CON 0x8001 #define I2C_FS_START_CON 0x1800 #define I2C_TIME_CLR_VALUE 0x0000 #define I2C_TIME_DEFAULT_VALUE 0x0003 #define I2C_WRRD_TRANAC_VALUE 0x0002 #define I2C_RD_TRANAC_VALUE 0x0001 #define I2C_SCL_MIS_COMP_VALUE 0x0000 #define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_RX 0x0001 Loading @@ -55,10 +54,13 @@ #define I2C_DMA_HARD_RST 0x0002 #define I2C_DMA_4G_MODE 0x0001 #define I2C_DEFAULT_CLK_DIV 5 #define MAX_SAMPLE_CNT_DIV 8 #define MAX_STEP_CNT_DIV 64 #define MAX_CLOCK_DIV 256 #define MAX_HS_STEP_CNT_DIV 8 #define I2C_STANDARD_MODE_BUFFER (1000 / 2) #define I2C_FAST_MODE_BUFFER (300 / 2) #define I2C_FAST_MODE_PLUS_BUFFER (20 / 2) #define I2C_CONTROL_RS (0x1 << 1) #define I2C_CONTROL_DMA_EN (0x1 << 2) Loading Loading @@ -123,6 +125,12 @@ enum I2C_REGS_OFFSET { OFFSET_TRANSFER_LEN_AUX, OFFSET_CLOCK_DIV, OFFSET_LTIMING, OFFSET_SCL_HIGH_LOW_RATIO, OFFSET_HS_SCL_HIGH_LOW_RATIO, OFFSET_SCL_MIS_COMP_POINT, OFFSET_STA_STO_AC_TIMING, OFFSET_HS_STA_STO_AC_TIMING, OFFSET_SDA_TIMING, }; static const u16 mt_i2c_regs_v1[] = { Loading Loading @@ -150,6 +158,12 @@ static const u16 mt_i2c_regs_v1[] = { [OFFSET_DEBUGCTRL] = 0x68, [OFFSET_TRANSFER_LEN_AUX] = 0x6c, [OFFSET_CLOCK_DIV] = 0x70, [OFFSET_SCL_HIGH_LOW_RATIO] = 0x74, [OFFSET_HS_SCL_HIGH_LOW_RATIO] = 0x78, [OFFSET_SCL_MIS_COMP_POINT] = 0x7C, [OFFSET_STA_STO_AC_TIMING] = 0x80, [OFFSET_HS_STA_STO_AC_TIMING] = 0x84, [OFFSET_SDA_TIMING] = 0x88, }; static const u16 mt_i2c_regs_v2[] = { Loading @@ -168,9 +182,11 @@ static const u16 mt_i2c_regs_v2[] = { [OFFSET_HS] = 0x30, [OFFSET_IO_CONFIG] = 0x34, [OFFSET_FIFO_ADDR_CLR] = 0x38, [OFFSET_SDA_TIMING] = 0x3c, [OFFSET_TRANSFER_LEN_AUX] = 0x44, [OFFSET_CLOCK_DIV] = 0x48, [OFFSET_SOFTRESET] = 0x50, [OFFSET_SCL_MIS_COMP_POINT] = 0x90, [OFFSET_DEBUGSTAT] = 0xe0, [OFFSET_DEBUGCTRL] = 0xe8, [OFFSET_FIFO_STAT] = 0xf4, Loading @@ -191,6 +207,19 @@ struct mtk_i2c_compatible { unsigned char ltiming_adjust: 1; }; struct mtk_i2c_ac_timing { u16 htiming; u16 ltiming; u16 hs; u16 ext; u16 inter_clk_div; u16 scl_hl_ratio; u16 hs_scl_hl_ratio; u16 sta_stop; u16 hs_sta_stop; u16 sda_timing; }; struct mtk_i2c { struct i2c_adapter adap; /* i2c host adapter */ struct device *dev; Loading @@ -215,9 +244,46 @@ struct mtk_i2c { u16 ltiming_reg; unsigned char auto_restart; bool ignore_restart_irq; struct mtk_i2c_ac_timing ac_timing; const struct mtk_i2c_compatible *dev_comp; }; /** * struct i2c_spec_values: * min_low_ns: min LOW period of the SCL clock * min_su_sta_ns: min set-up time for a repeated START condition * max_hd_dat_ns: max data hold time * min_su_dat_ns: min data set-up time */ struct i2c_spec_values { unsigned int min_low_ns; unsigned int min_high_ns; unsigned int min_su_sta_ns; unsigned int max_hd_dat_ns; unsigned int min_su_dat_ns; }; static const struct i2c_spec_values standard_mode_spec = { .min_low_ns = 4700 + I2C_STANDARD_MODE_BUFFER, .min_su_sta_ns = 4700 + I2C_STANDARD_MODE_BUFFER, .max_hd_dat_ns = 3450 - I2C_STANDARD_MODE_BUFFER, .min_su_dat_ns = 250 + I2C_STANDARD_MODE_BUFFER, }; static const struct i2c_spec_values fast_mode_spec = { .min_low_ns = 1300 + I2C_FAST_MODE_BUFFER, .min_su_sta_ns = 600 + I2C_FAST_MODE_BUFFER, .max_hd_dat_ns = 900 - I2C_FAST_MODE_BUFFER, .min_su_dat_ns = 100 + I2C_FAST_MODE_BUFFER, }; static const struct i2c_spec_values fast_mode_plus_spec = { .min_low_ns = 500 + I2C_FAST_MODE_PLUS_BUFFER, .min_su_sta_ns = 260 + I2C_FAST_MODE_PLUS_BUFFER, .max_hd_dat_ns = 400 - I2C_FAST_MODE_PLUS_BUFFER, .min_su_dat_ns = 50 + I2C_FAST_MODE_PLUS_BUFFER, }; static const struct i2c_adapter_quirks mt6577_i2c_quirks = { .flags = I2C_AQ_COMB_WRITE_THEN_READ, .max_num_msgs = 1, Loading Loading @@ -397,14 +463,38 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) if (i2c->dev_comp->dcm) mtk_i2c_writew(i2c, I2C_DCM_DISABLE, OFFSET_DCM_EN); if (i2c->dev_comp->timing_adjust) mtk_i2c_writew(i2c, I2C_DEFAULT_CLK_DIV - 1, OFFSET_CLOCK_DIV); mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING); mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS); if (i2c->dev_comp->ltiming_adjust) mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING); if (i2c->dev_comp->timing_adjust) { mtk_i2c_writew(i2c, i2c->ac_timing.ext, OFFSET_EXT_CONF); mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div, OFFSET_CLOCK_DIV); mtk_i2c_writew(i2c, I2C_SCL_MIS_COMP_VALUE, OFFSET_SCL_MIS_COMP_POINT); mtk_i2c_writew(i2c, i2c->ac_timing.sda_timing, OFFSET_SDA_TIMING); if (i2c->dev_comp->ltiming_adjust) { mtk_i2c_writew(i2c, i2c->ac_timing.htiming, OFFSET_TIMING); mtk_i2c_writew(i2c, i2c->ac_timing.hs, OFFSET_HS); mtk_i2c_writew(i2c, i2c->ac_timing.ltiming, OFFSET_LTIMING); } else { mtk_i2c_writew(i2c, i2c->ac_timing.scl_hl_ratio, OFFSET_SCL_HIGH_LOW_RATIO); mtk_i2c_writew(i2c, i2c->ac_timing.hs_scl_hl_ratio, OFFSET_HS_SCL_HIGH_LOW_RATIO); mtk_i2c_writew(i2c, i2c->ac_timing.sta_stop, OFFSET_STA_STO_AC_TIMING); mtk_i2c_writew(i2c, i2c->ac_timing.hs_sta_stop, OFFSET_HS_STA_STO_AC_TIMING); } } /* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */ if (i2c->have_pmic) mtk_i2c_writew(i2c, I2C_CONTROL_WRAPPER, OFFSET_PATH_DIR); Loading @@ -422,6 +512,126 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); } static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed) { if (speed <= I2C_MAX_STANDARD_MODE_FREQ) return &standard_mode_spec; else if (speed <= I2C_MAX_FAST_MODE_FREQ) return &fast_mode_spec; else return &fast_mode_plus_spec; } static int mtk_i2c_max_step_cnt(unsigned int target_speed) { if (target_speed > I2C_MAX_FAST_MODE_FREQ) return MAX_HS_STEP_CNT_DIV; else return MAX_STEP_CNT_DIV; } /* * Check and Calculate i2c ac-timing * * Hardware design: * sample_ns = (1000000000 * (sample_cnt + 1)) / clk_src * xxx_cnt_div = spec->min_xxx_ns / sample_ns * * Sample_ns is rounded down for xxx_cnt_div would be greater * than the smallest spec. * The sda_timing is chosen as the middle value between * the largest and smallest. */ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c, unsigned int clk_src, unsigned int check_speed, unsigned int step_cnt, unsigned int sample_cnt) { const struct i2c_spec_values *spec; unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt; unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f; unsigned int sample_ns = div_u64(1000000000ULL * (sample_cnt + 1), clk_src); if (!i2c->dev_comp->timing_adjust) return 0; if (i2c->dev_comp->ltiming_adjust) max_sta_cnt = 0x100; spec = mtk_i2c_get_spec(check_speed); if (i2c->dev_comp->ltiming_adjust) clk_ns = 1000000000 / clk_src; else clk_ns = sample_ns / 2; su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns); if (su_sta_cnt > max_sta_cnt) return -1; low_cnt = DIV_ROUND_UP(spec->min_low_ns, sample_ns); max_step_cnt = mtk_i2c_max_step_cnt(check_speed); if ((2 * step_cnt) > low_cnt && low_cnt < max_step_cnt) { if (low_cnt > step_cnt) { high_cnt = 2 * step_cnt - low_cnt; } else { high_cnt = step_cnt; low_cnt = step_cnt; } } else { return -2; } sda_max = spec->max_hd_dat_ns / sample_ns; if (sda_max > low_cnt) sda_max = 0; sda_min = DIV_ROUND_UP(spec->min_su_dat_ns, sample_ns); if (sda_min < low_cnt) sda_min = 0; if (sda_min > sda_max) return -3; if (check_speed > I2C_MAX_FAST_MODE_FREQ) { if (i2c->dev_comp->ltiming_adjust) { i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (high_cnt << 8); i2c->ac_timing.ltiming &= ~GENMASK(15, 9); i2c->ac_timing.ltiming |= (sample_cnt << 12) | (low_cnt << 9); i2c->ac_timing.ext &= ~GENMASK(7, 1); i2c->ac_timing.ext |= (su_sta_cnt << 1) | (1 << 0); } else { i2c->ac_timing.hs_scl_hl_ratio = (1 << 12) | (high_cnt << 6) | low_cnt; i2c->ac_timing.hs_sta_stop = (su_sta_cnt << 8) | su_sta_cnt; } i2c->ac_timing.sda_timing &= ~GENMASK(11, 6); i2c->ac_timing.sda_timing |= (1 << 12) | ((sda_max + sda_min) / 2) << 6; } else { if (i2c->dev_comp->ltiming_adjust) { i2c->ac_timing.htiming = (sample_cnt << 8) | (high_cnt); i2c->ac_timing.ltiming = (sample_cnt << 6) | (low_cnt); i2c->ac_timing.ext = (su_sta_cnt << 8) | (1 << 0); } else { i2c->ac_timing.scl_hl_ratio = (1 << 12) | (high_cnt << 6) | low_cnt; i2c->ac_timing.sta_stop = (su_sta_cnt << 8) | su_sta_cnt; } i2c->ac_timing.sda_timing = (1 << 12) | (sda_max + sda_min) / 2; } return 0; } /* * Calculate i2c port speed * Loading @@ -446,15 +656,12 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, unsigned int opt_div; unsigned int best_mul; unsigned int cnt_mul; int ret = -EINVAL; if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ; if (target_speed > I2C_MAX_FAST_MODE_FREQ) max_step_cnt = MAX_HS_STEP_CNT_DIV; else max_step_cnt = MAX_STEP_CNT_DIV; max_step_cnt = mtk_i2c_max_step_cnt(target_speed); base_step_cnt = max_step_cnt; /* Find the best combination */ opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed); Loading @@ -473,6 +680,11 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, continue; if (cnt_mul < best_mul) { ret = mtk_i2c_check_ac_timing(i2c, clk_src, target_speed, step_cnt - 1, sample_cnt - 1); if (ret) continue; best_mul = cnt_mul; base_sample_cnt = sample_cnt; base_step_cnt = step_cnt; Loading @@ -481,6 +693,9 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, } } if (ret) return -EINVAL; sample_cnt = base_sample_cnt; step_cnt = base_step_cnt; Loading @@ -506,47 +721,68 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) unsigned int l_step_cnt; unsigned int l_sample_cnt; unsigned int target_speed; unsigned int clk_div; unsigned int max_clk_div; int ret; clk_src = parent_clk / i2c->clk_src_div; target_speed = i2c->speed_hz; parent_clk /= i2c->clk_src_div; if (i2c->dev_comp->timing_adjust) max_clk_div = MAX_CLOCK_DIV; else max_clk_div = 1; for (clk_div = 1; clk_div <= max_clk_div; clk_div++) { clk_src = parent_clk / clk_div; if (target_speed > I2C_MAX_FAST_MODE_FREQ) { /* Set master code speed register */ ret = mtk_i2c_calculate_speed(i2c, clk_src, I2C_MAX_FAST_MODE_FREQ, &l_step_cnt, &l_sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, I2C_MAX_FAST_MODE_FREQ, &l_step_cnt, &l_sample_cnt); if (ret < 0) return ret; continue; i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; /* Set the high speed mode register */ ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); if (ret < 0) return ret; continue; i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (step_cnt << 8); if (i2c->dev_comp->ltiming_adjust) i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt | i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt | (sample_cnt << 12) | (step_cnt << 9); } else { ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &step_cnt, &sample_cnt); ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, &l_step_cnt, &l_sample_cnt); if (ret < 0) return ret; continue; i2c->timing_reg = (sample_cnt << 8) | step_cnt; i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; /* Disable the high speed transaction */ i2c->high_speed_reg = I2C_TIME_CLR_VALUE; if (i2c->dev_comp->ltiming_adjust) i2c->ltiming_reg = (sample_cnt << 6) | step_cnt; i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt; } break; } i2c->ac_timing.inter_clk_div = clk_div - 1; return 0; } Loading Loading @@ -586,12 +822,6 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL); /* set start condition */ if (i2c->speed_hz <= I2C_MAX_STANDARD_MODE_FREQ) mtk_i2c_writew(i2c, I2C_ST_START_CON, OFFSET_EXT_CONF); else mtk_i2c_writew(i2c, I2C_FS_START_CON, OFFSET_EXT_CONF); addr_reg = i2c_8bit_addr_from_msg(msgs); mtk_i2c_writew(i2c, addr_reg, OFFSET_SLAVE_ADDR); Loading Loading @@ -948,9 +1178,6 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (ret) return -EINVAL; if (i2c->dev_comp->timing_adjust) i2c->clk_src_div *= I2C_DEFAULT_CLK_DIV; if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c) return -EINVAL; Loading