public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs
@ 2016-08-05 22:10 Stephen Warren
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs Stephen Warren
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Stephen Warren @ 2016-08-05 22:10 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

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.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
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(-)

diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index 75e56c4ea786..07ef4c04c858 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -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 */
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index c9d9432e5e87..7a6671e44ae9 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -9,6 +9,7 @@
 
 #include <bouncebuf.h>
 #include <common.h>
+#include <dm/device.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #ifndef CONFIG_TEGRA186
@@ -19,6 +20,15 @@
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.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;
 
 struct mmc_host mmc_host[CONFIG_SYS_MMC_MAX_DEVICE];
@@ -359,11 +369,14 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
 	 */
 	if (clock == 0)
 		goto out;
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	{
+		ulong rate = clk_set_rate(&host->clk, clock);
+		div = (rate + clock - 1) / clock;
+	}
+#else
 	clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock,
 				    &div);
-#else
-	div = (20000000 + clock - 1) / clock;
 #endif
 	debug("div = %d\n", div);
 
@@ -538,6 +551,9 @@ static int do_mmc_init(int dev_index, bool removable)
 {
 	struct mmc_host *host;
 	struct mmc *mmc;
+#ifdef CONFIG_TEGRA186
+	int ret;
+#endif
 
 	/* DT should have been read & host config filled in */
 	host = &mmc_host[dev_index];
@@ -549,7 +565,21 @@ static int do_mmc_init(int dev_index, bool removable)
 	      gpio_get_number(&host->cd_gpio));
 
 	host->clock = 0;
-#ifndef CONFIG_TEGRA186
+
+#ifdef CONFIG_TEGRA186
+	ret = reset_assert(&host->reset_ctl);
+	if (ret)
+		return ret;
+	ret = clk_enable(&host->clk);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(&host->clk, 20000000);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+	ret = reset_deassert(&host->reset_ctl);
+	if (ret)
+		return ret;
+#else
 	clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
 #endif
 
@@ -576,11 +606,7 @@ static int do_mmc_init(int dev_index, bool removable)
 	 *  (actually 52MHz)
 	 */
 	host->cfg.f_min = 375000;
-#ifndef CONFIG_TEGRA186
 	host->cfg.f_max = 48000000;
-#else
-	host->cfg.f_max = 375000;
-#endif
 
 	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
@@ -612,7 +638,27 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
 		return -FDT_ERR_NOTFOUND;
 	}
 
-#ifndef CONFIG_TEGRA186
+#ifdef CONFIG_TEGRA186
+	{
+		/*
+		 * FIXME: This variable should go away when the MMC device
+		 * actually is a udevice.
+		 */
+		struct udevice dev;
+		int ret;
+		dev.of_offset = node;
+		ret = reset_get_by_name(&dev, "sdmmc", &host->reset_ctl);
+		if (ret) {
+			debug("reset_get_by_index() failed: %d\n", ret);
+			return ret;
+		}
+		ret = clk_get_by_name(&dev, "sdmmc", &host->clk);
+		if (ret) {
+			debug("clk_get_by_index() failed: %d\n", ret);
+			return ret;
+		}
+	}
+#else
 	host->mmc_id = clock_decode_periph_id(blob, node);
 	if (host->mmc_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id\n", __func__);
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs
  2016-08-05 22:10 [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Stephen Warren
@ 2016-08-05 22:10 ` Stephen Warren
  2016-08-06  1:40   ` Simon Glass
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support Stephen Warren
  2016-08-06  1:40 ` [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Simon Glass
  2 siblings, 1 reply; 7+ messages in thread
From: Stephen Warren @ 2016-08-05 22:10 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

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.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
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(-)

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 26aa2b0930a0..669e37bb5dc5 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -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
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index 352cdef56ab4..ea8adb98db33 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -13,22 +13,35 @@
 #define pr_fmt(fmt) "tegra-pcie: " fmt
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <pci.h>
+#include <power-domain.h>
+#include <reset.h>
 
 #include <asm/io.h>
 #include <asm/gpio.h>
 
+#include <linux/list.h>
+
+#ifndef CONFIG_TEGRA186
 #include <asm/arch/clock.h>
 #include <asm/arch/powergate.h>
 #include <asm/arch-tegra/xusb-padctl.h>
-
-#include <linux/list.h>
-
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+#endif
+
+/*
+ * 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;
 
@@ -103,6 +116,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222	(0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1	(0x1 << 20)
 #define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411	(0x2 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211	(0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111	(0x2 << 20)
 
 #define AFI_FUSE			0x104
 #define  AFI_FUSE_PCIE_T0_GEN2_DIS	(1 << 2)
@@ -110,6 +126,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define AFI_PEX0_CTRL			0x110
 #define AFI_PEX1_CTRL			0x118
 #define AFI_PEX2_CTRL			0x128
+#define AFI_PEX2_CTRL_T186		0x19c
 #define  AFI_PEX_CTRL_RST		(1 << 0)
 #define  AFI_PEX_CTRL_CLKREQ_EN		(1 << 1)
 #define  AFI_PEX_CTRL_REFCLK_EN		(1 << 3)
@@ -173,6 +190,7 @@ enum tegra_pci_id {
 	TEGRA30_PCIE,
 	TEGRA124_PCIE,
 	TEGRA210_PCIE,
+	TEGRA186_PCIE,
 };
 
 struct tegra_pcie_port {
@@ -189,6 +207,7 @@ struct tegra_pcie_soc {
 	unsigned int num_ports;
 	unsigned long pads_pll_ctl;
 	unsigned long tx_ref_sel;
+	unsigned long afi_pex2_ctrl;
 	u32 pads_refclk_cfg0;
 	u32 pads_refclk_cfg1;
 	bool has_pex_clkreq_en;
@@ -209,7 +228,17 @@ struct tegra_pcie {
 	unsigned long xbar;
 
 	const struct tegra_pcie_soc *soc;
+
+#ifdef CONFIG_TEGRA186
+	struct clk clk_afi;
+	struct clk clk_pex;
+	struct reset_ctl reset_afi;
+	struct reset_ctl reset_pex;
+	struct reset_ctl reset_pcie_x;
+	struct power_domain pwrdom;
+#else
 	struct tegra_xusb_phy *phy;
+#endif
 };
 
 static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
@@ -229,10 +258,12 @@ static void pads_writel(struct tegra_pcie *pcie, unsigned long value,
 	writel(value, pcie->pads.start + offset);
 }
 
+#ifndef CONFIG_TEGRA186
 static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset)
 {
 	return readl(pcie->pads.start + offset);
 }
+#endif
 
 static unsigned long rp_readl(struct tegra_pcie_port *port,
 			      unsigned long offset)
@@ -400,6 +431,24 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
 			return 0;
 		}
 		break;
+	case TEGRA186_PCIE:
+		switch (lanes) {
+		case 0x0010004:
+			debug("x4 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401;
+			return 0;
+
+		case 0x0010102:
+			debug("x2 x1 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211;
+			return 0;
+
+		case 0x0010101:
+			debug("x1 x1 x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111;
+			return 0;
+		}
+		break;
 	default:
 		break;
 	}
@@ -471,6 +520,7 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
 		return err;
 	}
 
+#ifndef CONFIG_TEGRA186
 	pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
 	if (pcie->phy) {
 		err = tegra_xusb_phy_prepare(pcie->phy);
@@ -479,6 +529,7 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
 			return err;
 		}
 	}
+#endif
 
 	fdt_for_each_subnode(fdt, subnode, node) {
 		unsigned int index = 0, num_lanes = 0;
@@ -523,6 +574,44 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
 	return 0;
 }
 
+#ifdef CONFIG_TEGRA186
+static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+{
+	int ret;
+
+	ret = power_domain_on(&pcie->pwrdom);
+	if (ret) {
+		error("power_domain_on() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&pcie->clk_afi);
+	if (ret) {
+		error("clk_enable(afi) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&pcie->clk_pex);
+	if (ret) {
+		error("clk_enable(pex) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&pcie->reset_afi);
+	if (ret) {
+		error("reset_deassert(afi) failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&pcie->reset_pex);
+	if (ret) {
+		error("reset_deassert(pex) failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+#else
 static int tegra_pcie_power_on(struct tegra_pcie *pcie)
 {
 	const struct tegra_pcie_soc *soc = pcie->soc;
@@ -639,6 +728,7 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
 
 	return 0;
 }
+#endif
 
 static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 {
@@ -647,7 +737,11 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 	u32 value;
 	int err;
 
+#ifdef CONFIG_TEGRA186
+	{
+#else
 	if (pcie->phy) {
+#endif
 		value = afi_readl(pcie, AFI_PLLE_CONTROL);
 		value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
 		value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
@@ -675,6 +769,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 
 	afi_writel(pcie, value, AFI_FUSE);
 
+#ifndef CONFIG_TEGRA186
 	if (pcie->phy)
 		err = tegra_xusb_phy_enable(pcie->phy);
 	else
@@ -684,9 +779,18 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 		error("failed to power on PHY: %d\n", err);
 		return err;
 	}
+#endif
 
 	/* take the PCIEXCLK logic out of reset */
+#ifdef CONFIG_TEGRA186
+	err = reset_deassert(&pcie->reset_pcie_x);
+	if (err) {
+		error("reset_deassert(pcie_x) failed: %d\n", err);
+		return err;
+	}
+#else
 	reset_set_enable(PERIPH_ID_PCIEXCLK, 0);
+#endif
 
 	/* finally enable PCIe */
 	value = afi_readl(pcie, AFI_CONFIGURATION);
@@ -787,7 +891,7 @@ static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
 		break;
 
 	case 2:
-		ret = AFI_PEX2_CTRL;
+		ret = port->pcie->soc->afi_pex2_ctrl;
 		break;
 	}
 
@@ -945,6 +1049,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = {
 		.num_ports = 3,
 		.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
 		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+		.afi_pex2_ctrl = AFI_PEX2_CTRL,
 		.pads_refclk_cfg0 = 0xfa5cfa5c,
 		.pads_refclk_cfg1 = 0xfa5cfa5c,
 		.has_pex_clkreq_en = true,
@@ -972,7 +1077,16 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = {
 		.has_cml_clk = true,
 		.has_gen2 = true,
 		.force_pca_enable = true,
-	}
+	},
+	[TEGRA186_PCIE] = {
+		.num_ports = 3,
+		.afi_pex2_ctrl = AFI_PEX2_CTRL_T186,
+		.pads_refclk_cfg0 = 0x80b880b8,
+		.pads_refclk_cfg1 = 0x000480b8,
+		.has_pex_clkreq_en = true,
+		.has_pex_bias_ctrl = true,
+		.has_gen2 = true,
+	},
 };
 
 static int pci_tegra_ofdata_to_platdata(struct udevice *dev)
@@ -996,6 +1110,44 @@ static int pci_tegra_probe(struct udevice *dev)
 	struct tegra_pcie *pcie = dev_get_priv(dev);
 	int err;
 
+#ifdef CONFIG_TEGRA186
+	err = clk_get_by_name(dev, "afi", &pcie->clk_afi);
+	if (err) {
+		debug("clk_get_by_name(afi) failed: %d\n", err);
+		return err;
+	}
+
+	err = clk_get_by_name(dev, "pex", &pcie->clk_pex);
+	if (err) {
+		debug("clk_get_by_name(pex) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "afi", &pcie->reset_afi);
+	if (err) {
+		debug("reset_get_by_name(afi) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "pex", &pcie->reset_pex);
+	if (err) {
+		debug("reset_get_by_name(pex) failed: %d\n", err);
+		return err;
+	}
+
+	err = reset_get_by_name(dev, "pcie_x", &pcie->reset_pcie_x);
+	if (err) {
+		debug("reset_get_by_name(pcie_x) failed: %d\n", err);
+		return err;
+	}
+
+	err = power_domain_get(dev, &pcie->pwrdom);
+	if (err) {
+		debug("power_domain_get() failed: %d\n", err);
+		return err;
+	}
+#endif
+
 	err = tegra_pcie_power_on(pcie);
 	if (err < 0) {
 		error("failed to power on");
@@ -1033,6 +1185,7 @@ static const struct udevice_id pci_tegra_ids[] = {
 	{ .compatible = "nvidia,tegra30-pcie", .data = TEGRA30_PCIE },
 	{ .compatible = "nvidia,tegra124-pcie", .data = TEGRA124_PCIE },
 	{ .compatible = "nvidia,tegra210-pcie", .data = TEGRA210_PCIE },
+	{ .compatible = "nvidia,tegra186-pcie", .data = TEGRA186_PCIE },
 	{ }
 };
 
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support
  2016-08-05 22:10 [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Stephen Warren
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs Stephen Warren
@ 2016-08-05 22:10 ` Stephen Warren
  2016-08-06  1:40   ` Simon Glass
  2016-08-08  4:15   ` Heiko Schocher
  2016-08-06  1:40 ` [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Simon Glass
  2 siblings, 2 replies; 7+ messages in thread
From: Stephen Warren @ 2016-08-05 22:10 UTC (permalink / raw)
  To: u-boot

From: Bryan Wu <pengw@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@nvidia.com>
(swarren, simplified some ifdefs, removed indent level inside an ifdef)
(swarren, added comment about the ifdefs)
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
v2: Add TODO comment describing the messy ifdefs.
---
 drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 4 deletions(-)

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 <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;
 }
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs
  2016-08-05 22:10 [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Stephen Warren
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs Stephen Warren
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support Stephen Warren
@ 2016-08-06  1:40 ` Simon Glass
  2 siblings, 0 replies; 7+ messages in thread
From: Simon Glass @ 2016-08-06  1:40 UTC (permalink / raw)
  To: u-boot

On 5 August 2016 at 16:10, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> 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.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> 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(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs Stephen Warren
@ 2016-08-06  1:40   ` Simon Glass
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Glass @ 2016-08-06  1:40 UTC (permalink / raw)
  To: u-boot

On 5 August 2016 at 16:10, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> 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.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> 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(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support Stephen Warren
@ 2016-08-06  1:40   ` Simon Glass
  2016-08-08  4:15   ` Heiko Schocher
  1 sibling, 0 replies; 7+ messages in thread
From: Simon Glass @ 2016-08-06  1:40 UTC (permalink / raw)
  To: u-boot

On 5 August 2016 at 16:10, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Bryan Wu <pengw@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@nvidia.com>
> (swarren, simplified some ifdefs, removed indent level inside an ifdef)
> (swarren, added comment about the ifdefs)
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> v2: Add TODO comment describing the messy ifdefs.
> ---
>  drivers/i2c/tegra_i2c.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 85 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support
  2016-08-05 22:10 ` [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support Stephen Warren
  2016-08-06  1:40   ` Simon Glass
@ 2016-08-08  4:15   ` Heiko Schocher
  1 sibling, 0 replies; 7+ messages in thread
From: Heiko Schocher @ 2016-08-08  4:15 UTC (permalink / raw)
  To: u-boot

Hello Stephen,

Am 06.08.2016 um 00:10 schrieb Stephen Warren:
> From: Bryan Wu <pengw@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@nvidia.com>
> (swarren, simplified some ifdefs, removed indent level inside an ifdef)
> (swarren, added comment about the ifdefs)
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> 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 <hs@denx.de>

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 <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;
>   }
>

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-08-08  4:15 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-05 22:10 [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Stephen Warren
2016-08-05 22:10 ` [U-Boot] [PATCH V2 2/3] pci: tegra: port to standard clock/reset/pwr domain APIs Stephen Warren
2016-08-06  1:40   ` Simon Glass
2016-08-05 22:10 ` [U-Boot] [PATCH V2 3/3] i2c: tegra: add standardized clk/reset API support Stephen Warren
2016-08-06  1:40   ` Simon Glass
2016-08-08  4:15   ` Heiko Schocher
2016-08-06  1:40 ` [U-Boot] [PATCH V2 1/3] mmc: tegra: port to standard clock/reset APIs Simon Glass

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox