Skip to contentSkip to conversation

mmc: tegra: port to standard clock/reset APIs

PATCH New Stephen Warren 3 participants 7 messages Aug 5, 2016 – Aug 8, 2016

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/3 mmc: tegra: port to standard clock/reset APIs

From: Stephen Warren <[email protected]>

Tegra186 supports the new standard clock and reset APIs. Older Tegra SoCs still use custom APIs. Enhance the Tegra MMC driver so that it can operate with either set of APIs.

---
v2: Add TODO comment describing the messy ifdefs.

---
 arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 +++-
 drivers/mmc/tegra_mmc.c                     | 64 +++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 10 deletions(-)
arch/arm/include/asm/arch-tegra/tegra_mmc.h +7 -1
index 75e56c4ea786..07ef4c04c858 100644
@@ -9,6 +9,9 @@
 #ifndef __TEGRA_MMC_H_
 #define __TEGRA_MMC_H_
 
+#include <common.h>
+#include <clk.h>
+#include <reset.h>
 #include <fdtdec.h>
 #include <asm/gpio.h>
 
@@ -134,7 +137,10 @@ struct mmc_host {
 	int id;			/* device id/number, 0-3 */
 	int enabled;		/* 1 to enable, 0 to disable */
 	int width;		/* Bus Width, 1, 4 or 8 */
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	struct reset_ctl reset_ctl;
+	struct clk clk;
+#else
 	enum periph_id mmc_id;	/* Peripheral ID: PERIPH_ID_... */
 #endif
 	struct gpio_desc cd_gpio;	/* Change Detect GPIO */
drivers/mmc/tegra_mmc.c +55 -9

109 lines not on this page · raw message

Signature · 1 line
2.9.2
#1 lore raw

PATCH v2 2/3 pci: tegra: port to standard clock/reset/pwr domain APIs

From: Stephen Warren <[email protected]>

Tegra186 supports the new standard clock, reset, and power domain APIs. Older Tegra SoCs still use custom APIs. Enhance the Tegra PCIe driver so that it can operate with either set of APIs.

On Tegra186, the BPMP handles all aspects of PCIe PHY (UPHY) programming. Consequently, this logic is disabled too.

---
v2: Add TODO comment describing the messy ifdefs.

---
 drivers/pci/Kconfig     |   1 +
 drivers/pci/pci_tegra.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 159 insertions(+), 5 deletions(-)
drivers/pci/Kconfig +1 -0
index 26aa2b0930a0..669e37bb5dc5 100644
@@ -31,6 +31,7 @@ config PCI_SANDBOX
 config PCI_TEGRA
 	bool "Tegra PCI support"
 	depends on TEGRA
+	depends on (TEGRA186 && POWER_DOMAIN) || (!TEGRA186)
 	help
 	  Enable support for the PCIe controller found on some generations of
 	  Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has
drivers/pci/pci_tegra.c +158 -5

305 lines not on this page · raw message

Signature · 1 line
2.9.2
#2 lore raw

PATCH v2 2/3 pci: tegra: port to standard clock/reset/pwr domain APIs

Quoted 9 lines · Stephen Warren

From: Stephen Warren <[email protected]>

Tegra186 supports the new standard clock, reset, and power domain APIs. Older Tegra SoCs still use custom APIs. Enhance the Tegra PCIe driver so that it can operate with either set of APIs.

On Tegra186, the BPMP handles all aspects of PCIe PHY (UPHY) programming. Consequently, this logic is disabled too.

Quoted 7 lines

---
v2: Add TODO comment describing the messy ifdefs.

---
 drivers/pci/Kconfig     |   1 +
 drivers/pci/pci_tegra.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 159 insertions(+), 5 deletions(-)
#3 lore raw

PATCH v2 3/3 i2c: tegra: add standardized clk/reset API support

In reply to Stephen Warren

From: Bryan Wu <[email protected]>

clk/reset API was tested on T186 platform and previous chip like T210/T124 will still use the old APIs.

(swarren, simplified some ifdefs, removed indent level inside an ifdef) (swarren, added comment about the ifdefs)

---
v2: Add TODO comment describing the messy ifdefs.

---
 drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 4 deletions(-)
drivers/i2c/tegra_i2c.c +85 -4
index 2fa07f9c57c4..31ba263b7295 100644
@@ -12,13 +12,27 @@
 #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>
 
+/*
+ * 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;
 }
Signature · 1 line
2.9.2
#4 lore raw

PATCH v2 3/3 i2c: tegra: add standardized clk/reset API support

Quoted 6 lines · Stephen Warren

From: Bryan Wu <[email protected]>

clk/reset API was tested on T186 platform and previous chip like T210/T124 will still use the old APIs.

Quoted 8 lines

(swarren, simplified some ifdefs, removed indent level inside an ifdef) (swarren, added comment about the ifdefs)

---
v2: Add TODO comment describing the messy ifdefs.

---
 drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 4 deletions(-)
#5 lore raw

PATCH v2 3/3 i2c: tegra: add standardized clk/reset API support

In reply to Stephen Warren

Hello Stephen,

Am 06.08.2016 um 00:10 schrieb Stephen Warren:

Quoted 6 lines

From: Bryan Wu <[email protected]>

clk/reset API was tested on T186 platform and previous chip like T210/T124 will still use the old APIs.

Quoted 8 lines

(swarren, simplified some ifdefs, removed indent level inside an ifdef) (swarren, added comment about the ifdefs)

---
v2: Add TODO comment describing the messy ifdefs.

---
  drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---
  1 file changed, 85 insertions(+), 4 deletions(-)

bye,
Heiko

Quoted 187 lines
drivers/i2c/tegra_i2c.c +85 -4
index 2fa07f9c57c4..31ba263b7295 100644
@@ -12,13 +12,27 @@
  #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>
 
+/*
+ * 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;
  }
Signature · 2 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#6 lore raw

PATCH v2 1/3 mmc: tegra: port to standard clock/reset APIs

In reply to Stephen Warren
Quoted 6 lines · Stephen Warren

From: Stephen Warren <[email protected]>

Tegra186 supports the new standard clock and reset APIs. Older Tegra SoCs still use custom APIs. Enhance the Tegra MMC driver so that it can operate with either set of APIs.

Quoted 7 lines

---
v2: Add TODO comment describing the messy ifdefs.

---
 arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 +++-
 drivers/mmc/tegra_mmc.c                     | 64 +++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 10 deletions(-)