blob: ec392f5d0752c63ce3df12f4b628b5c96188d856 [file] [log] [blame]
Karthik Anantha Ramd114a202018-06-19 12:51:45 -07001/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Junzhe Zoucc79a572017-08-22 16:18:57 -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#include <linux/platform_device.h>
14#include <linux/of.h>
15#include <linux/of_device.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <media/cam_req_mgr.h>
20
21#include "cam_subdev.h"
22#include "cam_lrme_hw_intf.h"
23#include "cam_lrme_hw_core.h"
24#include "cam_lrme_hw_soc.h"
25#include "cam_lrme_hw_reg.h"
26#include "cam_req_mgr_workq.h"
27#include "cam_lrme_hw_mgr.h"
28#include "cam_mem_mgr_api.h"
29#include "cam_smmu_api.h"
30
Junzhe Zoucc79a572017-08-22 16:18:57 -070031static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core,
32 struct cam_hw_info *lrme_hw)
33{
34 int rc, i;
35 struct cam_cdm_bl_request *cdm_cmd;
36 struct cam_cdm_acquire_data cdm_acquire;
37 struct cam_lrme_cdm_info *hw_cdm_info;
38
39 hw_cdm_info = kzalloc(sizeof(struct cam_lrme_cdm_info),
40 GFP_KERNEL);
41 if (!hw_cdm_info) {
42 CAM_ERR(CAM_LRME, "No memory for hw_cdm_info");
43 return -ENOMEM;
44 }
45
46 cdm_cmd = kzalloc((sizeof(struct cam_cdm_bl_request) +
47 ((CAM_LRME_MAX_HW_ENTRIES - 1) *
48 sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
49 if (!cdm_cmd) {
50 CAM_ERR(CAM_LRME, "No memory for cdm_cmd");
51 kfree(hw_cdm_info);
52 return -ENOMEM;
53 }
54
55 memset(&cdm_acquire, 0, sizeof(cdm_acquire));
56 strlcpy(cdm_acquire.identifier, "lrmecdm", sizeof("lrmecdm"));
57 cdm_acquire.cell_index = lrme_hw->soc_info.index;
58 cdm_acquire.handle = 0;
59 cdm_acquire.userdata = hw_cdm_info;
60 cdm_acquire.cam_cdm_callback = NULL;
61 cdm_acquire.id = CAM_CDM_VIRTUAL;
62 cdm_acquire.base_array_cnt = lrme_hw->soc_info.num_reg_map;
63 for (i = 0; i < lrme_hw->soc_info.num_reg_map; i++)
64 cdm_acquire.base_array[i] = &lrme_hw->soc_info.reg_map[i];
65
66 rc = cam_cdm_acquire(&cdm_acquire);
67 if (rc) {
68 CAM_ERR(CAM_LRME, "Can't acquire cdm");
69 goto error;
70 }
71
72 hw_cdm_info->cdm_cmd = cdm_cmd;
73 hw_cdm_info->cdm_ops = cdm_acquire.ops;
74 hw_cdm_info->cdm_handle = cdm_acquire.handle;
75
76 lrme_core->hw_cdm_info = hw_cdm_info;
77 CAM_DBG(CAM_LRME, "cdm acquire done");
78
79 return 0;
80error:
81 kfree(cdm_cmd);
82 kfree(hw_cdm_info);
83 return rc;
84}
85
86static int cam_lrme_hw_dev_probe(struct platform_device *pdev)
87{
88 struct cam_hw_info *lrme_hw;
89 struct cam_hw_intf lrme_hw_intf;
90 struct cam_lrme_core *lrme_core;
91 const struct of_device_id *match_dev = NULL;
92 struct cam_lrme_hw_info *hw_info;
93 int rc, i;
94
95 lrme_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
96 if (!lrme_hw) {
97 CAM_ERR(CAM_LRME, "No memory to create lrme_hw");
98 return -ENOMEM;
99 }
100
101 lrme_core = kzalloc(sizeof(struct cam_lrme_core), GFP_KERNEL);
102 if (!lrme_core) {
103 CAM_ERR(CAM_LRME, "No memory to create lrme_core");
104 kfree(lrme_hw);
105 return -ENOMEM;
106 }
107
108 lrme_hw->core_info = lrme_core;
109 lrme_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
110 lrme_hw->soc_info.pdev = pdev;
111 lrme_hw->soc_info.dev = &pdev->dev;
112 lrme_hw->soc_info.dev_name = pdev->name;
113 lrme_hw->open_count = 0;
114 lrme_core->state = CAM_LRME_CORE_STATE_INIT;
115
116 mutex_init(&lrme_hw->hw_mutex);
117 spin_lock_init(&lrme_hw->hw_lock);
118 init_completion(&lrme_hw->hw_complete);
119 init_completion(&lrme_core->reset_complete);
120
121 rc = cam_req_mgr_workq_create("cam_lrme_hw_worker",
122 CAM_LRME_HW_WORKQ_NUM_TASK,
Karthik Anantha Ramd114a202018-06-19 12:51:45 -0700123 &lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0);
Junzhe Zoucc79a572017-08-22 16:18:57 -0700124 if (rc) {
125 CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc);
126 goto free_memory;
127 }
128
129 for (i = 0; i < CAM_LRME_HW_WORKQ_NUM_TASK; i++)
130 lrme_core->work->task.pool[i].payload =
131 &lrme_core->work_data[i];
132
133 match_dev = of_match_device(pdev->dev.driver->of_match_table,
134 &pdev->dev);
135 if (!match_dev || !match_dev->data) {
136 CAM_ERR(CAM_LRME, "No Of_match data, %pK", match_dev);
137 rc = -EINVAL;
138 goto destroy_workqueue;
139 }
140 hw_info = (struct cam_lrme_hw_info *)match_dev->data;
141 lrme_core->hw_info = hw_info;
142
143 rc = cam_lrme_soc_init_resources(&lrme_hw->soc_info,
144 cam_lrme_hw_irq, lrme_hw);
145 if (rc) {
146 CAM_ERR(CAM_LRME, "Failed to init soc, rc=%d", rc);
147 goto destroy_workqueue;
148 }
149
150 rc = cam_lrme_hw_dev_util_cdm_acquire(lrme_core, lrme_hw);
151 if (rc) {
152 CAM_ERR(CAM_LRME, "Failed to acquire cdm");
153 goto deinit_platform_res;
154 }
155
156 rc = cam_smmu_get_handle("lrme", &lrme_core->device_iommu.non_secure);
157 if (rc) {
158 CAM_ERR(CAM_LRME, "Get iommu handle failed");
159 goto release_cdm;
160 }
161
162 rc = cam_smmu_ops(lrme_core->device_iommu.non_secure, CAM_SMMU_ATTACH);
163 if (rc) {
164 CAM_ERR(CAM_LRME, "LRME attach iommu handle failed, rc=%d", rc);
165 goto destroy_smmu;
166 }
167
168 rc = cam_lrme_hw_start(lrme_hw, NULL, 0);
169 if (rc) {
170 CAM_ERR(CAM_LRME, "Failed to hw init, rc=%d", rc);
171 goto detach_smmu;
172 }
173
174 rc = cam_lrme_hw_util_get_caps(lrme_hw, &lrme_core->hw_caps);
175 if (rc) {
176 CAM_ERR(CAM_LRME, "Failed to get hw caps, rc=%d", rc);
177 if (cam_lrme_hw_stop(lrme_hw, NULL, 0))
178 CAM_ERR(CAM_LRME, "Failed in hw deinit");
179 goto detach_smmu;
180 }
181
182 rc = cam_lrme_hw_stop(lrme_hw, NULL, 0);
183 if (rc) {
184 CAM_ERR(CAM_LRME, "Failed to deinit hw, rc=%d", rc);
185 goto detach_smmu;
186 }
187
188 lrme_core->hw_idx = lrme_hw->soc_info.index;
189 lrme_hw_intf.hw_priv = lrme_hw;
190 lrme_hw_intf.hw_idx = lrme_hw->soc_info.index;
191 lrme_hw_intf.hw_ops.get_hw_caps = cam_lrme_hw_get_caps;
192 lrme_hw_intf.hw_ops.init = NULL;
193 lrme_hw_intf.hw_ops.deinit = NULL;
194 lrme_hw_intf.hw_ops.reset = cam_lrme_hw_reset;
195 lrme_hw_intf.hw_ops.reserve = NULL;
196 lrme_hw_intf.hw_ops.release = NULL;
197 lrme_hw_intf.hw_ops.start = cam_lrme_hw_start;
198 lrme_hw_intf.hw_ops.stop = cam_lrme_hw_stop;
199 lrme_hw_intf.hw_ops.read = NULL;
200 lrme_hw_intf.hw_ops.write = NULL;
201 lrme_hw_intf.hw_ops.process_cmd = cam_lrme_hw_process_cmd;
Junzhe Zou4b11e7a2017-11-13 17:21:32 -0800202 lrme_hw_intf.hw_ops.flush = cam_lrme_hw_flush;
Junzhe Zoucc79a572017-08-22 16:18:57 -0700203 lrme_hw_intf.hw_type = CAM_HW_LRME;
204
205 rc = cam_cdm_get_iommu_handle("lrmecdm", &lrme_core->cdm_iommu);
206 if (rc) {
207 CAM_ERR(CAM_LRME, "Failed to acquire the CDM iommu handles");
208 goto detach_smmu;
209 }
210
211 rc = cam_lrme_mgr_register_device(&lrme_hw_intf,
212 &lrme_core->device_iommu,
213 &lrme_core->cdm_iommu);
214 if (rc) {
215 CAM_ERR(CAM_LRME, "Failed to register device");
216 goto detach_smmu;
217 }
218
219 platform_set_drvdata(pdev, lrme_hw);
220 CAM_DBG(CAM_LRME, "LRME-%d probe successful", lrme_hw_intf.hw_idx);
221
222 return rc;
223
224detach_smmu:
225 cam_smmu_ops(lrme_core->device_iommu.non_secure, CAM_SMMU_DETACH);
226destroy_smmu:
227 cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure);
228release_cdm:
229 cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle);
230 kfree(lrme_core->hw_cdm_info->cdm_cmd);
231 kfree(lrme_core->hw_cdm_info);
232deinit_platform_res:
233 if (cam_lrme_soc_deinit_resources(&lrme_hw->soc_info))
234 CAM_ERR(CAM_LRME, "Failed in soc deinit");
235 mutex_destroy(&lrme_hw->hw_mutex);
236destroy_workqueue:
237 cam_req_mgr_workq_destroy(&lrme_core->work);
238free_memory:
239 mutex_destroy(&lrme_hw->hw_mutex);
240 kfree(lrme_hw);
241 kfree(lrme_core);
242
243 return rc;
244}
245
246static int cam_lrme_hw_dev_remove(struct platform_device *pdev)
247{
248 int rc = 0;
249 struct cam_hw_info *lrme_hw;
250 struct cam_lrme_core *lrme_core;
251
252 lrme_hw = platform_get_drvdata(pdev);
253 if (!lrme_hw) {
254 CAM_ERR(CAM_LRME, "Invalid lrme_hw from fd_hw_intf");
255 rc = -ENODEV;
256 goto deinit_platform_res;
257 }
258
259 lrme_core = (struct cam_lrme_core *)lrme_hw->core_info;
260 if (!lrme_core) {
261 CAM_ERR(CAM_LRME, "Invalid lrme_core from fd_hw");
262 rc = -EINVAL;
263 goto deinit_platform_res;
264 }
265
266 cam_smmu_ops(lrme_core->device_iommu.non_secure, CAM_SMMU_DETACH);
267 cam_smmu_destroy_handle(lrme_core->device_iommu.non_secure);
268 cam_cdm_release(lrme_core->hw_cdm_info->cdm_handle);
269 cam_lrme_mgr_deregister_device(lrme_core->hw_idx);
270
271 kfree(lrme_core->hw_cdm_info->cdm_cmd);
272 kfree(lrme_core->hw_cdm_info);
273 kfree(lrme_core);
274
275deinit_platform_res:
276 rc = cam_lrme_soc_deinit_resources(&lrme_hw->soc_info);
277 if (rc)
278 CAM_ERR(CAM_LRME, "Error in LRME soc deinit, rc=%d", rc);
279
280 mutex_destroy(&lrme_hw->hw_mutex);
281 kfree(lrme_hw);
282
283 return rc;
284}
285
286static const struct of_device_id cam_lrme_hw_dt_match[] = {
287 {
288 .compatible = "qcom,lrme",
289 .data = &cam_lrme10_hw_info,
290 },
291 {}
292};
293
294MODULE_DEVICE_TABLE(of, cam_lrme_hw_dt_match);
295
296static struct platform_driver cam_lrme_hw_driver = {
297 .probe = cam_lrme_hw_dev_probe,
298 .remove = cam_lrme_hw_dev_remove,
299 .driver = {
300 .name = "cam_lrme_hw",
301 .owner = THIS_MODULE,
302 .of_match_table = cam_lrme_hw_dt_match,
303 },
304};
305
306static int __init cam_lrme_hw_init_module(void)
307{
308 return platform_driver_register(&cam_lrme_hw_driver);
309}
310
311static void __exit cam_lrme_hw_exit_module(void)
312{
313 platform_driver_unregister(&cam_lrme_hw_driver);
314}
315
316module_init(cam_lrme_hw_init_module);
317module_exit(cam_lrme_hw_exit_module);
318MODULE_DESCRIPTION("CAM LRME HW driver");
319MODULE_LICENSE("GPL v2");