All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188
@ 2018-02-26 17:42 Alexander Kochetkov
  2018-02-26 20:26 ` Dr. Philipp Tomsich
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Alexander Kochetkov @ 2018-02-26 17:42 UTC (permalink / raw)
  To: u-boot

rk3066 and rk3188 has two I2C controller implementations.
Current I2C driver wan't work with legacy implementation.
Switching between controllers is performed using a bit inside
GFR_SOC_CON1 register. The bit setting is performed by pinctrl
driver. The patch ask pinctrl to do settings.

Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 drivers/i2c/rk_i2c.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
index 332280c..ce6b441 100644
--- a/drivers/i2c/rk_i2c.c
+++ b/drivers/i2c/rk_i2c.c
@@ -34,6 +34,18 @@ struct rk_i2c {
 	unsigned int speed;
 };
 
+enum {
+	RK_I2C_LEGACY,
+	RK_I2C_NEW,
+};
+
+/**
+ * @controller_type: i2c controller type
+ */
+struct rk_i2c_soc_data {
+	int controller_type;
+};
+
 static inline void rk_i2c_get_div(int div, int *divh, int *divl)
 {
 	*divl = div / 2;
@@ -381,9 +393,38 @@ static int rockchip_i2c_ofdata_to_platdata(struct udevice *bus)
 static int rockchip_i2c_probe(struct udevice *bus)
 {
 	struct rk_i2c *priv = dev_get_priv(bus);
+	struct rk_i2c_soc_data *soc_data;
+	struct udevice *pinctrl;
+	int bus_nr;
+	int ret;
 
 	priv->regs = dev_read_addr_ptr(bus);
 
+	soc_data = (struct rk_i2c_soc_data*)dev_get_driver_data(bus);
+
+	if (soc_data->controller_type == RK_I2C_LEGACY) {
+		ret = dev_read_alias_seq(bus, &bus_nr);
+		if (ret < 0) {
+			debug("%s: Could not get alias for %s: %d\n",
+			 __func__, bus->name, ret);
+			return ret;
+		}
+
+		ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+		if (ret) {
+			debug("%s: Cannot find pinctrl device\n", __func__);
+			return ret;
+		}
+
+		/* pinctrl will switch I2C to new type */
+		ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_I2C0 + bus_nr);
+		if (ret) {
+			debug("%s: Failed to switch I2C to new type %s: %d\n",
+				__func__, bus->name, ret);
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
@@ -392,12 +433,51 @@ static const struct dm_i2c_ops rockchip_i2c_ops = {
 	.set_bus_speed	= rockchip_i2c_set_bus_speed,
 };
 
+static const struct rk_i2c_soc_data rk3066_soc_data = {
+	.controller_type = RK_I2C_LEGACY,
+};
+
+static const struct rk_i2c_soc_data rk3188_soc_data = {
+	.controller_type = RK_I2C_LEGACY,
+};
+
+static const struct rk_i2c_soc_data rk3228_soc_data = {
+	.controller_type = RK_I2C_NEW,
+};
+
+static const struct rk_i2c_soc_data rk3288_soc_data = {
+	.controller_type = RK_I2C_NEW,
+};
+
+static const struct rk_i2c_soc_data rk3328_soc_data = {
+	.controller_type = RK_I2C_NEW,
+};
+
+static const struct rk_i2c_soc_data rk3399_soc_data = {
+	.controller_type = RK_I2C_NEW,
+};
+
 static const struct udevice_id rockchip_i2c_ids[] = {
-	{ .compatible = "rockchip,rk3066-i2c" },
-	{ .compatible = "rockchip,rk3188-i2c" },
-	{ .compatible = "rockchip,rk3288-i2c" },
-	{ .compatible = "rockchip,rk3328-i2c" },
-	{ .compatible = "rockchip,rk3399-i2c" },
+	{
+		.compatible = "rockchip,rk3066-i2c",
+		.data = (ulong)&rk3066_soc_data,
+	},
+	{
+		.compatible = "rockchip,rk3188-i2c",
+		.data = (ulong)&rk3188_soc_data,
+	},
+	{
+		.compatible = "rockchip,rk3288-i2c",
+		.data = (ulong)&rk3288_soc_data,
+	},
+	{
+		.compatible = "rockchip,rk3328-i2c",
+		.data = (ulong)&rk3328_soc_data,
+	},
+	{
+		.compatible = "rockchip,rk3399-i2c",
+		.data = (ulong)&rk3399_soc_data,
+	},
 	{ }
 };
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188
  2018-02-26 17:42 [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188 Alexander Kochetkov
@ 2018-02-26 20:26 ` Dr. Philipp Tomsich
  2018-02-26 21:48   ` Alexander Kochetkov
  2018-03-18 16:12 ` [U-Boot] [U-Boot, " Philipp Tomsich
  2018-07-13 10:25 ` Philipp Tomsich
  2 siblings, 1 reply; 5+ messages in thread
From: Dr. Philipp Tomsich @ 2018-02-26 20:26 UTC (permalink / raw)
  To: u-boot

Alexander,

Sorry for being a bother.  See below for two comments.

Cheers,
Phil.

> On 26 Feb 2018, at 18:42, Alexander Kochetkov <al.kochet@gmail.com> wrote:
> 
> rk3066 and rk3188 has two I2C controller implementations.
> Current I2C driver wan't work with legacy implementation.
> Switching between controllers is performed using a bit inside
> GFR_SOC_CON1 register. The bit setting is performed by pinctrl
> driver. The patch ask pinctrl to do settings.
> 
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> ---
> drivers/i2c/rk_i2c.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 85 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
> index 332280c..ce6b441 100644
> --- a/drivers/i2c/rk_i2c.c
> +++ b/drivers/i2c/rk_i2c.c
> @@ -34,6 +34,18 @@ struct rk_i2c {
> 	unsigned int speed;
> };
> 
> +enum {
> +	RK_I2C_LEGACY,
> +	RK_I2C_NEW,
> +};
> +
> +/**
> + * @controller_type: i2c controller type
> + */
> +struct rk_i2c_soc_data {
> +	int controller_type;
> +};
> +
> static inline void rk_i2c_get_div(int div, int *divh, int *divl)
> {
> 	*divl = div / 2;
> @@ -381,9 +393,38 @@ static int rockchip_i2c_ofdata_to_platdata(struct udevice *bus)
> static int rockchip_i2c_probe(struct udevice *bus)
> {
> 	struct rk_i2c *priv = dev_get_priv(bus);
> +	struct rk_i2c_soc_data *soc_data;
> +	struct udevice *pinctrl;
> +	int bus_nr;
> +	int ret;
> 
> 	priv->regs = dev_read_addr_ptr(bus);
> 
> +	soc_data = (struct rk_i2c_soc_data*)dev_get_driver_data(bus);
> +
> +	if (soc_data->controller_type == RK_I2C_LEGACY) {

This should be safe both from legacy and new variants.

> +		ret = dev_read_alias_seq(bus, &bus_nr);
> +		if (ret < 0) {
> +			debug("%s: Could not get alias for %s: %d\n",
> +			 __func__, bus->name, ret);
> +			return ret;
> +		}
> +
> +		ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> +		if (ret) {
> +			debug("%s: Cannot find pinctrl device\n", __func__);
> +			return ret;
> +		}
> +
> +		/* pinctrl will switch I2C to new type */
> +		ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_I2C0 + bus_nr);
> +		if (ret) {
> +			debug("%s: Failed to switch I2C to new type %s: %d\n",
> +				__func__, bus->name, ret);
> +			return ret;
> +		}

I wonder if this is really necessary (or if there’s something going wrong in the
device framework)…  The way I always understood our device framework was
that if there’s a pinctrl associated with the DTS node, then it should get processed
automatically during probing.

See the following in drivers/core/device.c:

        /*
         * Process pinctrl for everything except the root device, and
         * continue regardless of the result of pinctrl. Don't process pinctrl
         * settings for pinctrl devices since the device may not yet be
         * probed.
         */
        if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
                pinctrl_select_state(dev, "default");


> +	}
> +
> 	return 0;
> }
> 
> @@ -392,12 +433,51 @@ static const struct dm_i2c_ops rockchip_i2c_ops = {
> 	.set_bus_speed	= rockchip_i2c_set_bus_speed,
> };
> 
> +static const struct rk_i2c_soc_data rk3066_soc_data = {
> +	.controller_type = RK_I2C_LEGACY,
> +};
> +
> +static const struct rk_i2c_soc_data rk3188_soc_data = {
> +	.controller_type = RK_I2C_LEGACY,
> +};
> +
> +static const struct rk_i2c_soc_data rk3228_soc_data = {
> +	.controller_type = RK_I2C_NEW,
> +};
> +
> +static const struct rk_i2c_soc_data rk3288_soc_data = {
> +	.controller_type = RK_I2C_NEW,
> +};
> +
> +static const struct rk_i2c_soc_data rk3328_soc_data = {
> +	.controller_type = RK_I2C_NEW,
> +};
> +
> +static const struct rk_i2c_soc_data rk3399_soc_data = {
> +	.controller_type = RK_I2C_NEW,
> +};
> +
> static const struct udevice_id rockchip_i2c_ids[] = {
> -	{ .compatible = "rockchip,rk3066-i2c" },
> -	{ .compatible = "rockchip,rk3188-i2c" },
> -	{ .compatible = "rockchip,rk3288-i2c" },
> -	{ .compatible = "rockchip,rk3328-i2c" },
> -	{ .compatible = "rockchip,rk3399-i2c" },
> +	{
> +		.compatible = "rockchip,rk3066-i2c",
> +		.data = (ulong)&rk3066_soc_data,
> +	},
> +	{
> +		.compatible = "rockchip,rk3188-i2c",
> +		.data = (ulong)&rk3188_soc_data,
> +	},
> +	{
> +		.compatible = "rockchip,rk3288-i2c",
> +		.data = (ulong)&rk3288_soc_data,
> +	},
> +	{
> +		.compatible = "rockchip,rk3328-i2c",
> +		.data = (ulong)&rk3328_soc_data,
> +	},
> +	{
> +		.compatible = "rockchip,rk3399-i2c",
> +		.data = (ulong)&rk3399_soc_data,
> +	},
> 	{ }
> };
> 
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188
  2018-02-26 20:26 ` Dr. Philipp Tomsich
@ 2018-02-26 21:48   ` Alexander Kochetkov
  0 siblings, 0 replies; 5+ messages in thread
From: Alexander Kochetkov @ 2018-02-26 21:48 UTC (permalink / raw)
  To: u-boot


> 26 февр. 2018 г., в 23:26, Dr. Philipp Tomsich <philipp.tomsich@theobroma-systems.com> написал(а):
> 
> I wonder if this is really necessary (or if there’s something going wrong in the
> device framework)…  The way I always understood our device framework was
> that if there’s a pinctrl associated with the DTS node, then it should get processed
> automatically during probing.

RKI2C0_SEL, RKI2C1_SEL and so on bits get updated by pinctrl_rk3188_i2c_config()
(drivers/pinctrl/rockchip/pinctrl_rk3188.c). The function is called by rk3188_pinctrl_request()
(rk3188 pinmux request method implementation) and by rk3188_pinctrl_set_state_simple()
(rk3188 pinmux set_state_simple implementation).

If CONFIG_PINCTRL_FULL is enabled, than pinctrl_select_state_full() will be used
by framework code to setup pinmux. It read pin description from DT and setup pins
using rk3188_pinctrl_set_state() (set_state implementation). rk3188_pinctrl_set_state()
doesn't update soc_con1 register.

If CONFIG_PINCTRL_FULL is not enabled, then pinctrl_select_state_simple() will be
used instead by framework code to setup pinmux. It do rk3188_pinctrl_set_state_simple()
request to pinmux driver which in turn calls pinctrl_rk3188_i2c_config().

In my code I do call to pinctrl_rk3188_i2c_config() using rk3188_pinctrl_request().

Regards,
Alexander.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [U-Boot, v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188
  2018-02-26 17:42 [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188 Alexander Kochetkov
  2018-02-26 20:26 ` Dr. Philipp Tomsich
@ 2018-03-18 16:12 ` Philipp Tomsich
  2018-07-13 10:25 ` Philipp Tomsich
  2 siblings, 0 replies; 5+ messages in thread
From: Philipp Tomsich @ 2018-03-18 16:12 UTC (permalink / raw)
  To: u-boot

> rk3066 and rk3188 has two I2C controller implementations.
> Current I2C driver wan't work with legacy implementation.
> Switching between controllers is performed using a bit inside
> GFR_SOC_CON1 register. The bit setting is performed by pinctrl
> driver. The patch ask pinctrl to do settings.
> 
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> ---
>  drivers/i2c/rk_i2c.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 85 insertions(+), 5 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [U-Boot, v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188
  2018-02-26 17:42 [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188 Alexander Kochetkov
  2018-02-26 20:26 ` Dr. Philipp Tomsich
  2018-03-18 16:12 ` [U-Boot] [U-Boot, " Philipp Tomsich
@ 2018-07-13 10:25 ` Philipp Tomsich
  2 siblings, 0 replies; 5+ messages in thread
From: Philipp Tomsich @ 2018-07-13 10:25 UTC (permalink / raw)
  To: u-boot

> rk3066 and rk3188 has two I2C controller implementations.
> Current I2C driver wan't work with legacy implementation.
> Switching between controllers is performed using a bit inside
> GFR_SOC_CON1 register. The bit setting is performed by pinctrl
> driver. The patch ask pinctrl to do settings.
> 
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
>  drivers/i2c/rk_i2c.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 85 insertions(+), 5 deletions(-)
> 

Applied to u-boot-rockchip, thanks!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-07-13 10:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-26 17:42 [U-Boot] [PATCH v2] rockchip: i2c: enable new I2C controller for rk3066 and rk3188 Alexander Kochetkov
2018-02-26 20:26 ` Dr. Philipp Tomsich
2018-02-26 21:48   ` Alexander Kochetkov
2018-03-18 16:12 ` [U-Boot] [U-Boot, " Philipp Tomsich
2018-07-13 10:25 ` Philipp Tomsich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.