[U-Boot] [PATCH v2] i2c: designware: Get clock rate from clock DM

Simon Goldschmidt simon.k.r.goldschmidt at gmail.com
Mon Jun 24 19:51:12 UTC 2019


Am 12.06.2019 um 03:48 schrieb Ley Foon Tan:
> Get clock rate from clock DM if CONFIG_CLK is enabled.
> Otherwise, uses IC_CLK define.
> 
> Signed-off-by: Ley Foon Tan <ley.foon.tan at intel.com>
> Acked-by: Marek Vasut <marex at denx.de>

Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>

> 
> ---
> v2:
> - Changed u32 to unsigned int for bus_mhz.
> - Added ACK from Marek
> ---
>   drivers/i2c/designware_i2c.c | 55 +++++++++++++++++++++++++++++-------
>   1 file changed, 45 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index 9ccc2411a6..606891fc2f 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -4,6 +4,7 @@
>    * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.com.
>    */
>   
> +#include <clk.h>
>   #include <common.h>
>   #include <dm.h>
>   #include <i2c.h>
> @@ -35,6 +36,9 @@ struct dw_i2c {
>   	struct i2c_regs *regs;
>   	struct dw_scl_sda_cfg *scl_sda_cfg;
>   	struct reset_ctl_bulk resets;
> +#if CONFIG_IS_ENABLED(CLK)
> +	struct clk clk;
> +#endif
>   };
>   
>   #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
> @@ -78,7 +82,8 @@ static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
>    */
>   static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   					   struct dw_scl_sda_cfg *scl_sda_cfg,
> -					   unsigned int speed)
> +					   unsigned int speed,
> +					   unsigned int bus_mhz)
>   {
>   	unsigned int cntl;
>   	unsigned int hcnt, lcnt;
> @@ -104,8 +109,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   			hcnt = scl_sda_cfg->fs_hcnt;
>   			lcnt = scl_sda_cfg->fs_lcnt;
>   		} else {
> -			hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
> -			lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
> +			hcnt = (bus_mhz * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (bus_mhz * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		}
>   		writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
>   		writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
> @@ -118,8 +123,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   			hcnt = scl_sda_cfg->ss_hcnt;
>   			lcnt = scl_sda_cfg->ss_lcnt;
>   		} else {
> -			hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
> -			lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
> +			hcnt = (bus_mhz * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (bus_mhz * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		}
>   		writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
>   		writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
> @@ -132,8 +137,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   			hcnt = scl_sda_cfg->fs_hcnt;
>   			lcnt = scl_sda_cfg->fs_lcnt;
>   		} else {
> -			hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
> -			lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
> +			hcnt = (bus_mhz * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (bus_mhz * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		}
>   		writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
>   		writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
> @@ -388,7 +393,7 @@ static int __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
>   	writel(IC_TX_TL, &i2c_base->ic_tx_tl);
>   	writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
>   #ifndef CONFIG_DM_I2C
> -	__dw_i2c_set_bus_speed(i2c_base, NULL, speed);
> +	__dw_i2c_set_bus_speed(i2c_base, NULL, speed, IC_CLK);
>   	writel(slaveaddr, &i2c_base->ic_sar);
>   #endif
>   
> @@ -433,7 +438,7 @@ static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
>   					 unsigned int speed)
>   {
>   	adap->speed = speed;
> -	return __dw_i2c_set_bus_speed(i2c_get_base(adap), NULL, speed);
> +	return __dw_i2c_set_bus_speed(i2c_get_base(adap), NULL, speed, IC_CLK);
>   }
>   
>   static void dw_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
> @@ -523,8 +528,20 @@ static int designware_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
>   static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
>   {
>   	struct dw_i2c *i2c = dev_get_priv(bus);
> +	ulong rate;
> +
> +#if CONFIG_IS_ENABLED(CLK)
> +	rate = clk_get_rate(&i2c->clk);
> +	if (IS_ERR_VALUE(rate))
> +		return -EINVAL;
>   
> -	return __dw_i2c_set_bus_speed(i2c->regs, i2c->scl_sda_cfg, speed);
> +	/* Convert to MHz */
> +	rate /= 1000000;
> +#else
> +	rate = IC_CLK;
> +#endif
> +	return __dw_i2c_set_bus_speed(i2c->regs, i2c->scl_sda_cfg, speed,
> +				      rate);
>   }
>   
>   static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> @@ -568,6 +585,19 @@ static int designware_i2c_probe(struct udevice *bus)
>   	else
>   		reset_deassert_bulk(&priv->resets);
>   
> +#if CONFIG_IS_ENABLED(CLK)
> +	ret = clk_get_by_index(bus, 0, &priv->clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_enable(&priv->clk);
> +	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
> +		clk_free(&priv->clk);
> +		dev_err(bus, "failed to enable clock\n");
> +		return ret;
> +	}
> +#endif
> +
>   	return __dw_i2c_init(priv->regs, 0, 0);
>   }
>   
> @@ -575,6 +605,11 @@ static int designware_i2c_remove(struct udevice *dev)
>   {
>   	struct dw_i2c *priv = dev_get_priv(dev);
>   
> +#if CONFIG_IS_ENABLED(CLK)
> +	clk_disable(&priv->clk);
> +	clk_free(&priv->clk);
> +#endif
> +
>   	return reset_release_bulk(&priv->resets);
>   }
>   
> 



More information about the U-Boot mailing list