Loading drivers/i2c/busses/i2c-msm-v2.c +15 −44 Original line number Diff line number Diff line Loading @@ -841,18 +841,15 @@ static void i2c_msm_prof_evnt_dump(struct i2c_msm_ctrl *ctrl) } /* * tag_lookup_table[is_high_speed][start_req][is_last][is_rx] * @start_req start or repeated-start * tag_lookup_table[is_new_addr][is_last][is_rx] * @is_new_addr Is start tag required? (which requires two more bytes.) * @is_last Use the XXXXX_N_STOP tag varient * @is_rx READ/WRITE * is_high_speed Requires a post-fix of a start-tag and the reserved * high-speed address. * * workaround! Due to an HW issues, a stop is issued after every read. * QUP_TAG2_DATA_READ is replaced by QUP_TAG2_DATA_READ_N_STOP. */ static const struct i2c_msm_tag tag_lookup_table[2][2][2][2] = { {{{{QUP_TAG2_DATA_WRITE , 2}, static const struct i2c_msm_tag tag_lookup_table[2][2][2] = { {{{QUP_TAG2_DATA_WRITE , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} }, /* last buffer */ {{QUP_TAG2_DATA_WRITE_N_STOP , 2}, Loading @@ -862,48 +859,29 @@ static const struct i2c_msm_tag tag_lookup_table[2][2][2][2] = { {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} }, /* last buffer + new addr */ {{QUP_TAG2_START | (QUP_TAG2_DATA_WRITE_N_STOP << 16), 4}, {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} } } }, /* high speed */ {{{{QUP_TAG2_DATA_WRITE , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} }, /* high speed + last buffer */ {{QUP_TAG2_DATA_WRITE_N_STOP , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} } }, /* high speed + new addr */ {{{QUP_TAG2_START_HS | (QUP_TAG2_DATA_WRITE << 32), 6}, {QUP_TAG2_START_HS | (QUP_TAG2_DATA_READ_N_STOP << 32), 6} }, /* high speed + last buffer + new addr */ {{QUP_TAG2_START_HS | (QUP_TAG2_DATA_WRITE_N_STOP << 32), 6}, {QUP_TAG2_START_HS | (QUP_TAG2_DATA_READ_N_STOP << 32), 6} } } }, {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} } }, }; /* * i2c_msm_tag_create: format a qup tag ver2 */ static struct i2c_msm_tag i2c_msm_tag_create(bool is_high_speed, bool start_req, bool is_last_buf, bool is_rx, u8 buf_len, u8 slave_addr) static struct i2c_msm_tag i2c_msm_tag_create(bool is_new_addr, bool is_last_buf, bool is_rx, u8 buf_len, u8 slave_addr) { struct i2c_msm_tag tag; /* Normalize booleans to 1 or 0 */ start_req = start_req ? 1 : 0; is_new_addr = is_new_addr ? 1 : 0; is_last_buf = is_last_buf ? 1 : 0; is_rx = is_rx ? 1 : 0; tag = tag_lookup_table[is_high_speed][start_req][is_last_buf][is_rx]; tag = tag_lookup_table[is_new_addr][is_last_buf][is_rx]; /* fill in the non-const value: the address and the length */ switch (tag.len) { case 6: *i2c_msm_tag_byte(&tag, 3) = slave_addr; *i2c_msm_tag_byte(&tag, 5) = buf_len; break; case 4: if (tag.len == I2C_MSM_TAG2_MAX_LEN) { *i2c_msm_tag_byte(&tag, 1) = slave_addr; *i2c_msm_tag_byte(&tag, 3) = buf_len; break; default: } else { *i2c_msm_tag_byte(&tag, 1) = buf_len; }; } return tag; } Loading Loading @@ -1082,11 +1060,6 @@ i2c_msm_qup_xfer_init_reset_state(struct i2c_msm_ctrl *ctrl) wmb(); } bool i2c_msm_xfer_is_high_speed(struct i2c_msm_ctrl *ctrl) { return ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_FAST_MAX_FREQ; } /* * i2c_msm_clk_div_fld: * @clk_freq_out output clock frequency Loading Loading @@ -3221,9 +3194,7 @@ static void i2c_msm_xfer_create_cur_tag(struct i2c_msm_ctrl *ctrl, { struct i2c_msm_xfer_buf *cur_buf = &ctrl->xfer.cur_buf; cur_buf->out_tag = i2c_msm_tag_create( i2c_msm_xfer_is_high_speed(ctrl), start_req, cur_buf->is_last, cur_buf->out_tag = i2c_msm_tag_create(start_req, cur_buf->is_last, cur_buf->is_rx, cur_buf->len, cur_buf->slv_addr); Loading Loading @@ -3728,7 +3699,7 @@ static int i2c_msm_rsrcs_clk_init(struct i2c_msm_ctrl *ctrl) int ret = 0; if ((ctrl->rsrcs.clk_freq_out <= 0) || (ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_HIGH_MAX_FREQ)) { (ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_FAST_PLUS_FREQ)) { dev_err(ctrl->dev, "error clock frequency %dKHZ is not supported\n", (ctrl->rsrcs.clk_freq_out / 1000)); Loading drivers/i2c/busses/i2c-msm-v2.h +11 −14 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ enum msm_i2_debug_level { #define MASK_IS_SET(val, mask) ((val & mask) == mask) #define MASK_IS_SET_BOOL(val, mask) (MASK_IS_SET(val, mask) ? 1 : 0) #define KHz(freq) (1000 * freq) #define I2C_MSM_CLK_FAST_PLUS_FREQ (1000000) #define I2C_MSM_TAG2_MAX_LEN (4) /* QUP Registers */ enum { Loading Loading @@ -144,11 +146,6 @@ enum { QUP_EN_VERSION_TWO_TAG = 1U, }; enum { I2C_MSM_CLK_FAST_MAX_FREQ = 1000000, I2C_MSM_CLK_HIGH_MAX_FREQ = 3400000, }; /* Register:QUP_I2C_MASTER_CLK_CTL field setters */ #define I2C_MSM_SCL_NOISE_REJECTION(reg_val, noise_rej_val) \ (((reg_val) & ~(0x3 << 24)) | (((noise_rej_val) & 0x3) << 24)) Loading Loading @@ -202,11 +199,11 @@ enum msm_i2c_power_state { /* * The max buffer size required for tags is for holding the following sequence: * [start | hs-addr] + [start | slv-addr] + [ rd/wr | len] * [start] + [start | slv-addr] + [ rd/wr | len] * which sum up to 6 bytes. However, we use u64 to hold the value, thus we say * that max length is 8 bytes. */ #define I2C_MSM_TAG2_MAX_LEN (8) #define I2C_MSM_TAG2_MAX_LEN (4) #define I2C_MSM_BAM_CONS_SZ (64) /* consumer pipe n entries */ #define I2C_MSM_BAM_PROD_SZ (32) /* producer pipe n entries */ #define I2C_MSM_BAM_DESC_ARR_SIZ (I2C_MSM_BAM_CONS_SZ + I2C_MSM_BAM_PROD_SZ) Loading @@ -217,7 +214,6 @@ enum msm_i2c_power_state { #define I2C_MSM_MAX_POLL_MSEC (100) #define I2C_MSM_TIMEOUT_SAFTY_COEF (10) #define I2C_MSM_TIMEOUT_MIN_USEC (500000) #define I2C_MSM_HS_ADDR (0x0f) #define I2C_QUP_MAX_BUS_RECOVERY_RETRY (10) /* QUP v2 tags */ Loading @@ -230,9 +226,6 @@ enum msm_i2c_power_state { #define QUP_TAG2_START_STOP (0x8AULL) #define QUP_TAG2_INPUT_EOT (0x93ULL) #define QUP_TAG2_FLUSH_STOP (0x96ULL) /* Aggregate the constatnt values of HS start sequence */ #define QUP_TAG2_START_HS (QUP_TAG2_START | (I2C_MSM_HS_ADDR << 8) | \ (QUP_TAG2_START << 16)) enum msm_spi_clk_path_vec_idx { I2C_MSM_CLK_PATH_SUSPEND_VEC, Loading Loading @@ -383,9 +376,13 @@ struct i2c_msm_xfer_mode_bam { * | input_tag | eot_... | tag_arr 0 | tag_arr 1 | .. | tag_arr n | * +-----------+---------+-----------+-----------+----+-----------+ * * I2C_MSM_TAG2_MAX_LEN bytes for input_tag * I2C_MSM_TAG2_MAX_LEN bytes for eot_n_flush_stop_tags * I2C_MSM_BAM_DESC_ARR_SIZ * I2C_MSM_TAG2_MAX_LEN bytes for tag_arr * Why +2? * One tag buffer for the input tags. This is a write only buffer for BAM, it is * used to read the tags of the input fifo. We let them overwrite each other, * since it is a throw-away from the driver's perspective. * Second tag buffer for the EOT and flush-stop tags. This is a read only * buffer (from BAM perspective). It is used to put EOT and flush-stop at the * end of every transaction. */ #define I2C_MSM_BAM_TAG_MEM_SZ \ ((I2C_MSM_BAM_DESC_ARR_SIZ + 2) * I2C_MSM_TAG2_MAX_LEN) Loading Loading
drivers/i2c/busses/i2c-msm-v2.c +15 −44 Original line number Diff line number Diff line Loading @@ -841,18 +841,15 @@ static void i2c_msm_prof_evnt_dump(struct i2c_msm_ctrl *ctrl) } /* * tag_lookup_table[is_high_speed][start_req][is_last][is_rx] * @start_req start or repeated-start * tag_lookup_table[is_new_addr][is_last][is_rx] * @is_new_addr Is start tag required? (which requires two more bytes.) * @is_last Use the XXXXX_N_STOP tag varient * @is_rx READ/WRITE * is_high_speed Requires a post-fix of a start-tag and the reserved * high-speed address. * * workaround! Due to an HW issues, a stop is issued after every read. * QUP_TAG2_DATA_READ is replaced by QUP_TAG2_DATA_READ_N_STOP. */ static const struct i2c_msm_tag tag_lookup_table[2][2][2][2] = { {{{{QUP_TAG2_DATA_WRITE , 2}, static const struct i2c_msm_tag tag_lookup_table[2][2][2] = { {{{QUP_TAG2_DATA_WRITE , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} }, /* last buffer */ {{QUP_TAG2_DATA_WRITE_N_STOP , 2}, Loading @@ -862,48 +859,29 @@ static const struct i2c_msm_tag tag_lookup_table[2][2][2][2] = { {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} }, /* last buffer + new addr */ {{QUP_TAG2_START | (QUP_TAG2_DATA_WRITE_N_STOP << 16), 4}, {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} } } }, /* high speed */ {{{{QUP_TAG2_DATA_WRITE , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} }, /* high speed + last buffer */ {{QUP_TAG2_DATA_WRITE_N_STOP , 2}, {QUP_TAG2_DATA_READ_N_STOP , 2} } }, /* high speed + new addr */ {{{QUP_TAG2_START_HS | (QUP_TAG2_DATA_WRITE << 32), 6}, {QUP_TAG2_START_HS | (QUP_TAG2_DATA_READ_N_STOP << 32), 6} }, /* high speed + last buffer + new addr */ {{QUP_TAG2_START_HS | (QUP_TAG2_DATA_WRITE_N_STOP << 32), 6}, {QUP_TAG2_START_HS | (QUP_TAG2_DATA_READ_N_STOP << 32), 6} } } }, {QUP_TAG2_START | (QUP_TAG2_DATA_READ_N_STOP << 16), 4} } }, }; /* * i2c_msm_tag_create: format a qup tag ver2 */ static struct i2c_msm_tag i2c_msm_tag_create(bool is_high_speed, bool start_req, bool is_last_buf, bool is_rx, u8 buf_len, u8 slave_addr) static struct i2c_msm_tag i2c_msm_tag_create(bool is_new_addr, bool is_last_buf, bool is_rx, u8 buf_len, u8 slave_addr) { struct i2c_msm_tag tag; /* Normalize booleans to 1 or 0 */ start_req = start_req ? 1 : 0; is_new_addr = is_new_addr ? 1 : 0; is_last_buf = is_last_buf ? 1 : 0; is_rx = is_rx ? 1 : 0; tag = tag_lookup_table[is_high_speed][start_req][is_last_buf][is_rx]; tag = tag_lookup_table[is_new_addr][is_last_buf][is_rx]; /* fill in the non-const value: the address and the length */ switch (tag.len) { case 6: *i2c_msm_tag_byte(&tag, 3) = slave_addr; *i2c_msm_tag_byte(&tag, 5) = buf_len; break; case 4: if (tag.len == I2C_MSM_TAG2_MAX_LEN) { *i2c_msm_tag_byte(&tag, 1) = slave_addr; *i2c_msm_tag_byte(&tag, 3) = buf_len; break; default: } else { *i2c_msm_tag_byte(&tag, 1) = buf_len; }; } return tag; } Loading Loading @@ -1082,11 +1060,6 @@ i2c_msm_qup_xfer_init_reset_state(struct i2c_msm_ctrl *ctrl) wmb(); } bool i2c_msm_xfer_is_high_speed(struct i2c_msm_ctrl *ctrl) { return ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_FAST_MAX_FREQ; } /* * i2c_msm_clk_div_fld: * @clk_freq_out output clock frequency Loading Loading @@ -3221,9 +3194,7 @@ static void i2c_msm_xfer_create_cur_tag(struct i2c_msm_ctrl *ctrl, { struct i2c_msm_xfer_buf *cur_buf = &ctrl->xfer.cur_buf; cur_buf->out_tag = i2c_msm_tag_create( i2c_msm_xfer_is_high_speed(ctrl), start_req, cur_buf->is_last, cur_buf->out_tag = i2c_msm_tag_create(start_req, cur_buf->is_last, cur_buf->is_rx, cur_buf->len, cur_buf->slv_addr); Loading Loading @@ -3728,7 +3699,7 @@ static int i2c_msm_rsrcs_clk_init(struct i2c_msm_ctrl *ctrl) int ret = 0; if ((ctrl->rsrcs.clk_freq_out <= 0) || (ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_HIGH_MAX_FREQ)) { (ctrl->rsrcs.clk_freq_out > I2C_MSM_CLK_FAST_PLUS_FREQ)) { dev_err(ctrl->dev, "error clock frequency %dKHZ is not supported\n", (ctrl->rsrcs.clk_freq_out / 1000)); Loading
drivers/i2c/busses/i2c-msm-v2.h +11 −14 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ enum msm_i2_debug_level { #define MASK_IS_SET(val, mask) ((val & mask) == mask) #define MASK_IS_SET_BOOL(val, mask) (MASK_IS_SET(val, mask) ? 1 : 0) #define KHz(freq) (1000 * freq) #define I2C_MSM_CLK_FAST_PLUS_FREQ (1000000) #define I2C_MSM_TAG2_MAX_LEN (4) /* QUP Registers */ enum { Loading Loading @@ -144,11 +146,6 @@ enum { QUP_EN_VERSION_TWO_TAG = 1U, }; enum { I2C_MSM_CLK_FAST_MAX_FREQ = 1000000, I2C_MSM_CLK_HIGH_MAX_FREQ = 3400000, }; /* Register:QUP_I2C_MASTER_CLK_CTL field setters */ #define I2C_MSM_SCL_NOISE_REJECTION(reg_val, noise_rej_val) \ (((reg_val) & ~(0x3 << 24)) | (((noise_rej_val) & 0x3) << 24)) Loading Loading @@ -202,11 +199,11 @@ enum msm_i2c_power_state { /* * The max buffer size required for tags is for holding the following sequence: * [start | hs-addr] + [start | slv-addr] + [ rd/wr | len] * [start] + [start | slv-addr] + [ rd/wr | len] * which sum up to 6 bytes. However, we use u64 to hold the value, thus we say * that max length is 8 bytes. */ #define I2C_MSM_TAG2_MAX_LEN (8) #define I2C_MSM_TAG2_MAX_LEN (4) #define I2C_MSM_BAM_CONS_SZ (64) /* consumer pipe n entries */ #define I2C_MSM_BAM_PROD_SZ (32) /* producer pipe n entries */ #define I2C_MSM_BAM_DESC_ARR_SIZ (I2C_MSM_BAM_CONS_SZ + I2C_MSM_BAM_PROD_SZ) Loading @@ -217,7 +214,6 @@ enum msm_i2c_power_state { #define I2C_MSM_MAX_POLL_MSEC (100) #define I2C_MSM_TIMEOUT_SAFTY_COEF (10) #define I2C_MSM_TIMEOUT_MIN_USEC (500000) #define I2C_MSM_HS_ADDR (0x0f) #define I2C_QUP_MAX_BUS_RECOVERY_RETRY (10) /* QUP v2 tags */ Loading @@ -230,9 +226,6 @@ enum msm_i2c_power_state { #define QUP_TAG2_START_STOP (0x8AULL) #define QUP_TAG2_INPUT_EOT (0x93ULL) #define QUP_TAG2_FLUSH_STOP (0x96ULL) /* Aggregate the constatnt values of HS start sequence */ #define QUP_TAG2_START_HS (QUP_TAG2_START | (I2C_MSM_HS_ADDR << 8) | \ (QUP_TAG2_START << 16)) enum msm_spi_clk_path_vec_idx { I2C_MSM_CLK_PATH_SUSPEND_VEC, Loading Loading @@ -383,9 +376,13 @@ struct i2c_msm_xfer_mode_bam { * | input_tag | eot_... | tag_arr 0 | tag_arr 1 | .. | tag_arr n | * +-----------+---------+-----------+-----------+----+-----------+ * * I2C_MSM_TAG2_MAX_LEN bytes for input_tag * I2C_MSM_TAG2_MAX_LEN bytes for eot_n_flush_stop_tags * I2C_MSM_BAM_DESC_ARR_SIZ * I2C_MSM_TAG2_MAX_LEN bytes for tag_arr * Why +2? * One tag buffer for the input tags. This is a write only buffer for BAM, it is * used to read the tags of the input fifo. We let them overwrite each other, * since it is a throw-away from the driver's perspective. * Second tag buffer for the EOT and flush-stop tags. This is a read only * buffer (from BAM perspective). It is used to put EOT and flush-stop at the * end of every transaction. */ #define I2C_MSM_BAM_TAG_MEM_SZ \ ((I2C_MSM_BAM_DESC_ARR_SIZ + 2) * I2C_MSM_TAG2_MAX_LEN) Loading