0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/module.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016
0017 struct tegra_aconnect {
0018 struct clk *ape_clk;
0019 struct clk *apb2ape_clk;
0020 };
0021
0022 static int tegra_aconnect_probe(struct platform_device *pdev)
0023 {
0024 struct tegra_aconnect *aconnect;
0025
0026 if (!pdev->dev.of_node)
0027 return -EINVAL;
0028
0029 aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect),
0030 GFP_KERNEL);
0031 if (!aconnect)
0032 return -ENOMEM;
0033
0034 aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape");
0035 if (IS_ERR(aconnect->ape_clk)) {
0036 dev_err(&pdev->dev, "Can't retrieve ape clock\n");
0037 return PTR_ERR(aconnect->ape_clk);
0038 }
0039
0040 aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape");
0041 if (IS_ERR(aconnect->apb2ape_clk)) {
0042 dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n");
0043 return PTR_ERR(aconnect->apb2ape_clk);
0044 }
0045
0046 dev_set_drvdata(&pdev->dev, aconnect);
0047 pm_runtime_enable(&pdev->dev);
0048
0049 of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
0050
0051 dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
0052
0053 return 0;
0054 }
0055
0056 static int tegra_aconnect_remove(struct platform_device *pdev)
0057 {
0058 pm_runtime_disable(&pdev->dev);
0059
0060 return 0;
0061 }
0062
0063 static int tegra_aconnect_runtime_resume(struct device *dev)
0064 {
0065 struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
0066 int ret;
0067
0068 ret = clk_prepare_enable(aconnect->ape_clk);
0069 if (ret) {
0070 dev_err(dev, "ape clk_enable failed: %d\n", ret);
0071 return ret;
0072 }
0073
0074 ret = clk_prepare_enable(aconnect->apb2ape_clk);
0075 if (ret) {
0076 clk_disable_unprepare(aconnect->ape_clk);
0077 dev_err(dev, "apb2ape clk_enable failed: %d\n", ret);
0078 return ret;
0079 }
0080
0081 return 0;
0082 }
0083
0084 static int tegra_aconnect_runtime_suspend(struct device *dev)
0085 {
0086 struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
0087
0088 clk_disable_unprepare(aconnect->ape_clk);
0089 clk_disable_unprepare(aconnect->apb2ape_clk);
0090
0091 return 0;
0092 }
0093
0094 static const struct dev_pm_ops tegra_aconnect_pm_ops = {
0095 SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
0096 tegra_aconnect_runtime_resume, NULL)
0097 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0098 pm_runtime_force_resume)
0099 };
0100
0101 static const struct of_device_id tegra_aconnect_of_match[] = {
0102 { .compatible = "nvidia,tegra210-aconnect", },
0103 { }
0104 };
0105 MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
0106
0107 static struct platform_driver tegra_aconnect_driver = {
0108 .probe = tegra_aconnect_probe,
0109 .remove = tegra_aconnect_remove,
0110 .driver = {
0111 .name = "tegra-aconnect",
0112 .of_match_table = tegra_aconnect_of_match,
0113 .pm = &tegra_aconnect_pm_ops,
0114 },
0115 };
0116 module_platform_driver(tegra_aconnect_driver);
0117
0118 MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver");
0119 MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
0120 MODULE_LICENSE("GPL v2");