diff options
author | Alexander Kochetkov <al.kochet@gmail.com> | 2018-02-26 20:42:54 +0300 |
---|---|---|
committer | Philipp Tomsich <philipp.tomsich@theobroma-systems.com> | 2018-07-21 01:55:25 +0200 |
commit | 5944bd9a25291560405e5d86612a75a6791acf23 (patch) | |
tree | 4ac8ac2eef0e04582b83ff66df3bbf504fad6342 | |
parent | 0dd1fc09bb16869fd8adaaad082cd554c60b2c1a (diff) |
rockchip: i2c: enable i2c controller for rk3066 and rk3188
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>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
[fix warnings by including the rk3228 variant in the compatible-list]:
Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
-rw-r--r-- | drivers/i2c/rk_i2c.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 001af668a8..f9a5796b96 100644 --- a/drivers/i2c/rk_i2c.c +++ b/drivers/i2c/rk_i2c.c @@ -31,6 +31,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; @@ -378,9 +390,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; } @@ -389,12 +430,55 @@ 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,rk3228-i2c", + .data = (ulong)&rk3228_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, + }, { } }; |