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

Commit b720423a authored by Nguyen Viet Dung's avatar Nguyen Viet Dung Committed by Wolfram Sang
Browse files

i2c: rcar: add rcar-H2 support



This patch modify I2C driver of rcar-H1 to usable on both rcar-H1 and rcar-H2.

Signed-off-by: default avatarNguyen Viet Dung <nv-dung@jinso.co.jp>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 617da00c
Loading
Loading
Loading
Loading
+33 −2
Original line number Original line Diff line number Diff line
@@ -101,6 +101,11 @@ enum {
#define ID_ARBLOST	(1 << 3)
#define ID_ARBLOST	(1 << 3)
#define ID_NACK		(1 << 4)
#define ID_NACK		(1 << 4)


enum rcar_i2c_type {
	I2C_RCAR_H1,
	I2C_RCAR_H2,
};

struct rcar_i2c_priv {
struct rcar_i2c_priv {
	void __iomem *io;
	void __iomem *io;
	struct i2c_adapter adap;
	struct i2c_adapter adap;
@@ -113,6 +118,7 @@ struct rcar_i2c_priv {
	int irq;
	int irq;
	u32 icccr;
	u32 icccr;
	u32 flags;
	u32 flags;
	enum rcar_i2c_type	devtype;
};
};


#define rcar_i2c_priv_to_dev(p)		((p)->adap.dev.parent)
#define rcar_i2c_priv_to_dev(p)		((p)->adap.dev.parent)
@@ -224,12 +230,25 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
	u32 scgd, cdf;
	u32 scgd, cdf;
	u32 round, ick;
	u32 round, ick;
	u32 scl;
	u32 scl;
	u32 cdf_width;


	if (!clkp) {
	if (!clkp) {
		dev_err(dev, "there is no peripheral_clk\n");
		dev_err(dev, "there is no peripheral_clk\n");
		return -EIO;
		return -EIO;
	}
	}


	switch (priv->devtype) {
	case I2C_RCAR_H1:
		cdf_width = 2;
		break;
	case I2C_RCAR_H2:
		cdf_width = 3;
		break;
	default:
		dev_err(dev, "device type error\n");
		return -EIO;
	}

	/*
	/*
	 * calculate SCL clock
	 * calculate SCL clock
	 * see
	 * see
@@ -245,7 +264,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
	 * clkp : peripheral_clk
	 * clkp : peripheral_clk
	 * F[]  : integer up-valuation
	 * F[]  : integer up-valuation
	 */
	 */
	for (cdf = 0; cdf < 4; cdf++) {
	for (cdf = 0; cdf < (1 << cdf_width); cdf++) {
		ick = clk_get_rate(clkp) / (1 + cdf);
		ick = clk_get_rate(clkp) / (1 + cdf);
		if (ick < 20000000)
		if (ick < 20000000)
			goto ick_find;
			goto ick_find;
@@ -287,7 +306,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
	/*
	/*
	 * keep icccr value
	 * keep icccr value
	 */
	 */
	priv->icccr = (scgd << 2 | cdf);
	priv->icccr = (scgd << (cdf_width) | cdf);


	return 0;
	return 0;
}
}
@@ -632,6 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
	bus_speed = 100000; /* default 100 kHz */
	bus_speed = 100000; /* default 100 kHz */
	if (pdata && pdata->bus_speed)
	if (pdata && pdata->bus_speed)
		bus_speed = pdata->bus_speed;
		bus_speed = pdata->bus_speed;

	priv->devtype = platform_get_device_id(pdev)->driver_data;

	ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
	ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;
@@ -686,6 +708,14 @@ static int rcar_i2c_remove(struct platform_device *pdev)
	return 0;
	return 0;
}
}


static struct platform_device_id rcar_i2c_id_table[] = {
	{ "i2c-rcar",		I2C_RCAR_H1 },
	{ "i2c-rcar_h1",	I2C_RCAR_H1 },
	{ "i2c-rcar_h2",	I2C_RCAR_H2 },
	{},
};
MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table);

static struct platform_driver rcar_i2c_driver = {
static struct platform_driver rcar_i2c_driver = {
	.driver	= {
	.driver	= {
		.name	= "i2c-rcar",
		.name	= "i2c-rcar",
@@ -693,6 +723,7 @@ static struct platform_driver rcar_i2c_driver = {
	},
	},
	.probe		= rcar_i2c_probe,
	.probe		= rcar_i2c_probe,
	.remove		= rcar_i2c_remove,
	.remove		= rcar_i2c_remove,
	.id_table	= rcar_i2c_id_table,
};
};


module_platform_driver(rcar_i2c_driver);
module_platform_driver(rcar_i2c_driver);