blob: 6095e08139b0841a5989d269731359896352ff20 [file] [log] [blame]
Praveen Chidambaramf53ef1b2011-12-06 08:27:49 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
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>
23
24#define DCVS_CMD_CREATE_GROUP 1
25#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
29
30struct scm_register_core {
31 uint32_t core_id;
32 uint32_t group_id;
33 phys_addr_t core_param_phy;
34 phys_addr_t freq_phy;
35};
36
37struct scm_algo {
38 uint32_t core_id;
39 phys_addr_t algo_phy;
40};
41
42struct scm_init {
43 uint32_t phy;
44 uint32_t size;
45};
46
47int msm_dcvs_scm_init(size_t size)
48{
49 int ret = 0;
50 struct scm_init init;
51 uint32_t p = 0;
52
53 /* Allocate word aligned non-cacheable memory */
54 p = allocate_contiguous_ebi_nomap(size, 4);
55 if (!p)
56 return -ENOMEM;
57
58 init.phy = p;
59 init.size = size;
60
61 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_INIT,
62 &init, sizeof(init), NULL, 0);
63
64 /* Not freed if the initialization succeeds */
65 if (ret)
66 free_contiguous_memory_by_paddr(p);
67
68 return ret;
69}
70EXPORT_SYMBOL(msm_dcvs_scm_init);
71
72int msm_dcvs_scm_create_group(uint32_t id)
73{
74 int ret = 0;
75
76 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_CREATE_GROUP,
77 &id, sizeof(uint32_t), NULL, 0);
78
79 return ret;
80}
81EXPORT_SYMBOL(msm_dcvs_scm_create_group);
82
83int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id,
84 struct msm_dcvs_core_param *param,
85 struct msm_dcvs_freq_entry *freq)
86{
87 int ret = 0;
88 struct scm_register_core reg_data;
89 struct msm_dcvs_core_param *p = NULL;
90 struct msm_dcvs_freq_entry *f = NULL;
91
92 p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_core_param)), GFP_KERNEL);
93 if (!p)
94 return -ENOMEM;
95
96 f = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry) *
97 param->num_freq), GFP_KERNEL);
98 if (!f) {
99 kfree(p);
100 return -ENOMEM;
101 }
102
103 memcpy(p, param, sizeof(struct msm_dcvs_core_param));
104 memcpy(f, freq, sizeof(struct msm_dcvs_freq_entry) * param->num_freq);
105
106 reg_data.core_id = core_id;
107 reg_data.group_id = group_id;
108 reg_data.core_param_phy = virt_to_phys(p);
109 reg_data.freq_phy = virt_to_phys(f);
110
111 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_REGISTER_CORE,
112 &reg_data, sizeof(reg_data), NULL, 0);
113
114 kfree(f);
115 kfree(p);
116
117 return ret;
118}
119EXPORT_SYMBOL(msm_dcvs_scm_register_core);
120
121int msm_dcvs_scm_set_algo_params(uint32_t core_id,
122 struct msm_dcvs_algo_param *param)
123{
124 int ret = 0;
125 struct scm_algo algo;
126 struct msm_dcvs_algo_param *p = NULL;
127
128 p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_algo_param)), GFP_KERNEL);
129 if (!p)
130 return -ENOMEM;
131
132 memcpy(p, param, sizeof(struct msm_dcvs_algo_param));
133
134 algo.core_id = core_id;
135 algo.algo_phy = virt_to_phys(p);
136
137 ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
138 &algo, sizeof(algo), NULL, 0);
139
140 kfree(p);
141
142 return ret;
143}
144EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params);
145
146int msm_dcvs_scm_event(uint32_t core_id,
147 enum msm_dcvs_scm_event event_id,
148 uint32_t param0, uint32_t param1,
149 uint32_t *ret0, uint32_t *ret1)
150{
151 int ret = -EINVAL;
152
153 if (!ret0 || !ret1)
154 return ret;
155
156 ret = scm_call_atomic4_3(SCM_SVC_DCVS, DCVS_CMD_EVENT,
157 core_id, event_id, param0, param1, ret0, ret1);
158
159 return ret;
160}
161EXPORT_SYMBOL(msm_dcvs_scm_event);