All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding
@ 2016-07-27 21:24 Stephen Warren
  2016-07-27 21:24 ` [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings Stephen Warren
                   ` (8 more replies)
  0 siblings, 9 replies; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

The DT binding for the Tegra186 HSP module apparently wasn't quite final
when I posted initial U-Boot support for it. Add the final DT binding doc
and adapt all code and DT files to match it.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/dts/tegra186.dtsi                         | 10 ++---
 .../mailbox/nvidia,tegra186-hsp.txt                | 52 ++++++++++++++++++++++
 drivers/mailbox/tegra-hsp.c                        | 47 +++++++++++++++----
 include/dt-bindings/mailbox/tegra-hsp.h            | 14 ------
 include/dt-bindings/mailbox/tegra186-hsp.h         | 19 ++++++++
 5 files changed, 113 insertions(+), 29 deletions(-)
 create mode 100644 doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
 delete mode 100644 include/dt-bindings/mailbox/tegra-hsp.h
 create mode 100644 include/dt-bindings/mailbox/tegra186-hsp.h

diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi
index 99d49254b36b..650feb60b1ab 100644
--- a/arch/arm/dts/tegra186.dtsi
+++ b/arch/arm/dts/tegra186.dtsi
@@ -1,7 +1,7 @@
 #include "skeleton.dtsi"
 #include <dt-bindings/gpio/tegra186-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/mailbox/tegra-hsp.h>
+#include <dt-bindings/mailbox/tegra186-hsp.h>
 
 / {
 	compatible = "nvidia,tegra186";
@@ -45,12 +45,8 @@
 		compatible = "nvidia,tegra186-hsp";
 		reg = <0x0 0x03c00000 0x0 0xa0000>;
 		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-		nvidia,num-SM = <0x8>;
-		nvidia,num-AS = <0x2>;
-		nvidia,num-SS = <0x2>;
-		nvidia,num-DB = <0x7>;
-		nvidia,num-SI = <0x8>;
-		#mbox-cells = <1>;
+		interrupt-names = "doorbell";
+		#mbox-cells = <2>;
 	};
 
 	gpio at c2f0000 {
diff --git a/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt b/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
new file mode 100644
index 000000000000..a9152380642d
--- /dev/null
+++ b/doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
@@ -0,0 +1,52 @@
+NVIDIA Tegra Hardware Synchronization Primitives (HSP)
+
+The HSP modules are used for the processors to share resources and communicate
+together. It provides a set of hardware synchronization primitives for
+interprocessor communication. So the interprocessor communication (IPC)
+protocols can use hardware synchronization primitives, when operating between
+two processors not in an SMP relationship.
+
+The features that HSP supported are shared mailboxes, shared semaphores,
+arbitrated semaphores and doorbells.
+
+Required properties:
+- name : Should be hsp
+- compatible
+    Array of strings.
+    one of:
+    - "nvidia,tegra186-hsp"
+- reg : Offset and length of the register set for the device.
+- interrupt-names
+    Array of strings.
+    Contains a list of names for the interrupts described by the interrupt
+    property. May contain the following entries, in any order:
+    - "doorbell"
+    Users of this binding MUST look up entries in the interrupt property
+    by name, using this interrupt-names property to do so.
+- interrupts
+    Array of interrupt specifiers.
+    Must contain one entry per entry in the interrupt-names property,
+    in a matching order.
+- #mbox-cells : Should be 2.
+
+The mbox specifier of the "mboxes" property in the client node should
+contain two data. The first one should be the HSP type and the second
+one should be the ID that the client is going to use. Those information
+can be found in the following file.
+
+- <dt-bindings/mailbox/tegra186-hsp.h>.
+
+Example:
+
+hsp_top0: hsp at 3c00000 {
+	compatible = "nvidia,tegra186-hsp";
+	reg = <0x0 0x03c00000 0x0 0xa0000>;
+	interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+	interrupt-names = "doorbell";
+	#mbox-cells = <2>;
+};
+
+client {
+	...
+	mboxes = <&hsp_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_XXX>;
+};
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 5c781a50b6ac..3d0362d58740 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -8,7 +8,19 @@
 #include <asm/io.h>
 #include <dm.h>
 #include <mailbox-uclass.h>
-#include <dt-bindings/mailbox/tegra-hsp.h>
+#include <dt-bindings/mailbox/tegra186-hsp.h>
+
+#define TEGRA_HSP_INT_DIMENSIONING		0x380
+#define TEGRA_HSP_INT_DIMENSIONING_NSI_SHIFT	16
+#define TEGRA_HSP_INT_DIMENSIONING_NSI_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NDB_SHIFT	12
+#define TEGRA_HSP_INT_DIMENSIONING_NDB_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT	8
+#define TEGRA_HSP_INT_DIMENSIONING_NAS_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT	4
+#define TEGRA_HSP_INT_DIMENSIONING_NSS_MASK	0xf
+#define TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT	0
+#define TEGRA_HSP_INT_DIMENSIONING_NSM_MASK	0xf
 
 #define TEGRA_HSP_DB_REG_TRIGGER	0x0
 #define TEGRA_HSP_DB_REG_ENABLE		0x4
@@ -51,7 +63,7 @@ static void tegra_hsp_writel(struct tegra_hsp *thsp, uint32_t val,
 static int tegra_hsp_db_id(ulong chan_id)
 {
 	switch (chan_id) {
-	case TEGRA_HSP_MASTER_BPMP:
+	case (HSP_MBOX_TYPE_DB << 16) | HSP_DB_MASTER_BPMP:
 		return TEGRA_HSP_DB_ID_BPMP;
 	default:
 		debug("Invalid channel ID\n");
@@ -59,6 +71,21 @@ static int tegra_hsp_db_id(ulong chan_id)
 	}
 }
 
+static int tegra_hsp_of_xlate(struct mbox_chan *chan,
+			      struct fdtdec_phandle_args *args)
+{
+	debug("%s(chan=%p)\n", __func__, chan);
+
+	if (args->args_count != 2) {
+		debug("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	chan->id = (args->args[0] << 16) | args->args[1];
+
+	return 0;
+}
+
 static int tegra_hsp_request(struct mbox_chan *chan)
 {
 	int db_id;
@@ -121,6 +148,7 @@ static int tegra_hsp_bind(struct udevice *dev)
 static int tegra_hsp_probe(struct udevice *dev)
 {
 	struct tegra_hsp *thsp = dev_get_priv(dev);
+	u32 val;
 	int nr_sm, nr_ss, nr_as;
 
 	debug("%s(dev=%p)\n", __func__, dev);
@@ -129,12 +157,14 @@ static int tegra_hsp_probe(struct udevice *dev)
 	if (thsp->regs == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
-	nr_sm = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SM",
-			       0);
-	nr_ss = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SS",
-			       0);
-	nr_as = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-AS",
-			       0);
+	val = readl(thsp->regs + TEGRA_HSP_INT_DIMENSIONING);
+	nr_sm = (val >> TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NSM_MASK;
+	nr_ss = (val >> TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NSS_MASK;
+	nr_as = (val >> TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT) &
+		TEGRA_HSP_INT_DIMENSIONING_NAS_MASK;
+
 	thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16;
 
 	return 0;
@@ -146,6 +176,7 @@ static const struct udevice_id tegra_hsp_ids[] = {
 };
 
 struct mbox_ops tegra_hsp_mbox_ops = {
+	.of_xlate = tegra_hsp_of_xlate,
 	.request = tegra_hsp_request,
 	.free = tegra_hsp_free,
 	.send = tegra_hsp_send,
diff --git a/include/dt-bindings/mailbox/tegra-hsp.h b/include/dt-bindings/mailbox/tegra-hsp.h
deleted file mode 100644
index e8c23fa91d23..000000000000
--- a/include/dt-bindings/mailbox/tegra-hsp.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This header provides constants for binding nvidia,tegra186-hsp.
- *
- * The number with TEGRA_HSP_MASTER prefix indicates the bit that is
- * associated with a master ID in the doorbell registers.
- */
-
-#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
-#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
-
-#define TEGRA_HSP_MASTER_CCPLEX		17
-#define TEGRA_HSP_MASTER_BPMP		19
-
-#endif
diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h
new file mode 100644
index 000000000000..b4864325d74b
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra186-hsp.h
@@ -0,0 +1,19 @@
+/*
+ * This header provides constants for binding nvidia,tegra186-hsp.
+ *
+ * The number with HSP_DB_MASTER prefix indicates the bit that is
+ * associated with a master ID in the doorbell registers.
+ */
+
+#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
+#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
+
+#define HSP_MBOX_TYPE_DB 0x0
+#define HSP_MBOX_TYPE_SM 0x1
+#define HSP_MBOX_TYPE_SS 0x2
+#define HSP_MBOX_TYPE_AS 0x3
+
+#define HSP_DB_MASTER_CCPLEX 17
+#define HSP_DB_MASTER_BPMP 19
+
+#endif
-- 
2.9.2

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

* [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT Stephen Warren
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

The Tegra BPMP (Boot and Power Management Processor) is a separate
auxiliary CPU embedded into Tegra to perform power management work, and
controls related features such as clocks, resets, power domains, PMIC I2C
bus, etc. These bindings dictate how to represent the BPMP in device tree.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 .../firmware/nvidia,tegra186-bpmp.txt              |  81 ++
 include/dt-bindings/clock/tegra186-clock.h         | 940 +++++++++++++++++++++
 include/dt-bindings/power/tegra186-powergate.h     |  29 +
 include/dt-bindings/reset/tegra186-reset.h         | 206 +++++
 4 files changed, 1256 insertions(+)
 create mode 100644 doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
 create mode 100644 include/dt-bindings/clock/tegra186-clock.h
 create mode 100644 include/dt-bindings/power/tegra186-powergate.h
 create mode 100644 include/dt-bindings/reset/tegra186-reset.h

diff --git a/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
new file mode 100644
index 000000000000..9a3864f56955
--- /dev/null
+++ b/doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
@@ -0,0 +1,81 @@
+NVIDIA Tegra Boot and Power Management Processor (BPMP)
+
+The BPMP is a specific processor in Tegra chip, which is designed for
+booting process handling and offloading the power management, clock
+management, and reset control tasks from the CPU. The binding document
+defines the resources that would be used by the BPMP firmware driver,
+which can create the interprocessor communication (IPC) between the CPU
+and BPMP.
+
+Required properties:
+- name : Should be bpmp
+- compatible
+    Array of strings
+    One of:
+    - "nvidia,tegra186-bpmp"
+- mboxes : The phandle of mailbox controller and the mailbox specifier.
+- shmem : List of the phandle of the TX and RX shared memory area that
+	  the IPC between CPU and BPMP is based on.
+- #clock-cells : Should be 1.
+- #power-domain-cells : Should be 1.
+- #reset-cells : Should be 1.
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+This node is a clock, power domain, and reset provider. See the following
+files for general documentation of those features, and the specifiers
+implemented by this node:
+
+- .../clock/clock-bindings.txt
+- <dt-bindings/clock/tegra186-clock.h>
+- ../power/power_domain.txt
+- <dt-bindings/power/tegra186-powergate.h>
+- .../reset/reset.txt
+- <dt-bindings/reset/tegra186-reset.h>
+
+The shared memory bindings for BPMP
+-----------------------------------
+
+The shared memory area for the IPC TX and RX between CPU and BPMP are
+predefined and work on top of sysram, which is an SRAM inside the chip.
+
+See ".../sram/sram.txt" for the bindings.
+
+Example:
+
+hsp_top0: hsp at 03c00000 {
+	...
+	#mbox-cells = <2>;
+};
+
+sysram at 30000000 {
+	compatible = "nvidia,tegra186-sysram", "mmio-sram";
+	reg = <0x0 0x30000000 0x0 0x50000>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+	cpu_bpmp_tx: bpmp_shmem at 4e000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4e000 0x0 0x1000>;
+	};
+
+	cpu_bpmp_rx: bpmp_shmem at 4f000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4f000 0x0 0x1000>;
+	};
+};
+
+bpmp {
+	compatible = "nvidia,tegra186-bpmp";
+	mboxes = <&hsp_top0 HSP_MBOX_TYPE_DB HSP_DB_MASTER_BPMP>;
+	shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
+	#clock-cells = <1>;
+	#power-domain-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h
new file mode 100644
index 000000000000..f73d32098f99
--- /dev/null
+++ b/include/dt-bindings/clock/tegra186-clock.h
@@ -0,0 +1,940 @@
+/** @file */
+
+#ifndef _MACH_T186_CLK_T186_H
+#define _MACH_T186_CLK_T186_H
+
+/**
+ * @defgroup clock_ids Clock Identifiers
+ * @{
+ *   @defgroup extern_input external input clocks
+ *   @{
+ *     @def TEGRA186_CLK_OSC
+ *     @def TEGRA186_CLK_CLK_32K
+ *     @def TEGRA186_CLK_DTV_INPUT
+ *     @def TEGRA186_CLK_SOR0_PAD_CLKOUT
+ *     @def TEGRA186_CLK_SOR1_PAD_CLKOUT
+ *     @def TEGRA186_CLK_I2S1_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S2_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S3_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S4_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S5_SYNC_INPUT
+ *     @def TEGRA186_CLK_I2S6_SYNC_INPUT
+ *     @def TEGRA186_CLK_SPDIFIN_SYNC_INPUT
+ *   @}
+ *
+ *   @defgroup extern_output external output clocks
+ *   @{
+ *     @def TEGRA186_CLK_EXTPERIPH1
+ *     @def TEGRA186_CLK_EXTPERIPH2
+ *     @def TEGRA186_CLK_EXTPERIPH3
+ *     @def TEGRA186_CLK_EXTPERIPH4
+ *   @}
+ *
+ *   @defgroup display_clks display related clocks
+ *   @{
+ *     @def TEGRA186_CLK_CEC
+ *     @def TEGRA186_CLK_DSIC
+ *     @def TEGRA186_CLK_DSIC_LP
+ *     @def TEGRA186_CLK_DSID
+ *     @def TEGRA186_CLK_DSID_LP
+ *     @def TEGRA186_CLK_DPAUX1
+ *     @def TEGRA186_CLK_DPAUX
+ *     @def TEGRA186_CLK_HDA2HDMICODEC
+ *     @def TEGRA186_CLK_NVDISPLAY_DISP
+ *     @def TEGRA186_CLK_NVDISPLAY_DSC
+ *     @def TEGRA186_CLK_NVDISPLAY_P0
+ *     @def TEGRA186_CLK_NVDISPLAY_P1
+ *     @def TEGRA186_CLK_NVDISPLAY_P2
+ *     @def TEGRA186_CLK_NVDISPLAYHUB
+ *     @def TEGRA186_CLK_SOR_SAFE
+ *     @def TEGRA186_CLK_SOR0
+ *     @def TEGRA186_CLK_SOR0_OUT
+ *     @def TEGRA186_CLK_SOR1
+ *     @def TEGRA186_CLK_SOR1_OUT
+ *     @def TEGRA186_CLK_DSI
+ *     @def TEGRA186_CLK_MIPI_CAL
+ *     @def TEGRA186_CLK_DSIA_LP
+ *     @def TEGRA186_CLK_DSIB
+ *     @def TEGRA186_CLK_DSIB_LP
+ *   @}
+ *
+ *   @defgroup camera_clks camera related clocks
+ *   @{
+ *     @def TEGRA186_CLK_NVCSI
+ *     @def TEGRA186_CLK_NVCSILP
+ *     @def TEGRA186_CLK_VI
+ *   @}
+ *
+ *   @defgroup audio_clks audio related clocks
+ *   @{
+ *     @def TEGRA186_CLK_ACLK
+ *     @def TEGRA186_CLK_ADSP
+ *     @def TEGRA186_CLK_ADSPNEON
+ *     @def TEGRA186_CLK_AHUB
+ *     @def TEGRA186_CLK_APE
+ *     @def TEGRA186_CLK_APB2APE
+ *     @def TEGRA186_CLK_AUD_MCLK
+ *     @def TEGRA186_CLK_DMIC1
+ *     @def TEGRA186_CLK_DMIC2
+ *     @def TEGRA186_CLK_DMIC3
+ *     @def TEGRA186_CLK_DMIC4
+ *     @def TEGRA186_CLK_DSPK1
+ *     @def TEGRA186_CLK_DSPK2
+ *     @def TEGRA186_CLK_HDA
+ *     @def TEGRA186_CLK_HDA2CODEC_2X
+ *     @def TEGRA186_CLK_I2S1
+ *     @def TEGRA186_CLK_I2S2
+ *     @def TEGRA186_CLK_I2S3
+ *     @def TEGRA186_CLK_I2S4
+ *     @def TEGRA186_CLK_I2S5
+ *     @def TEGRA186_CLK_I2S6
+ *     @def TEGRA186_CLK_MAUD
+ *     @def TEGRA186_CLK_PLL_A_OUT0
+ *     @def TEGRA186_CLK_SPDIF_DOUBLER
+ *     @def TEGRA186_CLK_SPDIF_IN
+ *     @def TEGRA186_CLK_SPDIF_OUT
+ *     @def TEGRA186_CLK_SYNC_DMIC1
+ *     @def TEGRA186_CLK_SYNC_DMIC2
+ *     @def TEGRA186_CLK_SYNC_DMIC3
+ *     @def TEGRA186_CLK_SYNC_DMIC4
+ *     @def TEGRA186_CLK_SYNC_DMIC5
+ *     @def TEGRA186_CLK_SYNC_DSPK1
+ *     @def TEGRA186_CLK_SYNC_DSPK2
+ *     @def TEGRA186_CLK_SYNC_I2S1
+ *     @def TEGRA186_CLK_SYNC_I2S2
+ *     @def TEGRA186_CLK_SYNC_I2S3
+ *     @def TEGRA186_CLK_SYNC_I2S4
+ *     @def TEGRA186_CLK_SYNC_I2S5
+ *     @def TEGRA186_CLK_SYNC_I2S6
+ *     @def TEGRA186_CLK_SYNC_SPDIF
+ *   @}
+ *
+ *   @defgroup uart_clks UART clocks
+ *   @{
+ *     @def TEGRA186_CLK_AON_UART_FST_MIPI_CAL
+ *     @def TEGRA186_CLK_UARTA
+ *     @def TEGRA186_CLK_UARTB
+ *     @def TEGRA186_CLK_UARTC
+ *     @def TEGRA186_CLK_UARTD
+ *     @def TEGRA186_CLK_UARTE
+ *     @def TEGRA186_CLK_UARTF
+ *     @def TEGRA186_CLK_UARTG
+ *     @def TEGRA186_CLK_UART_FST_MIPI_CAL
+ *   @}
+ *
+ *   @defgroup i2c_clks I2C clocks
+ *   @{
+ *     @def TEGRA186_CLK_AON_I2C_SLOW
+ *     @def TEGRA186_CLK_I2C1
+ *     @def TEGRA186_CLK_I2C2
+ *     @def TEGRA186_CLK_I2C3
+ *     @def TEGRA186_CLK_I2C4
+ *     @def TEGRA186_CLK_I2C5
+ *     @def TEGRA186_CLK_I2C6
+ *     @def TEGRA186_CLK_I2C8
+ *     @def TEGRA186_CLK_I2C9
+ *     @def TEGRA186_CLK_I2C1
+ *     @def TEGRA186_CLK_I2C12
+ *     @def TEGRA186_CLK_I2C13
+ *     @def TEGRA186_CLK_I2C14
+ *     @def TEGRA186_CLK_I2C_SLOW
+ *     @def TEGRA186_CLK_VI_I2C
+ *   @}
+ *
+ *   @defgroup spi_clks SPI clocks
+ *   @{
+ *     @def TEGRA186_CLK_SPI1
+ *     @def TEGRA186_CLK_SPI2
+ *     @def TEGRA186_CLK_SPI3
+ *     @def TEGRA186_CLK_SPI4
+ *   @}
+ *
+ *   @defgroup storage storage related clocks
+ *   @{
+ *     @def TEGRA186_CLK_SATA
+ *     @def TEGRA186_CLK_SATA_OOB
+ *     @def TEGRA186_CLK_SATA_IOBIST
+ *     @def TEGRA186_CLK_SDMMC_LEGACY_TM
+ *     @def TEGRA186_CLK_SDMMC1
+ *     @def TEGRA186_CLK_SDMMC2
+ *     @def TEGRA186_CLK_SDMMC3
+ *     @def TEGRA186_CLK_SDMMC4
+ *     @def TEGRA186_CLK_QSPI
+ *     @def TEGRA186_CLK_QSPI_OUT
+ *     @def TEGRA186_CLK_UFSDEV_REF
+ *     @def TEGRA186_CLK_UFSHC
+ *   @}
+ *
+ *   @defgroup pwm_clks PWM clocks
+ *   @{
+ *     @def TEGRA186_CLK_PWM1
+ *     @def TEGRA186_CLK_PWM2
+ *     @def TEGRA186_CLK_PWM3
+ *     @def TEGRA186_CLK_PWM4
+ *     @def TEGRA186_CLK_PWM5
+ *     @def TEGRA186_CLK_PWM6
+ *     @def TEGRA186_CLK_PWM7
+ *     @def TEGRA186_CLK_PWM8
+ *   @}
+ *
+ *   @defgroup plls PLLs and related clocks
+ *   @{
+ *     @def TEGRA186_CLK_PLLREFE_OUT_GATED
+ *     @def TEGRA186_CLK_PLLREFE_OUT1
+ *     @def TEGRA186_CLK_PLLD_OUT1
+ *     @def TEGRA186_CLK_PLLP_OUT0
+ *     @def TEGRA186_CLK_PLLP_OUT5
+ *     @def TEGRA186_CLK_PLLA
+ *     @def TEGRA186_CLK_PLLE_PWRSEQ
+ *     @def TEGRA186_CLK_PLLA_OUT1
+ *     @def TEGRA186_CLK_PLLREFE_REF
+ *     @def TEGRA186_CLK_UPHY_PLL0_PWRSEQ
+ *     @def TEGRA186_CLK_UPHY_PLL1_PWRSEQ
+ *     @def TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH
+ *     @def TEGRA186_CLK_PLLREFE_PEX
+ *     @def TEGRA186_CLK_PLLREFE_IDDQ
+ *     @def TEGRA186_CLK_PLLC_OUT_AON
+ *     @def TEGRA186_CLK_PLLC_OUT_ISP
+ *     @def TEGRA186_CLK_PLLC_OUT_VE
+ *     @def TEGRA186_CLK_PLLC4_OUT
+ *     @def TEGRA186_CLK_PLLREFE_OUT
+ *     @def TEGRA186_CLK_PLLREFE_PLL_REF
+ *     @def TEGRA186_CLK_PLLE
+ *     @def TEGRA186_CLK_PLLC
+ *     @def TEGRA186_CLK_PLLP
+ *     @def TEGRA186_CLK_PLLD
+ *     @def TEGRA186_CLK_PLLD2
+ *     @def TEGRA186_CLK_PLLREFE_VCO
+ *     @def TEGRA186_CLK_PLLC2
+ *     @def TEGRA186_CLK_PLLC3
+ *     @def TEGRA186_CLK_PLLDP
+ *     @def TEGRA186_CLK_PLLC4_VCO
+ *     @def TEGRA186_CLK_PLLA1
+ *     @def TEGRA186_CLK_PLLNVCSI
+ *     @def TEGRA186_CLK_PLLDISPHUB
+ *     @def TEGRA186_CLK_PLLD3
+ *     @def TEGRA186_CLK_PLLBPMPCAM
+ *     @def TEGRA186_CLK_PLLAON
+ *     @def TEGRA186_CLK_PLLU
+ *     @def TEGRA186_CLK_PLLC4_VCO_DIV2
+ *     @def TEGRA186_CLK_PLL_REF
+ *     @def TEGRA186_CLK_PLLREFE_OUT1_DIV5
+ *     @def TEGRA186_CLK_UTMIP_PLL_PWRSEQ
+ *     @def TEGRA186_CLK_PLL_U_48M
+ *     @def TEGRA186_CLK_PLL_U_480M
+ *     @def TEGRA186_CLK_PLLC4_OUT0
+ *     @def TEGRA186_CLK_PLLC4_OUT1
+ *     @def TEGRA186_CLK_PLLC4_OUT2
+ *     @def TEGRA186_CLK_PLLC4_OUT_MUX
+ *     @def TEGRA186_CLK_DFLLDISP_DIV
+ *     @def TEGRA186_CLK_PLLDISPHUB_DIV
+ *     @def TEGRA186_CLK_PLLP_DIV8
+ *   @}
+ *
+ *   @defgroup nafll_clks NAFLL clock sources
+ *   @{
+ *     @def TEGRA186_CLK_NAFLL_AXI_CBB
+ *     @def TEGRA186_CLK_NAFLL_BCPU
+ *     @def TEGRA186_CLK_NAFLL_BPMP
+ *     @def TEGRA186_CLK_NAFLL_DISP
+ *     @def TEGRA186_CLK_NAFLL_GPU
+ *     @def TEGRA186_CLK_NAFLL_ISP
+ *     @def TEGRA186_CLK_NAFLL_MCPU
+ *     @def TEGRA186_CLK_NAFLL_NVDEC
+ *     @def TEGRA186_CLK_NAFLL_NVENC
+ *     @def TEGRA186_CLK_NAFLL_NVJPG
+ *     @def TEGRA186_CLK_NAFLL_SCE
+ *     @def TEGRA186_CLK_NAFLL_SE
+ *     @def TEGRA186_CLK_NAFLL_TSEC
+ *     @def TEGRA186_CLK_NAFLL_TSECB
+ *     @def TEGRA186_CLK_NAFLL_VI
+ *     @def TEGRA186_CLK_NAFLL_VIC
+ *   @}
+ *
+ *   @defgroup mphy MPHY related clocks
+ *   @{
+ *     @def TEGRA186_CLK_MPHY_L0_RX_SYMB
+ *     @def TEGRA186_CLK_MPHY_L0_RX_LS_BIT
+ *     @def TEGRA186_CLK_MPHY_L0_TX_SYMB
+ *     @def TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT
+ *     @def TEGRA186_CLK_MPHY_L0_RX_ANA
+ *     @def TEGRA186_CLK_MPHY_L1_RX_ANA
+ *     @def TEGRA186_CLK_MPHY_IOBIST
+ *     @def TEGRA186_CLK_MPHY_TX_1MHZ_REF
+ *     @def TEGRA186_CLK_MPHY_CORE_PLL_FIXED
+ *   @}
+ *
+ *   @defgroup eavb EAVB related clocks
+ *   @{
+ *     @def TEGRA186_CLK_EQOS_AXI
+ *     @def TEGRA186_CLK_EQOS_PTP_REF
+ *     @def TEGRA186_CLK_EQOS_RX
+ *     @def TEGRA186_CLK_EQOS_RX_INPUT
+ *     @def TEGRA186_CLK_EQOS_TX
+ *   @}
+ *
+ *   @defgroup usb USB related clocks
+ *   @{
+ *     @def TEGRA186_CLK_PEX_USB_PAD0_MGMT
+ *     @def TEGRA186_CLK_PEX_USB_PAD1_MGMT
+ *     @def TEGRA186_CLK_HSIC_TRK
+ *     @def TEGRA186_CLK_USB2_TRK
+ *     @def TEGRA186_CLK_USB2_HSIC_TRK
+ *     @def TEGRA186_CLK_XUSB_CORE_SS
+ *     @def TEGRA186_CLK_XUSB_CORE_DEV
+ *     @def TEGRA186_CLK_XUSB_FALCON
+ *     @def TEGRA186_CLK_XUSB_FS
+ *     @def TEGRA186_CLK_XUSB
+ *     @def TEGRA186_CLK_XUSB_DEV
+ *     @def TEGRA186_CLK_XUSB_HOST
+ *     @def TEGRA186_CLK_XUSB_SS
+ *   @}
+ *
+ *   @defgroup bigblock compute block related clocks
+ *   @{
+ *     @def TEGRA186_CLK_GPCCLK
+ *     @def TEGRA186_CLK_GPC2CLK
+ *     @def TEGRA186_CLK_GPU
+ *     @def TEGRA186_CLK_HOST1X
+ *     @def TEGRA186_CLK_ISP
+ *     @def TEGRA186_CLK_NVDEC
+ *     @def TEGRA186_CLK_NVENC
+ *     @def TEGRA186_CLK_NVJPG
+ *     @def TEGRA186_CLK_SE
+ *     @def TEGRA186_CLK_TSEC
+ *     @def TEGRA186_CLK_TSECB
+ *     @def TEGRA186_CLK_VIC
+ *   @}
+ *
+ *   @defgroup can CAN bus related clocks
+ *   @{
+ *     @def TEGRA186_CLK_CAN1
+ *     @def TEGRA186_CLK_CAN1_HOST
+ *     @def TEGRA186_CLK_CAN2
+ *     @def TEGRA186_CLK_CAN2_HOST
+ *   @}
+ *
+ *   @defgroup system basic system clocks
+ *   @{
+ *     @def TEGRA186_CLK_ACTMON
+ *     @def TEGRA186_CLK_AON_APB
+ *     @def TEGRA186_CLK_AON_CPU_NIC
+ *     @def TEGRA186_CLK_AON_NIC
+ *     @def TEGRA186_CLK_AXI_CBB
+ *     @def TEGRA186_CLK_BPMP_APB
+ *     @def TEGRA186_CLK_BPMP_CPU_NIC
+ *     @def TEGRA186_CLK_BPMP_NIC_RATE
+ *     @def TEGRA186_CLK_CLK_M
+ *     @def TEGRA186_CLK_EMC
+ *     @def TEGRA186_CLK_MSS_ENCRYPT
+ *     @def TEGRA186_CLK_SCE_APB
+ *     @def TEGRA186_CLK_SCE_CPU_NIC
+ *     @def TEGRA186_CLK_SCE_NIC
+ *     @def TEGRA186_CLK_TSC
+ *   @}
+ *
+ *   @defgroup pcie_clks PCIe related clocks
+ *   @{
+ *     @def TEGRA186_CLK_AFI
+ *     @def TEGRA186_CLK_PCIE
+ *     @def TEGRA186_CLK_PCIE2_IOBIST
+ *     @def TEGRA186_CLK_PCIERX0
+ *     @def TEGRA186_CLK_PCIERX1
+ *     @def TEGRA186_CLK_PCIERX2
+ *     @def TEGRA186_CLK_PCIERX3
+ *     @def TEGRA186_CLK_PCIERX4
+ *   @}
+ */
+
+/** @brief output of gate CLK_ENB_FUSE */
+#define TEGRA186_CLK_FUSE 0
+/**
+ * @brief It's not what you think
+ * @details output of gate CLK_ENB_GPU. This output connects to the GPU
+ * pwrclk. @warning: This is almost certainly not the clock you think
+ * it is. If you're looking for the clock of the graphics engine, see
+ * TEGRA186_GPCCLK
+ */
+#define TEGRA186_CLK_GPU 1
+/** @brief output of gate CLK_ENB_PCIE */
+#define TEGRA186_CLK_PCIE 3
+/** @brief output of the divider IPFS_CLK_DIVISOR */
+#define TEGRA186_CLK_AFI 4
+/** @brief output of gate CLK_ENB_PCIE2_IOBIST */
+#define TEGRA186_CLK_PCIE2_IOBIST 5
+/** @brief output of gate CLK_ENB_PCIERX0*/
+#define TEGRA186_CLK_PCIERX0 6
+/** @brief output of gate CLK_ENB_PCIERX1*/
+#define TEGRA186_CLK_PCIERX1 7
+/** @brief output of gate CLK_ENB_PCIERX2*/
+#define TEGRA186_CLK_PCIERX2 8
+/** @brief output of gate CLK_ENB_PCIERX3*/
+#define TEGRA186_CLK_PCIERX3 9
+/** @brief output of gate CLK_ENB_PCIERX4*/
+#define TEGRA186_CLK_PCIERX4 10
+/** @brief output branch of PLL_C for ISP, controlled by gate CLK_ENB_PLLC_OUT_ISP */
+#define TEGRA186_CLK_PLLC_OUT_ISP 11
+/** @brief output branch of PLL_C for VI, controlled by gate CLK_ENB_PLLC_OUT_VE */
+#define TEGRA186_CLK_PLLC_OUT_VE 12
+/** @brief output branch of PLL_C for AON domain, controlled by gate CLK_ENB_PLLC_OUT_AON */
+#define TEGRA186_CLK_PLLC_OUT_AON 13
+/** @brief output of gate CLK_ENB_SOR_SAFE */
+#define TEGRA186_CLK_SOR_SAFE 39
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 */
+#define TEGRA186_CLK_I2S2 42
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S3 */
+#define TEGRA186_CLK_I2S3 43
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDF_IN */
+#define TEGRA186_CLK_SPDIF_IN 44
+/** @brief output of gate CLK_ENB_SPDIF_DOUBLER */
+#define TEGRA186_CLK_SPDIF_DOUBLER 45
+/**  @clkdesc{spi_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_SPI3} */
+#define TEGRA186_CLK_SPI3 46
+/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1} */
+#define TEGRA186_CLK_I2C1 47
+/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5} */
+#define TEGRA186_CLK_I2C5 48
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI1 */
+#define TEGRA186_CLK_SPI1 49
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_ISP */
+#define TEGRA186_CLK_ISP 50
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI */
+#define TEGRA186_CLK_VI 51
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 */
+#define TEGRA186_CLK_SDMMC1 52
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 */
+#define TEGRA186_CLK_SDMMC2 53
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 */
+#define TEGRA186_CLK_SDMMC4 54
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTA */
+#define TEGRA186_CLK_UARTA 55
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTB */
+#define TEGRA186_CLK_UARTB 56
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X */
+#define TEGRA186_CLK_HOST1X 57
+/**
+ * @brief controls the EMC clock frequency.
+ * @details Doing a clk_set_rate on this clock will select the
+ * appropriate clock source, program the source rate and execute a
+ * specific sequence to switch to the new clock source for both memory
+ * controllers. This can be used to control the balance between memory
+ * throughput and memory controller power.
+ */
+#define TEGRA186_CLK_EMC 58
+/* @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH4 */
+#define TEGRA186_CLK_EXTPERIPH4 73
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI4 */
+#define TEGRA186_CLK_SPI4 74
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 */
+#define TEGRA186_CLK_I2C3 75
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 */
+#define TEGRA186_CLK_SDMMC3 76
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTD */
+#define TEGRA186_CLK_UARTD 77
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S1 */
+#define TEGRA186_CLK_I2S1 79
+/** output of gate CLK_ENB_DTV */
+#define TEGRA186_CLK_DTV 80
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSEC */
+#define TEGRA186_CLK_TSEC 81
+/** @brief output of gate CLK_ENB_DP2 */
+#define TEGRA186_CLK_DP2 82
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S4 */
+#define TEGRA186_CLK_I2S4 84
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S5 */
+#define TEGRA186_CLK_I2S5 85
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 */
+#define TEGRA186_CLK_I2C4 86
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AHUB */
+#define TEGRA186_CLK_AHUB 87
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA2CODEC_2X */
+#define TEGRA186_CLK_HDA2CODEC_2X 88
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 */
+#define TEGRA186_CLK_EXTPERIPH1 89
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 */
+#define TEGRA186_CLK_EXTPERIPH2 90
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH3 */
+#define TEGRA186_CLK_EXTPERIPH3 91
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C_SLOW */
+#define TEGRA186_CLK_I2C_SLOW 92
+/** @brief output of the SOR1_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
+#define TEGRA186_CLK_SOR1 93
+/** @brief output of gate CLK_ENB_CEC */
+#define TEGRA186_CLK_CEC 94
+/** @brief output of gate CLK_ENB_DPAUX1 */
+#define TEGRA186_CLK_DPAUX1 95
+/** @brief output of gate CLK_ENB_DPAUX */
+#define TEGRA186_CLK_DPAUX 96
+/** @brief output of the SOR0_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
+#define TEGRA186_CLK_SOR0 97
+/** @brief output of gate CLK_ENB_HDA2HDMICODEC */
+#define TEGRA186_CLK_HDA2HDMICODEC 98
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SATA */
+#define TEGRA186_CLK_SATA 99
+/** @brief output of gate CLK_ENB_SATA_OOB */
+#define TEGRA186_CLK_SATA_OOB 100
+/** @brief output of gate CLK_ENB_SATA_IOBIST */
+#define TEGRA186_CLK_SATA_IOBIST 101
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA */
+#define TEGRA186_CLK_HDA 102
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SE */
+#define TEGRA186_CLK_SE 103
+/** @brief output of gate CLK_ENB_APB2APE */
+#define TEGRA186_CLK_APB2APE 104
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_APE */
+#define TEGRA186_CLK_APE 105
+/** @brief output of gate CLK_ENB_IQC1 */
+#define TEGRA186_CLK_IQC1 106
+/** @brief output of gate CLK_ENB_IQC2 */
+#define TEGRA186_CLK_IQC2 107
+/** divide by 2 version of TEGRA186_CLK_PLLREFE_VCO */
+#define TEGRA186_CLK_PLLREFE_OUT 108
+/** @brief output of gate CLK_ENB_PLLREFE_PLL_REF */
+#define TEGRA186_CLK_PLLREFE_PLL_REF 109
+/** @brief output of gate CLK_ENB_PLLC4_OUT */
+#define TEGRA186_CLK_PLLC4_OUT 110
+/** @brief output of mux xusb_core_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB 111
+/** controls xusb_dev_ce signal on page 66 and 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_DEV 112
+/** controls xusb_host_ce signal on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_HOST 113
+/** controls xusb_ss_ce signal on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_SS 114
+/** @brief output of gate CLK_ENB_DSI */
+#define TEGRA186_CLK_DSI 115
+/** @brief output of gate CLK_ENB_MIPI_CAL */
+#define TEGRA186_CLK_MIPI_CAL 116
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP */
+#define TEGRA186_CLK_DSIA_LP 117
+/** @brief output of gate CLK_ENB_DSIB */
+#define TEGRA186_CLK_DSIB 118
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIB_LP */
+#define TEGRA186_CLK_DSIB_LP 119
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC1 */
+#define TEGRA186_CLK_DMIC1 122
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC2 */
+#define TEGRA186_CLK_DMIC2 123
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AUD_MCLK */
+#define TEGRA186_CLK_AUD_MCLK 124
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
+#define TEGRA186_CLK_I2C6 125
+/**output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL */
+#define TEGRA186_CLK_UART_FST_MIPI_CAL 126
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VIC */
+#define TEGRA186_CLK_VIC 127
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM */
+#define TEGRA186_CLK_SDMMC_LEGACY_TM 128
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC */
+#define TEGRA186_CLK_NVDEC 129
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG */
+#define TEGRA186_CLK_NVJPG 130
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVENC */
+#define TEGRA186_CLK_NVENC 131
+/** @brief output of the QSPI_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
+#define TEGRA186_CLK_QSPI 132
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI_I2C */
+#define TEGRA186_CLK_VI_I2C 133
+/** @brief output of gate CLK_ENB_HSIC_TRK */
+#define TEGRA186_CLK_HSIC_TRK 134
+/** @brief output of gate CLK_ENB_USB2_TRK */
+#define TEGRA186_CLK_USB2_TRK 135
+/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MAUD */
+#define TEGRA186_CLK_MAUD 136
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSECB */
+#define TEGRA186_CLK_TSECB 137
+/** @brief output of gate CLK_ENB_ADSP */
+#define TEGRA186_CLK_ADSP 138
+/** @brief output of gate CLK_ENB_ADSPNEON */
+#define TEGRA186_CLK_ADSPNEON 139
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_RX_LS_SYMB */
+#define TEGRA186_CLK_MPHY_L0_RX_SYMB 140
+/** @brief output of gate CLK_ENB_MPHY_L0_RX_LS_BIT */
+#define TEGRA186_CLK_MPHY_L0_RX_LS_BIT 141
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_TX_LS_SYMB */
+#define TEGRA186_CLK_MPHY_L0_TX_SYMB 142
+/** @brief output of gate CLK_ENB_MPHY_L0_TX_LS_3XBIT */
+#define TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT 143
+/** @brief output of gate CLK_ENB_MPHY_L0_RX_ANA */
+#define TEGRA186_CLK_MPHY_L0_RX_ANA 144
+/** @brief output of gate CLK_ENB_MPHY_L1_RX_ANA */
+#define TEGRA186_CLK_MPHY_L1_RX_ANA 145
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_IOBIST */
+#define TEGRA186_CLK_MPHY_IOBIST 146
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_TX_1MHZ_REF */
+#define TEGRA186_CLK_MPHY_TX_1MHZ_REF 147
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_CORE_PLL_FIXED */
+#define TEGRA186_CLK_MPHY_CORE_PLL_FIXED 148
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AXI_CBB */
+#define TEGRA186_CLK_AXI_CBB 149
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC3 */
+#define TEGRA186_CLK_DMIC3 150
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC4 */
+#define TEGRA186_CLK_DMIC4 151
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK1 */
+#define TEGRA186_CLK_DSPK1 152
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK2 */
+#define TEGRA186_CLK_DSPK2 153
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
+#define TEGRA186_CLK_I2S6 154
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P0 */
+#define TEGRA186_CLK_NVDISPLAY_P0 155
+/** @brief output of the NVDISPLAY_DISP_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP */
+#define TEGRA186_CLK_NVDISPLAY_DISP 156
+/** @brief output of gate CLK_ENB_NVDISPLAY_DSC */
+#define TEGRA186_CLK_NVDISPLAY_DSC 157
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAYHUB */
+#define TEGRA186_CLK_NVDISPLAYHUB 158
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P1 */
+#define TEGRA186_CLK_NVDISPLAY_P1 159
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P2 */
+#define TEGRA186_CLK_NVDISPLAY_P2 160
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TACH */
+#define TEGRA186_CLK_TACH 166
+/** @brief output of gate CLK_ENB_EQOS */
+#define TEGRA186_CLK_EQOS_AXI 167
+/** @brief output of gate CLK_ENB_EQOS_RX */
+#define TEGRA186_CLK_EQOS_RX 168
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSHC_CG_SYS */
+#define TEGRA186_CLK_UFSHC 178
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSDEV_REF */
+#define TEGRA186_CLK_UFSDEV_REF 179
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSI */
+#define TEGRA186_CLK_NVCSI 180
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSILP */
+#define TEGRA186_CLK_NVCSILP 181
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C7 */
+#define TEGRA186_CLK_I2C7 182
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C9 */
+#define TEGRA186_CLK_I2C9 183
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C12 */
+#define TEGRA186_CLK_I2C12 184
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C13 */
+#define TEGRA186_CLK_I2C13 185
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C14 */
+#define TEGRA186_CLK_I2C14 186
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM1 */
+#define TEGRA186_CLK_PWM1 187
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM2 */
+#define TEGRA186_CLK_PWM2 188
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM3 */
+#define TEGRA186_CLK_PWM3 189
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM5 */
+#define TEGRA186_CLK_PWM5 190
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM6 */
+#define TEGRA186_CLK_PWM6 191
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM7 */
+#define TEGRA186_CLK_PWM7 192
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM8 */
+#define TEGRA186_CLK_PWM8 193
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTE */
+#define TEGRA186_CLK_UARTE 194
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTF */
+#define TEGRA186_CLK_UARTF 195
+/** @deprecated */
+#define TEGRA186_CLK_DBGAPB 196
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_CPU_NIC */
+#define TEGRA186_CLK_BPMP_CPU_NIC 197
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_APB */
+#define TEGRA186_CLK_BPMP_APB 199
+/** @brief output of mux controlled by TEGRA186_CLK_SOC_ACTMON */
+#define TEGRA186_CLK_ACTMON 201
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_CPU_NIC */
+#define TEGRA186_CLK_AON_CPU_NIC 208
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN1 */
+#define TEGRA186_CLK_CAN1 210
+/** @brief output of gate CLK_ENB_CAN1_HOST */
+#define TEGRA186_CLK_CAN1_HOST 211
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN2 */
+#define TEGRA186_CLK_CAN2 212
+/** @brief output of gate CLK_ENB_CAN2_HOST */
+#define TEGRA186_CLK_CAN2_HOST 213
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_APB */
+#define TEGRA186_CLK_AON_APB 214
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTC */
+#define TEGRA186_CLK_UARTC 215
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTG */
+#define TEGRA186_CLK_UARTG 216
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_UART_FST_MIPI_CAL */
+#define TEGRA186_CLK_AON_UART_FST_MIPI_CAL 217
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 */
+#define TEGRA186_CLK_I2C2 218
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C8 */
+#define TEGRA186_CLK_I2C8 219
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C10 */
+#define TEGRA186_CLK_I2C10 220
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_I2C_SLOW */
+#define TEGRA186_CLK_AON_I2C_SLOW 221
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI2 */
+#define TEGRA186_CLK_SPI2 222
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC5 */
+#define TEGRA186_CLK_DMIC5 223
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_TOUCH */
+#define TEGRA186_CLK_AON_TOUCH 224
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM4 */
+#define TEGRA186_CLK_PWM4 225
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSC. This clock object is read only and is used for all timers in the system. */
+#define TEGRA186_CLK_TSC 226
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MSS_ENCRYPT */
+#define TEGRA186_CLK_MSS_ENCRYPT 227
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_CPU_NIC */
+#define TEGRA186_CLK_SCE_CPU_NIC 228
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_APB */
+#define TEGRA186_CLK_SCE_APB 230
+/** @brief output of gate CLK_ENB_DSIC */
+#define TEGRA186_CLK_DSIC 231
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIC_LP */
+#define TEGRA186_CLK_DSIC_LP 232
+/** @brief output of gate CLK_ENB_DSID */
+#define TEGRA186_CLK_DSID 233
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSID_LP */
+#define TEGRA186_CLK_DSID_LP 234
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_SATA_USB_RX_BYP */
+#define TEGRA186_CLK_PEX_SATA_USB_RX_BYP 236
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDIF_OUT */
+#define TEGRA186_CLK_SPDIF_OUT 238
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_PTP_REF_CLK_0 */
+#define TEGRA186_CLK_EQOS_PTP_REF 239
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_TX_CLK */
+#define TEGRA186_CLK_EQOS_TX 240
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK */
+#define TEGRA186_CLK_USB2_HSIC_TRK 241
+/** @brief output of mux xusb_ss_clk_switch on page 66 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_CORE_SS 242
+/** @brief output of mux xusb_core_dev_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_CORE_DEV 243
+/** @brief output of mux xusb_core_falcon_clk_switch on page 67 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_FALCON 244
+/** @brief output of mux xusb_fs_clk_switch on page 66 of T186_Clocks_IAS.doc */
+#define TEGRA186_CLK_XUSB_FS 245
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLA_OUT */
+#define TEGRA186_CLK_PLL_A_OUT0 246
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S1 */
+#define TEGRA186_CLK_SYNC_I2S1 247
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S2 */
+#define TEGRA186_CLK_SYNC_I2S2 248
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S3 */
+#define TEGRA186_CLK_SYNC_I2S3 249
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S4 */
+#define TEGRA186_CLK_SYNC_I2S4 250
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S5 */
+#define TEGRA186_CLK_SYNC_I2S5 251
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S6 */
+#define TEGRA186_CLK_SYNC_I2S6 252
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK1 */
+#define TEGRA186_CLK_SYNC_DSPK1 253
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK2 */
+#define TEGRA186_CLK_SYNC_DSPK2 254
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC1 */
+#define TEGRA186_CLK_SYNC_DMIC1 255
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC2 */
+#define TEGRA186_CLK_SYNC_DMIC2 256
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC3 */
+#define TEGRA186_CLK_SYNC_DMIC3 257
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC4 */
+#define TEGRA186_CLK_SYNC_DMIC4 259
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_SPDIF */
+#define TEGRA186_CLK_SYNC_SPDIF 260
+/** @brief output of gate CLK_ENB_PLLREFE_OUT */
+#define TEGRA186_CLK_PLLREFE_OUT_GATED 261
+/** @brief output of the divider PLLREFE_DIVP in CLK_RST_CONTROLLER_PLLREFE_BASE. PLLREFE has 2 outputs:
+  *      * VCO/pdiv defined by this clock object
+  *      * VCO/2 defined by TEGRA186_CLK_PLLREFE_OUT
+  */
+#define TEGRA186_CLK_PLLREFE_OUT1 262
+#define TEGRA186_CLK_PLLD_OUT1 267
+/** @brief output of the divider PLLP_DIVP in CLK_RST_CONTROLLER_PLLP_BASE */
+#define TEGRA186_CLK_PLLP_OUT0 269
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLP_OUTC */
+#define TEGRA186_CLK_PLLP_OUT5 270
+/** PLL controlled by CLK_RST_CONTROLLER_PLLA_BASE for use by audio clocks */
+#define TEGRA186_CLK_PLLA 271
+/** @brief output of mux controlled by CLK_RST_CONTROLLER_ACLK_BURST_POLICY divided by the divider controlled by ACLK_CLK_DIVISOR in CLK_RST_CONTROLLER_SUPER_ACLK_DIVIDER */
+#define TEGRA186_CLK_ACLK 273
+/** fixed 48MHz clock divided down from TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLL_U_48M 274
+/** fixed 480MHz clock divided down from TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLL_U_480M 275
+/** @brief output of the divider PLLC4_DIVP in CLK_RST_CONTROLLER_PLLC4_BASE. Output frequency is TEGRA186_CLK_PLLC4_VCO/PLLC4_DIVP */
+#define TEGRA186_CLK_PLLC4_OUT0 276
+/** fixed /3 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/3 */
+#define TEGRA186_CLK_PLLC4_OUT1 277
+/** fixed /5 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/5 */
+#define TEGRA186_CLK_PLLC4_OUT2 278
+/** @brief output of mux controlled by PLLC4_CLK_SEL in CLK_RST_CONTROLLER_PLLC4_MISC1 */
+#define TEGRA186_CLK_PLLC4_OUT_MUX 279
+/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when DFLLDISP_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
+#define TEGRA186_CLK_DFLLDISP_DIV 284
+/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when PLLDISPHUB_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
+#define TEGRA186_CLK_PLLDISPHUB_DIV 285
+/** fixed /8 divider which is used as the input for TEGRA186_CLK_SOR_SAFE */
+#define TEGRA186_CLK_PLLP_DIV8 286
+/** @brief output of divider CLK_RST_CONTROLLER_BPMP_NIC_RATE */
+#define TEGRA186_CLK_BPMP_NIC 287
+/** @brief output of the divider CLK_RST_CONTROLLER_PLLA1_OUT1 */
+#define TEGRA186_CLK_PLL_A_OUT1 288
+/** @deprecated */
+#define TEGRA186_CLK_GPC2CLK 289
+/** A fake clock which must be enabled during KFUSE read operations to ensure adequate VDD_CORE voltage. */
+#define TEGRA186_CLK_KFUSE 293
+/**
+ * @brief controls the PLLE hardware sequencer.
+ * @details This clock only has enable and disable methods. When the
+ * PLLE hw sequencer is enabled, PLLE, will be enabled or disabled by
+ * hw based on the control signals from the PCIe, SATA and XUSB
+ * clocks. When the PLLE hw sequencer is disabled, the state of PLLE
+ * is controlled by sw using clk_enable/clk_disable on
+ * TEGRA186_CLK_PLLE.
+ */
+#define TEGRA186_CLK_PLLE_PWRSEQ 294
+/** fixed 60MHz clock divided down from, TEGRA186_CLK_PLL_U */
+#define TEGRA186_CLK_PLLREFE_REF 295
+/** @brief output of mux controlled by SOR0_CLK_SEL0 and SOR0_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
+#define TEGRA186_CLK_SOR0_OUT 296
+/** @brief output of mux controlled by SOR1_CLK_SEL0 and SOR1_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
+#define TEGRA186_CLK_SOR1_OUT 297
+/** @brief fixed /5 divider.  Output frequency of this clock is TEGRA186_CLK_PLLREFE_OUT1/5. Used as input for TEGRA186_CLK_EQOS_AXI */
+#define TEGRA186_CLK_PLLREFE_OUT1_DIV5 298
+/** @brief controls the UTMIP_PLL (aka PLLU) hardware sqeuencer */
+#define TEGRA186_CLK_UTMIP_PLL_PWRSEQ 301
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL0_MGMT */
+#define TEGRA186_CLK_PEX_USB_PAD0_MGMT 302
+/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL1_MGMT */
+#define TEGRA186_CLK_PEX_USB_PAD1_MGMT 303
+/** @brief controls the UPHY_PLL0 hardware sqeuencer */
+#define TEGRA186_CLK_UPHY_PLL0_PWRSEQ 304
+/** @brief controls the UPHY_PLL1 hardware sqeuencer */
+#define TEGRA186_CLK_UPHY_PLL1_PWRSEQ 305
+/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC so the bypass output even be used when the PLL is disabled */
+#define TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH 306
+/** @brief output of the mux controlled by PLLREFE_SEL_CLKIN_PEX in CLK_RST_CONTROLLER_PLLREFE_MISC */
+#define TEGRA186_CLK_PLLREFE_PEX 307
+/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC to turn on the PLL when enabled */
+#define TEGRA186_CLK_PLLREFE_IDDQ 308
+/** @brief output of the divider QSPI_CLK_DIV2_SEL in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
+#define TEGRA186_CLK_QSPI_OUT 309
+/**
+ * @brief GPC2CLK-div-2
+ * @details fixed /2 divider. Output frequency is
+ * TEGRA186_CLK_GPC2CLK/2. The frequency of this clock is the
+ * frequency at which the GPU graphics engine runs. */
+#define TEGRA186_CLK_GPCCLK 310
+/** @brief output of divider CLK_RST_CONTROLLER_AON_NIC_RATE */
+#define TEGRA186_CLK_AON_NIC 450
+/** @brief output of divider CLK_RST_CONTROLLER_SCE_NIC_RATE */
+#define TEGRA186_CLK_SCE_NIC 451
+/** Fixed 100MHz PLL for PCIe, SATA and superspeed USB */
+#define TEGRA186_CLK_PLLE 512
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC_BASE */
+#define TEGRA186_CLK_PLLC 513
+/** Fixed 408MHz PLL for use by peripheral clocks */
+#define TEGRA186_CLK_PLLP 516
+/** @deprecated */
+#define TEGRA186_CLK_PLL_P TEGRA186_CLK_PLLP
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD_BASE for use by DSI */
+#define TEGRA186_CLK_PLLD 518
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD2_BASE for use by HDMI or DP */
+#define TEGRA186_CLK_PLLD2 519
+/**
+ * @brief PLL controlled by CLK_RST_CONTROLLER_PLLREFE_BASE.
+ * @details Note that this clock only controls the VCO output, before
+ * the post-divider. See TEGRA186_CLK_PLLREFE_OUT1 for more
+ * information.
+ */
+#define TEGRA186_CLK_PLLREFE_VCO 520
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC2_BASE */
+#define TEGRA186_CLK_PLLC2 521
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC3_BASE */
+#define TEGRA186_CLK_PLLC3 522
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDP_BASE for use as the DP link clock */
+#define TEGRA186_CLK_PLLDP 523
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC4_BASE */
+#define TEGRA186_CLK_PLLC4_VCO 524
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLA1_BASE for use by audio clocks */
+#define TEGRA186_CLK_PLLA1 525
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLNVCSI_BASE */
+#define TEGRA186_CLK_PLLNVCSI 526
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDISPHUB_BASE */
+#define TEGRA186_CLK_PLLDISPHUB 527
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD3_BASE for use by HDMI or DP */
+#define TEGRA186_CLK_PLLD3 528
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLBPMPCAM_BASE */
+#define TEGRA186_CLK_PLLBPMPCAM 531
+/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLAON_BASE for use by IP blocks in the AON domain */
+#define TEGRA186_CLK_PLLAON 532
+/** Fixed frequency 960MHz PLL for USB and EAVB */
+#define TEGRA186_CLK_PLLU 533
+/** fixed /2 divider. Output frequency is TEGRA186_CLK_PLLC4_VCO/2 */
+#define TEGRA186_CLK_PLLC4_VCO_DIV2 535
+/** @brief NAFLL clock source for AXI_CBB */
+#define TEGRA186_CLK_NAFLL_AXI_CBB 564
+/** @brief NAFLL clock source for BPMP */
+#define TEGRA186_CLK_NAFLL_BPMP 565
+/** @brief NAFLL clock source for ISP */
+#define TEGRA186_CLK_NAFLL_ISP 566
+/** @brief NAFLL clock source for NVDEC */
+#define TEGRA186_CLK_NAFLL_NVDEC 567
+/** @brief NAFLL clock source for NVENC */
+#define TEGRA186_CLK_NAFLL_NVENC 568
+/** @brief NAFLL clock source for NVJPG */
+#define TEGRA186_CLK_NAFLL_NVJPG 569
+/** @brief NAFLL clock source for SCE */
+#define TEGRA186_CLK_NAFLL_SCE 570
+/** @brief NAFLL clock source for SE */
+#define TEGRA186_CLK_NAFLL_SE 571
+/** @brief NAFLL clock source for TSEC */
+#define TEGRA186_CLK_NAFLL_TSEC 572
+/** @brief NAFLL clock source for TSECB */
+#define TEGRA186_CLK_NAFLL_TSECB 573
+/** @brief NAFLL clock source for VI */
+#define TEGRA186_CLK_NAFLL_VI 574
+/** @brief NAFLL clock source for VIC */
+#define TEGRA186_CLK_NAFLL_VIC 575
+/** @brief NAFLL clock source for DISP */
+#define TEGRA186_CLK_NAFLL_DISP 576
+/** @brief NAFLL clock source for GPU */
+#define TEGRA186_CLK_NAFLL_GPU 577
+/** @brief NAFLL clock source for M-CPU cluster */
+#define TEGRA186_CLK_NAFLL_MCPU 578
+/** @brief NAFLL clock source for B-CPU cluster */
+#define TEGRA186_CLK_NAFLL_BCPU 579
+/** @brief input from Tegra's CLK_32K_IN pad */
+#define TEGRA186_CLK_CLK_32K 608
+/** @brief output of divider CLK_RST_CONTROLLER_CLK_M_DIVIDE */
+#define TEGRA186_CLK_CLK_M 609
+/** @brief output of divider PLL_REF_DIV in CLK_RST_CONTROLLER_OSC_CTRL */
+#define TEGRA186_CLK_PLL_REF 610
+/** @brief input from Tegra's XTAL_IN */
+#define TEGRA186_CLK_OSC 612
+/** @brief clock recovered from EAVB input */
+#define TEGRA186_CLK_EQOS_RX_INPUT 613
+/** @brief clock recovered from DTV input */
+#define TEGRA186_CLK_DTV_INPUT 614
+/** @brief SOR0 brick output which feeds into SOR0_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0*/
+#define TEGRA186_CLK_SOR0_PAD_CLKOUT 615
+/** @brief SOR1 brick output which feeds into SOR1_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1*/
+#define TEGRA186_CLK_SOR1_PAD_CLKOUT 616
+/** @brief clock recovered from I2S1 input */
+#define TEGRA186_CLK_I2S1_SYNC_INPUT 617
+/** @brief clock recovered from I2S2 input */
+#define TEGRA186_CLK_I2S2_SYNC_INPUT 618
+/** @brief clock recovered from I2S3 input */
+#define TEGRA186_CLK_I2S3_SYNC_INPUT 619
+/** @brief clock recovered from I2S4 input */
+#define TEGRA186_CLK_I2S4_SYNC_INPUT 620
+/** @brief clock recovered from I2S5 input */
+#define TEGRA186_CLK_I2S5_SYNC_INPUT 621
+/** @brief clock recovered from I2S6 input */
+#define TEGRA186_CLK_I2S6_SYNC_INPUT 622
+/** @brief clock recovered from SPDIFIN input */
+#define TEGRA186_CLK_SPDIFIN_SYNC_INPUT 623
+
+/**
+ * @brief subject to change
+ * @details maximum clock identifier value plus one.
+ */
+#define TEGRA186_CLK_CLK_MAX 624
+
+/** @} */
+
+#endif
diff --git a/include/dt-bindings/power/tegra186-powergate.h b/include/dt-bindings/power/tegra186-powergate.h
new file mode 100644
index 000000000000..70630c6ea768
--- /dev/null
+++ b/include/dt-bindings/power/tegra186-powergate.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
+#define _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
+
+#define TEGRA186_POWER_DOMAIN_AUD	0
+#define TEGRA186_POWER_DOMAIN_DFD	1
+#define TEGRA186_POWER_DOMAIN_DISP	2
+#define TEGRA186_POWER_DOMAIN_DISPB	3
+#define TEGRA186_POWER_DOMAIN_DISPC	4
+#define TEGRA186_POWER_DOMAIN_ISPA	5
+#define TEGRA186_POWER_DOMAIN_NVDEC	6
+#define TEGRA186_POWER_DOMAIN_NVJPG	7
+#define TEGRA186_POWER_DOMAIN_MPE	8
+#define TEGRA186_POWER_DOMAIN_PCX	9
+#define TEGRA186_POWER_DOMAIN_SAX	10
+#define TEGRA186_POWER_DOMAIN_VE	11
+#define TEGRA186_POWER_DOMAIN_VIC	12
+#define TEGRA186_POWER_DOMAIN_XUSBA	13
+#define TEGRA186_POWER_DOMAIN_XUSBB	14
+#define TEGRA186_POWER_DOMAIN_XUSBC	15
+#define TEGRA186_POWER_DOMAIN_GPU	43
+#define TEGRA186_POWER_DOMAIN_MAX	44
+
+#endif
diff --git a/include/dt-bindings/reset/tegra186-reset.h b/include/dt-bindings/reset/tegra186-reset.h
new file mode 100644
index 000000000000..26b4ba9b0a57
--- /dev/null
+++ b/include/dt-bindings/reset/tegra186-reset.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ABI_MACH_T186_RESET_T186_H_
+#define _ABI_MACH_T186_RESET_T186_H_
+
+#define TEGRA186_RESET_ACTMON			0
+#define TEGRA186_RESET_AFI			1
+#define TEGRA186_RESET_CEC			2
+#define TEGRA186_RESET_CSITE			3
+#define TEGRA186_RESET_DP2			4
+#define TEGRA186_RESET_DPAUX			5
+#define TEGRA186_RESET_DSI			6
+#define TEGRA186_RESET_DSIB			7
+#define TEGRA186_RESET_DTV			8
+#define TEGRA186_RESET_DVFS			9
+#define TEGRA186_RESET_ENTROPY			10
+#define TEGRA186_RESET_EXTPERIPH1		11
+#define TEGRA186_RESET_EXTPERIPH2		12
+#define TEGRA186_RESET_EXTPERIPH3		13
+#define TEGRA186_RESET_GPU			14
+#define TEGRA186_RESET_HDA			15
+#define TEGRA186_RESET_HDA2CODEC_2X		16
+#define TEGRA186_RESET_HDA2HDMICODEC		17
+#define TEGRA186_RESET_HOST1X			18
+#define TEGRA186_RESET_I2C1			19
+#define TEGRA186_RESET_I2C2			20
+#define TEGRA186_RESET_I2C3			21
+#define TEGRA186_RESET_I2C4			22
+#define TEGRA186_RESET_I2C5			23
+#define TEGRA186_RESET_I2C6			24
+#define TEGRA186_RESET_ISP			25
+#define TEGRA186_RESET_KFUSE			26
+#define TEGRA186_RESET_LA			27
+#define TEGRA186_RESET_MIPI_CAL			28
+#define TEGRA186_RESET_PCIE			29
+#define TEGRA186_RESET_PCIEXCLK			30
+#define TEGRA186_RESET_SATA			31
+#define TEGRA186_RESET_SATACOLD			32
+#define TEGRA186_RESET_SDMMC1			33
+#define TEGRA186_RESET_SDMMC2			34
+#define TEGRA186_RESET_SDMMC3			35
+#define TEGRA186_RESET_SDMMC4			36
+#define TEGRA186_RESET_SE			37
+#define TEGRA186_RESET_SOC_THERM		38
+#define TEGRA186_RESET_SOR0			39
+#define TEGRA186_RESET_SPI1			40
+#define TEGRA186_RESET_SPI2			41
+#define TEGRA186_RESET_SPI3			42
+#define TEGRA186_RESET_SPI4			43
+#define TEGRA186_RESET_TMR			44
+#define TEGRA186_RESET_TRIG_SYS			45
+#define TEGRA186_RESET_TSEC			46
+#define TEGRA186_RESET_UARTA			47
+#define TEGRA186_RESET_UARTB			48
+#define TEGRA186_RESET_UARTC			49
+#define TEGRA186_RESET_UARTD			50
+#define TEGRA186_RESET_VI			51
+#define TEGRA186_RESET_VIC			52
+#define TEGRA186_RESET_XUSB_DEV			53
+#define TEGRA186_RESET_XUSB_HOST		54
+#define TEGRA186_RESET_XUSB_PADCTL		55
+#define TEGRA186_RESET_XUSB_SS			56
+#define TEGRA186_RESET_AON_APB			57
+#define TEGRA186_RESET_AXI_CBB			58
+#define TEGRA186_RESET_BPMP_APB			59
+#define TEGRA186_RESET_CAN1			60
+#define TEGRA186_RESET_CAN2			61
+#define TEGRA186_RESET_DMIC5			62
+#define TEGRA186_RESET_DSIC			63
+#define TEGRA186_RESET_DSID			64
+#define TEGRA186_RESET_EMC_EMC			65
+#define TEGRA186_RESET_EMC_MEM			66
+#define TEGRA186_RESET_EMCSB_EMC		67
+#define TEGRA186_RESET_EMCSB_MEM		68
+#define TEGRA186_RESET_EQOS			69
+#define TEGRA186_RESET_GPCDMA			70
+#define TEGRA186_RESET_GPIO_CTL0		71
+#define TEGRA186_RESET_GPIO_CTL1		72
+#define TEGRA186_RESET_GPIO_CTL2		73
+#define TEGRA186_RESET_GPIO_CTL3		74
+#define TEGRA186_RESET_GPIO_CTL4		75
+#define TEGRA186_RESET_GPIO_CTL5		76
+#define TEGRA186_RESET_I2C10			77
+#define TEGRA186_RESET_I2C12			78
+#define TEGRA186_RESET_I2C13			79
+#define TEGRA186_RESET_I2C14			80
+#define TEGRA186_RESET_I2C7			81
+#define TEGRA186_RESET_I2C8			82
+#define TEGRA186_RESET_I2C9			83
+#define TEGRA186_RESET_JTAG2AXI			84
+#define TEGRA186_RESET_MPHY_IOBIST		85
+#define TEGRA186_RESET_MPHY_L0_RX		86
+#define TEGRA186_RESET_MPHY_L0_TX		87
+#define TEGRA186_RESET_NVCSI			88
+#define TEGRA186_RESET_NVDISPLAY0_HEAD0		89
+#define TEGRA186_RESET_NVDISPLAY0_HEAD1		90
+#define TEGRA186_RESET_NVDISPLAY0_HEAD2		91
+#define TEGRA186_RESET_NVDISPLAY0_MISC		92
+#define TEGRA186_RESET_NVDISPLAY0_WGRP0		93
+#define TEGRA186_RESET_NVDISPLAY0_WGRP1		94
+#define TEGRA186_RESET_NVDISPLAY0_WGRP2		95
+#define TEGRA186_RESET_NVDISPLAY0_WGRP3		96
+#define TEGRA186_RESET_NVDISPLAY0_WGRP4		97
+#define TEGRA186_RESET_NVDISPLAY0_WGRP5		98
+#define TEGRA186_RESET_PWM1			99
+#define TEGRA186_RESET_PWM2			100
+#define TEGRA186_RESET_PWM3			101
+#define TEGRA186_RESET_PWM4			102
+#define TEGRA186_RESET_PWM5			103
+#define TEGRA186_RESET_PWM6			104
+#define TEGRA186_RESET_PWM7			105
+#define TEGRA186_RESET_PWM8			106
+#define TEGRA186_RESET_SCE_APB			107
+#define TEGRA186_RESET_SOR1			108
+#define TEGRA186_RESET_TACH			109
+#define TEGRA186_RESET_TSC			110
+#define TEGRA186_RESET_UARTF			111
+#define TEGRA186_RESET_UARTG			112
+#define TEGRA186_RESET_UFSHC			113
+#define TEGRA186_RESET_UFSHC_AXI_M		114
+#define TEGRA186_RESET_UPHY			115
+#define TEGRA186_RESET_ADSP			116
+#define TEGRA186_RESET_ADSPDBG			117
+#define TEGRA186_RESET_ADSPINTF			118
+#define TEGRA186_RESET_ADSPNEON			119
+#define TEGRA186_RESET_ADSPPERIPH		120
+#define TEGRA186_RESET_ADSPSCU			121
+#define TEGRA186_RESET_ADSPWDT			122
+#define TEGRA186_RESET_APE			123
+#define TEGRA186_RESET_DPAUX1			124
+#define TEGRA186_RESET_NVDEC			125
+#define TEGRA186_RESET_NVENC			126
+#define TEGRA186_RESET_NVJPG			127
+#define TEGRA186_RESET_PEX_USB_UPHY		128
+#define TEGRA186_RESET_QSPI			129
+#define TEGRA186_RESET_TSECB			130
+#define TEGRA186_RESET_VI_I2C			131
+#define TEGRA186_RESET_UARTE			132
+#define TEGRA186_RESET_TOP_GTE			133
+#define TEGRA186_RESET_SHSP			134
+#define TEGRA186_RESET_PEX_USB_UPHY_L5		135
+#define TEGRA186_RESET_PEX_USB_UPHY_L4		136
+#define TEGRA186_RESET_PEX_USB_UPHY_L3		137
+#define TEGRA186_RESET_PEX_USB_UPHY_L2		138
+#define TEGRA186_RESET_PEX_USB_UPHY_L1		139
+#define TEGRA186_RESET_PEX_USB_UPHY_L0		140
+#define TEGRA186_RESET_PEX_USB_UPHY_PLL1	141
+#define TEGRA186_RESET_PEX_USB_UPHY_PLL0	142
+#define TEGRA186_RESET_TSCTNVI			143
+#define TEGRA186_RESET_EXTPERIPH4		144
+#define TEGRA186_RESET_DSIPADCTL		145
+#define TEGRA186_RESET_AUD_MCLK			146
+#define TEGRA186_RESET_MPHY_CLK_CTL		147
+#define TEGRA186_RESET_MPHY_L1_RX		148
+#define TEGRA186_RESET_MPHY_L1_TX		149
+#define TEGRA186_RESET_UFSHC_LP			150
+#define TEGRA186_RESET_BPMP_NIC			151
+#define TEGRA186_RESET_BPMP_NSYSPORESET		152
+#define TEGRA186_RESET_BPMP_NRESET		153
+#define TEGRA186_RESET_BPMP_DBGRESETN		154
+#define TEGRA186_RESET_BPMP_PRESETDBGN		155
+#define TEGRA186_RESET_BPMP_PM			156
+#define TEGRA186_RESET_BPMP_CVC			157
+#define TEGRA186_RESET_BPMP_DMA			158
+#define TEGRA186_RESET_BPMP_HSP			159
+#define TEGRA186_RESET_TSCTNBPMP		160
+#define TEGRA186_RESET_BPMP_TKE			161
+#define TEGRA186_RESET_BPMP_GTE			162
+#define TEGRA186_RESET_BPMP_PM_ACTMON		163
+#define TEGRA186_RESET_AON_NIC			164
+#define TEGRA186_RESET_AON_NSYSPORESET		165
+#define TEGRA186_RESET_AON_NRESET		166
+#define TEGRA186_RESET_AON_DBGRESETN		167
+#define TEGRA186_RESET_AON_PRESETDBGN		168
+#define TEGRA186_RESET_AON_ACTMON		169
+#define TEGRA186_RESET_AOPM			170
+#define TEGRA186_RESET_AOVC			171
+#define TEGRA186_RESET_AON_DMA			172
+#define TEGRA186_RESET_AON_GPIO			173
+#define TEGRA186_RESET_AON_HSP			174
+#define TEGRA186_RESET_TSCTNAON			175
+#define TEGRA186_RESET_AON_TKE			176
+#define TEGRA186_RESET_AON_GTE			177
+#define TEGRA186_RESET_SCE_NIC			178
+#define TEGRA186_RESET_SCE_NSYSPORESET		179
+#define TEGRA186_RESET_SCE_NRESET		180
+#define TEGRA186_RESET_SCE_DBGRESETN		181
+#define TEGRA186_RESET_SCE_PRESETDBGN		182
+#define TEGRA186_RESET_SCE_ACTMON		183
+#define TEGRA186_RESET_SCE_PM			184
+#define TEGRA186_RESET_SCE_DMA			185
+#define TEGRA186_RESET_SCE_HSP			186
+#define TEGRA186_RESET_TSCTNSCE			187
+#define TEGRA186_RESET_SCE_TKE			188
+#define TEGRA186_RESET_SCE_GTE			189
+#define TEGRA186_RESET_SCE_CFG			190
+#define TEGRA186_RESET_ADSP_ALL			191
+/** @brief controls the power up/down sequence of UFSHC PSW partition. Controls LP_PWR_READY, LP_ISOL_EN, and LP_RESET_N signals */
+#define TEGRA186_RESET_UFSHC_LP_SEQ		192
+#define TEGRA186_RESET_SIZE			193
+
+#endif
-- 
2.9.2

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

* [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
  2016-07-27 21:24 ` [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver Stephen Warren
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

This adds the DT content that's needed to allow board DTs to enable use
of BPMP, clocks, resets, GPIOs, eMMC, and SD cards.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/dts/tegra186.dtsi | 55 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi
index 650feb60b1ab..25e1e8dfc035 100644
--- a/arch/arm/dts/tegra186.dtsi
+++ b/arch/arm/dts/tegra186.dtsi
@@ -1,14 +1,16 @@
 #include "skeleton.dtsi"
+#include <dt-bindings/clock/tegra186-clock.h>
 #include <dt-bindings/gpio/tegra186-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/tegra186-hsp.h>
+#include <dt-bindings/reset/tegra186-reset.h>
 
 / {
 	compatible = "nvidia,tegra186";
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	gpio at 2200000 {
+	gpio_main: gpio at 2200000 {
 		compatible = "nvidia,tegra186-gpio";
 		reg-names = "security", "gpio";
 		reg =
@@ -34,9 +36,24 @@
 		status = "disabled";
 	};
 
+	sdhci at 3400000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03400000 0x0 0x200>;
+		resets = <&bpmp TEGRA186_RESET_SDMMC1>;
+		reset-names = "sdmmc";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC1>;
+		clock-names = "sdmmc";
+		interrupts = <GIC_SPI 62 0x04>;
+		status = "disabled";
+	};
+
 	sdhci at 3460000 {
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03460000 0x0 0x200>;
+		resets = <&bpmp TEGRA186_RESET_SDMMC4>;
+		reset-names = "sdmmc";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC4>;
+		clock-names = "sdmmc";
 		interrupts = <GIC_SPI 31 0x04>;
 		status = "disabled";
 	};
@@ -49,7 +66,7 @@
 		#mbox-cells = <2>;
 	};
 
-	gpio at c2f0000 {
+	gpio_aon: gpio at c2f0000 {
 		compatible = "nvidia,tegra186-gpio-aon";
 		reg-names = "security", "gpio";
 		reg =
@@ -62,4 +79,38 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sysram at 30000000 {
+		compatible = "nvidia,tegra186-sysram", "mmio-sram";
+		reg = <0x0 0x30000000 0x0 0x50000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+		sysram_cpu_bpmp_tx: shmem at 4e000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4e000 0x0 0x1000>;
+		};
+
+		sysram_cpu_bpmp_rx: shmem at 4f000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4f000 0x0 0x1000>;
+		};
+	};
+
+	bpmp: bpmp {
+		compatible = "nvidia,tegra186-bpmp";
+		mboxes = <&hsp HSP_MBOX_TYPE_DB HSP_DB_MASTER_BPMP>;
+		/*
+		 * In theory, these references, and the configuration in the
+		 * node these reference point at, are board-specific, since
+		 * they depend on the BCT's memory carve-out setup, the
+		 * firmware that's actually loaded onto the BPMP, etc. However,
+		 * in practice, all boards are likely to use identical values.
+		 */
+		shmem = <&sysram_cpu_bpmp_tx &sysram_cpu_bpmp_rx>;
+		#clock-cells = <1>;
+		#power-domain-cells = <1>;
+		#reset-cells = <1>;
+	};
 };
-- 
2.9.2

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

* [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
  2016-07-27 21:24 ` [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings Stephen Warren
  2016-07-27 21:24 ` [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver Stephen Warren
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

The Tegra BPMP (Boot and Power Management Processor) is a separate
auxiliary CPU embedded into Tegra to perform power management work, and
controls related features such as clocks, resets, power domains, PMIC I2C
bus, etc. This driver provides the core low-level communication path by
which feature-specific drivers (such as clock) can make requests to the
BPMP. This driver is similar to an MFD driver in the Linux kernel. It is
unconditionally selected by CONFIG_TEGRA186 since virtually any Tegra186
build of U-Boot will need the feature.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/include/asm/arch-tegra/bpmp_abi.h      | 1601 +++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/tegra186_bpmp.h |   14 +
 arch/arm/mach-tegra/Kconfig                     |    2 +
 drivers/misc/Kconfig                            |   12 +
 drivers/misc/Makefile                           |    1 +
 drivers/misc/tegra186_bpmp.c                    |  250 ++++
 6 files changed, 1880 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-tegra/bpmp_abi.h
 create mode 100644 arch/arm/include/asm/arch-tegra/tegra186_bpmp.h
 create mode 100644 drivers/misc/tegra186_bpmp.c

diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
new file mode 100644
index 000000000000..0aaef5960e29
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
@@ -0,0 +1,1601 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ABI_BPMP_ABI_H_
+#define _ABI_BPMP_ABI_H_
+
+#ifdef LK
+#include <stdint.h>
+#endif
+
+#ifndef __ABI_PACKED
+#define __ABI_PACKED __attribute__((packed))
+#endif
+
+#ifdef NO_GCC_EXTENSIONS
+#define EMPTY char empty;
+#define EMPTY_ARRAY 1
+#else
+#define EMPTY
+#define EMPTY_ARRAY 0
+#endif
+
+#ifndef __UNION_ANON
+#define __UNION_ANON
+#endif
+/**
+ * @file
+ */
+
+
+/**
+ * @defgroup MRQ MRQ Messages
+ * @brief Messages sent to/from BPMP via IPC
+ * @{
+ *   @defgroup MRQ_Format Message Format
+ *   @defgroup MRQ_Codes Message Request (MRQ) Codes
+ *   @defgroup MRQ_Payloads Message Payloads
+ *   @defgroup Error_Codes Error Codes
+ * @}
+ */
+
+/**
+ * @addtogroup MRQ_Format Message Format
+ * @{
+ * The CPU requests the BPMP to perform a particular service by
+ * sending it an IVC frame containing a single MRQ message. An MRQ
+ * message consists of a @ref mrq_request followed by a payload whose
+ * format depends on mrq_request::mrq.
+ *
+ * The BPMP processes the data and replies with an IVC frame (on the
+ * same IVC channel) containing and MRQ response. An MRQ response
+ * consists of a @ref mrq_response followed by a payload whose format
+ * depends on the associated mrq_request::mrq.
+ *
+ * A well-defined subset of the MRQ messages that the CPU sends to the
+ * BPMP can lead to BPMP eventually sending an MRQ message to the
+ * CPU. For example, when the CPU uses an #MRQ_THERMAL message to set
+ * a thermal trip point, the BPMP may eventually send a single
+ * #MRQ_THERMAL message of its own to the CPU indicating that the trip
+ * point has been crossed.
+ * @}
+ */
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ message
+ *
+ * Provides the MRQ number for the MRQ message: #mrq. The remainder of
+ * the MRQ message is a payload (immediately following the
+ * mrq_request) whose format depends on mrq.
+ *
+ * @todo document the flags
+ */
+struct mrq_request {
+	/** @brief MRQ number of the request */
+	uint32_t mrq;
+	/** @brief flags for the request */
+	uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * @brief header for an MRQ response
+ *
+ *  Provides an error code for the associated MRQ message. The
+ *  remainder of the MRQ response is a payload (immediately following
+ *  the mrq_response) whose format depends on the associated
+ *  mrq_request::mrq
+ *
+ * @todo document the flags
+ */
+struct mrq_response {
+	/** @brief error code for the MRQ request itself */
+	int32_t err;
+	/** @brief flags for the response */
+	uint32_t flags;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Format
+ * Minimum needed size for an IPC message buffer
+ */
+#define MSG_MIN_SZ	128
+/**
+ * @ingroup MRQ_Format
+ *  Minimum size guaranteed for data in an IPC message buffer
+ */
+#define MSG_DATA_MIN_SZ	120
+
+/**
+ * @ingroup MRQ_Codes
+ * @name Legal MRQ codes
+ * These are the legal values for mrq_request::mrq
+ * @{
+ */
+
+#define MRQ_PING		0
+#define MRQ_QUERY_TAG		1
+#define MRQ_MODULE_LOAD		4
+#define MRQ_MODULE_UNLOAD	5
+#define MRQ_TRACE_MODIFY	7
+#define MRQ_WRITE_TRACE		8
+#define MRQ_THREADED_PING	9
+#define MRQ_MODULE_MAIL		11
+#define MRQ_DEBUGFS		19
+#define MRQ_RESET		20
+#define MRQ_I2C			21
+#define MRQ_CLK			22
+#define MRQ_QUERY_ABI		23
+#define MRQ_PG_READ_STATE	25
+#define MRQ_PG_UPDATE_STATE	26
+#define MRQ_THERMAL		27
+#define MRQ_CPU_VHINT		28
+#define MRQ_ABI_RATCHET		29
+#define MRQ_EMC_DVFS_LATENCY	31
+#define MRQ_TRACE_ITER		64
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @brief Maximum MRQ code to be sent by CPU software to
+ * BPMP. Subject to change in future
+ */
+#define MAX_CPU_MRQ_ID		64
+
+/**
+ * @addtogroup MRQ_Payloads Message Payloads
+ * @{
+ *   @defgroup Ping
+ *   @defgroup Query_Tag Query Tag
+ *   @defgroup Module Loadable Modules
+ *   @defgroup Trace
+ *   @defgroup Debugfs
+ *   @defgroup Reset
+ *   @defgroup I2C
+ *   @defgroup Clocks
+ *   @defgroup ABI_info ABI Info
+ *   @defgroup MC_Flush MC Flush
+ *   @defgroup Powergating
+ *   @defgroup Thermal
+ *   @defgroup Vhint CPU Voltage hint
+ *   @defgroup MRQ_Deprecated Deprecated MRQ messages
+ *   @defgroup EMC
+ * @}
+ */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PING
+ * @brief A simple ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * @ingroup MRQ_Codes
+ * @def MRQ_THREADED_PING
+ * @brief A deeper ping
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_ping_request
+ * * Response Payload: @ref mrq_ping_response
+ *
+ * Behavior is equivalent to a simple #MRQ_PING except that BPMP
+ * responds from a thread context (providing a slightly more robust
+ * sign of life).
+ *
+ */
+
+/**
+ * @ingroup Ping
+ * @brief request with #MRQ_PING
+ *
+ * Used by the sender of an #MRQ_PING message to request a pong from
+ * recipient. The response from the recipient is computed based on
+ * #challenge.
+ */
+struct mrq_ping_request {
+/** @brief arbitrarily chosen value */
+	uint32_t challenge;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Ping
+ * @brief response to #MRQ_PING
+ *
+ * Sent in response to an #MRQ_PING message. #reply should be the
+ * mrq_ping_request challenge left shifted by 1 with the carry-bit
+ * dropped.
+ *
+ */
+struct mrq_ping_response {
+	/** @brief response to the MRQ_PING challege */
+	uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_TAG
+ * @brief Query BPMP firmware's tag (i.e. version information)
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_query_tag_request
+ * * Response Payload: N/A
+ *
+ */
+
+/**
+ * @ingroup Query_Tag
+ * @brief request with #MRQ_QUERY_TAG
+ *
+ * Used by #MRQ_QUERY_TAG call to ask BPMP to fill in the memory
+ * pointed by #addr with BPMP firmware header.
+ *
+ * The sender is reponsible for ensuring that #addr is mapped in to
+ * the recipient's address map.
+ */
+struct mrq_query_tag_request {
+  /** @brief base address to store the firmware header */
+	uint32_t addr;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_LOAD
+ * @brief dynamically load a BPMP code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_load_request
+ * * Response Payload: @ref mrq_module_load_response
+ *
+ * @note This MRQ is disabled on production systems
+ *
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_LOAD
+ *
+ * Used by #MRQ_MODULE_LOAD calls to ask the recipient to dynamically
+ * load the code located at #phys_addr and having size #size
+ * bytes. #phys_addr is treated as a void pointer.
+ *
+ * The recipient copies the code from #phys_addr to locally allocated
+ * memory prior to responding to this message.
+ *
+ * @todo document the module header format
+ *
+ * The sender is responsible for ensuring that the code is mapped in
+ * the recipient's address map.
+ *
+ */
+struct mrq_module_load_request {
+	/** @brief base address of the code to load. Treated as (void *) */
+	uint32_t phys_addr; /* (void *) */
+	/** @brief size in bytes of code to load */
+	uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_LOAD
+ *
+ * @todo document mrq_response::err
+ */
+struct mrq_module_load_response {
+	/** @brief handle to the loaded module */
+	uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_UNLOAD
+ * @brief unload a previously loaded code module
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_unload_request
+ * * Response Payload: N/A
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_UNLOAD
+ *
+ * Used by #MRQ_MODULE_UNLOAD calls to request that a previously loaded
+ * module be unloaded.
+ */
+struct mrq_module_unload_request {
+	/** @brief handle of the module to unload */
+	uint32_t base;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_MODIFY
+ * @brief modify the set of enabled trace events
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_trace_modify_request
+ * * Response Payload: @ref mrq_trace_modify_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_TRACE_MODIFY
+ *
+ * Used by %MRQ_TRACE_MODIFY calls to enable or disable specify trace
+ * events.  #set takes precedence for any bit set in both #set and
+ * #clr.
+ */
+struct mrq_trace_modify_request {
+	/** @brief bit mask of trace events to disable */
+	uint32_t clr;
+	/** @brief bit mask of trace events to enable */
+	uint32_t set;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_TRACE_MODIFY
+ *
+ * Sent in repsonse to an #MRQ_TRACE_MODIFY message. #mask reflects the
+ * state of which events are enabled after the recipient acted on the
+ * message.
+ *
+ */
+struct mrq_trace_modify_response {
+	/** @brief bit mask of trace event enable states */
+	uint32_t mask;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_WRITE_TRACE
+ * @brief Write trace data to a buffer
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_write_trace_request
+ * * Response Payload: @ref mrq_write_trace_response
+ *
+ * mrq_response::err depends on the @ref mrq_write_trace_request field
+ * values. err is -#BPMP_EINVAL if size is zero or area is NULL or
+ * area is in an illegal range. A positive value for err indicates the
+ * number of bytes written to area.
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Trace
+ * @brief request with #MRQ_WRITE_TRACE
+ *
+ * Used by MRQ_WRITE_TRACE calls to ask the recipient to copy trace
+ * data from the recipient's local buffer to the output buffer. #area
+ * is treated as a byte-aligned pointer in the recipient's address
+ * space.
+ *
+ * The sender is responsible for ensuring that the output
+ * buffer is mapped in the recipient's address map. The recipient is
+ * responsible for protecting its own code and data from accidental
+ * overwrites.
+ */
+struct mrq_write_trace_request {
+	/** @brief base address of output buffer */
+	uint32_t area;
+	/** @brief size in bytes of the output buffer */
+	uint32_t size;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Trace
+ * @brief response to #MRQ_WRITE_TRACE
+ *
+ * Once this response is sent, the respondent will not access the
+ * output buffer further.
+ */
+struct mrq_write_trace_response {
+	/**
+	 * @brief flag whether more data remains in local buffer
+	 *
+	 * Value is 1 if the entire local trace buffer has been
+	 * drained to the outputbuffer. Value is 0 otherwise.
+	 */
+	uint32_t eof;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_request {
+	uint32_t challenge;
+} __ABI_PACKED;
+
+/** @private */
+struct mrq_threaded_ping_response {
+	uint32_t reply;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_MODULE_MAIL
+ * @brief send a message to a loadable module
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_module_mail_request
+ * * Response Payload: @ref mrq_module_mail_response
+ *
+ * @note This MRQ is disabled on production systems
+ */
+
+/**
+ * @ingroup Module
+ * @brief request with #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_request {
+	/** @brief handle to the previously loaded module */
+	uint32_t base;
+	/** @brief module-specific mail payload
+	 *
+	 * The length of data[ ] is unknown to the BPMP core firmware
+	 * but it is limited to the size of an IPC message.
+	 */
+	uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup Module
+ * @brief response to #MRQ_MODULE_MAIL
+ */
+struct mrq_module_mail_response {
+	/** @brief module-specific mail payload
+	 *
+	 * The length of data[ ] is unknown to the BPMP core firmware
+	 * but it is limited to the size of an IPC message.
+	 */
+	uint8_t data[EMPTY_ARRAY];
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_DEBUGFS
+ * @brief Interact with BPMP's debugfs file nodes
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_debugfs_request
+ * * Response Payload: @ref mrq_debugfs_response
+ */
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ *
+ * The BPMP firmware implements a pseudo-filesystem called
+ * debugfs. Any driver within the firmware may register with debugfs
+ * to expose an arbitrary set of "files" in the filesystem. When
+ * software on the CPU writes to a debugfs file, debugfs passes the
+ * written data to a callback provided by the driver. When software on
+ * the CPU reads a debugfs file, debugfs queries the driver for the
+ * data to return to the CPU. The intention of the debugfs filesystem
+ * is to provide information useful for debugging the system at
+ * runtime.
+ *
+ * @note The files exposed via debugfs are not part of the
+ * BPMP firmware's ABI. debugfs files may be added or removed in any
+ * given version of the firmware. Typically the semantics of a debugfs
+ * file are consistent from version to version but even that is not
+ * guaranteed.
+ *
+ * @}
+ */
+/** @ingroup Debugfs */
+enum mrq_debugfs_commands {
+	CMD_DEBUGFS_READ = 1,
+	CMD_DEBUGFS_WRITE = 2,
+	CMD_DEBUGFS_DUMPDIR = 3,
+	CMD_DEBUGFS_MAX
+};
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_request {
+	/** @brief physical address pointing at filename */
+	uint32_t fnameaddr;
+	/** @brief length in bytes of filename buffer */
+	uint32_t fnamelen;
+	/** @brief physical address pointing to data buffer */
+	uint32_t dataaddr;
+	/** @brief length in bytes of data buffer */
+	uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief parameters for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_dumpdir_request {
+	/** @brief physical address pointing to data buffer */
+	uint32_t dataaddr;
+	/** @brief length in bytes of data buffer */
+	uint32_t datalen;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_READ/WRITE command
+ */
+struct cmd_debugfs_fileop_response {
+	/** @brief always 0 */
+	uint32_t reserved;
+	/** @brief number of bytes read from or written to data buffer */
+	uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief response data for CMD_DEBUGFS_DUMPDIR command
+ */
+struct cmd_debugfs_dumpdir_response {
+	/** @brief always 0 */
+	uint32_t reserved;
+	/** @brief number of bytes read from or written to data buffer */
+	uint32_t nbytes;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ * @brief request with #MRQ_DEBUGFS.
+ *
+ * The sender of an MRQ_DEBUGFS message uses #cmd to specify a debugfs
+ * command to execute. Legal commands are the values of @ref
+ * mrq_debugfs_commands. Each command requires a specific additional
+ * payload of data.
+ *
+ * |command            |payload|
+ * |-------------------|-------|
+ * |CMD_DEBUGFS_READ   |fop    |
+ * |CMD_DEBUGFS_WRITE  |fop    |
+ * |CMD_DEBUGFS_DUMPDIR|dumpdir|
+ */
+struct mrq_debugfs_request {
+	uint32_t cmd;
+	union {
+		struct cmd_debugfs_fileop_request fop;
+		struct cmd_debugfs_dumpdir_request dumpdir;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Debugfs
+ */
+struct mrq_debugfs_response {
+	/** @brief always 0 */
+	int32_t reserved;
+	union {
+		/** @brief response data for CMD_DEBUGFS_READ OR
+		 * CMD_DEBUGFS_WRITE command
+		 */
+		struct cmd_debugfs_fileop_response fop;
+		/** @brief response data for CMD_DEBUGFS_DUMPDIR command */
+		struct cmd_debugfs_dumpdir_response dumpdir;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @addtogroup Debugfs
+ * @{
+ */
+#define DEBUGFS_S_ISDIR	(1 << 9)
+#define DEBUGFS_S_IRUSR	(1 << 8)
+#define DEBUGFS_S_IWUSR	(1 << 7)
+/** @} */
+
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_RESET
+ * @brief reset an IP block
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_reset_request
+ * * Response Payload: N/A
+ */
+
+/**
+ * @ingroup Reset
+ */
+enum mrq_reset_commands {
+	CMD_RESET_ASSERT = 1,
+	CMD_RESET_DEASSERT = 2,
+	CMD_RESET_MODULE = 3,
+	CMD_RESET_MAX, /* not part of ABI and subject to change */
+};
+
+/**
+ * @ingroup Reset
+ * @brief request with MRQ_RESET
+ *
+ * Used by the sender of an #MRQ_RESET message to request BPMP to
+ * assert or or deassert a given reset line.
+ */
+struct mrq_reset_request {
+	/** @brief reset action to perform (@enum mrq_reset_commands) */
+	uint32_t cmd;
+	/** @brief id of the reset to affected */
+	uint32_t reset_id;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_I2C
+ * @brief issue an i2c transaction
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_i2c_request
+ * * Response Payload: @ref mrq_i2c_response
+ */
+
+/**
+ * @addtogroup I2C
+ * @{
+ */
+#define TEGRA_I2C_IPC_MAX_IN_BUF_SIZE	(MSG_DATA_MIN_SZ - 12)
+#define TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE	(MSG_DATA_MIN_SZ - 4)
+/** @} */
+
+/**
+ * @ingroup I2C
+ * @name Serial I2C flags
+ * Use these flags with serial_i2c_request::flags
+ * @{
+ */
+#define SERIALI2C_TEN           0x0010
+#define SERIALI2C_RD            0x0001
+#define SERIALI2C_STOP          0x8000
+#define SERIALI2C_NOSTART       0x4000
+#define SERIALI2C_REV_DIR_ADDR  0x2000
+#define SERIALI2C_IGNORE_NAK    0x1000
+#define SERIALI2C_NO_RD_ACK     0x0800
+#define SERIALI2C_RECV_LEN      0x0400
+/** @} */
+/** @ingroup I2C */
+enum {
+	CMD_I2C_XFER = 1
+};
+
+/**
+ * @ingroup I2C
+ * @brief serializable i2c request
+ *
+ * Instances of this structure are packed (little-endian) into
+ * cmd_i2c_xfer_request::data_buf. Each instance represents a single
+ * transaction (or a portion of a transaction with repeated starts) on
+ * an i2c bus.
+ *
+ * Because these structures are packed, some instances are likely to
+ * be misaligned. Additionally because #data is variable length, it is
+ * not possible to iterate through a serialized list of these
+ * structures without inspecting #len in each instance.  It may be
+ * easier to serialize or deserialize cmd_i2c_xfer_request::data_buf
+ * manually rather than using this structure definition.
+*/
+struct serial_i2c_request {
+	/** @brief I2C slave address */
+	uint16_t addr;
+	/** @brief bitmask of SERIALI2C_ flags */
+	uint16_t flags;
+	/** @brief length of I2C transaction in bytes */
+	uint16_t len;
+	/** @brief for write transactions only, #len bytes of data */
+	uint8_t data[];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief trigger one or more i2c transactions
+ */
+struct cmd_i2c_xfer_request {
+	/** @brief valid bus number from mach-t186/i2c-t186.h*/
+	uint32_t bus_id;
+
+	/** @brief count of valid bytes in #data_buf*/
+	uint32_t data_size;
+
+	/** @brief serialized packed instances of @ref serial_i2c_request*/
+	uint8_t data_buf[TEGRA_I2C_IPC_MAX_IN_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief container for data read from the i2c bus
+ *
+ * Processing an cmd_i2c_xfer_request::data_buf causes BPMP to execute
+ * zero or more I2C reads. The data read from the bus is serialized
+ * into #data_buf.
+ */
+struct cmd_i2c_xfer_response {
+	/** @brief count of valid bytes in #data_buf*/
+	uint32_t data_size;
+	/** @brief i2c read data */
+	uint8_t data_buf[TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE];
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief request with #MRQ_I2C
+ */
+struct mrq_i2c_request {
+	/** @brief always CMD_I2C_XFER (i.e. 1) */
+	uint32_t cmd;
+	/** @brief parameters of the transfer request */
+	struct cmd_i2c_xfer_request xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup I2C
+ * @brief response to #MRQ_I2C
+ */
+struct mrq_i2c_response {
+	struct cmd_i2c_xfer_response xfer;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CLK
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_clk_request
+ * * Response Payload: @ref mrq_clk_response
+ * @addtogroup Clocks
+ * @{
+ */
+
+/**
+ * @name MRQ_CLK sub-commands
+ * @{
+ */
+enum {
+	CMD_CLK_GET_RATE = 1,
+	CMD_CLK_SET_RATE = 2,
+	CMD_CLK_ROUND_RATE = 3,
+	CMD_CLK_GET_PARENT = 4,
+	CMD_CLK_SET_PARENT = 5,
+	CMD_CLK_IS_ENABLED = 6,
+	CMD_CLK_ENABLE = 7,
+	CMD_CLK_DISABLE = 8,
+	CMD_CLK_GET_ALL_INFO = 14,
+	CMD_CLK_GET_MAX_CLK_ID = 15,
+	CMD_CLK_MAX,
+};
+/** @} */
+
+#define MRQ_CLK_NAME_MAXLEN	40
+#define MRQ_CLK_MAX_PARENTS	16
+
+/** @private */
+struct cmd_clk_get_rate_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_request {
+	int32_t unused;
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_set_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_request {
+	int32_t unused;
+	int64_t rate;
+} __ABI_PACKED;
+
+struct cmd_clk_round_rate_response {
+	int64_t rate;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_parent_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_parent_response {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_request {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+struct cmd_clk_set_parent_response {
+	uint32_t parent_id;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_is_enabled_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_is_enabled_response {
+	int32_t state;
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_request {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_enable_response {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_request {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_disable_response {
+	EMPTY
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_all_info_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_all_info_response {
+	uint32_t flags;
+	uint32_t parent;
+	uint32_t parents[MRQ_CLK_MAX_PARENTS];
+	uint8_t num_parents;
+	uint8_t name[MRQ_CLK_NAME_MAXLEN];
+} __ABI_PACKED;
+
+/** @private */
+struct cmd_clk_get_max_clk_id_request {
+	EMPTY
+} __ABI_PACKED;
+
+struct cmd_clk_get_max_clk_id_response {
+	uint32_t max_id;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup Clocks
+ * @brief request with #MRQ_CLK
+ *
+ * Used by the sender of an #MRQ_CLK message to control clocks. The
+ * clk_request is split into several sub-commands. Some sub-commands
+ * require no additional data. Others have a sub-command specific
+ * payload
+ *
+ * |sub-command                 |payload                |
+ * |----------------------------|-----------------------|
+ * |CMD_CLK_GET_RATE            |-                      |
+ * |CMD_CLK_SET_RATE            |clk_set_rate           |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate         |
+ * |CMD_CLK_GET_PARENT          |-                      |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent         |
+ * |CMD_CLK_IS_ENABLED          |-                      |
+ * |CMD_CLK_ENABLE              |-                      |
+ * |CMD_CLK_DISABLE             |-                      |
+ * |CMD_CLK_GET_ALL_INFO        |-                      |
+ * |CMD_CLK_GET_MAX_CLK_ID      |-                      |
+ *
+ */
+
+struct mrq_clk_request {
+	/** @brief sub-command and clock id concatenated to 32-bit word.
+	 * - bits[31..24] is the sub-cmd.
+	 * - bits[23..0] is the clock id
+	 */
+	uint32_t cmd_and_id;
+
+	union {
+		/** @private */
+		struct cmd_clk_get_rate_request clk_get_rate;
+		struct cmd_clk_set_rate_request clk_set_rate;
+		struct cmd_clk_round_rate_request clk_round_rate;
+		/** @private */
+		struct cmd_clk_get_parent_request clk_get_parent;
+		struct cmd_clk_set_parent_request clk_set_parent;
+		/** @private */
+		struct cmd_clk_enable_request clk_enable;
+		/** @private */
+		struct cmd_clk_disable_request clk_disable;
+		/** @private */
+		struct cmd_clk_is_enabled_request clk_is_enabled;
+		/** @private */
+		struct cmd_clk_get_all_info_request clk_get_all_info;
+		/** @private */
+		struct cmd_clk_get_max_clk_id_request clk_get_max_clk_id;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup Clocks
+ * @brief response to MRQ_CLK
+ *
+ * Each sub-command supported by @ref mrq_clk_request may return
+ * sub-command-specific data. Some do and some do not as indicated in
+ * the following table
+ *
+ * |sub-command                 |payload                 |
+ * |----------------------------|------------------------|
+ * |CMD_CLK_GET_RATE            |clk_get_rate            |
+ * |CMD_CLK_SET_RATE            |clk_set_rate            |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate          |
+ * |CMD_CLK_GET_PARENT          |clk_get_parent          |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent          |
+ * |CMD_CLK_IS_ENABLED          |clk_is_enabled          |
+ * |CMD_CLK_ENABLE              |-                       |
+ * |CMD_CLK_DISABLE             |-                       |
+ * |CMD_CLK_GET_ALL_INFO        |clk_get_all_info        |
+ * |CMD_CLK_GET_MAX_CLK_ID      |clk_get_max_id          |
+ *
+ */
+
+struct mrq_clk_response {
+	union {
+		struct cmd_clk_get_rate_response clk_get_rate;
+		struct cmd_clk_set_rate_response clk_set_rate;
+		struct cmd_clk_round_rate_response clk_round_rate;
+		struct cmd_clk_get_parent_response clk_get_parent;
+		struct cmd_clk_set_parent_response clk_set_parent;
+		/** @private */
+		struct cmd_clk_enable_response clk_enable;
+		/** @private */
+		struct cmd_clk_disable_response clk_disable;
+		struct cmd_clk_is_enabled_response clk_is_enabled;
+		struct cmd_clk_get_all_info_response clk_get_all_info;
+		struct cmd_clk_get_max_clk_id_response clk_get_max_clk_id;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_QUERY_ABI
+ * @brief check if an MRQ is implemented
+ *
+ * * Platforms: All
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: @ref mrq_query_abi_request
+ * * Response Payload: @ref mrq_query_abi_response
+ */
+
+/**
+ * @ingroup ABI_info
+ * @brief request with MRQ_QUERY_ABI
+ *
+ * Used by #MRQ_QUERY_ABI call to check if MRQ code #mrq is supported
+ * by the recipient.
+ */
+struct mrq_query_abi_request {
+	/** @brief MRQ code to query */
+	uint32_t mrq;
+} __ABI_PACKED;
+
+/**
+ * @ingroup ABI_info
+ * @brief response to MRQ_QUERY_ABI
+ */
+struct mrq_query_abi_response {
+	/** @brief 0 if queried MRQ is supported. Else, -#BPMP_ENODEV */
+	int32_t status;
+} __ABI_PACKED;
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_READ_STATE
+ * @brief read the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_read_state_request
+ * * Response Payload: @ref mrq_pg_read_state_response
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_PG_READ_STATE
+ *
+ * Used by MRQ_PG_READ_STATE call to read the current state of a
+ * partition.
+ */
+struct mrq_pg_read_state_request {
+	/** @brief ID of partition */
+	uint32_t partition_id;
+} __ABI_PACKED;
+
+/**
+ * @brief response to MRQ_PG_READ_STATE
+ * @todo define possible errors.
+ */
+struct mrq_pg_read_state_response {
+	/** @brief read as don't care */
+	uint32_t sram_state;
+	/** @brief state of power partition
+	 * * 0 : off
+	 * * 1 : on
+	 */
+	uint32_t logic_state;
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_PG_UPDATE_STATE
+ * @brief modify the power-gating state of a partition
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_pg_update_state_request
+ * * Response Payload: N/A
+ * @addtogroup Powergating
+ * @{
+ */
+
+/**
+ * @brief request with mrq_pg_update_state_request
+ *
+ * Used by #MRQ_PG_UPDATE_STATE call to request BPMP to change the
+ * state of a power partition #partition_id.
+ */
+struct mrq_pg_update_state_request {
+	/** @brief ID of partition */
+	uint32_t partition_id;
+	/** @brief secondary control of power partition
+	 *  @details Ignored by many versions of the BPMP
+	 *  firmware. For maximum compatibility, set the value
+	 *  according to @logic_state
+	 * *  0x1: power ON partition (@ref logic_state == 0x3)
+	 * *  0x3: power OFF partition (@ref logic_state == 0x1)
+	 */
+	uint32_t sram_state;
+	/** @brief controls state of power partition, legal values are
+	 * *  0x1 : power OFF partition
+	 * *  0x3 : power ON partition
+	 */
+	uint32_t logic_state;
+	/** @brief change state of clocks of the power partition, legal values
+	 * *  0x0 : do not change clock state
+	 * *  0x1 : disable partition clocks (only applicable when
+	 *          @ref logic_state == 0x1)
+	 * *  0x3 : enable partition clocks (only applicable when
+	 *          @ref logic_state == 0x3)
+	 */
+	uint32_t clock_state;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_THERMAL
+ * @brief interact with BPMP thermal framework
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: Any
+ * * Request Payload: TODO
+ * * Response Payload: TODO
+ *
+ * @addtogroup Thermal
+ *
+ * The BPMP firmware includes a thermal framework. Drivers within the
+ * bpmp firmware register with the framework to provide thermal
+ * zones. Each thermal zone corresponds to an entity whose temperature
+ * can be measured. The framework also has a notion of trip points. A
+ * trip point consists of a thermal zone id, a temperature, and a
+ * callback routine. The framework invokes the callback when the zone
+ * hits the indicated temperature. The BPMP firmware uses this thermal
+ * framework interally to implement various temperature-dependent
+ * functions.
+ *
+ * Software on the CPU can use #MRQ_THERMAL (with payload @ref
+ * mrq_thermal_host_to_bpmp_request) to interact with the BPMP thermal
+ * framework. The CPU must It can query the number of supported zones,
+ * query zone temperatures, and set trip points.
+ *
+ * When a trip point set by the CPU gets crossed, BPMP firmware issues
+ * an IPC to the CPU having mrq_request::mrq = #MRQ_THERMAL and a
+ * payload of @ref mrq_thermal_bpmp_to_host_request.
+ * @{
+ */
+enum mrq_thermal_host_to_bpmp_cmd {
+	/**
+	 * @brief Check whether the BPMP driver supports the specified
+	 * request type.
+	 *
+	 * Host needs to supply request parameters.
+	 *
+	 * mrq_response::err is 0 if the specified request is
+	 * supported and -#BPMP_ENODEV otherwise.
+	 */
+	CMD_THERMAL_QUERY_ABI = 0,
+
+	/**
+	 * @brief Get the current temperature of the specified zone.
+	 *
+	 * Host needs to supply request parameters.
+	 *
+	 * mrq_response::err is
+	 * *  0: Temperature query succeeded.
+	 * *  -#BPMP_EINVAL: Invalid request parameters.
+	 * *  -#BPMP_ENOENT: No driver registered for thermal zone..
+	 * *  -#BPMP_EFAULT: Problem reading temperature measurement.
+	 */
+	CMD_THERMAL_GET_TEMP = 1,
+
+	/**
+	 * @brief Enable or disable and set the lower and upper
+	 *   thermal limits for a thermal trip point. Each zone has
+	 *   one trip point.
+	 *
+	 * Host needs to supply request parameters. Once the
+	 * temperature hits a trip point, the BPMP will send a message
+	 * to the CPU having MRQ=MRQ_THERMAL and
+	 * type=CMD_THERMAL_HOST_TRIP_REACHED
+	 *
+	 * mrq_response::err is
+	 * *  0: Trip successfully set.
+	 * *  -#BPMP_EINVAL: Invalid request parameters.
+	 * *  -#BPMP_ENOENT: No driver registered for thermal zone.
+	 * *  -#BPMP_EFAULT: Problem setting trip point.
+	 */
+	CMD_THERMAL_SET_TRIP = 2,
+
+	/**
+	 * @brief Get the number of supported thermal zones.
+	 *
+	 * No request parameters required.
+	 *
+	 * mrq_response::err is always 0, indicating success.
+	 */
+	CMD_THERMAL_GET_NUM_ZONES = 3,
+
+	/** @brief: number of supported host-to-bpmp commands. May
+	 * increase in future
+	 */
+	CMD_THERMAL_HOST_TO_BPMP_NUM
+};
+
+enum mrq_thermal_bpmp_to_host_cmd {
+	/**
+	 * @brief Indication that the temperature for a zone has
+	 *   exceeded the range indicated in the thermal trip point
+	 *   for the zone.
+	 *
+	 * BPMP needs to supply request parameters. Host only needs to
+	 * acknowledge.
+	 */
+	CMD_THERMAL_HOST_TRIP_REACHED = 100,
+
+	/** @brief: number of supported bpmp-to-host commands. May
+	 * increase in future
+	 */
+	CMD_THERMAL_BPMP_TO_HOST_NUM
+};
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_QUERY_ABI
+ *
+ * zone: Request type for which to check existence.
+ */
+struct cmd_thermal_query_abi_request {
+	uint32_t type;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_GET_TEMP
+ *
+ * zone: Number of thermal zone.
+ */
+struct cmd_thermal_get_temp_request {
+	uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request CMD_THERMAL_GET_TEMP
+ *
+ * error: 0 if request succeeded.
+ *	-BPMP_EINVAL if request parameters were invalid.
+ *      -BPMP_ENOENT if no driver was registered for the specified thermal zone.
+ *      -BPMP_EFAULT for other thermal zone driver errors.
+ * temp: Current temperature in millicelsius.
+ */
+struct cmd_thermal_get_temp_response {
+	int32_t temp;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data for request type CMD_THERMAL_SET_TRIP
+ *
+ * zone: Number of thermal zone.
+ * low: Temperature of lower trip point in millicelsius
+ * high: Temperature of upper trip point in millicelsius
+ * enabled: 1 to enable trip point, 0 to disable trip point
+ */
+struct cmd_thermal_set_trip_request {
+	uint32_t zone;
+	int32_t low;
+	int32_t high;
+	uint32_t enabled;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data for request type CMD_THERMAL_HOST_TRIP_REACHED
+ *
+ * zone: Number of thermal zone where trip point was reached.
+ */
+struct cmd_thermal_host_trip_reached_request {
+	uint32_t zone;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host reply data for request type CMD_THERMAL_GET_NUM_ZONES
+ *
+ * num: Number of supported thermal zones. The thermal zones are indexed
+ *      starting from zero.
+ */
+struct cmd_thermal_get_num_zones_response {
+	uint32_t num;
+} __ABI_PACKED;
+
+/*
+ * Host->BPMP request data.
+ *
+ * Reply type is union mrq_thermal_bpmp_to_host_response.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_host_to_bpmp_request {
+	uint32_t type;
+	union {
+		struct cmd_thermal_query_abi_request query_abi;
+		struct cmd_thermal_get_temp_request get_temp;
+		struct cmd_thermal_set_trip_request set_trip;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * BPMP->Host request data.
+ *
+ * type: Type of request. Values listed in enum mrq_thermal_type.
+ * data: Request type specific parameters.
+ */
+struct mrq_thermal_bpmp_to_host_request {
+	uint32_t type;
+	union {
+		struct cmd_thermal_host_trip_reached_request host_trip_reached;
+	} __UNION_ANON;
+} __ABI_PACKED;
+
+/*
+ * Data in reply to a Host->BPMP request.
+ */
+union mrq_thermal_bpmp_to_host_response {
+	struct cmd_thermal_get_temp_response get_temp;
+	struct cmd_thermal_get_num_zones_response get_num_zones;
+} __ABI_PACKED;
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_CPU_VHINT
+ * @brief Query CPU voltage hint data
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_cpu_vhint_request
+ * * Response Payload: N/A
+ *
+ * @addtogroup Vhint CPU Voltage hint
+ * @{
+ */
+
+/**
+ * @brief request with #MRQ_CPU_VHINT
+ *
+ * Used by #MRQ_CPU_VHINT call by CCPLEX to retrieve voltage hint data
+ * from BPMP to memory space pointed by #addr. CCPLEX is responsible
+ * to allocate sizeof(cpu_vhint_data) sized block of memory and
+ * appropriately map it for BPMP before sending the request.
+ */
+struct mrq_cpu_vhint_request {
+	/** @brief IOVA address for the #cpu_vhint_data */
+	uint32_t addr; /* struct cpu_vhint_data * */
+	/** @brief ID of the cluster whose data is requested */
+	uint32_t cluster_id; /* enum cluster_id */
+} __ABI_PACKED;
+
+/**
+ * @brief description of the CPU v/f relation
+ *
+ * Used by #MRQ_CPU_VHINT call to carry data pointed by #addr of
+ * struct mrq_cpu_vhint_request
+ */
+struct cpu_vhint_data {
+	uint32_t ref_clk_hz; /**< reference frequency in Hz */
+	uint16_t pdiv; /**< post divider value */
+	uint16_t mdiv; /**< input divider value */
+	uint16_t ndiv_max; /**< fMAX expressed with max NDIV value */
+	/** table of ndiv values as a function of vINDEX (voltage index) */
+	uint16_t ndiv[80];
+	/** minimum allowed NDIV value */
+	uint16_t ndiv_min;
+	/** minimum allowed voltage hint value (as in vINDEX) */
+	uint16_t vfloor;
+	/** maximum allowed voltage hint value (as in vINDEX) */
+	uint16_t vceil;
+	/** post-multiplier for vindex value */
+	uint16_t vindex_mult;
+	/** post-divider for vindex value */
+	uint16_t vindex_div;
+	/** reserved for future use */
+	uint16_t reserved[328];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_ABI_RATCHET
+ * @brief ABI ratchet value query
+ *
+ * * Platforms: T186
+ * * Initiators: Any
+ * * Targets: BPMP
+ * * Request Payload: @ref mrq_abi_ratchet_request
+ * * Response Payload: @ref mrq_abi_ratchet_response
+ * @addtogroup ABI_info
+ * @{
+ */
+
+/**
+ * @brief an ABI compatibility mechanism
+ *
+ * BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future
+ * revision of this header file.
+ * 1. That future revision deprecates some MRQ
+ * 2. That future revision introduces a breaking change to an existing
+ *    MRQ or
+ * 3. A bug is discovered in an existing implementation of the BPMP-FW
+ *    (or possibly one of its clients) which warrants deprecating that
+ *    implementation.
+ */
+#define BPMP_ABI_RATCHET_VALUE 3
+
+/**
+ * @brief request with #MRQ_ABI_RATCHET.
+ *
+ * #ratchet should be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which the requester was compiled.
+ *
+ * If ratchet is less than BPMP's #BPMP_ABI_RATCHET_VALUE, BPMP may
+ * reply with mrq_response::err = -#BPMP_ERANGE to indicate that
+ * BPMP-FW cannot interoperate correctly with the requester. Requester
+ * should cease further communication with BPMP.
+ *
+ * Otherwise, err shall be 0.
+ */
+struct mrq_abi_ratchet_request {
+	/** @brief requester's ratchet value */
+	uint16_t ratchet;
+};
+
+/**
+ * @brief response to #MRQ_ABI_RATCHET
+ *
+ * #ratchet shall be #BPMP_ABI_RATCHET_VALUE from the ABI header
+ * against which BPMP firwmare was compiled.
+ *
+ * If #ratchet is less than the requester's #BPMP_ABI_RATCHET_VALUE,
+ * the requster must either interoperate with BPMP according to an ABI
+ * header version with BPMP_ABI_RATCHET_VALUE = ratchet or cease
+ * communication with BPMP.
+ *
+ * If mrq_response::err is 0 and ratchet is greater than or equal to the
+ * requester's BPMP_ABI_RATCHET_VALUE, the requester should continue
+ * normal operation.
+ */
+struct mrq_abi_ratchet_response {
+	/** @brief BPMP's ratchet value */
+	uint16_t ratchet;
+};
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_EMC_DVFS_LATENCY
+ * @brief query frequency dependent EMC DVFS latency
+ *
+ * * Platforms: T186
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_emc_dvfs_latency_response
+ * @addtogroup EMC
+ * @{
+ */
+
+/**
+ * @brief used by @ref mrq_emc_dvfs_latency_response
+ */
+struct emc_dvfs_latency {
+	/** @brief EMC frequency in kHz */
+	uint32_t freq;
+	/** @brief EMC DVFS latency in nanoseconds */
+	uint32_t latency;
+} __ABI_PACKED;
+
+#define EMC_DVFS_LATENCY_MAX_SIZE	14
+/**
+ * @brief response to #MRQ_EMC_DVFS_LATENCY
+ */
+struct mrq_emc_dvfs_latency_response {
+	/** @brief the number valid entries in #pairs */
+	uint32_t num_pairs;
+	/** @brief EMC <frequency, latency> information */
+	struct emc_dvfs_latency pairs[EMC_DVFS_LATENCY_MAX_SIZE];
+} __ABI_PACKED;
+
+/** @} */
+
+/**
+ * @ingroup MRQ_Codes
+ * @def MRQ_TRACE_ITER
+ * @brief manage the trace iterator
+ *
+ * * Platforms: All
+ * * Initiators: CCPLEX
+ * * Targets: BPMP
+ * * Request Payload: N/A
+ * * Response Payload: @ref mrq_trace_iter_request
+ * @addtogroup Trace
+ * @{
+ */
+enum {
+	/** @brief (re)start the tracing now. Ignore older events */
+	TRACE_ITER_INIT = 0,
+	/** @brief clobber all events in the trace buffer */
+	TRACE_ITER_CLEAN = 1
+};
+
+/**
+ * @brief request with #MRQ_TRACE_ITER
+ */
+struct mrq_trace_iter_request {
+	/** @brief TRACE_ITER_INIT or TRACE_ITER_CLEAN */
+	uint32_t cmd;
+} __ABI_PACKED;
+
+/** @} */
+
+/*
+ *  4. Enumerations
+ */
+
+/*
+ *   4.1 CPU enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.2 CPU Cluster enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ *
+ *   4.3 System low power state enumerations
+ *
+ * See <mach-t186/system-t186.h>
+ */
+
+/*
+ *   4.4 Clock enumerations
+ *
+ * For clock enumerations, see <mach-t186/clk-t186.h>
+ */
+
+/*
+ *   4.5 Reset enumerations
+ *
+ * For reset enumerations, see <mach-t186/reset-t186.h>
+ */
+
+/*
+ *   4.6 Thermal sensor enumerations
+ *
+ * For thermal sensor enumerations, see <mach-t186/thermal-t186.h>
+ */
+
+/**
+ * @defgroup Error_Codes
+ * Negative values for mrq_response::err generally indicate some
+ * error. The ABI defines the following error codes. Negating these
+ * defines is an exercise left to the user.
+ * @{
+ */
+/** @brief No such file or directory */
+#define BPMP_ENOENT	2
+/** @brief No MRQ handler */
+#define BPMP_ENOHANDLER	3
+/** @brief I/O error */
+#define BPMP_EIO	5
+/** @brief Bad sub-MRQ command */
+#define BPMP_EBADCMD	6
+/** @brief Not enough memory */
+#define BPMP_ENOMEM	12
+/** @brief Permission denied */
+#define BPMP_EACCES	13
+/** @brief Bad address */
+#define BPMP_EFAULT	14
+/** @brief No such device */
+#define BPMP_ENODEV	19
+/** @brief Argument is a directory */
+#define BPMP_EISDIR	21
+/** @brief Invalid argument */
+#define BPMP_EINVAL	22
+/** @brief Timeout during operation */
+#define BPMP_ETIMEDOUT  23
+/** @brief Out of range */
+#define BPMP_ERANGE	34
+/** @} */
+/** @} */
+#endif
diff --git a/arch/arm/include/asm/arch-tegra/tegra186_bpmp.h b/arch/arm/include/asm/arch-tegra/tegra186_bpmp.h
new file mode 100644
index 000000000000..d98f94ffecdf
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/tegra186_bpmp.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _TEGRA186_BPMP_H
+#define _TEGRA186_BPMP_H
+
+int tegra186_bpmp_call(struct udevice *dev, uint32_t mrq,
+		       void *tx_msg, uint32_t tx_size,
+		       void *rx_msg, uint32_t rx_size);
+
+#endif
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 85ae3b7f4209..ec2d8ac6a1a3 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -65,6 +65,8 @@ config TEGRA210
 config TEGRA186
 	bool "Tegra186 family"
 	select DM_MAILBOX
+	select MISC
+	select TEGRA186_BPMP
 	select TEGRA186_GPIO
 	select TEGRA_ARMV8_COMMON
 	select TEGRA_HSP
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2373037685c2..55c6845c0cb2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -130,6 +130,18 @@ config SYSRESET
 	  to effect a reset. The uclass will try all available drivers when
 	  reset_walk() is called.
 
+config TEGRA186_BPMP
+	bool "Enable support for the Tegra186 BPMP driver"
+	depends on TEGRA186
+	help
+	  The Tegra BPMP (Boot and Power Management Processor) is a separate
+	  auxiliary CPU embedded into Tegra to perform power management work,
+	  and controls related features such as clocks, resets, power domains,
+	  PMIC I2C bus, etc. This driver provides the core low-level
+	  communication path by which feature-specific drivers (such as clock)
+	  can make requests to the BPMP. This driver is similar to an MFD
+	  driver in the Linux kernel.
+
 config WINBOND_W83627
 	bool "Enable Winbond Super I/O driver"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 066639ba1f10..679a24d36d87 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
 obj-$(CONFIG_STATUS_LED) += status_led.o
 obj-$(CONFIG_SANDBOX) += swap_case.o
 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
+obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
new file mode 100644
index 000000000000..147528da9269
--- /dev/null
+++ b/drivers/misc/tegra186_bpmp.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <mailbox.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/ivc.h>
+#include <asm/arch-tegra/tegra186_bpmp.h>
+
+#define BPMP_IVC_FRAME_COUNT 1
+#define BPMP_IVC_FRAME_SIZE 128
+
+#define BPMP_FLAG_DO_ACK	BIT(0)
+#define BPMP_FLAG_RING_DOORBELL	BIT(1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_bpmp {
+	struct mbox_chan mbox;
+	struct tegra_ivc ivc;
+};
+
+int tegra186_bpmp_call(struct udevice *dev, uint32_t mrq,
+		       void *tx_msg, uint32_t tx_size,
+		       void *rx_msg, uint32_t rx_size)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+	int ret, err;
+	void *ivc_frame;
+	struct mrq_request *req;
+	struct mrq_response *resp;
+	ulong start_time;
+
+	debug("%s(dev=%p, mrq=%u, tx_msg=%p, tx_size=%u, rx_msg=%p, rx_size=%u) (priv=%p)\n",
+	      __func__, dev, mrq, tx_msg, tx_size, rx_msg, rx_size, priv);
+
+	if ((tx_size > BPMP_IVC_FRAME_SIZE) || (rx_size > BPMP_IVC_FRAME_SIZE))
+		return -EINVAL;
+
+	ret = tegra_ivc_write_get_next_frame(&priv->ivc, &ivc_frame);
+	if (ret) {
+		error("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
+		return ret;
+	}
+
+	req = ivc_frame;
+	req->mrq = mrq;
+	req->flags = BPMP_FLAG_DO_ACK | BPMP_FLAG_RING_DOORBELL;
+	memcpy(req + 1, tx_msg, tx_size);
+
+	ret = tegra_ivc_write_advance(&priv->ivc);
+	if (ret) {
+		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		return ret;
+	}
+
+	start_time = timer_get_us();
+	for (;;) {
+		ret = tegra_ivc_channel_notified(&priv->ivc);
+		if (ret) {
+			error("tegra_ivc_channel_notified() failed: %d\n", ret);
+			return ret;
+		}
+
+		ret = tegra_ivc_read_get_next_frame(&priv->ivc, &ivc_frame);
+		if (!ret)
+			break;
+
+		/* Timeout 20ms; roughly 10x current max observed duration */
+		if ((timer_get_us() - start_time) > 20 * 1000) {
+			error("tegra_ivc_read_get_next_frame() timed out (%d)\n",
+			      ret);
+			return -ETIMEDOUT;
+		}
+	}
+
+	resp = ivc_frame;
+	err = resp->err;
+	if (!err && rx_msg && rx_size)
+		memcpy(rx_msg, resp + 1, rx_size);
+
+	ret = tegra_ivc_read_advance(&priv->ivc);
+	if (ret) {
+		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		return ret;
+	}
+
+	if (err) {
+		error("BPMP responded with error %d\n", err);
+		/* err isn't a U-Boot error code, so don't that */
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * The BPMP exposes multiple different services. We create a sub-device for
+ * each separate type of service, since each device must be of the appropriate
+ * UCLASS.
+ */
+static int tegra186_bpmp_bind(struct udevice *dev)
+{
+	int ret;
+	struct udevice *child;
+
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
+					 dev->of_offset, &child);
+	if (ret)
+		return ret;
+
+	ret = device_bind_driver_to_node(dev, "tegra186_reset",
+					 "tegra186_reset", dev->of_offset,
+					 &child);
+	if (ret)
+		return ret;
+
+	ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
+					 "tegra186_power_domain",
+					 dev->of_offset, &child);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
+{
+	int ret;
+	struct fdtdec_phandle_args args;
+	struct udevice fakedev;
+	fdt_addr_t reg;
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					      "shmem", NULL, 0, index, &args);
+	if (ret < 0) {
+		error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
+		return ret;
+	}
+
+	fakedev.of_offset = args.node;
+	reg = dev_get_addr_index(&fakedev, 0);
+	if (reg == FDT_ADDR_T_NONE) {
+		error("dev_get_addr_index() failed\n");
+		return -ENODEV;
+	}
+
+	return reg;
+}
+
+static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc)
+{
+	struct tegra186_bpmp *priv =
+		container_of(ivc, struct tegra186_bpmp, ivc);
+	int ret;
+
+	ret = mbox_send(&priv->mbox, NULL);
+	if (ret)
+		error("mbox_send() failed: %d\n", ret);
+}
+
+static int tegra186_bpmp_probe(struct udevice *dev)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+	int ret;
+	ulong tx_base, rx_base, start_time;
+
+	debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+	ret = mbox_get_by_index(dev, 0, &priv->mbox);
+	if (ret) {
+		error("mbox_get_by_index() failed: %d\n", ret);
+		return ret;
+	}
+
+	tx_base = tegra186_bpmp_get_shmem(dev, 0);
+	if (IS_ERR_VALUE(tx_base)) {
+		error("tegra186_bpmp_get_shmem failed for tx_base\n");
+		return tx_base;
+	}
+	rx_base = tegra186_bpmp_get_shmem(dev, 1);
+	if (IS_ERR_VALUE(rx_base)) {
+		error("tegra186_bpmp_get_shmem failed for rx_base\n");
+		return rx_base;
+	}
+	debug("shmem: rx=%lx, tx=%lx\n", rx_base, tx_base);
+
+	ret = tegra_ivc_init(&priv->ivc, rx_base, tx_base, BPMP_IVC_FRAME_COUNT,
+			     BPMP_IVC_FRAME_SIZE, tegra186_bpmp_ivc_notify);
+	if (ret) {
+		error("tegra_ivc_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	tegra_ivc_channel_reset(&priv->ivc);
+	start_time = timer_get_us();
+	for (;;) {
+		ret = tegra_ivc_channel_notified(&priv->ivc);
+		if (!ret)
+			break;
+
+		/* Timeout 100ms */
+		if ((timer_get_us() - start_time) > 100 * 1000) {
+			error("Initial IVC reset timed out (%d)\n", ret);
+			ret = -ETIMEDOUT;
+			goto err_free_mbox;
+		}
+	}
+
+	return 0;
+
+err_free_mbox:
+	mbox_free(&priv->mbox);
+
+	return ret;
+}
+
+static int tegra186_bpmp_remove(struct udevice *dev)
+{
+	struct tegra186_bpmp *priv = dev_get_priv(dev);
+
+	debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
+
+	mbox_free(&priv->mbox);
+
+	return 0;
+}
+
+static const struct udevice_id tegra186_bpmp_ids[] = {
+	{ .compatible = "nvidia,tegra186-bpmp" },
+	{ }
+};
+
+U_BOOT_DRIVER(tegra186_bpmp) = {
+	.name		= "tegra186_bpmp",
+	.id		= UCLASS_MISC,
+	.of_match	= tegra186_bpmp_ids,
+	.bind		= tegra186_bpmp_bind,
+	.probe		= tegra186_bpmp_probe,
+	.remove		= tegra186_bpmp_remove,
+	.priv_auto_alloc_size = sizeof(struct tegra186_bpmp),
+};
-- 
2.9.2

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

* [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (2 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver Stephen Warren
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

In Tegra186, on-SoC clocks are manipulated using IPC requests to the BPMP
(Boot and Power Management Processor). This change implements a driver
that does that. A tegra/ sub-directory is created to follow the existing
pattern. It is unconditionally selected by CONFIG_TEGRA186 since virtually
any Tegra186 build of U-Boot will need the feature.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/Kconfig      |  2 +
 drivers/clk/Kconfig              |  1 +
 drivers/clk/Makefile             |  2 +
 drivers/clk/tegra/Kconfig        |  6 +++
 drivers/clk/tegra/Makefile       |  5 ++
 drivers/clk/tegra/tegra186-clk.c | 99 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 115 insertions(+)
 create mode 100644 drivers/clk/tegra/Kconfig
 create mode 100644 drivers/clk/tegra/Makefile
 create mode 100644 drivers/clk/tegra/tegra186-clk.c

diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index ec2d8ac6a1a3..e8186d515856 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -64,9 +64,11 @@ config TEGRA210
 
 config TEGRA186
 	bool "Tegra186 family"
+	select CLK
 	select DM_MAILBOX
 	select MISC
 	select TEGRA186_BPMP
+	select TEGRA186_CLOCK
 	select TEGRA186_GPIO
 	select TEGRA_ARMV8_COMMON
 	select TEGRA_HSP
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6eee8eb369bf..7dd56738b06a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -20,6 +20,7 @@ config SPL_CLK
 	  setting up clocks within SPL, and allows the same drivers to be
 	  used as U-Boot proper.
 
+source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/exynos/Kconfig"
 
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7a88912e06a..37b946cb6bdc 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -11,5 +11,7 @@ obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
 obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
+
+obj-y += tegra/
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
new file mode 100644
index 000000000000..659fe022c2af
--- /dev/null
+++ b/drivers/clk/tegra/Kconfig
@@ -0,0 +1,6 @@
+config TEGRA186_CLOCK
+	bool "Enable Tegra186 BPMP-based clock driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC clocks via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
new file mode 100644
index 000000000000..f32998ccc27d
--- /dev/null
+++ b/drivers/clk/tegra/Makefile
@@ -0,0 +1,5 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_TEGRA186_CLOCK) += tegra186-clk.o
diff --git a/drivers/clk/tegra/tegra186-clk.c b/drivers/clk/tegra/tegra186-clk.c
new file mode 100644
index 000000000000..fcfe3b47714a
--- /dev/null
+++ b/drivers/clk/tegra/tegra186-clk.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/tegra186_bpmp.h>
+
+static ulong tegra186_clk_get_rate(struct clk *clk)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+	int ret;
+
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
+
+	ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
+				 &req, sizeof(req), &resp, sizeof(resp));
+	if (ret)
+		return ret;
+
+	return resp.clk_get_rate.rate;
+}
+
+static ulong tegra186_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+	int ret;
+
+	debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate,
+	      clk->dev, clk->id);
+
+	req.cmd_and_id = (CMD_CLK_SET_RATE << 24) | clk->id;
+	req.clk_set_rate.rate = rate;
+
+	ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
+				 &req, sizeof(req), &resp, sizeof(resp));
+	if (ret)
+		return ret;
+
+	return resp.clk_set_rate.rate;
+}
+
+static int tegra186_clk_en_dis(struct clk *clk,
+			       enum mrq_reset_commands cmd)
+{
+	struct mrq_clk_request req;
+	struct mrq_clk_response resp;
+
+	req.cmd_and_id = (cmd << 24) | clk->id;
+
+	return tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
+				  &req, sizeof(req), &resp, sizeof(resp));
+}
+
+static int tegra186_clk_enable(struct clk *clk)
+{
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	return tegra186_clk_en_dis(clk, CMD_CLK_ENABLE);
+}
+
+static int tegra186_clk_disable(struct clk *clk)
+{
+	debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
+	      clk->id);
+
+	return tegra186_clk_en_dis(clk, CMD_CLK_DISABLE);
+}
+
+static struct clk_ops tegra186_clk_ops = {
+	.get_rate = tegra186_clk_get_rate,
+	.set_rate = tegra186_clk_set_rate,
+	.enable = tegra186_clk_enable,
+	.disable = tegra186_clk_disable,
+};
+
+static int tegra186_clk_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_clk) = {
+	.name		= "tegra186_clk",
+	.id		= UCLASS_CLK,
+	.probe		= tegra186_clk_probe,
+	.ops = &tegra186_clk_ops,
+};
-- 
2.9.2

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

* [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (3 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver Stephen Warren
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

In Tegra186, on-SoC reset signals are manipulated using IPC requests to
the BPMP (Boot and Power Management Processor). This change implements a
driver that does that. It is unconditionally selected by CONFIG_TEGRA186
since virtually any Tegra186 build of U-Boot will need the feature.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/Kconfig    |  2 ++
 drivers/reset/Kconfig          |  7 ++++
 drivers/reset/Makefile         |  1 +
 drivers/reset/tegra186-reset.c | 76 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+)
 create mode 100644 drivers/reset/tegra186-reset.c

diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index e8186d515856..1eaf40627254 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -66,10 +66,12 @@ config TEGRA186
 	bool "Tegra186 family"
 	select CLK
 	select DM_MAILBOX
+	select DM_RESET
 	select MISC
 	select TEGRA186_BPMP
 	select TEGRA186_CLOCK
 	select TEGRA186_GPIO
+	select TEGRA186_RESET
 	select TEGRA_ARMV8_COMMON
 	select TEGRA_HSP
 	select TEGRA_IVC
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0fe8cc3827f1..5b84f2178b71 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -20,4 +20,11 @@ config SANDBOX_RESET
 	  simply accepts requests to reset various HW modules without actually
 	  doing anything beyond a little error checking.
 
+config TEGRA186_RESET
+	bool "Enable Tegra186 BPMP-based reset driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC reset signals via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 71f3b219613e..ff0e0907758b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_DM_RESET) += reset-uclass.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
+obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
diff --git a/drivers/reset/tegra186-reset.c b/drivers/reset/tegra186-reset.c
new file mode 100644
index 000000000000..47bc6b843fea
--- /dev/null
+++ b/drivers/reset/tegra186-reset.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/tegra186_bpmp.h>
+
+static int tegra186_reset_request(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int tegra186_reset_free(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return 0;
+}
+
+static int tegra186_reset_common(struct reset_ctl *reset_ctl,
+				 enum mrq_reset_commands cmd)
+{
+	struct mrq_reset_request req;
+
+	req.cmd = cmd;
+	req.reset_id = reset_ctl->id;
+
+	return tegra186_bpmp_call(reset_ctl->dev->parent, MRQ_RESET,
+				  &req, sizeof(req), NULL, 0);
+}
+
+static int tegra186_reset_assert(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return tegra186_reset_common(reset_ctl, CMD_RESET_ASSERT);
+}
+
+static int tegra186_reset_deassert(struct reset_ctl *reset_ctl)
+{
+	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+	      reset_ctl->dev, reset_ctl->id);
+
+	return tegra186_reset_common(reset_ctl, CMD_RESET_DEASSERT);
+}
+
+struct reset_ops tegra186_reset_ops = {
+	.request = tegra186_reset_request,
+	.free = tegra186_reset_free,
+	.rst_assert = tegra186_reset_assert,
+	.rst_deassert = tegra186_reset_deassert,
+};
+
+static int tegra186_reset_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_reset) = {
+	.name		= "tegra186_reset",
+	.id		= UCLASS_RESET,
+	.probe		= tegra186_reset_probe,
+	.ops = &tegra186_reset_ops,
+};
-- 
2.9.2

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

* [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (4 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs Stephen Warren
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

In Tegra186, SoC power domains are manipulated using IPC requests to
the BPMP (Boot and Power Management Processor). This change implements a
driver that does that.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 drivers/power/domain/Kconfig                 |  7 +++
 drivers/power/domain/Makefile                |  1 +
 drivers/power/domain/tegra186-power-domain.c | 88 ++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+)
 create mode 100644 drivers/power/domain/tegra186-power-domain.c

diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index b90409743398..132e33250e8c 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -17,4 +17,11 @@ config SANDBOX_POWER_DOMAIN
 	  simply accepts requests to power on/off various HW modules without
 	  actually doing anything beyond a little error checking.
 
+config TEGRA186_POWER_DOMAIN
+	bool "Enable Tegra186 BPMP-based power domain driver"
+	depends on TEGRA186_BPMP
+	help
+	  Enable support for manipulating Tegra's on-SoC power domains via IPC
+	  requests to the BPMP (Boot and Power Management Processor).
+
 endmenu
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index c18292f0ec88..2c3d92638fbe 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
+obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
diff --git a/drivers/power/domain/tegra186-power-domain.c b/drivers/power/domain/tegra186-power-domain.c
new file mode 100644
index 000000000000..4ae4baabe57e
--- /dev/null
+++ b/drivers/power/domain/tegra186-power-domain.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power-domain-uclass.h>
+#include <asm/arch-tegra/bpmp_abi.h>
+#include <asm/arch-tegra/tegra186_bpmp.h>
+
+#define UPDATE	BIT(0)
+#define ON	BIT(1)
+
+static int tegra186_power_domain_request(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return 0;
+}
+
+static int tegra186_power_domain_free(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return 0;
+}
+
+static int tegra186_power_domain_common(struct power_domain *power_domain,
+					bool on)
+{
+	struct mrq_pg_update_state_request req;
+	int on_state = on ? ON : 0;
+
+	req.partition_id = power_domain->id;
+	req.logic_state = UPDATE | on_state;
+	req.sram_state = UPDATE | on_state;
+	/*
+	 * Drivers manage their own clocks so they don't get out of sync, and
+	 * since some power domains have many clocks, only a subset of which
+	 * are actually needed depending on use-case.
+	 */
+	req.clock_state = UPDATE;
+
+	return tegra186_bpmp_call(power_domain->dev->parent,
+				  MRQ_PG_UPDATE_STATE, &req, sizeof(req), NULL,
+				  0);
+}
+
+static int tegra186_power_domain_on(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return tegra186_power_domain_common(power_domain, true);
+}
+
+static int tegra186_power_domain_off(struct power_domain *power_domain)
+{
+	debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
+	      power_domain, power_domain->dev, power_domain->id);
+
+	return tegra186_power_domain_common(power_domain, false);
+}
+
+struct power_domain_ops tegra186_power_domain_ops = {
+	.request = tegra186_power_domain_request,
+	.free = tegra186_power_domain_free,
+	.on = tegra186_power_domain_on,
+	.off = tegra186_power_domain_off,
+};
+
+static int tegra186_power_domain_probe(struct udevice *dev)
+{
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(tegra186_power_domain) = {
+	.name = "tegra186_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.probe = tegra186_power_domain_probe,
+	.ops = &tegra186_power_domain_ops,
+};
-- 
2.9.2

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (5 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-07-28  1:09   ` Jaehoon Chung
  2016-08-01  2:20   ` Simon Glass
  2016-07-27 21:24 ` [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186 Stephen Warren
  2016-08-01  1:01 ` [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Simon Glass
  8 siblings, 2 replies; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 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>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
 drivers/mmc/tegra_mmc.c                     | 55 ++++++++++++++++++++++++-----
 2 files changed, 53 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..b27ca635ac50 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
@@ -359,11 +360,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 +542,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 +556,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 +597,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 +629,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] 30+ messages in thread

* [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (6 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs Stephen Warren
@ 2016-07-27 21:24 ` Stephen Warren
  2016-08-01  1:02   ` Simon Glass
  2016-08-01  1:01 ` [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Simon Glass
  8 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-07-27 21:24 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

Introduce tegra_board_init() and call it from board_init(). Tegra wil use
tegra_board_init() for board-specific initialization, and board_init() for
SoC-specific initialization.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/board186.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
index 876ccba5e599..a7583d443833 100644
--- a/arch/arm/mach-tegra/board186.c
+++ b/arch/arm/mach-tegra/board186.c
@@ -16,11 +16,16 @@ int board_early_init_f(void)
 	return 0;
 }
 
-int board_init(void)
+__weak int tegra_board_init(void)
 {
 	return 0;
 }
 
+int board_init(void)
+{
+	return tegra_board_init();
+}
+
 int board_late_init(void)
 {
 	return 0;
-- 
2.9.2

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-07-27 21:24 ` [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs Stephen Warren
@ 2016-07-28  1:09   ` Jaehoon Chung
  2016-07-28 16:03     ` Stephen Warren
  2016-08-01  2:20   ` Simon Glass
  1 sibling, 1 reply; 30+ messages in thread
From: Jaehoon Chung @ 2016-07-28  1:09 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 07/28/2016 06:24 AM, Stephen Warren 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>
> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
> ---
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
>  drivers/mmc/tegra_mmc.c                     | 55 ++++++++++++++++++++++++-----
>  2 files changed, 53 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..b27ca635ac50 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
> @@ -359,11 +360,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;
> +	}

It seems that doesn't need to add the bracket.

> +#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 +542,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 +556,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 +597,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 +629,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;
> +		}
> +	}

Ditto.

Best Regards,
Jaehoon Chung

> +#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__);
> 

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-07-28  1:09   ` Jaehoon Chung
@ 2016-07-28 16:03     ` Stephen Warren
  0 siblings, 0 replies; 30+ messages in thread
From: Stephen Warren @ 2016-07-28 16:03 UTC (permalink / raw)
  To: u-boot

On 07/27/2016 07:09 PM, Jaehoon Chung wrote:
> Hi Stephen,
>
> On 07/28/2016 06:24 AM, Stephen Warren 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.

>> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h

>> +#ifdef CONFIG_TEGRA186
>> +	{
>> +		ulong rate = clk_set_rate(&host->clk, clock);
>> +		div = (rate + clock - 1) / clock;
>> +	}
>
> It seems that doesn't need to add the bracket.

There's a variable declaration at the start of the block. Without the 
brackets, the compiler can/will complain about variable declarations 
being in the middle of a block.

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

* [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding
  2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
                   ` (7 preceding siblings ...)
  2016-07-27 21:24 ` [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186 Stephen Warren
@ 2016-08-01  1:01 ` Simon Glass
  8 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:01 UTC (permalink / raw)
  To: u-boot

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> The DT binding for the Tegra186 HSP module apparently wasn't quite final
> when I posted initial U-Boot support for it. Add the final DT binding doc
> and adapt all code and DT files to match it.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/dts/tegra186.dtsi                         | 10 ++---
>  .../mailbox/nvidia,tegra186-hsp.txt                | 52 ++++++++++++++++++++++
>  drivers/mailbox/tegra-hsp.c                        | 47 +++++++++++++++----
>  include/dt-bindings/mailbox/tegra-hsp.h            | 14 ------
>  include/dt-bindings/mailbox/tegra186-hsp.h         | 19 ++++++++
>  5 files changed, 113 insertions(+), 29 deletions(-)
>  create mode 100644 doc/device-tree-bindings/mailbox/nvidia,tegra186-hsp.txt
>  delete mode 100644 include/dt-bindings/mailbox/tegra-hsp.h
>  create mode 100644 include/dt-bindings/mailbox/tegra186-hsp.h

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

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

* [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings
  2016-07-27 21:24 ` [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  2016-08-01 15:28     ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> The Tegra BPMP (Boot and Power Management Processor) is a separate
> auxiliary CPU embedded into Tegra to perform power management work, and
> controls related features such as clocks, resets, power domains, PMIC I2C
> bus, etc. These bindings dictate how to represent the BPMP in device tree.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  .../firmware/nvidia,tegra186-bpmp.txt              |  81 ++
>  include/dt-bindings/clock/tegra186-clock.h         | 940 +++++++++++++++++++++
>  include/dt-bindings/power/tegra186-powergate.h     |  29 +
>  include/dt-bindings/reset/tegra186-reset.h         | 206 +++++
>  4 files changed, 1256 insertions(+)
>  create mode 100644 doc/device-tree-bindings/firmware/nvidia,tegra186-bpmp.txt
>  create mode 100644 include/dt-bindings/clock/tegra186-clock.h
>  create mode 100644 include/dt-bindings/power/tegra186-powergate.h
>  create mode 100644 include/dt-bindings/reset/tegra186-reset.h

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

The comment format seems novel. Is it docbook-compatible?

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

* [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT
  2016-07-27 21:24 ` [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> This adds the DT content that's needed to allow board DTs to enable use
> of BPMP, clocks, resets, GPIOs, eMMC, and SD cards.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/dts/tegra186.dtsi | 55 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 53 insertions(+), 2 deletions(-)

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

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

* [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver
  2016-07-27 21:24 ` [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  2016-08-01 15:41     ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> The Tegra BPMP (Boot and Power Management Processor) is a separate
> auxiliary CPU embedded into Tegra to perform power management work, and
> controls related features such as clocks, resets, power domains, PMIC I2C
> bus, etc. This driver provides the core low-level communication path by
> which feature-specific drivers (such as clock) can make requests to the
> BPMP. This driver is similar to an MFD driver in the Linux kernel. It is
> unconditionally selected by CONFIG_TEGRA186 since virtually any Tegra186
> build of U-Boot will need the feature.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/include/asm/arch-tegra/bpmp_abi.h      | 1601 +++++++++++++++++++++++
>  arch/arm/include/asm/arch-tegra/tegra186_bpmp.h |   14 +
>  arch/arm/mach-tegra/Kconfig                     |    2 +
>  drivers/misc/Kconfig                            |   12 +
>  drivers/misc/Makefile                           |    1 +
>  drivers/misc/tegra186_bpmp.c                    |  250 ++++
>  6 files changed, 1880 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-tegra/bpmp_abi.h
>  create mode 100644 arch/arm/include/asm/arch-tegra/tegra186_bpmp.h
>  create mode 100644 drivers/misc/tegra186_bpmp.c
>
> diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
> new file mode 100644
> index 000000000000..0aaef5960e29
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
> @@ -0,0 +1,1601 @@
> +/*
> + * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.

Can this use SPDX? Or if it is generated, where from?

> + */
> +

[...]

> diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
> new file mode 100644
> index 000000000000..147528da9269
> --- /dev/null
> +++ b/drivers/misc/tegra186_bpmp.c
> @@ -0,0 +1,250 @@
> +/*
> + * Copyright (c) 2016, NVIDIA CORPORATION.
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <dm/root.h>
> +#include <mailbox.h>
> +#include <asm/arch-tegra/bpmp_abi.h>
> +#include <asm/arch-tegra/ivc.h>
> +#include <asm/arch-tegra/tegra186_bpmp.h>
> +
> +#define BPMP_IVC_FRAME_COUNT 1
> +#define BPMP_IVC_FRAME_SIZE 128
> +
> +#define BPMP_FLAG_DO_ACK       BIT(0)
> +#define BPMP_FLAG_RING_DOORBELL        BIT(1)
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct tegra186_bpmp {
> +       struct mbox_chan mbox;
> +       struct tegra_ivc ivc;
> +};
> +
> +int tegra186_bpmp_call(struct udevice *dev, uint32_t mrq,
> +                      void *tx_msg, uint32_t tx_size,
> +                      void *rx_msg, uint32_t rx_size)

Function comment? Also why is this exported? Shouldn't calls come in via DM??

> +{
> +       struct tegra186_bpmp *priv = dev_get_priv(dev);
> +       int ret, err;
> +       void *ivc_frame;
> +       struct mrq_request *req;
> +       struct mrq_response *resp;
> +       ulong start_time;
> +
> +       debug("%s(dev=%p, mrq=%u, tx_msg=%p, tx_size=%u, rx_msg=%p, rx_size=%u) (priv=%p)\n",
> +             __func__, dev, mrq, tx_msg, tx_size, rx_msg, rx_size, priv);
> +
> +       if ((tx_size > BPMP_IVC_FRAME_SIZE) || (rx_size > BPMP_IVC_FRAME_SIZE))
> +               return -EINVAL;
> +
> +       ret = tegra_ivc_write_get_next_frame(&priv->ivc, &ivc_frame);
> +       if (ret) {
> +               error("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       req = ivc_frame;
> +       req->mrq = mrq;
> +       req->flags = BPMP_FLAG_DO_ACK | BPMP_FLAG_RING_DOORBELL;
> +       memcpy(req + 1, tx_msg, tx_size);
> +
> +       ret = tegra_ivc_write_advance(&priv->ivc);
> +       if (ret) {
> +               error("tegra_ivc_write_advance() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       start_time = timer_get_us();
> +       for (;;) {
> +               ret = tegra_ivc_channel_notified(&priv->ivc);
> +               if (ret) {
> +                       error("tegra_ivc_channel_notified() failed: %d\n", ret);
> +                       return ret;
> +               }
> +
> +               ret = tegra_ivc_read_get_next_frame(&priv->ivc, &ivc_frame);
> +               if (!ret)
> +                       break;
> +
> +               /* Timeout 20ms; roughly 10x current max observed duration */
> +               if ((timer_get_us() - start_time) > 20 * 1000) {
> +                       error("tegra_ivc_read_get_next_frame() timed out (%d)\n",
> +                             ret);
> +                       return -ETIMEDOUT;
> +               }
> +       }
> +
> +       resp = ivc_frame;
> +       err = resp->err;
> +       if (!err && rx_msg && rx_size)
> +               memcpy(rx_msg, resp + 1, rx_size);
> +
> +       ret = tegra_ivc_read_advance(&priv->ivc);
> +       if (ret) {
> +               error("tegra_ivc_write_advance() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       if (err) {
> +               error("BPMP responded with error %d\n", err);
> +               /* err isn't a U-Boot error code, so don't that */
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * The BPMP exposes multiple different services. We create a sub-device for
> + * each separate type of service, since each device must be of the appropriate
> + * UCLASS.
> + */
> +static int tegra186_bpmp_bind(struct udevice *dev)
> +{
> +       int ret;
> +       struct udevice *child;
> +
> +       debug("%s(dev=%p)\n", __func__, dev);
> +
> +       ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
> +                                        dev->of_offset, &child);
> +       if (ret)
> +               return ret;
> +
> +       ret = device_bind_driver_to_node(dev, "tegra186_reset",
> +                                        "tegra186_reset", dev->of_offset,
> +                                        &child);
> +       if (ret)
> +               return ret;
> +
> +       ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
> +                                        "tegra186_power_domain",
> +                                        dev->of_offset, &child);
> +       if (ret)
> +               return ret;

What's happening here? Is there one device tree node with 3 devices?

> +
> +       return 0;
> +}
> +
> +static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
> +{
> +       int ret;
> +       struct fdtdec_phandle_args args;
> +       struct udevice fakedev;
> +       fdt_addr_t reg;
> +
> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
> +                                             "shmem", NULL, 0, index, &args);
> +       if (ret < 0) {
> +               error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       fakedev.of_offset = args.node;
> +       reg = dev_get_addr_index(&fakedev, 0);

This is nasty. If you don't set fakedev.parent, how does this work?
Can you instead call fdtdec_get_addr_size_auto_parent() or similar?

> +       if (reg == FDT_ADDR_T_NONE) {
> +               error("dev_get_addr_index() failed\n");
> +               return -ENODEV;
> +       }
> +
> +       return reg;
> +}
> +
> +static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc)
> +{
> +       struct tegra186_bpmp *priv =
> +               container_of(ivc, struct tegra186_bpmp, ivc);
> +       int ret;
> +
> +       ret = mbox_send(&priv->mbox, NULL);
> +       if (ret)
> +               error("mbox_send() failed: %d\n", ret);

Then why not return the error?

> +}
> +
> +static int tegra186_bpmp_probe(struct udevice *dev)
> +{
> +       struct tegra186_bpmp *priv = dev_get_priv(dev);
> +       int ret;
> +       ulong tx_base, rx_base, start_time;
> +
> +       debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
> +
> +       ret = mbox_get_by_index(dev, 0, &priv->mbox);
> +       if (ret) {
> +               error("mbox_get_by_index() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       tx_base = tegra186_bpmp_get_shmem(dev, 0);
> +       if (IS_ERR_VALUE(tx_base)) {
> +               error("tegra186_bpmp_get_shmem failed for tx_base\n");
> +               return tx_base;
> +       }
> +       rx_base = tegra186_bpmp_get_shmem(dev, 1);
> +       if (IS_ERR_VALUE(rx_base)) {
> +               error("tegra186_bpmp_get_shmem failed for rx_base\n");
> +               return rx_base;
> +       }
> +       debug("shmem: rx=%lx, tx=%lx\n", rx_base, tx_base);
> +
> +       ret = tegra_ivc_init(&priv->ivc, rx_base, tx_base, BPMP_IVC_FRAME_COUNT,
> +                            BPMP_IVC_FRAME_SIZE, tegra186_bpmp_ivc_notify);
> +       if (ret) {
> +               error("tegra_ivc_init() failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       tegra_ivc_channel_reset(&priv->ivc);
> +       start_time = timer_get_us();
> +       for (;;) {
> +               ret = tegra_ivc_channel_notified(&priv->ivc);
> +               if (!ret)
> +                       break;
> +
> +               /* Timeout 100ms */
> +               if ((timer_get_us() - start_time) > 100 * 1000) {
> +                       error("Initial IVC reset timed out (%d)\n", ret);
> +                       ret = -ETIMEDOUT;
> +                       goto err_free_mbox;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_free_mbox:
> +       mbox_free(&priv->mbox);
> +
> +       return ret;
> +}
> +
> +static int tegra186_bpmp_remove(struct udevice *dev)
> +{
> +       struct tegra186_bpmp *priv = dev_get_priv(dev);
> +
> +       debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv);
> +
> +       mbox_free(&priv->mbox);
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id tegra186_bpmp_ids[] = {
> +       { .compatible = "nvidia,tegra186-bpmp" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(tegra186_bpmp) = {
> +       .name           = "tegra186_bpmp",
> +       .id             = UCLASS_MISC,
> +       .of_match       = tegra186_bpmp_ids,
> +       .bind           = tegra186_bpmp_bind,
> +       .probe          = tegra186_bpmp_probe,
> +       .remove         = tegra186_bpmp_remove,
> +       .priv_auto_alloc_size = sizeof(struct tegra186_bpmp),
> +};
> --
> 2.9.2
>

Regards,
Simon

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

* [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver
  2016-07-27 21:24 ` [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  2016-08-01 15:46     ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> In Tegra186, on-SoC clocks are manipulated using IPC requests to the BPMP
> (Boot and Power Management Processor). This change implements a driver
> that does that. A tegra/ sub-directory is created to follow the existing
> pattern. It is unconditionally selected by CONFIG_TEGRA186 since virtually
> any Tegra186 build of U-Boot will need the feature.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/mach-tegra/Kconfig      |  2 +
>  drivers/clk/Kconfig              |  1 +
>  drivers/clk/Makefile             |  2 +
>  drivers/clk/tegra/Kconfig        |  6 +++
>  drivers/clk/tegra/Makefile       |  5 ++
>  drivers/clk/tegra/tegra186-clk.c | 99 ++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 115 insertions(+)
>  create mode 100644 drivers/clk/tegra/Kconfig
>  create mode 100644 drivers/clk/tegra/Makefile
>  create mode 100644 drivers/clk/tegra/tegra186-clk.c
>
> diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
> index ec2d8ac6a1a3..e8186d515856 100644
> --- a/arch/arm/mach-tegra/Kconfig
> +++ b/arch/arm/mach-tegra/Kconfig
> @@ -64,9 +64,11 @@ config TEGRA210
>
>  config TEGRA186
>         bool "Tegra186 family"
> +       select CLK
>         select DM_MAILBOX
>         select MISC
>         select TEGRA186_BPMP
> +       select TEGRA186_CLOCK
>         select TEGRA186_GPIO
>         select TEGRA_ARMV8_COMMON
>         select TEGRA_HSP
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 6eee8eb369bf..7dd56738b06a 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -20,6 +20,7 @@ config SPL_CLK
>           setting up clocks within SPL, and allows the same drivers to be
>           used as U-Boot proper.
>
> +source "drivers/clk/tegra/Kconfig"
>  source "drivers/clk/uniphier/Kconfig"
>  source "drivers/clk/exynos/Kconfig"
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index f7a88912e06a..37b946cb6bdc 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -11,5 +11,7 @@ obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
>  obj-$(CONFIG_SANDBOX) += clk_sandbox.o
>  obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
>  obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
> +
> +obj-y += tegra/
>  obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
>  obj-$(CONFIG_CLK_EXYNOS) += exynos/
> diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
> new file mode 100644
> index 000000000000..659fe022c2af
> --- /dev/null
> +++ b/drivers/clk/tegra/Kconfig
> @@ -0,0 +1,6 @@
> +config TEGRA186_CLOCK
> +       bool "Enable Tegra186 BPMP-based clock driver"
> +       depends on TEGRA186_BPMP
> +       help
> +         Enable support for manipulating Tegra's on-SoC clocks via IPC
> +         requests to the BPMP (Boot and Power Management Processor).
> diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
> new file mode 100644
> index 000000000000..f32998ccc27d
> --- /dev/null
> +++ b/drivers/clk/tegra/Makefile
> @@ -0,0 +1,5 @@
> +# Copyright (c) 2016, NVIDIA CORPORATION.
> +#
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_TEGRA186_CLOCK) += tegra186-clk.o
> diff --git a/drivers/clk/tegra/tegra186-clk.c b/drivers/clk/tegra/tegra186-clk.c
> new file mode 100644
> index 000000000000..fcfe3b47714a
> --- /dev/null
> +++ b/drivers/clk/tegra/tegra186-clk.c
> @@ -0,0 +1,99 @@
> +/*
> + * Copyright (c) 2016, NVIDIA CORPORATION.
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <asm/arch-tegra/bpmp_abi.h>
> +#include <asm/arch-tegra/tegra186_bpmp.h>
> +
> +static ulong tegra186_clk_get_rate(struct clk *clk)
> +{
> +       struct mrq_clk_request req;
> +       struct mrq_clk_response resp;
> +       int ret;
> +
> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
> +             clk->id);
> +
> +       req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
> +
> +       ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
> +                                &req, sizeof(req), &resp, sizeof(resp));

Isn't his a MISC driver? Perhaps you can add a new method to
UCLASS_MISC matching your requirements here?

> +       if (ret)
> +               return ret;
> +
> +       return resp.clk_get_rate.rate;
> +}
> +
> +static ulong tegra186_clk_set_rate(struct clk *clk, ulong rate)
> +{
> +       struct mrq_clk_request req;
> +       struct mrq_clk_response resp;
> +       int ret;
> +
> +       debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate,
> +             clk->dev, clk->id);
> +
> +       req.cmd_and_id = (CMD_CLK_SET_RATE << 24) | clk->id;
> +       req.clk_set_rate.rate = rate;
> +
> +       ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
> +                                &req, sizeof(req), &resp, sizeof(resp));
> +       if (ret)
> +               return ret;
> +
> +       return resp.clk_set_rate.rate;
> +}
> +
> +static int tegra186_clk_en_dis(struct clk *clk,
> +                              enum mrq_reset_commands cmd)
> +{
> +       struct mrq_clk_request req;
> +       struct mrq_clk_response resp;
> +
> +       req.cmd_and_id = (cmd << 24) | clk->id;
> +
> +       return tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
> +                                 &req, sizeof(req), &resp, sizeof(resp));
> +}
> +
> +static int tegra186_clk_enable(struct clk *clk)
> +{
> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
> +             clk->id);
> +
> +       return tegra186_clk_en_dis(clk, CMD_CLK_ENABLE);
> +}
> +
> +static int tegra186_clk_disable(struct clk *clk)
> +{
> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
> +             clk->id);
> +
> +       return tegra186_clk_en_dis(clk, CMD_CLK_DISABLE);
> +}
> +
> +static struct clk_ops tegra186_clk_ops = {
> +       .get_rate = tegra186_clk_get_rate,
> +       .set_rate = tegra186_clk_set_rate,
> +       .enable = tegra186_clk_enable,
> +       .disable = tegra186_clk_disable,
> +};
> +
> +static int tegra186_clk_probe(struct udevice *dev)
> +{
> +       debug("%s(dev=%p)\n", __func__, dev);
> +
> +       return 0;
> +}
> +
> +U_BOOT_DRIVER(tegra186_clk) = {
> +       .name           = "tegra186_clk",
> +       .id             = UCLASS_CLK,
> +       .probe          = tegra186_clk_probe,
> +       .ops = &tegra186_clk_ops,
> +};
> --
> 2.9.2
>

Regards,
Simon

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

* [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver
  2016-07-27 21:24 ` [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> In Tegra186, on-SoC reset signals are manipulated using IPC requests to
> the BPMP (Boot and Power Management Processor). This change implements a
> driver that does that. It is unconditionally selected by CONFIG_TEGRA186
> since virtually any Tegra186 build of U-Boot will need the feature.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/mach-tegra/Kconfig    |  2 ++
>  drivers/reset/Kconfig          |  7 ++++
>  drivers/reset/Makefile         |  1 +
>  drivers/reset/tegra186-reset.c | 76 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 86 insertions(+)
>  create mode 100644 drivers/reset/tegra186-reset.c

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

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

* [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver
  2016-07-27 21:24 ` [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> In Tegra186, SoC power domains are manipulated using IPC requests to
> the BPMP (Boot and Power Management Processor). This change implements a
> driver that does that.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  drivers/power/domain/Kconfig                 |  7 +++
>  drivers/power/domain/Makefile                |  1 +
>  drivers/power/domain/tegra186-power-domain.c | 88 ++++++++++++++++++++++++++++
>  3 files changed, 96 insertions(+)
>  create mode 100644 drivers/power/domain/tegra186-power-domain.c
>
> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> index b90409743398..132e33250e8c 100644
> --- a/drivers/power/domain/Kconfig
> +++ b/drivers/power/domain/Kconfig
> @@ -17,4 +17,11 @@ config SANDBOX_POWER_DOMAIN
>           simply accepts requests to power on/off various HW modules without
>           actually doing anything beyond a little error checking.
>
> +config TEGRA186_POWER_DOMAIN
> +       bool "Enable Tegra186 BPMP-based power domain driver"
> +       depends on TEGRA186_BPMP
> +       help
> +         Enable support for manipulating Tegra's on-SoC power domains via IPC
> +         requests to the BPMP (Boot and Power Management Processor).
> +
>  endmenu
> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> index c18292f0ec88..2c3d92638fbe 100644
> --- a/drivers/power/domain/Makefile
> +++ b/drivers/power/domain/Makefile
> @@ -5,3 +5,4 @@
>  obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o
>  obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
>  obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
> +obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
> diff --git a/drivers/power/domain/tegra186-power-domain.c b/drivers/power/domain/tegra186-power-domain.c
> new file mode 100644
> index 000000000000..4ae4baabe57e
> --- /dev/null
> +++ b/drivers/power/domain/tegra186-power-domain.c
> @@ -0,0 +1,88 @@
> +/*
> + * Copyright (c) 2016, NVIDIA CORPORATION.
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <power-domain-uclass.h>
> +#include <asm/arch-tegra/bpmp_abi.h>
> +#include <asm/arch-tegra/tegra186_bpmp.h>
> +
> +#define UPDATE BIT(0)
> +#define ON     BIT(1)
> +
> +static int tegra186_power_domain_request(struct power_domain *power_domain)
> +{
> +       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
> +             power_domain, power_domain->dev, power_domain->id);
> +
> +       return 0;
> +}
> +
> +static int tegra186_power_domain_free(struct power_domain *power_domain)
> +{
> +       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
> +             power_domain, power_domain->dev, power_domain->id);
> +
> +       return 0;
> +}
> +
> +static int tegra186_power_domain_common(struct power_domain *power_domain,
> +                                       bool on)
> +{
> +       struct mrq_pg_update_state_request req;
> +       int on_state = on ? ON : 0;
> +
> +       req.partition_id = power_domain->id;
> +       req.logic_state = UPDATE | on_state;
> +       req.sram_state = UPDATE | on_state;
> +       /*
> +        * Drivers manage their own clocks so they don't get out of sync, and
> +        * since some power domains have many clocks, only a subset of which
> +        * are actually needed depending on use-case.
> +        */
> +       req.clock_state = UPDATE;
> +
> +       return tegra186_bpmp_call(power_domain->dev->parent,
> +                                 MRQ_PG_UPDATE_STATE, &req, sizeof(req), NULL,
> +                                 0);

Again I wonder if this can use UCLASS_MISC?

> +}
> +
> +static int tegra186_power_domain_on(struct power_domain *power_domain)
> +{
> +       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
> +             power_domain, power_domain->dev, power_domain->id);
> +
> +       return tegra186_power_domain_common(power_domain, true);
> +}
> +
> +static int tegra186_power_domain_off(struct power_domain *power_domain)
> +{
> +       debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__,
> +             power_domain, power_domain->dev, power_domain->id);
> +
> +       return tegra186_power_domain_common(power_domain, false);
> +}
> +
> +struct power_domain_ops tegra186_power_domain_ops = {
> +       .request = tegra186_power_domain_request,
> +       .free = tegra186_power_domain_free,
> +       .on = tegra186_power_domain_on,
> +       .off = tegra186_power_domain_off,
> +};
> +
> +static int tegra186_power_domain_probe(struct udevice *dev)
> +{
> +       debug("%s(dev=%p)\n", __func__, dev);
> +
> +       return 0;
> +}
> +
> +U_BOOT_DRIVER(tegra186_power_domain) = {
> +       .name = "tegra186_power_domain",
> +       .id = UCLASS_POWER_DOMAIN,
> +       .probe = tegra186_power_domain_probe,
> +       .ops = &tegra186_power_domain_ops,
> +};
> --
> 2.9.2
>

Regards,
Simon

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

* [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186
  2016-07-27 21:24 ` [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186 Stephen Warren
@ 2016-08-01  1:02   ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2016-08-01  1:02 UTC (permalink / raw)
  To: u-boot

On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> Introduce tegra_board_init() and call it from board_init(). Tegra wil use
> tegra_board_init() for board-specific initialization, and board_init() for
> SoC-specific initialization.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/mach-tegra/board186.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

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

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-07-27 21:24 ` [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs Stephen Warren
  2016-07-28  1:09   ` Jaehoon Chung
@ 2016-08-01  2:20   ` Simon Glass
  2016-08-01 15:50     ` Stephen Warren
  1 sibling, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-01  2:20 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 27 July 2016 at 15:24, 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>
> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
> ---
>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
>  drivers/mmc/tegra_mmc.c                     | 55 ++++++++++++++++++++++++-----
>  2 files changed, 53 insertions(+), 10 deletions(-)

Shouldn't we fix up the code to all use the new APIs?

- Simon

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

* [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings
  2016-08-01  1:02   ` Simon Glass
@ 2016-08-01 15:28     ` Stephen Warren
  0 siblings, 0 replies; 30+ messages in thread
From: Stephen Warren @ 2016-08-01 15:28 UTC (permalink / raw)
  To: u-boot

On 07/31/2016 07:02 PM, Simon Glass wrote:
> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> The Tegra BPMP (Boot and Power Management Processor) is a separate
>> auxiliary CPU embedded into Tegra to perform power management work, and
>> controls related features such as clocks, resets, power domains, PMIC I2C
>> bus, etc. These bindings dictate how to represent the BPMP in device tree.

> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> The comment format seems novel. Is it docbook-compatible?

I think that it's Doxygen.

Note that the BPMP FW team publishes these headers along with the FW. I 
deliberately didn't change these files beyond adapting to the U-Boot 
license header format so that incorporating further updates from that 
team would be trivial.

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

* [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver
  2016-08-01  1:02   ` Simon Glass
@ 2016-08-01 15:41     ` Stephen Warren
  2016-08-01 18:46       ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-08-01 15:41 UTC (permalink / raw)
  To: u-boot

On 07/31/2016 07:02 PM, Simon Glass wrote:
> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> The Tegra BPMP (Boot and Power Management Processor) is a separate
>> auxiliary CPU embedded into Tegra to perform power management work, and
>> controls related features such as clocks, resets, power domains, PMIC I2C
>> bus, etc. This driver provides the core low-level communication path by
>> which feature-specific drivers (such as clock) can make requests to the
>> BPMP. This driver is similar to an MFD driver in the Linux kernel. It is
>> unconditionally selected by CONFIG_TEGRA186 since virtually any Tegra186
>> build of U-Boot will need the feature.

>> diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
>> new file mode 100644
>> index 000000000000..0aaef5960e29
>> --- /dev/null
>> +++ b/arch/arm/include/asm/arch-tegra/bpmp_abi.h
>> @@ -0,0 +1,1601 @@
>> +/*
>> + * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>
> Can this use SPDX? Or if it is generated, where from?

I forgot to convert this one. These headers are shipped alongside the 
BPMP FW so I deliberately edited it as little as possible, but I did 
mean to convert the license header.

>> diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c

>> +int tegra186_bpmp_call(struct udevice *dev, uint32_t mrq,
>> +                      void *tx_msg, uint32_t tx_size,
>> +                      void *rx_msg, uint32_t rx_size)
>
> ... Also why is this exported? Shouldn't calls come in via DM??

This is an internal API between the core BPMP driver and the "services" 
drivers that are part of it. More below.

>> +/**
>> + * The BPMP exposes multiple different services. We create a sub-device for
>> + * each separate type of service, since each device must be of the appropriate
>> + * UCLASS.
>> + */
>> +static int tegra186_bpmp_bind(struct udevice *dev)
>> +{
>> +       int ret;
>> +       struct udevice *child;
>> +
>> +       debug("%s(dev=%p)\n", __func__, dev);
>> +
>> +       ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
>> +                                        dev->of_offset, &child);
>> +       if (ret)
>> +               return ret;
>> +
>> +       ret = device_bind_driver_to_node(dev, "tegra186_reset",
>> +                                        "tegra186_reset", dev->of_offset,
>> +                                        &child);
>> +       if (ret)
>> +               return ret;
>> +
>> +       ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
>> +                                        "tegra186_power_domain",
>> +                                        dev->of_offset, &child);
>> +       if (ret)
>> +               return ret;
>
> What's happening here? Is there one device tree node with 3 devices?

The BPMP is a single device, hence a single DT node, that exports a 
multitude of services. This file/patch is the top-level/core driver for 
the BPMP. This function is instantiating a separate U-Boot driver for 
each type of service; DM requires each device/drive object be a single 
uclass. This is logically extremely similar to MFD devices in the Linux 
kernel.

>> +static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
>> +{
>> +       int ret;
>> +       struct fdtdec_phandle_args args;
>> +       struct udevice fakedev;
>> +       fdt_addr_t reg;
>> +
>> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
>> +                                             "shmem", NULL, 0, index, &args);
>> +       if (ret < 0) {
>> +               error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
>> +               return ret;
>> +       }
>> +
>> +       fakedev.of_offset = args.node;
>> +       reg = dev_get_addr_index(&fakedev, 0);
>
> This is nasty. If you don't set fakedev.parent, how does this work?

Hmmm. Good question; I thought dev_get_addr_index() only used the 
device's own of_offset, but it does look like it uses the parent device 
too. I'll have to look into this.

> Can you instead call fdtdec_get_addr_size_auto_parent() or similar?

dev_get_addr_index() is the only API which applies address translation 
(i.e. processes the DT ranges property).

>> +static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc)
>> +{
>> +       struct tegra186_bpmp *priv =
>> +               container_of(ivc, struct tegra186_bpmp, ivc);
>> +       int ret;
>> +
>> +       ret = mbox_send(&priv->mbox, NULL);
>> +       if (ret)
>> +               error("mbox_send() failed: %d\n", ret);
>
> Then why not return the error?

This is a callback from the IVC library. The callback prototype doesn't 
allow errors to be returned. I'd rather not change that code since it's 
almost identical across various OSs (e.g. shared with mainline Linux).

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

* [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver
  2016-08-01  1:02   ` Simon Glass
@ 2016-08-01 15:46     ` Stephen Warren
  2016-08-05  1:36       ` Simon Glass
  0 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-08-01 15:46 UTC (permalink / raw)
  To: u-boot

On 07/31/2016 07:02 PM, Simon Glass wrote:
> Hi Stephen,
>
> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> In Tegra186, on-SoC clocks are manipulated using IPC requests to the BPMP
>> (Boot and Power Management Processor). This change implements a driver
>> that does that. A tegra/ sub-directory is created to follow the existing
>> pattern. It is unconditionally selected by CONFIG_TEGRA186 since virtually
>> any Tegra186 build of U-Boot will need the feature.

>> diff --git a/drivers/clk/tegra/tegra186-clk.c b/drivers/clk/tegra/tegra186-clk.c

>> +static ulong tegra186_clk_get_rate(struct clk *clk)
>> +{
>> +       struct mrq_clk_request req;
>> +       struct mrq_clk_response resp;
>> +       int ret;
>> +
>> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
>> +             clk->id);
>> +
>> +       req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
>> +
>> +       ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
>> +                                &req, sizeof(req), &resp, sizeof(resp));
>
> Isn't his a MISC driver? Perhaps you can add a new method to
> UCLASS_MISC matching your requirements here?

The core BPMP driver is a MISC driver, yes.

I don't see any advantage of making this call something that the MISC 
uclass supports directly. This function is an internal implementation 
detail of the BPMP, and certainly not something that every single MISC 
driver (for any SoC for any HW module) would implement. If we did add 
direct support to the MISC uclass, then the MISC "ops" structure would 
basically grow forever since every single SoC's/HW's internal function 
calls would be added to it. This would just bloat it up unnecessarily, 
and I don't see any advantage to offset the disadvantage of that bloat.

FWIW, the Linux MFD (Multi-Function Devices) stack typically has "child" 
(sub-)devices call custom APIs like this on the "parent"/container.

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-08-01  2:20   ` Simon Glass
@ 2016-08-01 15:50     ` Stephen Warren
  2016-08-04  1:16       ` Simon Glass
  0 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-08-01 15:50 UTC (permalink / raw)
  To: u-boot

On 07/31/2016 08:20 PM, Simon Glass wrote:
> Hi Stephen,
>
> On 27 July 2016 at 15:24, 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>
>> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
>> ---
>>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
>>  drivers/mmc/tegra_mmc.c                     | 55 ++++++++++++++++++++++++-----
>>  2 files changed, 53 insertions(+), 10 deletions(-)
>
> Shouldn't we fix up the code to all use the new APIs?

Eventually yes. However, that's something that will take a lot of work. 
When similar common APIs were introduced into Linux, there was a 
transition period of 1-2 years where new code was immediately written to 
the new APIs, and old code (e.g. legacy clock API implementation, and 
its callers) was slowly converted. I would expect the same thing in 
U-Boot; any other approach means preventing new work until the 
conversions are complete, which would be rather stagnating.

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

* [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver
  2016-08-01 15:41     ` Stephen Warren
@ 2016-08-01 18:46       ` Stephen Warren
  0 siblings, 0 replies; 30+ messages in thread
From: Stephen Warren @ 2016-08-01 18:46 UTC (permalink / raw)
  To: u-boot

On 08/01/2016 09:41 AM, Stephen Warren wrote:
> On 07/31/2016 07:02 PM, Simon Glass wrote:
>> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> From: Stephen Warren <swarren@nvidia.com>
>>>
>>> The Tegra BPMP (Boot and Power Management Processor) is a separate
>>> auxiliary CPU embedded into Tegra to perform power management work, and
>>> controls related features such as clocks, resets, power domains, PMIC
>>> I2C
>>> bus, etc. This driver provides the core low-level communication path by
>>> which feature-specific drivers (such as clock) can make requests to the
>>> BPMP. This driver is similar to an MFD driver in the Linux kernel. It is
>>> unconditionally selected by CONFIG_TEGRA186 since virtually any Tegra186
>>> build of U-Boot will need the feature.

>>> diff --git a/arch/arm/include/asm/arch-tegra/bpmp_abi.h

>>> +static ulong tegra186_bpmp_get_shmem(struct udevice *dev, int index)
>>> +{
>>> +       int ret;
>>> +       struct fdtdec_phandle_args args;
>>> +       struct udevice fakedev;
>>> +       fdt_addr_t reg;
>>> +
>>> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
>>> dev->of_offset,
>>> +                                             "shmem", NULL, 0,
>>> index, &args);
>>> +       if (ret < 0) {
>>> +               error("fdtdec_parse_phandle_with_args() failed:
>>> %d\n", ret);
>>> +               return ret;
>>> +       }
>>> +
>>> +       fakedev.of_offset = args.node;
>>> +       reg = dev_get_addr_index(&fakedev, 0);
>>
>> This is nasty. If you don't set fakedev.parent, how does this work?
>
> Hmmm. Good question; I thought dev_get_addr_index() only used the
> device's own of_offset, but it does look like it uses the parent device
> too. I'll have to look into this.

How sad. It works because dev->parent happens to be 0, and address 0 is 
part of the mapped MMIO space so is mapped in the MMU, and then 
dev->parent->of_offset happens to be 0, so dev_get_addr_index() ends up 
querying #address-calls/#size-cells from the root node, and those happen 
to match the values for the node we're actually interested in:-(

I guess the simplest approach is to use 
fdtdec_get_addr_size_auto_parent() or similar as you say, but also  call 
fdt_translate_address() afterwards.

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-08-01 15:50     ` Stephen Warren
@ 2016-08-04  1:16       ` Simon Glass
  2016-08-04 18:59         ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-04  1:16 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 1 August 2016 at 09:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 07/31/2016 08:20 PM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 27 July 2016 at 15:24, 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>
>>> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
>>> ---
>>>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
>>>  drivers/mmc/tegra_mmc.c                     | 55
>>> ++++++++++++++++++++++++-----
>>>  2 files changed, 53 insertions(+), 10 deletions(-)
>>
>>
>> Shouldn't we fix up the code to all use the new APIs?
>
>
> Eventually yes. However, that's something that will take a lot of work. When
> similar common APIs were introduced into Linux, there was a transition
> period of 1-2 years where new code was immediately written to the new APIs,
> and old code (e.g. legacy clock API implementation, and its callers) was
> slowly converted. I would expect the same thing in U-Boot; any other
> approach means preventing new work until the conversions are complete, which
> would be rather stagnating.

I still don't like the #ifdefs? Does Linux have #ifdefs in the mmc driver?

Also the work to convert to CONFIG_BLK, CONFIG_DM_MMC_OPS is not a lot of work.

Regards,
Simon

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-08-04  1:16       ` Simon Glass
@ 2016-08-04 18:59         ` Stephen Warren
  2016-08-04 21:42           ` Tom Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Stephen Warren @ 2016-08-04 18:59 UTC (permalink / raw)
  To: u-boot

On 08/03/2016 07:16 PM, Simon Glass wrote:
> Hi Stephen,
>
> On 1 August 2016 at 09:50, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 07/31/2016 08:20 PM, Simon Glass wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 27 July 2016 at 15:24, 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>
>>>> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
>>>> ---
>>>>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
>>>>  drivers/mmc/tegra_mmc.c                     | 55
>>>> ++++++++++++++++++++++++-----
>>>>  2 files changed, 53 insertions(+), 10 deletions(-)
>>>
>>>
>>> Shouldn't we fix up the code to all use the new APIs?
>>
>>
>> Eventually yes. However, that's something that will take a lot of work. When
>> similar common APIs were introduced into Linux, there was a transition
>> period of 1-2 years where new code was immediately written to the new APIs,
>> and old code (e.g. legacy clock API implementation, and its callers) was
>> slowly converted. I would expect the same thing in U-Boot; any other
>> approach means preventing new work until the conversions are complete, which
>> would be rather stagnating.
>
> I still don't like the #ifdefs? Does Linux have #ifdefs in the mmc driver?

Linux is fully converted already. See my other response for more details.

> Also the work to convert to CONFIG_BLK, CONFIG_DM_MMC_OPS is not a lot of work.

Sure, but that's a separate API conversion. I really don't want to dump 
too many conversions, especially unrelated conversions, into a single 
patch or series. Besides, I could have sworn that either you or TomW had 
started work on that or agreed to do it?

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

* [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
  2016-08-04 18:59         ` Stephen Warren
@ 2016-08-04 21:42           ` Tom Warren
  0 siblings, 0 replies; 30+ messages in thread
From: Tom Warren @ 2016-08-04 21:42 UTC (permalink / raw)
  To: u-boot

Stephen,

> -----Original Message-----
> From: Stephen Warren [mailto:swarren at wwwdotorg.org]
> Sent: Thursday, August 04, 2016 11:59 AM
> To: Simon Glass <sjg@chromium.org>
> Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Tom Warren
> <TWarren@nvidia.com>; Stephen Warren <swarren@nvidia.com>; Pantelis
> Antoniou <panto@antoniou-consulting.com>
> Subject: Re: [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs
> 
> On 08/03/2016 07:16 PM, Simon Glass wrote:
> > Hi Stephen,
> >
> > On 1 August 2016 at 09:50, Stephen Warren <swarren@wwwdotorg.org>
> wrote:
> >> On 07/31/2016 08:20 PM, Simon Glass wrote:
> >>>
> >>> Hi Stephen,
> >>>
> >>> On 27 July 2016 at 15:24, 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>
> >>>> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
> >>>> ---
> >>>>  arch/arm/include/asm/arch-tegra/tegra_mmc.h |  8 ++++-
> >>>>  drivers/mmc/tegra_mmc.c                     | 55
> >>>> ++++++++++++++++++++++++-----
> >>>>  2 files changed, 53 insertions(+), 10 deletions(-)
> >>>
> >>>
> >>> Shouldn't we fix up the code to all use the new APIs?
> >>
> >>
> >> Eventually yes. However, that's something that will take a lot of
> >> work. When similar common APIs were introduced into Linux, there was
> >> a transition period of 1-2 years where new code was immediately
> >> written to the new APIs, and old code (e.g. legacy clock API
> >> implementation, and its callers) was slowly converted. I would expect
> >> the same thing in U-Boot; any other approach means preventing new
> >> work until the conversions are complete, which would be rather stagnating.
> >
> > I still don't like the #ifdefs? Does Linux have #ifdefs in the mmc driver?
> 
> Linux is fully converted already. See my other response for more details.
> 
> > Also the work to convert to CONFIG_BLK, CONFIG_DM_MMC_OPS is not a lot
> of work.
> 
> Sure, but that's a separate API conversion. I really don't want to dump too many
> conversions, especially unrelated conversions, into a single patch or series.
> Besides, I could have sworn that either you or TomW had started work on that
> or agreed to do it?

I started on the DM_MMC conversion, then got side-tracked/reprioritized. I'll take it up again when I have some spare BW (hopefully soon).

Tom
--
nvpublic

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

* [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver
  2016-08-01 15:46     ` Stephen Warren
@ 2016-08-05  1:36       ` Simon Glass
  2016-08-05 16:17         ` Stephen Warren
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2016-08-05  1:36 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 1 August 2016 at 09:46, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 07/31/2016 07:02 PM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>
>>> From: Stephen Warren <swarren@nvidia.com>
>>>
>>> In Tegra186, on-SoC clocks are manipulated using IPC requests to the BPMP
>>> (Boot and Power Management Processor). This change implements a driver
>>> that does that. A tegra/ sub-directory is created to follow the existing
>>> pattern. It is unconditionally selected by CONFIG_TEGRA186 since
>>> virtually
>>> any Tegra186 build of U-Boot will need the feature.
>
>
>>> diff --git a/drivers/clk/tegra/tegra186-clk.c
>>> b/drivers/clk/tegra/tegra186-clk.c
>
>
>>> +static ulong tegra186_clk_get_rate(struct clk *clk)
>>> +{
>>> +       struct mrq_clk_request req;
>>> +       struct mrq_clk_response resp;
>>> +       int ret;
>>> +
>>> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
>>> +             clk->id);
>>> +
>>> +       req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
>>> +
>>> +       ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
>>> +                                &req, sizeof(req), &resp, sizeof(resp));
>>
>>
>> Isn't his a MISC driver? Perhaps you can add a new method to
>> UCLASS_MISC matching your requirements here?
>
>
> The core BPMP driver is a MISC driver, yes.
>
> I don't see any advantage of making this call something that the MISC uclass
> supports directly. This function is an internal implementation detail of the
> BPMP, and certainly not something that every single MISC driver (for any SoC
> for any HW module) would implement. If we did add direct support to the MISC
> uclass, then the MISC "ops" structure would basically grow forever since
> every single SoC's/HW's internal function calls would be added to it. This
> would just bloat it up unnecessarily, and I don't see any advantage to
> offset the disadvantage of that bloat.

I'm really just suggesting that you could add one more method to the
misc uclass, which does a simultaneous write and read.

>
> FWIW, the Linux MFD (Multi-Function Devices) stack typically has "child"
> (sub-)devices call custom APIs like this on the "parent"/container.

Yes, I'm just trying to encourage use of the driver-model features -
one of the design goals is to expose otherwise private driver
interfaces.

Regards,
Simon

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

* [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver
  2016-08-05  1:36       ` Simon Glass
@ 2016-08-05 16:17         ` Stephen Warren
  0 siblings, 0 replies; 30+ messages in thread
From: Stephen Warren @ 2016-08-05 16:17 UTC (permalink / raw)
  To: u-boot

On 08/04/2016 07:36 PM, Simon Glass wrote:
> Hi Stephen,
>
> On 1 August 2016 at 09:46, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 07/31/2016 07:02 PM, Simon Glass wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 27 July 2016 at 15:24, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>
>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>
>>>> In Tegra186, on-SoC clocks are manipulated using IPC requests to the BPMP
>>>> (Boot and Power Management Processor). This change implements a driver
>>>> that does that. A tegra/ sub-directory is created to follow the existing
>>>> pattern. It is unconditionally selected by CONFIG_TEGRA186 since
>>>> virtually
>>>> any Tegra186 build of U-Boot will need the feature.
>>
>>
>>>> diff --git a/drivers/clk/tegra/tegra186-clk.c
>>>> b/drivers/clk/tegra/tegra186-clk.c
>>
>>
>>>> +static ulong tegra186_clk_get_rate(struct clk *clk)
>>>> +{
>>>> +       struct mrq_clk_request req;
>>>> +       struct mrq_clk_response resp;
>>>> +       int ret;
>>>> +
>>>> +       debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev,
>>>> +             clk->id);
>>>> +
>>>> +       req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id;
>>>> +
>>>> +       ret = tegra186_bpmp_call(clk->dev->parent, MRQ_CLK,
>>>> +                                &req, sizeof(req), &resp, sizeof(resp));
>>>
>>>
>>> Isn't his a MISC driver? Perhaps you can add a new method to
>>> UCLASS_MISC matching your requirements here?
>>
>>
>> The core BPMP driver is a MISC driver, yes.
>>
>> I don't see any advantage of making this call something that the MISC uclass
>> supports directly. This function is an internal implementation detail of the
>> BPMP, and certainly not something that every single MISC driver (for any SoC
>> for any HW module) would implement. If we did add direct support to the MISC
>> uclass, then the MISC "ops" structure would basically grow forever since
>> every single SoC's/HW's internal function calls would be added to it. This
>> would just bloat it up unnecessarily, and I don't see any advantage to
>> offset the disadvantage of that bloat.
>
> I'm really just suggesting that you could add one more method to the
> misc uclass, which does a simultaneous write and read.

OK, I guess I will do that if I must. However, I doubt we will see 
much/any benefit from this.

Taking a look at the cros_ec example you mentioned in your other mail, 
you'll note that the EC and BPMP ABIs are different. Sure, both accept:

device(udev) to "communicate on"
TX buffer, length
RX buffer, length

However, both of these functions take the message body from the client, 
locally create the TX header before sending, and strip off the RX header 
before giving it back to the caller. This means the function also takes 
all the parameters to construct the message header. These are different 
for EC (message number and version) vs. BPMP (just message number). 
While we could make the prototype of the misc uclass function accept 
both and just ignore the extra information, that seems quite hokey. 
Eventually we'll probably end up with some other similar situation that 
needs more parameters and we'll just have to edit every existing caller 
to provide dummy data. Equally, routing everything through the uclass 
function prevents any kind of type-safety for these generic parameters 
(say using an enum, or appropriate data size) since by definition the 
common function is common and therefore must use very generic types.

It's very obvious to me how routing truly common operations through 
standard APIs makes sense; it brings order, allows drivers to use the 
same APIs on all platforms, etc. However, once you get down to low-level 
internal details of tightly couple drivers, the benefits disappear.

Ideally, we'd actually have a single BPMP driver that provided all of 
clock, reset, power domain, I2C, ... from the one device (instantiated 
from the one BPMP device node). It's just an artificial limitation of 
U-Boot's DM that a given driver/device can only provide one service, so 
we must have multiple communicating devices. If DM allowed separation 
between devices and the services they provide (as Linux does for most 
subsystems at least), there wouldn't even be any 
driver-to-driver/device-to-device within the context of BPMP, so all 
this would be irrelevant.

>> FWIW, the Linux MFD (Multi-Function Devices) stack typically has "child"
>> (sub-)devices call custom APIs like this on the "parent"/container.
>
> Yes, I'm just trying to encourage use of the driver-model features -
> one of the design goals is to expose otherwise private driver
> interfaces.

I'm not sure that's a good goal as an absolute general thing. Sure it 
makes sense to standardize interfaces between unrelated drivers to 
remove coupling. However, when the devices/drivers really are tightly 
coupled rather than independent IP blocks, and especially if they only 
artificially exist due to DM structure, I don't see any benefit of 
forcing everything through DM.

You'd mentioned enhancing debug and visibility in your other email. I 
don't believe either would be benefited here. The debugger will step 
through a call to a function or a call to a function pointer just as 
easily. A human on the other hand will be able to understand what's 
going on much more easily if the call is directly to a named function 
rather than having to look up where a function pointer points, since 
there's no extra work to find out where the function pointer points.

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

end of thread, other threads:[~2016-08-05 16:17 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-27 21:24 [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Stephen Warren
2016-07-27 21:24 ` [U-Boot] [PATCH 2/9] ARM: tegra: add BPMP DT bindings Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-08-01 15:28     ` Stephen Warren
2016-07-27 21:24 ` [U-Boot] [PATCH 3/9] ARM: tegra: add BPMP and dependencies to Tegra186 DT Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-07-27 21:24 ` [U-Boot] [PATCH 4/9] misc: add Tegra BPMP driver Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-08-01 15:41     ` Stephen Warren
2016-08-01 18:46       ` Stephen Warren
2016-07-27 21:24 ` [U-Boot] [PATCH 5/9] clock: add Tegra186 clock driver Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-08-01 15:46     ` Stephen Warren
2016-08-05  1:36       ` Simon Glass
2016-08-05 16:17         ` Stephen Warren
2016-07-27 21:24 ` [U-Boot] [PATCH 6/9] reset: add Tegra186 reset driver Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-07-27 21:24 ` [U-Boot] [PATCH 7/9] power domain: add Tegra186 driver Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-07-27 21:24 ` [U-Boot] [PATCH 8/9] mmc: tegra: port to standard clock/reset APIs Stephen Warren
2016-07-28  1:09   ` Jaehoon Chung
2016-07-28 16:03     ` Stephen Warren
2016-08-01  2:20   ` Simon Glass
2016-08-01 15:50     ` Stephen Warren
2016-08-04  1:16       ` Simon Glass
2016-08-04 18:59         ` Stephen Warren
2016-08-04 21:42           ` Tom Warren
2016-07-27 21:24 ` [U-Boot] [PATCH 9/9] ARM: tegra: call tegra_board_init on Tegra186 Stephen Warren
2016-08-01  1:02   ` Simon Glass
2016-08-01  1:01 ` [U-Boot] [PATCH 1/9] ARM: tegra: adapt to latest HSP DT binding Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.