Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit faddc83d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "i3c: i3c-master-qcom-geni: Support for OD,PUSH-PULL mode frequency switch"

parents 743fc536 137b5f57
Loading
Loading
Loading
Loading
+36 −12
Original line number Diff line number Diff line
@@ -199,12 +199,18 @@ enum geni_i3c_err_code {
#define TLMM_I3C_MODE	0x24
#define IBI_SW_RESET_MIN_SLEEP 1000
#define IBI_SW_RESET_MAX_SLEEP 2000
#define I3C_OD_CLK_RATE 370000

enum i3c_trans_dir {
	WRITE_TRANSACTION = 0,
	READ_TRANSACTION = 1
};

enum i3c_bus_phase {
	OPEN_DRAIN_MODE  = 0,
	PUSH_PULL_MODE   = 1
};

struct geni_se {
	void __iomem *base;
	void __iomem *ibi_base;
@@ -262,6 +268,7 @@ struct geni_i3c_dev {
	int cur_idx;
	unsigned long newaddrslots[(I3C_ADDR_MASK + 1) / BITS_PER_LONG];
	const struct geni_i3c_clk_fld *clk_fld;
	const struct geni_i3c_clk_fld *clk_od_fld;
	struct geni_ibi ibi;
};

@@ -302,9 +309,9 @@ struct geni_i3c_clk_fld {
	u8  clk_div;
	u8  i2c_t_high_cnt;
	u8  i2c_t_low_cnt;
	u8  i2c_t_cycle_cnt;
	u8  i3c_t_high_cnt;
	u8  i3c_t_cycle_cnt;
	u32 i2c_t_cycle_cnt;
};

static struct geni_i3c_dev*
@@ -332,11 +339,12 @@ to_geni_i3c_master(struct i3c_master_controller *master)
 * clk_freq_out = t / t_cycle
 */
static const struct geni_i3c_clk_fld geni_i3c_clk_map[] = {
	{ KHZ(100),    19200, 7, 10, 11, 26, 0, 0 },
	{ KHZ(400),    19200, 2,  5, 12, 24, 0, 0 },
	{ KHZ(1000),   19200, 1,  3,  9, 18, 7, 0 },
	{ KHZ(1920),   19200, 1,  4,  9, 19, 7, 8 },
	{ KHZ(12500), 100000, 1, 60, 140, 250, 8, 16 },
	{ KHZ(100),    19200,  7, 10, 11,  0,  0,  26},
	{ KHZ(400),    19200,  2,  5, 12,  0,  0,  24},
	{ KHZ(1000),   19200,  1,  3,  9,  7,  0,  18},
	{ KHZ(1920),   19200,  1,  4,  9,  7,  8,  19},
	{ KHZ(370),   100000, 20,  4,  7,  8, 14,  14},
	{ KHZ(12500), 100000,  1, 72, 168, 6,  7, 300},
};

static int geni_i3c_clk_map_idx(struct geni_i3c_dev *gi3c)
@@ -351,13 +359,21 @@ static int geni_i3c_clk_map_idx(struct geni_i3c_dev *gi3c)
			 itr->clk_freq_out == bus->scl_rate.i3c) &&
			 KHZ(itr->clk_src_freq) == gi3c->clk_src_freq) {
			gi3c->clk_fld = itr;
			return 0;
		}

		if (itr->clk_freq_out == I3C_OD_CLK_RATE)
			gi3c->clk_od_fld = itr;
	}

	if ((!gi3c->clk_fld) || (!gi3c->clk_od_fld)) {
		GENI_SE_ERR(gi3c->ipcl, true, gi3c->se.dev,
			"%s : clk mapping failed", __func__);
		return -EINVAL;
	}

	return 0;
}

static void set_new_addr_slot(unsigned long *addrslot, u8 addr)
{
	unsigned long *ptr;
@@ -391,13 +407,17 @@ static bool is_new_addr_slot_set(unsigned long *addrslot, u8 addr)
	return ((*ptr & (1 << (addr % BITS_PER_LONG))) != 0);
}

static void qcom_geni_i3c_conf(struct geni_i3c_dev *gi3c)
static void qcom_geni_i3c_conf(struct geni_i3c_dev *gi3c,
	enum i3c_bus_phase bus_phase)
{
	const struct geni_i3c_clk_fld *itr = gi3c->clk_fld;
	u32 val;
	unsigned long freq;
	int ret = 0;

	if (bus_phase == OPEN_DRAIN_MODE)
		itr = gi3c->clk_od_fld;

	if (gi3c->dfs_idx > DFS_INDEX_MAX)
		ret = geni_se_clk_freq_match(&gi3c->se.i3c_rsc,
				KHZ(itr->clk_src_freq),
@@ -673,8 +693,6 @@ static int i3c_geni_runtime_get_mutex_lock(struct geni_i3c_dev *gi3c)
		return ret;
	}

	qcom_geni_i3c_conf(gi3c);

	return 0; /* return 0 to indicate SUCCESS */
}

@@ -923,6 +941,8 @@ static int geni_i3c_master_send_ccc_cmd
	if (ret)
		return ret;

	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);

	for (i = 0; i < cmd->ndests; i++) {
		int stall = (i < (cmd->ndests - 1)) ||
			(cmd->id == I3C_CCC_ENTDAA);
@@ -1000,6 +1020,8 @@ static int geni_i3c_master_priv_xfers
	if (ret)
		return ret;

	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);

	for (i = 0; i < nxfers; i++) {
		bool stall = (i < (nxfers - 1));
		struct i3c_xfer_params xfer = { FIFO_MODE };
@@ -1051,6 +1073,8 @@ static int geni_i3c_master_i2c_xfers
	if (ret)
		return ret;

	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);

	GENI_SE_DBG(gi3c->ipcl, false, gi3c->se.dev,
		"i2c xfer:num:%d, msgs:len:%d,flg:%d\n",
		num, msgs[0].len, msgs[0].flags);
@@ -1193,7 +1217,7 @@ static int geni_i3c_master_bus_init(struct i3c_master_controller *m)
		goto err_cleanup;
	}

	qcom_geni_i3c_conf(gi3c);
	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);

	/* Get an address for the master. */
	ret = i3c_master_get_free_addr(m, 0);