blob: 55a2e1b10c8a0f1fae74ded66ede3d254ed581ad [file] [log] [blame]
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -07001/* Copyright (c) 2017, The Linux Foundation. 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
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070013#include <linux/of.h>
14#include <linux/debugfs.h>
15#include <linux/videodev2.h>
16#include <linux/uaccess.h>
17#include <linux/platform_device.h>
18#include <linux/firmware.h>
19#include <linux/delay.h>
20#include <linux/timer.h>
21#include "cam_io_util.h"
22#include "cam_hw.h"
23#include "cam_hw_intf.h"
24#include "bps_core.h"
25#include "bps_soc.h"
26#include "cam_soc_util.h"
27#include "cam_io_util.h"
28#include "cam_bps_hw_intf.h"
29#include "cam_icp_hw_intf.h"
30#include "cam_icp_hw_mgr_intf.h"
31#include "cam_cpas_api.h"
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070032#include "cam_debug_util.h"
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070033
34static int cam_bps_cpas_vote(struct cam_bps_device_core_info *core_info,
35 struct cam_icp_cpas_vote *cpas_vote)
36{
37 int rc = 0;
38
39 if (cpas_vote->ahb_vote_valid)
40 rc = cam_cpas_update_ahb_vote(core_info->cpas_handle,
41 &cpas_vote->ahb_vote);
42 if (cpas_vote->axi_vote_valid)
43 rc = cam_cpas_update_axi_vote(core_info->cpas_handle,
44 &cpas_vote->axi_vote);
45
46 if (rc < 0)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070047 CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070048
49 return rc;
50}
51
52
53int cam_bps_init_hw(void *device_priv,
54 void *init_hw_args, uint32_t arg_size)
55{
56 struct cam_hw_info *bps_dev = device_priv;
57 struct cam_hw_soc_info *soc_info = NULL;
58 struct cam_bps_device_core_info *core_info = NULL;
59 struct cam_icp_cpas_vote cpas_vote;
60 int rc = 0;
61
62 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070063 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070064 return -EINVAL;
65 }
66
67 soc_info = &bps_dev->soc_info;
68 core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
69
70 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070071 CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
72 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070073 return -EINVAL;
74 }
75
76 cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070077 cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070078 cpas_vote.axi_vote.compressed_bw = ICP_TURBO_VOTE;
79 cpas_vote.axi_vote.uncompressed_bw = ICP_TURBO_VOTE;
80
81 rc = cam_cpas_start(core_info->cpas_handle,
82 &cpas_vote.ahb_vote, &cpas_vote.axi_vote);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070083 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070084 CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070085 return rc;
86 }
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070087 core_info->cpas_start = true;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070088
89 rc = cam_bps_enable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070090 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070091 CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070092 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070093 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070094 else
95 core_info->cpas_start = false;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070096 }
97
98 return rc;
99}
100
101int cam_bps_deinit_hw(void *device_priv,
102 void *init_hw_args, uint32_t arg_size)
103{
104 struct cam_hw_info *bps_dev = device_priv;
105 struct cam_hw_soc_info *soc_info = NULL;
106 struct cam_bps_device_core_info *core_info = NULL;
107 int rc = 0;
108
109 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700110 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700111 return -EINVAL;
112 }
113
114 soc_info = &bps_dev->soc_info;
115 core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
116 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700117 CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
118 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700119 return -EINVAL;
120 }
121
122 rc = cam_bps_disable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700123 if (rc)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700124 CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700125
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700126 if (core_info->cpas_start) {
127 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700128 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700129 else
130 core_info->cpas_start = false;
131 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700132
133 return rc;
134}
135
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530136static int cam_bps_handle_pc(struct cam_hw_info *bps_dev)
137{
138 struct cam_hw_soc_info *soc_info = NULL;
139 struct cam_bps_device_core_info *core_info = NULL;
140 struct cam_bps_device_hw_info *hw_info = NULL;
141 int pwr_ctrl;
142 int pwr_status;
143
144 soc_info = &bps_dev->soc_info;
145 core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
146 hw_info = core_info->bps_hw_info;
147
148 cam_cpas_reg_read(core_info->cpas_handle,
149 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl,
150 true, &pwr_ctrl);
151 if (!(pwr_ctrl & BPS_COLLAPSE_MASK)) {
152 cam_cpas_reg_read(core_info->cpas_handle,
153 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status,
154 true, &pwr_status);
155
156 cam_cpas_reg_write(core_info->cpas_handle,
157 CAM_CPAS_REG_CPASTOP,
158 hw_info->pwr_ctrl, true, 0x1);
159
160 if ((pwr_status >> BPS_PWR_ON_MASK))
161 return -EINVAL;
162 }
163 cam_bps_get_gdsc_control(soc_info);
164 cam_cpas_reg_read(core_info->cpas_handle,
165 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true,
166 &pwr_ctrl);
167 cam_cpas_reg_read(core_info->cpas_handle,
168 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status,
169 true, &pwr_status);
170 CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x",
171 pwr_ctrl, pwr_status);
172
173 return 0;
174}
175
176static int cam_bps_handle_resume(struct cam_hw_info *bps_dev)
177{
178 struct cam_hw_soc_info *soc_info = NULL;
179 struct cam_bps_device_core_info *core_info = NULL;
180 struct cam_bps_device_hw_info *hw_info = NULL;
181 int pwr_ctrl;
182 int pwr_status;
183 int rc = 0;
184
185 soc_info = &bps_dev->soc_info;
186 core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
187 hw_info = core_info->bps_hw_info;
188
189 cam_cpas_reg_read(core_info->cpas_handle,
190 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
191 if (pwr_ctrl & BPS_COLLAPSE_MASK) {
192 CAM_ERR(CAM_ICP, "BPS: resume failed : %d", pwr_ctrl);
193 return -EINVAL;
194 }
195
196 rc = cam_bps_transfer_gdsc_control(soc_info);
197 cam_cpas_reg_read(core_info->cpas_handle,
198 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
199 cam_cpas_reg_read(core_info->cpas_handle,
200 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status, true, &pwr_status);
201 CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x",
202 pwr_ctrl, pwr_status);
203
204 return rc;
205}
206
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700207int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type,
208 void *cmd_args, uint32_t arg_size)
209{
210 struct cam_hw_info *bps_dev = device_priv;
211 struct cam_hw_soc_info *soc_info = NULL;
212 struct cam_bps_device_core_info *core_info = NULL;
213 struct cam_bps_device_hw_info *hw_info = NULL;
214 int rc = 0;
215
216 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700217 CAM_ERR(CAM_ICP, "Invalid arguments");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700218 return -EINVAL;
219 }
220
221 if (cmd_type >= CAM_ICP_BPS_CMD_MAX) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700222 CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700223 return -EINVAL;
224 }
225
226 soc_info = &bps_dev->soc_info;
227 core_info = (struct cam_bps_device_core_info *)bps_dev->core_info;
228 hw_info = core_info->bps_hw_info;
229
230 switch (cmd_type) {
231 case CAM_ICP_BPS_CMD_VOTE_CPAS: {
232 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
233
234 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700235 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700236 return -EINVAL;
237 }
238
239 cam_bps_cpas_vote(core_info, cpas_vote);
240 break;
241 }
242
243 case CAM_ICP_BPS_CMD_CPAS_START: {
244 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
245
246 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700247 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700248 return -EINVAL;
249 }
250
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700251 if (!core_info->cpas_start) {
252 rc = cam_cpas_start(core_info->cpas_handle,
253 &cpas_vote->ahb_vote,
254 &cpas_vote->axi_vote);
255 core_info->cpas_start = true;
256 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700257 break;
258 }
259
260 case CAM_ICP_BPS_CMD_CPAS_STOP:
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700261 if (core_info->cpas_start) {
262 cam_cpas_stop(core_info->cpas_handle);
263 core_info->cpas_start = false;
264 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700265 break;
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530266 case CAM_ICP_BPS_CMD_POWER_COLLAPSE:
267 rc = cam_bps_handle_pc(bps_dev);
268 break;
269 case CAM_ICP_BPS_CMD_POWER_RESUME:
270 rc = cam_bps_handle_resume(bps_dev);
271 break;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700272 default:
273 break;
274 }
275 return rc;
276}
277
278irqreturn_t cam_bps_irq(int irq_num, void *data)
279{
280 return IRQ_HANDLED;
281}