xref: /openbmc/linux/drivers/bus/tegra-aconnect.c (revision 1427736e)
146a88534SJon Hunter /*
246a88534SJon Hunter  * Tegra ACONNECT Bus Driver
346a88534SJon Hunter  *
446a88534SJon Hunter  * Copyright (C) 2016, NVIDIA CORPORATION.  All rights reserved.
546a88534SJon Hunter  *
646a88534SJon Hunter  * This file is subject to the terms and conditions of the GNU General Public
746a88534SJon Hunter  * License.  See the file "COPYING" in the main directory of this archive
846a88534SJon Hunter  * for more details.
946a88534SJon Hunter  */
1046a88534SJon Hunter 
1146a88534SJon Hunter #include <linux/clk.h>
1246a88534SJon Hunter #include <linux/module.h>
1346a88534SJon Hunter #include <linux/of_platform.h>
1446a88534SJon Hunter #include <linux/platform_device.h>
1546a88534SJon Hunter #include <linux/pm_runtime.h>
1646a88534SJon Hunter 
170d7dab92SSameer Pujar struct tegra_aconnect {
180d7dab92SSameer Pujar 	struct clk	*ape_clk;
190d7dab92SSameer Pujar 	struct clk	*apb2ape_clk;
200d7dab92SSameer Pujar };
210d7dab92SSameer Pujar 
tegra_aconnect_probe(struct platform_device * pdev)2246a88534SJon Hunter static int tegra_aconnect_probe(struct platform_device *pdev)
2346a88534SJon Hunter {
240d7dab92SSameer Pujar 	struct tegra_aconnect *aconnect;
2546a88534SJon Hunter 
2646a88534SJon Hunter 	if (!pdev->dev.of_node)
2746a88534SJon Hunter 		return -EINVAL;
2846a88534SJon Hunter 
290d7dab92SSameer Pujar 	aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect),
300d7dab92SSameer Pujar 				GFP_KERNEL);
310d7dab92SSameer Pujar 	if (!aconnect)
320d7dab92SSameer Pujar 		return -ENOMEM;
3346a88534SJon Hunter 
340d7dab92SSameer Pujar 	aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape");
350d7dab92SSameer Pujar 	if (IS_ERR(aconnect->ape_clk)) {
360d7dab92SSameer Pujar 		dev_err(&pdev->dev, "Can't retrieve ape clock\n");
370d7dab92SSameer Pujar 		return PTR_ERR(aconnect->ape_clk);
380d7dab92SSameer Pujar 	}
3946a88534SJon Hunter 
400d7dab92SSameer Pujar 	aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape");
410d7dab92SSameer Pujar 	if (IS_ERR(aconnect->apb2ape_clk)) {
420d7dab92SSameer Pujar 		dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n");
430d7dab92SSameer Pujar 		return PTR_ERR(aconnect->apb2ape_clk);
440d7dab92SSameer Pujar 	}
4546a88534SJon Hunter 
460d7dab92SSameer Pujar 	dev_set_drvdata(&pdev->dev, aconnect);
4746a88534SJon Hunter 	pm_runtime_enable(&pdev->dev);
4846a88534SJon Hunter 
4946a88534SJon Hunter 	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
5046a88534SJon Hunter 
5146a88534SJon Hunter 	dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
5246a88534SJon Hunter 
5346a88534SJon Hunter 	return 0;
5446a88534SJon Hunter }
5546a88534SJon Hunter 
tegra_aconnect_remove(struct platform_device * pdev)5646a88534SJon Hunter static int tegra_aconnect_remove(struct platform_device *pdev)
5746a88534SJon Hunter {
5846a88534SJon Hunter 	pm_runtime_disable(&pdev->dev);
5946a88534SJon Hunter 
6046a88534SJon Hunter 	return 0;
6146a88534SJon Hunter }
6246a88534SJon Hunter 
tegra_aconnect_runtime_resume(struct device * dev)6346a88534SJon Hunter static int tegra_aconnect_runtime_resume(struct device *dev)
6446a88534SJon Hunter {
650d7dab92SSameer Pujar 	struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
660d7dab92SSameer Pujar 	int ret;
670d7dab92SSameer Pujar 
680d7dab92SSameer Pujar 	ret = clk_prepare_enable(aconnect->ape_clk);
690d7dab92SSameer Pujar 	if (ret) {
700d7dab92SSameer Pujar 		dev_err(dev, "ape clk_enable failed: %d\n", ret);
710d7dab92SSameer Pujar 		return ret;
720d7dab92SSameer Pujar 	}
730d7dab92SSameer Pujar 
740d7dab92SSameer Pujar 	ret = clk_prepare_enable(aconnect->apb2ape_clk);
750d7dab92SSameer Pujar 	if (ret) {
760d7dab92SSameer Pujar 		clk_disable_unprepare(aconnect->ape_clk);
770d7dab92SSameer Pujar 		dev_err(dev, "apb2ape clk_enable failed: %d\n", ret);
780d7dab92SSameer Pujar 		return ret;
790d7dab92SSameer Pujar 	}
800d7dab92SSameer Pujar 
810d7dab92SSameer Pujar 	return 0;
8246a88534SJon Hunter }
8346a88534SJon Hunter 
tegra_aconnect_runtime_suspend(struct device * dev)8446a88534SJon Hunter static int tegra_aconnect_runtime_suspend(struct device *dev)
8546a88534SJon Hunter {
860d7dab92SSameer Pujar 	struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
870d7dab92SSameer Pujar 
880d7dab92SSameer Pujar 	clk_disable_unprepare(aconnect->ape_clk);
890d7dab92SSameer Pujar 	clk_disable_unprepare(aconnect->apb2ape_clk);
900d7dab92SSameer Pujar 
910d7dab92SSameer Pujar 	return 0;
9246a88534SJon Hunter }
9346a88534SJon Hunter 
9446a88534SJon Hunter static const struct dev_pm_ops tegra_aconnect_pm_ops = {
9546a88534SJon Hunter 	SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
9646a88534SJon Hunter 			   tegra_aconnect_runtime_resume, NULL)
971427736eSSameer Pujar 	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
981427736eSSameer Pujar 				      pm_runtime_force_resume)
9946a88534SJon Hunter };
10046a88534SJon Hunter 
10146a88534SJon Hunter static const struct of_device_id tegra_aconnect_of_match[] = {
10246a88534SJon Hunter 	{ .compatible = "nvidia,tegra210-aconnect", },
10346a88534SJon Hunter 	{ }
10446a88534SJon Hunter };
10546a88534SJon Hunter MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
10646a88534SJon Hunter 
10746a88534SJon Hunter static struct platform_driver tegra_aconnect_driver = {
10846a88534SJon Hunter 	.probe = tegra_aconnect_probe,
10946a88534SJon Hunter 	.remove = tegra_aconnect_remove,
11046a88534SJon Hunter 	.driver = {
11146a88534SJon Hunter 		.name = "tegra-aconnect",
11246a88534SJon Hunter 		.of_match_table = tegra_aconnect_of_match,
11346a88534SJon Hunter 		.pm = &tegra_aconnect_pm_ops,
11446a88534SJon Hunter 	},
11546a88534SJon Hunter };
11646a88534SJon Hunter module_platform_driver(tegra_aconnect_driver);
11746a88534SJon Hunter 
11846a88534SJon Hunter MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver");
11946a88534SJon Hunter MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
12046a88534SJon Hunter MODULE_LICENSE("GPL v2");
121