Merge tag 'tegra-for-4.8-bus' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra...
authorOlof Johansson <olof@lixom.net>
Thu, 7 Jul 2016 05:32:11 +0000 (22:32 -0700)
committerOlof Johansson <olof@lixom.net>
Thu, 7 Jul 2016 05:32:11 +0000 (22:32 -0700)
bus: NVIDIA Tegra ACONNECT support

Adds support for the Tegra ACONNECT bus that's used to access the APE
(audio processing engine) on Tegra X1.

* tag 'tegra-for-4.8-bus' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  bus: Add support for Tegra ACONNECT
  dt-bindings: bus: Add documentation for Tegra210 ACONNECT

Signed-off-by: Olof Johansson <olof@lixom.net>
Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt [new file with mode: 0644]
drivers/bus/Kconfig
drivers/bus/Makefile
drivers/bus/tegra-aconnect.c [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt b/Documentation/devicetree/bindings/bus/nvidia,tegra210-aconnect.txt
new file mode 100644 (file)
index 0000000..7ff13be
--- /dev/null
@@ -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 aconnect address space. Should be 1.
+- #size-cells: The number of cells used to represent the size of an address
+  range in the aconnect address space. Should be 1.
+- ranges: 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 = <1>;
+               #size-cells = <1>;
+               ranges = <0x702c0000 0x0 0x702c0000 0x00040000>;
+
+               status = "disabled";
+
+               child1 {
+                       ...
+               };
+
+               child2 {
+                       ...
+               };
+       };
index c5a7de9..3b205e2 100644 (file)
@@ -132,6 +132,19 @@ config SUNXI_RSB
          with various RSB based devices, such as AXP223, AXP8XX PMICs,
          and AC100/AC200 ICs.
 
+# TODO: This uses pm_clk_*() symbols that aren't exported in v4.7 and hence
+# the driver will fail to build as a module. However there are patches to
+# address that queued for v4.8, so this can be turned into a tristate symbol
+# after v4.8-rc1.
+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
index ccff007..ac84cc4 100644 (file)
@@ -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 (file)
index 0000000..7e4104b
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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("NVIDIA Tegra ACONNECT Bus Driver");
+MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
+MODULE_LICENSE("GPL v2");