[U-Boot] [PATCH 3/5] i2c: tegra: add standardized clk/reset API support
Simon Glass
sjg at chromium.org
Mon Aug 1 03:02:38 CEST 2016
Hi Stephen,
On 27 July 2016 at 15:48, Stephen Warren <swarren at wwwdotorg.org> wrote:
> From: Bryan Wu <pengw at nvidia.com>
>
> clk/reset API was tested on T186 platform and previous chip like
> T210/T124 will still use the old APIs.
>
> Signed-off-by: Bryan Wu <pengw at nvidia.com>
> (swarren, simplified some ifdefs, removed indent level inside an ifdef)
> Signed-off-by: Stephen Warren <swarren at nvidia.com>
> Cc: Heiko Schocher <hs at denx.de>
> ---
> drivers/i2c/tegra_i2c.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 76 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
> index 2fa07f9c57c4..b8cb24ec87d5 100644
> --- a/drivers/i2c/tegra_i2c.c
> +++ b/drivers/i2c/tegra_i2c.c
> @@ -12,11 +12,16 @@
> #include <fdtdec.h>
> #include <i2c.h>
> #include <asm/io.h>
> +#ifdef CONFIG_TEGRA186
> +#include <clk.h>
> +#include <reset.h>
> +#else
> #include <asm/arch/clock.h>
> #include <asm/arch/funcmux.h>
> -#include <asm/arch/gpio.h>
> #include <asm/arch/pinmux.h>
> #include <asm/arch-tegra/clk_rst.h>
> +#endif
> +#include <asm/arch/gpio.h>
> #include <asm/arch-tegra/tegra_i2c.h>
>
> DECLARE_GLOBAL_DATA_PTR;
> @@ -30,7 +35,12 @@ enum i2c_type {
> /* Information about i2c controller */
> struct i2c_bus {
> int id;
> +#ifdef CONFIG_TEGRA186
> + struct reset_ctl reset_ctl;
> + struct clk clk;
> +#else
> enum periph_id periph_id;
> +#endif
This doesn't seem right - the drivers should be SoC-independent at compile-time.
> int speed;
> int pinmux_config;
> struct i2c_control *control;
> @@ -62,12 +72,41 @@ static void set_packet_mode(struct i2c_bus *i2c_bus)
> static void i2c_reset_controller(struct i2c_bus *i2c_bus)
> {
> /* Reset I2C controller. */
> +#ifdef CONFIG_TEGRA186
> + reset_assert(&i2c_bus->reset_ctl);
> + udelay(1);
> + reset_deassert(&i2c_bus->reset_ctl);
> + udelay(1);
> +#else
> reset_periph(i2c_bus->periph_id, 1);
> +#endif
>
> /* re-program config register to packet mode */
> set_packet_mode(i2c_bus);
> }
>
> +#ifdef CONFIG_TEGRA186
> +static int i2c_init_clock(struct i2c_bus *i2c_bus, unsigned rate)
> +{
> + int ret;
> +
> + ret = reset_assert(&i2c_bus->reset_ctl);
> + if (ret)
> + return ret;
> + ret = clk_enable(&i2c_bus->clk);
> + if (ret)
> + return ret;
> + ret = clk_set_rate(&i2c_bus->clk, rate);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> + ret = reset_deassert(&i2c_bus->reset_ctl);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +#endif
> +
> static void i2c_init_controller(struct i2c_bus *i2c_bus)
> {
> if (!i2c_bus->speed)
> @@ -78,8 +117,12 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
> * here, in section 23.3.1, but in fact we seem to need a factor of
> * 16 to get the right frequency.
> */
> +#ifdef CONFIG_TEGRA186
> + i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);
> +#else
> clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
> i2c_bus->speed * 2 * 8);
> +#endif
>
> if (i2c_bus->type == TYPE_114) {
> /*
> @@ -94,12 +137,17 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
> * is running, we hang, and we need it for the new calc.
> */
> int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
> + unsigned rate = CLK_MULT_STD_FAST_MODE *
> + (clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
> debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
> clk_div_stdfst_mode);
>
> +#ifdef CONFIG_TEGRA186
> + i2c_init_clock(i2c_bus, rate);
> +#else
> clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
> - CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) *
> - i2c_bus->speed * 2);
> + rate);
> +#endif
> }
>
> /* Reset I2C controller. */
> @@ -112,7 +160,9 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
> setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
> }
>
> +#ifndef CONFIG_TEGRA186
> funcmux_select(i2c_bus->periph_id, i2c_bus->pinmux_config);
> +#endif
> }
>
> static void send_packet_headers(
> @@ -333,8 +383,12 @@ static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
> static int tegra_i2c_probe(struct udevice *dev)
> {
> struct i2c_bus *i2c_bus = dev_get_priv(dev);
> +#ifdef CONFIG_TEGRA186
> + int ret;
> +#else
> const void *blob = gd->fdt_blob;
> int node = dev->of_offset;
> +#endif
> bool is_dvc;
>
> i2c_bus->id = dev->seq;
> @@ -345,6 +399,18 @@ static int tegra_i2c_probe(struct udevice *dev)
> * We don't have a binding for pinmux yet. Leave it out for now. So
> * far no one needs anything other than the default.
> */
> +#ifdef CONFIG_TEGRA186
> + ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
> + if (ret) {
> + error("reset_get_by_name() failed: %d\n", ret);
> + return ret;
> + }
> + ret = clk_get_by_name(dev, "i2c", &i2c_bus->clk);
> + if (ret) {
> + error("clk_get_by_name() failed: %d\n", ret);
> + return ret;
> + }
> +#else
> i2c_bus->pinmux_config = FUNCMUX_DEFAULT;
> i2c_bus->periph_id = clock_decode_periph_id(blob, node);
>
> @@ -359,6 +425,7 @@ static int tegra_i2c_probe(struct udevice *dev)
> */
> if (i2c_bus->periph_id == -1)
> return -EINVAL;
> +#endif
>
> is_dvc = dev_get_driver_data(dev) == TYPE_DVC;
> if (is_dvc) {
> @@ -370,7 +437,12 @@ static int tegra_i2c_probe(struct udevice *dev)
> i2c_init_controller(i2c_bus);
> debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
> is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs,
> - i2c_bus->periph_id, i2c_bus->speed);
> +#ifndef CONFIG_TEGRA186
> + i2c_bus->periph_id,
Probably the concept of periph_id can go away now? Perhaps this driver
needs a clean-up?
> +#else
> + -1,
> +#endif
> + i2c_bus->speed);
>
> return 0;
> }
> --
> 2.9.2
>
Regards,
Simon
More information about the U-Boot
mailing list