2016-04-29 13:54:07

by Jon Hunter

[permalink] [raw]
Subject: [PATCH 0/3] bus: Add support for Tegra210 ACONNECT

Add support for the ACONNECT bus which is part of the audio sub-system
on Tegra210.

I did look to see if we could use the simple-pm-bus infrastructure for
this, however, in the end I found that it did was not a good fit because
of the way clocks for the bus are handled. The simple-pm-bus is tightly
coupled to the genpd subsystem and is reliant on the power-domain
associated with the bus to have the flag GENPD_FLAG_PM_CLK set and uses
the genpd function pointer, attach_dev(), as a hook to populate the
clocks. For Tegra this does not work because the power-domains are
instantiated from device-tree rather than platform code. In this case
for Tegra it is simpler to keep the clock management of devices within
the power-domain separated from the power-domain itself.

Jon Hunter (3):
dt-bindings: bus: Add documentation for Tegra210 ACONNECT
bus: Add support for Tegra ACONNECT
arm64: tegra: Add ACONNECT bus node for Tegra210

.../bindings/bus/nvidia,tegra210-aconnect.txt | 45 ++++++++
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 12 +++
drivers/bus/Kconfig | 9 ++
drivers/bus/Makefile | 1 +
drivers/bus/tegra-aconnect.c | 113 +++++++++++++++++++++
5 files changed, 180 insertions(+)
create mode 100644 Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt
create mode 100644 drivers/bus/tegra-aconnect.c

--
2.1.4


2016-04-29 13:54:31

by Jon Hunter

[permalink] [raw]
Subject: [PATCH 1/3] dt-bindings: bus: Add documentation for Tegra210 ACONNECT

Add binding documentation for the Tegra ACONNECT bus that is part of the
Audio Processing Engine (APE) on Tegra210. The ACONNECT bus is used to
access devices within the APE subsystem. The APE is located in a
separate power domain and so accesses made to the ACONNECT require the
power domain to be enabled as well as some platform specific clocks.

Signed-off-by: Jon Hunter <[email protected]>
---
.../bindings/bus/nvidia,tegra210-aconnect.txt | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt

diff --git a/Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt b/Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt
new file mode 100644
index 000000000000..e5e915f8fca7
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt
@@ -0,0 +1,45 @@
+NVIDIA Tegra ACONNECT Bus
+
+The Tegra ACONNECT bus is an AXI switch which is used to connnect various
+components inside the Audio Processing Engine (APE). All CPU accesses to
+the APE subsystem go through the ACONNECT via an APB to AXI wrapper.
+
+Required properties:
+- compatible: Must be "nvidia,tegra210-aconnect".
+- clocks: Must contain the entries for the APE clock (TEGRA210_CLK_APE),
+ and APE interface clock (TEGRA210_CLK_APB2APE).
+- clock-names: Must contain the names "ape" and "apb2ape" for the corresponding
+ 'clocks' entries.
+- power-domains: Must contain a phandle that points to the audio powergate
+ (namely 'aud') for Tegra210.
+- #address-cells: The number of cells used to represent physical base addresses
+ in the host1x address space. Should be 2.
+- #size-cells: The number of cells used to represent the size of an address
+ range in the host1x address space. Should be 2.
+- ranges: 1:1 mapping of the aconnect address space to the CPU address space.
+
+All devices accessed via the ACONNNECT are described by child-nodes.
+
+Example:
+
+ aconnect@702c0000 {
+ compatible = "nvidia,tegra210-aconnect";
+ clocks = <&tegra_car TEGRA210_CLK_APE>,
+ <&tegra_car TEGRA210_CLK_APB2APE>;
+ clock-names = "ape", "apb2ape";
+ power-domains = <&pd_audio>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x702c0000 0x0 0x702c0000 0x0 0x00040000>;
+
+ status = "disabled";
+
+ child1 {
+ ...
+ };
+
+ child2 {
+ ...
+ };
+ };
--
2.1.4

2016-04-29 13:54:47

by Jon Hunter

[permalink] [raw]
Subject: [PATCH 3/3] arm64: tegra: Add ACONNECT bus node for Tegra210

Add the ACONNECT bus node for Tegra210 which is used to interface to
the various devices in the Audio Processing Engine (APE).

Signed-off-by: Jon Hunter <[email protected]>
---
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 76fe31faa1a5..02491ec88ab2 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -673,6 +673,18 @@
#nvidia,mipi-calibrate-cells = <1>;
};

+ aconnect@702c0000 {
+ compatible = "nvidia,tegra210-aconnect";
+ clocks = <&tegra_car TEGRA210_CLK_APE>,
+ <&tegra_car TEGRA210_CLK_APB2APE>;
+ clock-names = "ape", "apb2ape";
+ power-domains = <&pd_audio>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x702c0000 0x0 0x702c0000 0x0 0x00040000>;
+ status = "disabled";
+ };
+
spi@70410000 {
compatible = "nvidia,tegra210-qspi";
reg = <0x0 0x70410000 0x0 0x1000>;
--
2.1.4

2016-04-29 13:54:46

by Jon Hunter

[permalink] [raw]
Subject: [PATCH 2/3] bus: Add support for Tegra ACONNECT

Add a bus driver for the Tegra ACONNECT which is used to interface to
various devices within the Audio Processing Engine (APE). The purpose
of the bus driver is to register child devices that are accessed via
the ACONNECT bus and through the device parent child relationship,
ensure that the appropriate power domain and clocks are enabled for
the ACONNECT when any of the child devices are active. Hence, the
ACONNECT driver simply enables runtime-pm for the ACONNECT device
so that when a child device is resumed, it will enable the power-domain
and clocks associated with the ACONNECT.

Signed-off-by: Jon Hunter <[email protected]>
---
drivers/bus/Kconfig | 9 ++++
drivers/bus/Makefile | 1 +
drivers/bus/tegra-aconnect.c | 113 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 123 insertions(+)
create mode 100644 drivers/bus/tegra-aconnect.c

diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index f5ea153f53e9..4d5d75112ad2 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -132,6 +132,15 @@ config SUNXI_RSB
with various RSB based devices, such as AXP223, AXP8XX PMICs,
and AC100/AC200 ICs.

+config TEGRA_ACONNECT
+ bool "Tegra ACONNECT Bus Driver"
+ depends on ARCH_TEGRA_210_SOC
+ depends on OF && PM
+ select PM_CLK
+ help
+ Driver for the Tegra ACONNECT bus which is used to interface with
+ the devices inside the Audio Processing Engine (APE) for Tegra210.
+
config UNIPHIER_SYSTEM_BUS
tristate "UniPhier System Bus driver"
depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index ccff007ee7e8..ac84cc4348e3 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
+obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c
new file mode 100644
index 000000000000..bad9e39dc8b3
--- /dev/null
+++ b/drivers/bus/tegra-aconnect.c
@@ -0,0 +1,113 @@
+/*
+ * Tegra ACONNECT Bus Driver
+ *
+ * Copyright (C) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+
+static int tegra_aconnect_add_clock(struct device *dev, char *name)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(dev, name);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "%s clock not found\n", name);
+ return PTR_ERR(clk);
+ }
+
+ ret = pm_clk_add_clk(dev, clk);
+ if (ret)
+ clk_put(clk);
+
+ return ret;
+}
+
+static int tegra_aconnect_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (!pdev->dev.of_node)
+ return -EINVAL;
+
+ ret = pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = tegra_aconnect_add_clock(&pdev->dev, "ape");
+ if (ret)
+ goto clk_destroy;
+
+ ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape");
+ if (ret)
+ goto clk_destroy;
+
+ pm_runtime_enable(&pdev->dev);
+
+ of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+
+ dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
+
+ return 0;
+
+clk_destroy:
+ pm_clk_destroy(&pdev->dev);
+
+ return ret;
+}
+
+static int tegra_aconnect_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ pm_clk_destroy(&pdev->dev);
+
+ return 0;
+}
+
+static int tegra_aconnect_runtime_resume(struct device *dev)
+{
+ return pm_clk_resume(dev);
+}
+
+static int tegra_aconnect_runtime_suspend(struct device *dev)
+{
+ return pm_clk_suspend(dev);
+}
+
+static const struct dev_pm_ops tegra_aconnect_pm_ops = {
+ SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
+ tegra_aconnect_runtime_resume, NULL)
+};
+
+static const struct of_device_id tegra_aconnect_of_match[] = {
+ { .compatible = "nvidia,tegra210-aconnect", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
+
+static struct platform_driver tegra_aconnect_driver = {
+ .probe = tegra_aconnect_probe,
+ .remove = tegra_aconnect_remove,
+ .driver = {
+ .name = "tegra-aconnect",
+ .of_match_table = tegra_aconnect_of_match,
+ .pm = &tegra_aconnect_pm_ops,
+ },
+};
+
+module_platform_driver(tegra_aconnect_driver);
+
+MODULE_DESCRIPTION("Tegra ACONNECT Bus Driver");
+MODULE_AUTHOR("Jon Hunter <[email protected]>");
+MODULE_LICENSE("GPL v2");
--
2.1.4