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

Commit 853c94b9 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "i2c: qcom: geni: Add support for Standard, Fast and Fast plus modes"

parents 874fe223 6f23120b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@ Required properties:
 - #size-cells: Should be <0> as i2c addresses have no size component
 - qcom,wrapper-core: Wrapper QUPv3 core containing this I2C controller.

Optional property:
 - qcom,clk-freq-out : Desired I2C bus clock frequency in Hz.
   When missing default to 400000Hz.

Child nodes should conform to i2c bus binding.

Example:
@@ -32,4 +36,5 @@ i2c@a94000 {
	#address-cells = <1>;
	#size-cells = <0>;
	qcom,wrapper-core = <&qupv3_0>;
	qcom,clk-freq-out = <400000>;
};
+63 −8
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ struct geni_i2c_dev {
	int cur_rd;
	struct device *wrapper_dev;
	void *ipcl;
	int clk_fld_idx;
};

struct geni_i2c_err_log {
@@ -109,12 +110,52 @@ static struct geni_i2c_err_log gi2c_log[] = {
	[GENI_TIMEOUT] = {-ETIMEDOUT, "I2C TXN timed out"},
};

static inline void qcom_geni_i2c_conf(void __iomem *base, int dfs, int div)
struct geni_i2c_clk_fld {
	u32	clk_freq_out;
	u8	clk_div;
	u8	t_high;
	u8	t_low;
	u8	t_cycle;
};

static struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
	{KHz(100), 7, 10, 11, 26},
	{KHz(400), 2,  5, 12, 24},
	{KHz(1000), 1, 3,  9, 18},
};

static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c)
{
	geni_write_reg(dfs, base, SE_GENI_CLK_SEL);
	geni_write_reg((div << 4) | 1, base, GENI_SER_M_CLK_CFG);
	geni_write_reg(((5 << 20) | (0xC << 10) | 0x18),
				base, SE_I2C_SCL_COUNTERS);
	int i;
	int ret = 0;
	bool clk_map_present = false;
	struct geni_i2c_clk_fld *itr = geni_i2c_clk_map;

	for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) {
		if (itr->clk_freq_out == gi2c->i2c_rsc.clk_freq_out) {
			clk_map_present = true;
			break;
		}
	}

	if (clk_map_present)
		gi2c->clk_fld_idx = i;
	else
		ret = -EINVAL;

	return ret;
}

static inline void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c, int dfs)
{
	struct geni_i2c_clk_fld *itr = geni_i2c_clk_map + gi2c->clk_fld_idx;

	geni_write_reg(dfs, gi2c->base, SE_GENI_CLK_SEL);

	geni_write_reg((itr->clk_div << 4) | 1, gi2c->base, GENI_SER_M_CLK_CFG);
	geni_write_reg(((itr->t_high << 20) | (itr->t_low << 10) |
			itr->t_cycle), gi2c->base, SE_I2C_SCL_COUNTERS);

	/*
	* Ensure Clk config completes before return.
	*/
@@ -283,7 +324,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
		pm_runtime_set_suspended(gi2c->dev);
		return ret;
	}
	qcom_geni_i2c_conf(gi2c->base, 0, 2);
	qcom_geni_i2c_conf(gi2c, 0);
	dev_dbg(gi2c->dev, "i2c xfer:num:%d, msgs:len:%d,flg:%d\n",
				num, msgs[0].len, msgs[0].flags);
	for (i = 0; i < num; i++) {
@@ -485,12 +526,26 @@ static int geni_i2c_probe(struct platform_device *pdev)
		return ret;
	}

	if (of_property_read_u32(pdev->dev.of_node, "qcom,clk-freq-out",
				&gi2c->i2c_rsc.clk_freq_out)) {
		dev_info(&pdev->dev,
			"Bus frequency not specified, default to 400KHz.\n");
		gi2c->i2c_rsc.clk_freq_out = KHz(400);
	}

	gi2c->irq = platform_get_irq(pdev, 0);
	if (gi2c->irq < 0) {
		dev_err(gi2c->dev, "IRQ error for i2c-geni\n");
		return gi2c->irq;
	}

	ret = geni_i2c_clk_map_idx(gi2c);
	if (ret) {
		dev_err(gi2c->dev, "Invalid clk frequency %d KHz: %d\n",
				gi2c->i2c_rsc.clk_freq_out, ret);
		return ret;
	}

	gi2c->adap.algo = &geni_i2c_algo;
	init_completion(&gi2c->xfer);
	platform_set_drvdata(pdev, gi2c);
+3 −0
Original line number Diff line number Diff line
@@ -64,11 +64,14 @@ struct se_geni_rsc {
	struct pinctrl *geni_pinctrl;
	struct pinctrl_state *geni_gpio_active;
	struct pinctrl_state *geni_gpio_sleep;
	int	clk_freq_out;
};

#define PINCTRL_DEFAULT	"default"
#define PINCTRL_SLEEP	"sleep"

#define KHz(freq) (1000 * (freq))

/* Common SE registers */
#define GENI_INIT_CFG_REVISION		(0x0)
#define GENI_S_INIT_CFG_REVISION	(0x4)