hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/soc/rockchip/rockchip_amp.c
....@@ -6,6 +6,7 @@
66 * Author: Tony Xie <tony.xie@rock-chips.com>
77 */
88
9
+#include <asm/cputype.h>
910 #include <linux/clk.h>
1011 #include <linux/module.h>
1112 #include <linux/of.h>
....@@ -13,10 +14,17 @@
1314 #include <linux/pm_domain.h>
1415 #include <linux/pm_runtime.h>
1516 #include <linux/rockchip/rockchip_sip.h>
17
+#include <soc/rockchip/rockchip_amp.h>
1618
1719 #define RK_CPU_STATUS_OFF 0
1820 #define RK_CPU_STATUS_ON 1
1921 #define RK_CPU_STATUS_BUSY -1
22
+#define AMP_AFF_MAX_CLUSTER 4
23
+#define AMP_AFF_MAX_CPU 8
24
+#define GPIO_BANK_NUM 16
25
+#define GPIO_GROUP_PRIO_MAX 3
26
+
27
+#define AMP_GIC_DBG(fmt, arg...) do { if (0) { pr_warn(fmt, ##arg); } } while (0)
2028
2129 enum amp_cpu_ctrl_status {
2230 AMP_CPU_STATUS_AMP_DIS = 0,
....@@ -43,6 +51,33 @@
4351 u64 entry;
4452 u64 cpu_id;
4553 } cpu_boot_info[CONFIG_NR_CPUS];
54
+
55
+struct amp_gpio_group_s {
56
+ u32 bank_id;
57
+ u32 prio;
58
+ u32 irq_aff[AMP_AFF_MAX_CPU];
59
+ u32 irq_id[AMP_AFF_MAX_CPU];
60
+ u32 en[AMP_AFF_MAX_CPU];
61
+};
62
+
63
+struct amp_irq_cfg_s {
64
+ u32 prio;
65
+ u32 cpumask;
66
+ u32 aff;
67
+ int amp_flag;
68
+} irqs_cfg[1024];
69
+
70
+static struct amp_gic_ctrl_s {
71
+ struct {
72
+ u32 aff;
73
+ u32 cpumask;
74
+ u32 flag;
75
+ } aff_to_cpumask[AMP_AFF_MAX_CLUSTER][AMP_AFF_MAX_CPU];
76
+ struct amp_irq_cfg_s irqs_cfg[1024];
77
+ u32 validmask[1020 / 32 + 1];
78
+ struct amp_gpio_group_s gpio_grp[GPIO_BANK_NUM][GPIO_GROUP_PRIO_MAX];
79
+ u32 gpio_banks;
80
+} amp_ctrl;
4681
4782 static int get_cpu_boot_info_idx(unsigned long cpu_id)
4883 {
....@@ -77,29 +112,29 @@
77112 static void cpu_status_print(unsigned long cpu_id, struct arm_smccc_res *res)
78113 {
79114 if (res->a0) {
80
- pr_info("get cpu-0x%lx status(%lx) error!\n", cpu_id, res->a0);
115
+ pr_info("failed to get cpu[%lx] status, ret=%lx!\n", cpu_id, res->a0);
81116 return;
82117 }
83118
84119 if (res->a1 == AMP_CPU_STATUS_AMP_DIS)
85
- pr_info("cpu-0x%lx amp is disable (%ld)\n", cpu_id, res->a1);
120
+ pr_info("cpu[%lx] amp is disabled (%ld)\n", cpu_id, res->a1);
86121 else if (res->a1 == AMP_CPU_STATUS_EN)
87
- pr_info("cpu-0x%lx amp is enable (%ld)\n", cpu_id, res->a1);
122
+ pr_info("cpu[%lx] amp is enabled (%ld)\n", cpu_id, res->a1);
88123 else if (res->a1 == AMP_CPU_STATUS_ON)
89
- pr_info("cpu-0x%lx amp: cpu is on (%ld)\n", cpu_id, res->a1);
124
+ pr_info("cpu[%lx] amp: cpu is on (%ld)\n", cpu_id, res->a1);
90125 else if (res->a1 == AMP_CPU_STATUS_OFF)
91
- pr_info("cpu-0x%lx amp: cpu is off(%ld)\n", cpu_id, res->a1);
126
+ pr_info("cpu[%lx] amp: cpu is off(%ld)\n", cpu_id, res->a1);
92127 else
93
- pr_info("cpu-0x%lx status(%ld) is error\n", cpu_id, res->a1);
128
+ pr_info("cpu[%lx] amp status(%ld) is error\n", cpu_id, res->a1);
94129
95130 if (res->a2 == RK_CPU_STATUS_OFF)
96
- pr_info("cpu-0x%lx status(%ld) is off\n", cpu_id, res->a2);
131
+ pr_info("cpu[%lx] status(%ld) is off\n", cpu_id, res->a2);
97132 else if (res->a2 == RK_CPU_STATUS_ON)
98
- pr_info("cpu-0x%lx status(%ld) is on\n", cpu_id, res->a2);
133
+ pr_info("cpu[%lx] status(%ld) is on\n", cpu_id, res->a2);
99134 else if (res->a2 == RK_CPU_STATUS_BUSY)
100
- pr_info("cpu-0x%lx status(%ld) is busy\n", cpu_id, res->a2);
135
+ pr_info("cpu[%lx] status(%ld) is busy\n", cpu_id, res->a2);
101136 else
102
- pr_info("cpu-0x%lx status(%ld) is error\n", cpu_id, res->a2);
137
+ pr_info("cpu[%lx] status(%ld) is error\n", cpu_id, res->a2);
103138 }
104139
105140 static ssize_t boot_cpu_store(struct device *dev,
....@@ -107,9 +142,9 @@
107142 const char *buf,
108143 size_t count)
109144 {
110
- char cmd[10];
111
- unsigned long cpu_id;
112145 struct arm_smccc_res res = {0};
146
+ unsigned long cpu_id;
147
+ char cmd[10];
113148 int ret, idx;
114149
115150 ret = sscanf(buf, "%s", cmd);
....@@ -120,12 +155,10 @@
120155
121156 if (!strncmp(cmd, "status", strlen("status"))) {
122157 ret = sscanf(buf, "%s %lx", cmd, &cpu_id);
123
-
124158 if (ret != 2)
125159 return -EINVAL;
126160
127
- res = sip_smc_get_amp_info(RK_AMP_SUB_FUNC_GET_CPU_STATUS,
128
- cpu_id);
161
+ res = sip_smc_get_amp_info(RK_AMP_SUB_FUNC_GET_CPU_STATUS, cpu_id);
129162 cpu_status_print(cpu_id, &res);
130163 } else if (!strncmp(cmd, "off", strlen("off"))) {
131164 ret = sscanf(buf, "%s %lx", cmd, &cpu_id);
....@@ -133,17 +166,14 @@
133166 return -EINVAL;
134167
135168 idx = get_cpu_boot_info_idx(cpu_id);
136
-
137169 if (idx >= 0 && cpu_boot_info[idx].en) {
138170 ret = sip_smc_amp_config(RK_AMP_SUB_FUNC_REQ_CPU_OFF,
139171 cpu_id, 0, 0);
140172 if (ret)
141
- pr_info("requesting a cpu off is error(%d)!\n",
142
- ret);
173
+ dev_warn(dev, "failed to request cpu[%lx] off, ret=%d!\n", cpu_id, ret);
143174 }
144175 } else if (!strncmp(cmd, "on", strlen("on"))) {
145176 ret = sscanf(buf, "%s %lx", cmd, &cpu_id);
146
-
147177 if (ret != 2)
148178 return -EINVAL;
149179
....@@ -154,11 +184,14 @@
154184 cpu_boot_info[idx].entry,
155185 0);
156186 if (ret)
157
- pr_info("booting up a cpu is error(%d)!\n",
158
- ret);
187
+ dev_warn(dev, "Brought up cpu[%lx] failed, ret=%d\n", cpu_id, ret);
188
+ else
189
+ pr_info("Brought up cpu[%lx] ok.\n", cpu_id);
190
+ } else {
191
+ dev_warn(dev, "cpu[%lx] is unavailable\n", cpu_id);
159192 }
160193 } else {
161
- pr_info("unsupported cmd(%s)\n", cmd);
194
+ dev_warn(dev, "unsupported cmd(%s)\n", cmd);
162195 }
163196
164197 return count;
....@@ -173,31 +206,34 @@
173206 struct device_node *cpu_node, int idx)
174207 {
175208 u64 cpu_entry, cpu_id;
176
- u32 cpu_mode;
209
+ u32 cpu_mode, boot_on;
177210 int ret;
178211
179212 if (idx >= CONFIG_NR_CPUS)
180213 return -1;
181214
215
+ if (of_property_read_u64_array(cpu_node, "id", &cpu_id, 1)) {
216
+ dev_warn(dev, "failed to get 'id'\n");
217
+ return -1;
218
+ }
219
+
182220 if (of_property_read_u64_array(cpu_node, "entry", &cpu_entry, 1)) {
183
- dev_warn(dev, "can not get the entry\n");
221
+ dev_warn(dev, "failed to get cpu[%llx] 'entry'\n", cpu_id);
184222 return -1;
185223 }
186224
187225 if (!cpu_entry) {
188
- dev_warn(dev, "cpu-entry is 0\n");
189
- return -1;
190
- }
191
-
192
- if (of_property_read_u64_array(cpu_node, "id", &cpu_id, 1)) {
193
- dev_warn(dev, "can not get the cpu id\n");
226
+ dev_warn(dev, "invalid cpu[%llx] 'entry': 0\n", cpu_id);
194227 return -1;
195228 }
196229
197230 if (of_property_read_u32_array(cpu_node, "mode", &cpu_mode, 1)) {
198
- dev_warn(dev, "can not get the cpu mode\n");
231
+ dev_warn(dev, "failed to get cpu[%llx] 'mode'\n", cpu_id);
199232 return -1;
200233 }
234
+
235
+ if (of_property_read_u32_array(cpu_node, "boot-on", &boot_on, 1))
236
+ boot_on = 1; /* compatible old action */
201237
202238 cpu_boot_info[idx].entry = cpu_entry;
203239 cpu_boot_info[idx].mode = cpu_mode;
....@@ -205,14 +241,18 @@
205241
206242 ret = sip_smc_amp_config(RK_AMP_SUB_FUNC_CFG_MODE, cpu_id, cpu_mode, 0);
207243 if (ret) {
208
- dev_warn(dev, "setting cpu mode is error(%d)!\n", ret);
244
+ dev_warn(dev, "failed to set cpu mode, ret=%d\n", ret);
209245 return ret;
210246 }
211247
212
- ret = sip_smc_amp_config(RK_AMP_SUB_FUNC_CPU_ON, cpu_id, cpu_entry, 0);
213
- if (ret) {
214
- dev_warn(dev, "booting up a cpu is error(%d)!\n", ret);
215
- return ret;
248
+ if (boot_on) {
249
+ ret = sip_smc_amp_config(RK_AMP_SUB_FUNC_CPU_ON, cpu_id, cpu_entry, 0);
250
+ if (ret) {
251
+ dev_warn(dev, "Brought up cpu[%llx] failed, ret=%d\n", cpu_id, ret);
252
+ return ret;
253
+ } else {
254
+ pr_info("Brought up cpu[%llx] ok.\n", cpu_id);
255
+ }
216256 }
217257
218258 cpu_boot_info[idx].en = 1;
....@@ -220,11 +260,262 @@
220260 return 0;
221261 }
222262
263
+int rockchip_amp_check_amp_irq(u32 irq)
264
+{
265
+ return amp_ctrl.irqs_cfg[irq].amp_flag;
266
+}
267
+
268
+u32 rockchip_amp_get_irq_prio(u32 irq)
269
+{
270
+ return amp_ctrl.irqs_cfg[irq].prio;
271
+}
272
+
273
+u32 rockchip_amp_get_irq_cpumask(u32 irq)
274
+{
275
+ return amp_ctrl.irqs_cfg[irq].cpumask;
276
+}
277
+
278
+static u32 amp_get_cpumask_bit(u32 aff)
279
+{
280
+ u32 aff_cluster, aff_cpu;
281
+
282
+ aff_cluster = MPIDR_AFFINITY_LEVEL(aff, 1);
283
+ aff_cpu = MPIDR_AFFINITY_LEVEL(aff, 0);
284
+
285
+ if (aff_cpu >= AMP_AFF_MAX_CPU || aff_cluster >= AMP_AFF_MAX_CLUSTER)
286
+ return 0;
287
+
288
+ AMP_GIC_DBG("%s: aff:%d-%d: %x\n", __func__, aff_cluster, aff_cpu,
289
+ amp_ctrl.aff_to_cpumask[aff_cluster][aff_cpu].cpumask);
290
+
291
+ return amp_ctrl.aff_to_cpumask[aff_cluster][aff_cpu].cpumask;
292
+}
293
+
294
+static int gic_amp_get_gpio_prio_group_info(struct device_node *np,
295
+ struct amp_gic_ctrl_s *amp_ctrl,
296
+ int prio_id)
297
+{
298
+ u32 gpio_bank, count0, count1, prio, irq_id, irq_aff;
299
+ int i;
300
+ struct amp_gpio_group_s *gpio_grp;
301
+ struct amp_irq_cfg_s *irqs_cfg;
302
+
303
+ if (prio_id >= GPIO_GROUP_PRIO_MAX)
304
+ return -EINVAL;
305
+
306
+ if (of_property_read_u32_array(np, "gpio-bank", &gpio_bank, 1))
307
+ return -EINVAL;
308
+ if (gpio_bank >= amp_ctrl->gpio_banks)
309
+ return -EINVAL;
310
+
311
+ gpio_grp = &amp_ctrl->gpio_grp[gpio_bank][prio_id];
312
+
313
+ if (of_property_read_u32_array(np, "prio", &prio, 1))
314
+ return -EINVAL;
315
+
316
+ if (gpio_bank >= GPIO_BANK_NUM)
317
+ return -EINVAL;
318
+
319
+ AMP_GIC_DBG("%s: gpio-%d, group prio:%d-%x\n",
320
+ __func__, gpio_bank, prio_id, prio);
321
+
322
+ count0 = of_property_count_u32_elems(np, "girq-id");
323
+ count1 = of_property_count_u32_elems(np, "girq-aff");
324
+
325
+ if (count0 != count1)
326
+ return -EINVAL;
327
+
328
+ gpio_grp->prio = prio;
329
+
330
+ for (i = 0; i < count0; i++) {
331
+ of_property_read_u32_index(np, "girq-id", i, &irq_id);
332
+ gpio_grp->irq_id[i] = irq_id;
333
+ of_property_read_u32_index(np, "girq-aff", i, &irq_aff);
334
+
335
+ gpio_grp->irq_aff[i] = irq_aff;
336
+
337
+ of_property_read_u32_index(np, "girq-en", i, &gpio_grp->en[i]);
338
+
339
+ irqs_cfg = &amp_ctrl->irqs_cfg[irq_id];
340
+
341
+ AMP_GIC_DBG(" %s: group cpu-%d, irq-%d: prio-%x, aff-%x en-%d\n",
342
+ __func__, i, gpio_grp->irq_id[i], gpio_grp->prio,
343
+ gpio_grp->irq_aff[i], gpio_grp->en[i]);
344
+
345
+ if (gpio_grp->en[i]) {
346
+ irqs_cfg->prio = gpio_grp->prio;
347
+ irqs_cfg->aff = irq_aff;
348
+ irqs_cfg->cpumask = amp_get_cpumask_bit(irq_aff);
349
+ irqs_cfg->amp_flag = 1;
350
+ }
351
+
352
+ AMP_GIC_DBG(" %s: irqs_cfg prio-%x aff-%x cpumaks-%x en-%d\n",
353
+ __func__, irqs_cfg->prio, irqs_cfg->aff,
354
+ irqs_cfg->cpumask, irqs_cfg->amp_flag);
355
+ }
356
+
357
+ return 0;
358
+}
359
+
360
+static int gic_amp_gpio_group_get_info(struct device_node *group_node,
361
+ struct amp_gic_ctrl_s *amp_ctrl,
362
+ int idx)
363
+{
364
+ int i = 0;
365
+ struct device_node *node;
366
+
367
+ if (group_node) {
368
+ for_each_available_child_of_node(group_node, node) {
369
+ if (i >= GPIO_GROUP_PRIO_MAX)
370
+ break;
371
+ if (!gic_amp_get_gpio_prio_group_info(node, amp_ctrl,
372
+ i)) {
373
+ i++;
374
+ }
375
+ }
376
+ }
377
+ return 0;
378
+}
379
+
380
+static void gic_of_get_gpio_group(struct device_node *np,
381
+ struct amp_gic_ctrl_s *amp_ctrl)
382
+{
383
+ struct device_node *gpio_group_node, *node;
384
+ int i = 0;
385
+
386
+ if (of_property_read_u32_array(np, "gpio-group-banks",
387
+ &amp_ctrl->gpio_banks, 1))
388
+ return;
389
+
390
+ gpio_group_node = of_get_child_by_name(np, "gpio-group");
391
+ if (gpio_group_node) {
392
+ for_each_available_child_of_node(gpio_group_node, node) {
393
+ if (i >= amp_ctrl->gpio_banks)
394
+ break;
395
+ if (!gic_amp_gpio_group_get_info(node, amp_ctrl, i))
396
+ i++;
397
+ }
398
+ }
399
+
400
+ of_node_put(gpio_group_node);
401
+}
402
+
403
+static int amp_gic_get_cpumask(struct device_node *np, struct amp_gic_ctrl_s *amp_ctrl)
404
+{
405
+ const struct property *prop;
406
+ int count, i;
407
+ u32 cluster, aff_cpu, aff, cpumask;
408
+
409
+ prop = of_find_property(np, "amp-cpu-aff-maskbits", NULL);
410
+ if (!prop)
411
+ return -1;
412
+
413
+ if (!prop->value)
414
+ return -1;
415
+
416
+ count = of_property_count_u32_elems(np, "amp-cpu-aff-maskbits");
417
+ if (count % 2)
418
+ return -1;
419
+
420
+ for (i = 0; i < count / 2; i++) {
421
+ of_property_read_u32_index(np, "amp-cpu-aff-maskbits",
422
+ 2 * i, &aff);
423
+ cluster = MPIDR_AFFINITY_LEVEL(aff, 1);
424
+ aff_cpu = MPIDR_AFFINITY_LEVEL(aff, 0);
425
+ amp_ctrl->aff_to_cpumask[cluster][aff_cpu].aff = aff;
426
+
427
+ of_property_read_u32_index(np, "amp-cpu-aff-maskbits",
428
+ 2 * i + 1, &cpumask);
429
+
430
+ amp_ctrl->aff_to_cpumask[cluster][aff_cpu].cpumask = cpumask;
431
+
432
+ AMP_GIC_DBG("cpumask: %d-%d: aff-%d cpumask-%d\n",
433
+ cluster, aff_cpu, aff, cpumask);
434
+
435
+ if (!cpumask)
436
+ return -1;
437
+ }
438
+
439
+ return 0;
440
+}
441
+
442
+static void amp_gic_get_irqs_config(struct device_node *np,
443
+ struct amp_gic_ctrl_s *amp_ctrl)
444
+{
445
+ const struct property *prop;
446
+ int count, i;
447
+ u32 irq, prio, aff;
448
+
449
+ prop = of_find_property(np, "amp-irqs", NULL);
450
+ if (!prop)
451
+ return;
452
+
453
+ if (!prop->value)
454
+ return;
455
+
456
+ count = of_property_count_u32_elems(np, "amp-irqs");
457
+
458
+ if (count < 0 || count % 3)
459
+ return;
460
+
461
+ for (i = 0; i < count / 3; i++) {
462
+ of_property_read_u32_index(np, "amp-irqs", 3 * i, &irq);
463
+
464
+ if (irq > 1020)
465
+ break;
466
+
467
+ of_property_read_u32_index(np, "amp-irqs", 3 * i + 1, &prio);
468
+ of_property_read_u32_index(np, "amp-irqs", 3 * i + 2, &aff);
469
+
470
+ AMP_GIC_DBG("%s: irq-%d aff-%d prio-%x\n",
471
+ __func__, irq, aff, prio);
472
+
473
+ amp_ctrl->irqs_cfg[irq].prio = prio;
474
+ amp_ctrl->irqs_cfg[irq].aff = aff;
475
+ amp_ctrl->irqs_cfg[irq].cpumask = amp_get_cpumask_bit(aff);
476
+
477
+ if (!amp_ctrl->irqs_cfg[irq].cpumask) {
478
+ AMP_GIC_DBG("%s: get cpumask error\n", __func__);
479
+ break;
480
+ }
481
+
482
+ if (!amp_ctrl->irqs_cfg[irq].aff &&
483
+ !amp_ctrl->irqs_cfg[irq].prio)
484
+ break;
485
+
486
+ amp_ctrl->irqs_cfg[irq].amp_flag = 1;
487
+
488
+ AMP_GIC_DBG("%s: irq-%d aff-%d cpumask-%d pri-%x\n",
489
+ __func__, irq, amp_ctrl->irqs_cfg[irq].aff,
490
+ amp_ctrl->irqs_cfg[irq].cpumask,
491
+ amp_ctrl->irqs_cfg[irq].prio);
492
+ }
493
+}
494
+
495
+void rockchip_amp_get_gic_info(void)
496
+{
497
+ struct device_node *np;
498
+
499
+ np = of_find_node_by_name(NULL, "rockchip-amp");
500
+ if (!np)
501
+ return;
502
+
503
+ if (amp_gic_get_cpumask(np, &amp_ctrl)) {
504
+ pr_err("%s: get amp gic cpu mask error\n", __func__);
505
+ goto exit;
506
+ }
507
+ gic_of_get_gpio_group(np, &amp_ctrl);
508
+ amp_gic_get_irqs_config(np, &amp_ctrl);
509
+
510
+exit:
511
+ of_node_put(np);
512
+}
513
+
223514 static int rockchip_amp_probe(struct platform_device *pdev)
224515 {
225
- struct rkamp_device *rkamp_dev = NULL;
226
- int ret, i, idx = 0;
227516 struct device_node *cpus_node, *cpu_node;
517
+ struct rkamp_device *rkamp_dev;
518
+ int ret, i, idx = 0;
228519
229520 rkamp_dev = devm_kzalloc(&pdev->dev, sizeof(*rkamp_dev), GFP_KERNEL);
230521 if (!rkamp_dev)
....@@ -233,18 +524,20 @@
233524 rkamp_dev->num_clks = devm_clk_bulk_get_all(&pdev->dev, &rkamp_dev->clks);
234525 if (rkamp_dev->num_clks < 0)
235526 return -ENODEV;
527
+
236528 ret = clk_bulk_prepare_enable(rkamp_dev->num_clks, rkamp_dev->clks);
237529 if (ret)
238530 return dev_err_probe(&pdev->dev, ret, "failed to prepare enable clks: %d\n", ret);
239531
240532 pm_runtime_enable(&pdev->dev);
241533
242
- rkamp_dev->num_pds = of_count_phandle_with_args(pdev->dev.of_node, "power-domains",
243
- "#power-domain-cells");
244
-
534
+ rkamp_dev->num_pds =
535
+ of_count_phandle_with_args(pdev->dev.of_node, "power-domains",
536
+ "#power-domain-cells");
245537 if (rkamp_dev->num_pds > 0) {
246
- rkamp_dev->pd_dev = devm_kmalloc_array(&pdev->dev, rkamp_dev->num_pds,
247
- sizeof(*rkamp_dev->pd_dev), GFP_KERNEL);
538
+ rkamp_dev->pd_dev =
539
+ devm_kmalloc_array(&pdev->dev, rkamp_dev->num_pds,
540
+ sizeof(*rkamp_dev->pd_dev), GFP_KERNEL);
248541 if (!rkamp_dev->pd_dev)
249542 return -ENOMEM;
250543
....@@ -265,14 +558,12 @@
265558 }
266559
267560 cpus_node = of_get_child_by_name(pdev->dev.of_node, "amp-cpus");
268
-
269561 if (cpus_node) {
270562 for_each_available_child_of_node(cpus_node, cpu_node) {
271
- if (!rockchip_amp_boot_cpus(&pdev->dev, cpu_node,
272
- idx)) {
563
+ if (!rockchip_amp_boot_cpus(&pdev->dev, cpu_node, idx))
273564 idx++;
274
- }
275565 }
566
+ of_node_put(cpus_node);
276567 }
277568
278569 rk_amp_kobj = kobject_create_and_add("rk_amp", NULL);
....@@ -290,8 +581,8 @@
290581
291582 static int rockchip_amp_remove(struct platform_device *pdev)
292583 {
293
- int i;
294584 struct rkamp_device *rkamp_dev = platform_get_drvdata(pdev);
585
+ int i;
295586
296587 clk_bulk_disable_unprepare(rkamp_dev->num_clks, rkamp_dev->clks);
297588