From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Mon, 8 Aug 2016 06:15:10 +0200 Subject: [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support In-Reply-To: <20160805221035.12157-3-swarren@wwwdotorg.org> References: <20160805221035.12157-1-swarren@wwwdotorg.org> <20160805221035.12157-3-swarren@wwwdotorg.org> Message-ID: <57A8074E.5030100@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello Stephen, Am 06.08.2016 um 00:10 schrieb Stephen Warren: > From: Bryan Wu > > 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 > (swarren, simplified some ifdefs, removed indent level inside an ifdef) > (swarren, added comment about the ifdefs) > Signed-off-by: Stephen Warren > --- > v2: Add TODO comment describing the messy ifdefs. > --- > drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 85 insertions(+), 4 deletions(-) Reviewed-by: Heiko Schocher bye, Heiko > > diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c > index 2fa07f9c57c4..31ba263b7295 100644 > --- a/drivers/i2c/tegra_i2c.c > +++ b/drivers/i2c/tegra_i2c.c > @@ -12,13 +12,27 @@ > #include > #include > #include > +#ifdef CONFIG_TEGRA186 > +#include > +#include > +#else > #include > #include > -#include > #include > #include > +#endif > +#include > #include > > +/* > + * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that > + * should not be present. These are needed because newer Tegra SoCs support > + * only the standard clock/reset APIs, whereas older Tegra SoCs support only > + * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be > + * fixed to implement the standard APIs, and all drivers converted to solely > + * use the new standard APIs, with no ifdefs. > + */ > + > DECLARE_GLOBAL_DATA_PTR; > > enum i2c_type { > @@ -30,7 +44,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 > int speed; > int pinmux_config; > struct i2c_control *control; > @@ -62,12 +81,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 +126,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 +146,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 +169,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 +392,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 +408,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 +434,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 +446,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, > +#else > + -1, > +#endif > + i2c_bus->speed); > > return 0; > } > -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany