1 /*
2 * Copyright (C) 2010, 2012-2017 ARM Limited. All rights reserved.
3 *
4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6 *
7 * A copy of the licence is included with the program, and can also be obtained from Free Software
8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
9 */
10
11 /**
12 * @file juno_opp.c
13 * Example: Set up opp table
14 * Using ARM64 juno specific SCPI_PROTOCOL get frequence inform
15 * Customer need implement your own platform releated logic
16 */
17 #ifdef CONFIG_ARCH_VEXPRESS
18 #ifdef CONFIG_MALI_DEVFREQ
19 #ifdef CONFIG_ARM64
20 #ifdef CONFIG_ARM_SCPI_PROTOCOL
21 #include <linux/module.h>
22 #include <linux/of_platform.h>
23 #include <linux/platform_device.h>
24 #include <linux/scpi_protocol.h>
25 #include <linux/version.h>
26 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
27 #include <linux/pm_opp.h>
28 #else /* Linux >= 3.13 */
29 /* In 3.13 the OPP include header file, types, and functions were all
30 * renamed. Use the old filename for the include, and define the new names to
31 * the old, when an old kernel is detected.
32 */
33 #include <linux/opp.h>
34 #define dev_pm_opp_add opp_add
35 #define dev_pm_opp_remove opp_remove
36 #endif /* Linux >= 3.13 */
37
38 #include "mali_kernel_common.h"
39
init_juno_opps_from_scpi(struct device * dev)40 static int init_juno_opps_from_scpi(struct device *dev)
41 {
42 struct scpi_dvfs_info *sinfo;
43 struct scpi_ops *sops;
44
45 int i;
46
47 sops = get_scpi_ops();
48 if (NULL == sops) {
49 MALI_DEBUG_PRINT(2, ("Mali didn't get any scpi ops \n"));
50 return -1;
51 }
52
53 /* Hard coded for Juno. 2 is GPU domain */
54 sinfo = sops->dvfs_get_info(2);
55 if (IS_ERR_OR_NULL(sinfo))
56 return PTR_ERR(sinfo);
57
58 for (i = 0; i < sinfo->count; i++) {
59 struct scpi_opp *e = &sinfo->opps[i];
60
61 MALI_DEBUG_PRINT(2, ("Mali OPP from SCPI: %u Hz @ %u mV\n", e->freq, e->m_volt));
62
63 dev_pm_opp_add(dev, e->freq, e->m_volt * 1000);
64 }
65
66 return 0;
67 }
68
setup_opps(void)69 int setup_opps(void)
70 {
71 struct device_node *np;
72 struct platform_device *pdev;
73 int err;
74
75 np = of_find_node_by_name(NULL, "gpu");
76 if (!np) {
77 pr_err("Failed to find DT entry for Mali\n");
78 return -EFAULT;
79 }
80
81 pdev = of_find_device_by_node(np);
82 if (!pdev) {
83 pr_err("Failed to find device for Mali\n");
84 of_node_put(np);
85 return -EFAULT;
86 }
87
88 err = init_juno_opps_from_scpi(&pdev->dev);
89
90 of_node_put(np);
91
92 return err;
93 }
94
term_opps(struct device * dev)95 int term_opps(struct device *dev)
96 {
97 struct scpi_dvfs_info *sinfo;
98 struct scpi_ops *sops;
99
100 int i;
101
102 sops = get_scpi_ops();
103 if (NULL == sops) {
104 MALI_DEBUG_PRINT(2, ("Mali didn't get any scpi ops \n"));
105 return -1;
106 }
107
108 /* Hard coded for Juno. 2 is GPU domain */
109 sinfo = sops->dvfs_get_info(2);
110 if (IS_ERR_OR_NULL(sinfo))
111 return PTR_ERR(sinfo);
112
113 for (i = 0; i < sinfo->count; i++) {
114 struct scpi_opp *e = &sinfo->opps[i];
115
116 MALI_DEBUG_PRINT(2, ("Mali Remove OPP: %u Hz \n", e->freq));
117
118 dev_pm_opp_remove(dev, e->freq);
119 }
120
121 return 0;
122
123 }
124 #endif
125 #endif
126 #endif
127 #endif
128