i2c: mediatek: Add i2c ac-timing adjust support
This patch adds a algorithm to calculate some ac-timing parameters which can fully meet I2C Spec. Signed-off-by: Qii Wang <qii.wang@mediatek.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
Родитель
7943f1d178
Коммит
be5ce0e97c
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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[] = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 (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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (i2c->dev_comp->timing_adjust)
|
||||
max_clk_div = MAX_CLOCK_DIV;
|
||||
else
|
||||
max_clk_div = 1;
|
||||
|
||||
i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt;
|
||||
for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
|
||||
clk_src = parent_clk / clk_div;
|
||||
|
||||
/* Set the high speed mode register */
|
||||
ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
|
||||
&step_cnt, &sample_cnt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
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);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
|
||||
(sample_cnt << 12) | (step_cnt << 8);
|
||||
i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt;
|
||||
|
||||
if (i2c->dev_comp->ltiming_adjust)
|
||||
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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Set the high speed mode register */
|
||||
ret = mtk_i2c_calculate_speed(i2c, clk_src,
|
||||
target_speed, &step_cnt,
|
||||
&sample_cnt);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
i2c->timing_reg = (sample_cnt << 8) | step_cnt;
|
||||
i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
|
||||
(sample_cnt << 12) | (step_cnt << 8);
|
||||
|
||||
/* Disable the high speed transaction */
|
||||
i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
|
||||
if (i2c->dev_comp->ltiming_adjust)
|
||||
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, &l_step_cnt,
|
||||
&l_sample_cnt);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
if (i2c->dev_comp->ltiming_adjust)
|
||||
i2c->ltiming_reg = (sample_cnt << 6) | 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 =
|
||||
(l_sample_cnt << 6) | l_step_cnt;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
i2c->ac_timing.inter_clk_div = clk_div - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче