blob: 78d62ac79bd7c15f7a9f66dd152ecc6999ed57bb [file] [log] [blame]
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/slab.h>
18#include <linux/mm.h>
19#include <linux/memory_alloc.h>
20#include <mach/memory.h>
21#include <mach/scm.h>
22#include <mach/msm_dcvs_scm.h>
Abhijeet Dharmapurikarf17f2d32012-09-13 19:05:13 -070023#include <trace/events/mpdcvs_trace.h>
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070024
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070025#define DCVS_CMD_REGISTER_CORE 2
26#define DCVS_CMD_SET_ALGO_PARAM 3
27#define DCVS_CMD_EVENT 4
28#define DCVS_CMD_INIT 5
Abhijeet Dharmapurikar44451662012-08-23 18:58:44 -070029#define DCVS_CMD_SET_POWER_PARAM 6
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070030
31struct scm_register_core {
32 uint32_t core_id;
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070033 phys_addr_t core_param_phy;
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070034};
35
36struct scm_algo {
37 uint32_t core_id;
38 phys_addr_t algo_phy;
39};
40
41struct scm_init {
42 uint32_t phy;
43 uint32_t size;
44};
45
Abhijeet Dharmapurikar44451662012-08-23 18:58:44 -070046struct scm_pwr_param {
47 uint32_t core_id;
48 phys_addr_t pwr_param_phy;
49 phys_addr_t freq_phy;
50 phys_addr_t coeffs_phy;
51};
52
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -070053struct msm_algo_param {
54 enum msm_dcvs_algo_param_type type;
55 union {
56 struct msm_dcvs_algo_param dcvs_param;
57 struct msm_mpd_algo_param mpd_param;
58 } u;
59};
60
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070061int msm_dcvs_scm_init(size_t size)
62{
63 int ret = 0;
64 struct scm_init init;
65 uint32_t p = 0;
66
67 /* Allocate word aligned non-cacheable memory */
68 p = allocate_contiguous_ebi_nomap(size, 4);
69 if (!p)
70 return -ENOMEM;
71
72 init.phy = p;
73 init.size = size;
74
75 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_INIT,
76 &init, sizeof(init), NULL, 0);
77
78 /* Not freed if the initialization succeeds */
79 if (ret)
80 free_contiguous_memory_by_paddr(p);
81
82 return ret;
83}
84EXPORT_SYMBOL(msm_dcvs_scm_init);
85
Abhijeet Dharmapurikar44451662012-08-23 18:58:44 -070086int msm_dcvs_scm_register_core(uint32_t core_id,
87 struct msm_dcvs_core_param *param)
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070088{
89 int ret = 0;
90 struct scm_register_core reg_data;
91 struct msm_dcvs_core_param *p = NULL;
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070092
93 p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_core_param)), GFP_KERNEL);
94 if (!p)
95 return -ENOMEM;
96
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070097 memcpy(p, param, sizeof(struct msm_dcvs_core_param));
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -070098
99 reg_data.core_id = core_id;
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700100 reg_data.core_param_phy = virt_to_phys(p);
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700101
102 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_REGISTER_CORE,
103 &reg_data, sizeof(reg_data), NULL, 0);
104
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700105 kfree(p);
106
107 return ret;
108}
109EXPORT_SYMBOL(msm_dcvs_scm_register_core);
110
111int msm_dcvs_scm_set_algo_params(uint32_t core_id,
112 struct msm_dcvs_algo_param *param)
113{
114 int ret = 0;
115 struct scm_algo algo;
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -0700116 struct msm_algo_param *p = NULL;
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700117
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -0700118 p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700119 if (!p)
120 return -ENOMEM;
121
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -0700122 p->type = MSM_DCVS_ALGO_DCVS_PARAM;
123 memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param));
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700124
125 algo.core_id = core_id;
126 algo.algo_phy = virt_to_phys(p);
127
128 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
129 &algo, sizeof(algo), NULL, 0);
130
131 kfree(p);
132
133 return ret;
134}
135EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params);
136
Abhijeet Dharmapurikara599de42012-08-23 13:49:45 -0700137int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param)
138{
139 int ret = 0;
140 struct scm_algo algo;
141 struct msm_algo_param *p = NULL;
142
143 p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
144 if (!p)
145 return -ENOMEM;
146
147 p->type = MSM_DCVS_ALGO_MPD_PARAM;
148 memcpy(&p->u.mpd_param, param, sizeof(struct msm_mpd_algo_param));
149
150 algo.core_id = 0;
151 algo.algo_phy = virt_to_phys(p);
152
153 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
154 &algo, sizeof(algo), NULL, 0);
155
156 kfree(p);
157
158 return ret;
159}
160EXPORT_SYMBOL(msm_mpd_scm_set_algo_params);
161
Abhijeet Dharmapurikar44451662012-08-23 18:58:44 -0700162int msm_dcvs_scm_set_power_params(uint32_t core_id,
163 struct msm_dcvs_power_params *pwr_param,
164 struct msm_dcvs_freq_entry *freq_entry,
165 struct msm_dcvs_energy_curve_coeffs *coeffs)
166{
167 int ret = 0;
168 struct scm_pwr_param pwr;
169 struct msm_dcvs_power_params *pwrt = NULL;
170 struct msm_dcvs_freq_entry *freqt = NULL;
171 struct msm_dcvs_energy_curve_coeffs *coefft = NULL;
172
173 pwrt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_power_params)),
174 GFP_KERNEL);
175 if (!pwrt)
176 return -ENOMEM;
177
178 freqt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry)
179 * pwr_param->num_freq),
180 GFP_KERNEL);
181 if (!freqt) {
182 kfree(pwrt);
183 return -ENOMEM;
184 }
185
186 coefft = kzalloc(PAGE_ALIGN(
187 sizeof(struct msm_dcvs_energy_curve_coeffs)),
188 GFP_KERNEL);
189 if (!coefft) {
190 kfree(pwrt);
191 kfree(freqt);
192 return -ENOMEM;
193 }
194
195 memcpy(pwrt, pwr_param, sizeof(struct msm_dcvs_power_params));
196 memcpy(freqt, freq_entry,
197 sizeof(struct msm_dcvs_freq_entry)*pwr_param->num_freq);
198 memcpy(coefft, coeffs, sizeof(struct msm_dcvs_energy_curve_coeffs));
199
200 pwr.core_id = core_id;
201 pwr.pwr_param_phy = virt_to_phys(pwrt);
202 pwr.freq_phy = virt_to_phys(freqt);
203 pwr.coeffs_phy = virt_to_phys(coefft);
204
205 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_POWER_PARAM,
206 &pwr, sizeof(pwr), NULL, 0);
207
208 kfree(pwrt);
209 kfree(freqt);
210 kfree(coefft);
211
212 return ret;
213}
214EXPORT_SYMBOL(msm_dcvs_scm_set_power_params);
215
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700216int msm_dcvs_scm_event(uint32_t core_id,
217 enum msm_dcvs_scm_event event_id,
218 uint32_t param0, uint32_t param1,
219 uint32_t *ret0, uint32_t *ret1)
220{
221 int ret = -EINVAL;
222
223 if (!ret0 || !ret1)
224 return ret;
225
226 ret = scm_call_atomic4_3(SCM_SVC_DCVS, DCVS_CMD_EVENT,
227 core_id, event_id, param0, param1, ret0, ret1);
228
Abhijeet Dharmapurikarf17f2d32012-09-13 19:05:13 -0700229 trace_msm_dcvs_scm_event(core_id, (int)event_id, param0, param1,
230 *ret0, *ret1);
231
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -0700232 return ret;
233}
234EXPORT_SYMBOL(msm_dcvs_scm_event);