diff options
| author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2013-03-15 20:50:43 +0100 | 
|---|---|---|
| committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2013-03-15 20:50:43 +0100 | 
| commit | b27673ccbd3d5435319b5c09c3e7061f559f925d (patch) | |
| tree | 24c58f5a1e950ec107f40690032ac89c62d3ad83 /drivers/i2c/tegra_i2c.c | |
| parent | 6579d15c58e2b6b051f126ea8b77dd767252aa14 (diff) | |
| parent | 477393e7875cf4261f107fdfb8887309ea7fc3f7 (diff) | |
| download | olio-uboot-2014.01-b27673ccbd3d5435319b5c09c3e7061f559f925d.tar.xz olio-uboot-2014.01-b27673ccbd3d5435319b5c09c3e7061f559f925d.zip | |
Merge branch 'u-boot-tegra/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers/i2c/tegra_i2c.c')
| -rw-r--r-- | drivers/i2c/tegra_i2c.c | 42 | 
1 files changed, 37 insertions, 5 deletions
| diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c index efc77fa91..ca71cd3ee 100644 --- a/drivers/i2c/tegra_i2c.c +++ b/drivers/i2c/tegra_i2c.c @@ -46,6 +46,7 @@ struct i2c_bus {  	struct i2c_control	*control;  	struct i2c_ctlr		*regs;  	int			is_dvc;	/* DVC type, rather than I2C */ +	int			is_scs;	/* single clock source (T114+) */  	int			inited;	/* bus is inited */  }; @@ -88,7 +89,28 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)  	 * 16 to get the right frequency.  	 */  	clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH, -			       i2c_bus->speed * 2 * 8); +		i2c_bus->speed * 2 * 8); + +	if (i2c_bus->is_scs) { +		/* +		 * T114 I2C went to a single clock source for standard/fast and +		 * HS clock speeds. The new clock rate setting calculation is: +		 *  SCL = CLK_SOURCE.I2C / +		 *   (CLK_MULT_STD_FAST_MODE * (I2C_CLK_DIV_STD_FAST_MODE+1) * +		 *   I2C FREQUENCY DIVISOR) as per the T114 TRM (sec 30.3.1). +		 * +		 * NOTE: We do this here, after the initial clock/pll start, +		 * because if we read the clk_div reg before the controller +		 * is running, we hang, and we need it for the new calc. +		 */ +		int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16; +		debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__, +			clk_div_stdfst_mode); + +		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); +	}  	/* Reset I2C controller. */  	i2c_reset_controller(i2c_bus); @@ -352,10 +374,11 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)   * @param node_list	list of nodes to process (any <=0 are ignored)   * @param count		number of nodes to process   * @param is_dvc	1 if these are DVC ports, 0 if standard I2C + * @param is_scs	1 if this HW uses a single clock source (T114+)   * @return 0 if ok, -1 on error   */  static int process_nodes(const void *blob, int node_list[], int count, -			 int is_dvc) +			 int is_dvc, int is_scs)  {  	struct i2c_bus *i2c_bus;  	int i; @@ -375,6 +398,8 @@ static int process_nodes(const void *blob, int node_list[], int count,  			return -1;  		} +		i2c_bus->is_scs = is_scs; +  		i2c_bus->is_dvc = is_dvc;  		if (is_dvc) {  			i2c_bus->control = @@ -403,18 +428,25 @@ void i2c_init_board(void)  	const void *blob = gd->fdt_blob;  	int count; -	/* First get the normal i2c ports */ +	/* First check for newer (T114+) I2C ports */ +	count = fdtdec_find_aliases_for_id(blob, "i2c", +			COMPAT_NVIDIA_TEGRA114_I2C, node_list, +			TEGRA_I2C_NUM_CONTROLLERS); +	if (process_nodes(blob, node_list, count, 0, 1)) +		return; + +	/* Now get the older (T20/T30) normal I2C ports */  	count = fdtdec_find_aliases_for_id(blob, "i2c",  			COMPAT_NVIDIA_TEGRA20_I2C, node_list,  			TEGRA_I2C_NUM_CONTROLLERS); -	if (process_nodes(blob, node_list, count, 0)) +	if (process_nodes(blob, node_list, count, 0, 0))  		return;  	/* Now look for dvc ports */  	count = fdtdec_add_aliases_for_id(blob, "i2c",  			COMPAT_NVIDIA_TEGRA20_DVC, node_list,  			TEGRA_I2C_NUM_CONTROLLERS); -	if (process_nodes(blob, node_list, count, 1)) +	if (process_nodes(blob, node_list, count, 1, 0))  		return;  } |