diff options
author | Olof Johansson <olof@lixom.net> | 2016-07-06 22:32:11 -0700 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2016-07-06 22:32:11 -0700 |
commit | 34df3b8bdc54709f78b0d72648fee6e53ffd8598 (patch) | |
tree | 62e112dfa330f2d0243c6b5199397f3ff38c37e0 /drivers | |
parent | b85751c761a56232e772f4c2d1aba2cd43d52849 (diff) | |
parent | 46a88534afb596eb4d9de07ddde778d0e9aa0e3a (diff) |
Merge tag 'tegra-for-4.8-bus' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bus/Kconfig | 13 | ||||
-rw-r--r-- | drivers/bus/Makefile | 1 | ||||
-rw-r--r-- | drivers/bus/tegra-aconnect.c | 112 |
3 files changed, 126 insertions, 0 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index c5a7de9bc783..3b205e212337 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -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 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..7e4104b74fa8 --- /dev/null +++ b/drivers/bus/tegra-aconnect.c @@ -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"); |