1 /*
2 * (C) COPYRIGHT RockChip Limited. All rights reserved.
3 *
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms
7 * of such GNU licence.
8 */
9
10 /**
11 * @file rk.c
12 * implementation of platform_specific_code on rk platforms, such as rk3328h.
13 *
14 * mali_device_driver(MDD) includes 2 parts :
15 * .DP : platform_dependent_part :
16 * located in <mdd_src_dir>/mali/platform/<platform_name>/
17 * .DP : common_part :
18 * common part implemented by ARM.
19 */
20
21 #define ENABLE_DEBUG_LOG
22 #include "custom_log.h"
23
24 #include <linux/platform_device.h>
25 #include <linux/version.h>
26 #include <linux/pm.h>
27 #include <linux/of.h>
28 #include <linux/clk.h>
29 #include <linux/regulator/consumer.h>
30 #ifdef CONFIG_PM
31 #include <linux/pm_runtime.h>
32 #endif
33 #include <linux/workqueue.h>
34 #include <linux/dma-mapping.h>
35 #include <linux/pm_runtime.h>
36 #include <linux/delay.h>
37 #include <linux/rockchip/cpu.h>
38 #include <soc/rockchip/rockchip_ipa.h>
39 #include <soc/rockchip/rockchip_opp_select.h>
40
41 #include <linux/mali/mali_utgard.h>
42 #include "mali_kernel_common.h"
43 #include "../../common/mali_osk_mali.h"
44
45 /*---------------------------------------------------------------------------*/
46
47 u32 mali_group_error;
48
49 /*---------------------------------------------------------------------------*/
50
51 #define DEFAULT_UTILISATION_PERIOD_IN_MS (100)
52
53 /*
54 * rk_platform_context_of_mali_device.
55 */
56 struct rk_context {
57 /* mali device. */
58 struct device *dev;
59 /* is the GPU powered on? */
60 bool is_powered;
61 /* debug only, the period in ms to count gpu_utilisation. */
62 unsigned int utilisation_period;
63 };
64
65 struct rk_context *s_rk_context;
66
67 /*---------------------------------------------------------------------------*/
68
69 #ifdef CONFIG_MALI_DEVFREQ
utilisation_period_show(struct device * dev,struct device_attribute * attr,char * buf)70 static ssize_t utilisation_period_show(struct device *dev,
71 struct device_attribute *attr,
72 char *buf)
73 {
74 struct rk_context *platform = s_rk_context;
75 ssize_t ret = 0;
76
77 ret += snprintf(buf, PAGE_SIZE, "%u\n", platform->utilisation_period);
78
79 return ret;
80 }
81
utilisation_period_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)82 static ssize_t utilisation_period_store(struct device *dev,
83 struct device_attribute *attr,
84 const char *buf,
85 size_t count)
86 {
87 struct rk_context *platform = s_rk_context;
88 int ret = 0;
89
90 ret = kstrtouint(buf, 0, &platform->utilisation_period);
91 if (ret) {
92 E("invalid input period : %s.", buf);
93 return ret;
94 }
95 D("set utilisation_period to '%d'.", platform->utilisation_period);
96
97 return count;
98 }
99
utilisation_show(struct device * dev,struct device_attribute * attr,char * buf)100 static ssize_t utilisation_show(struct device *dev,
101 struct device_attribute *attr,
102 char *buf)
103 {
104 struct rk_context *platform = s_rk_context;
105 struct mali_device *mdev = dev_get_drvdata(dev);
106 ssize_t ret = 0;
107 unsigned long period_in_us = platform->utilisation_period * 1000;
108 unsigned long total_time;
109 unsigned long busy_time;
110 unsigned long utilisation;
111
112 mali_pm_reset_dvfs_utilisation(mdev);
113 usleep_range(period_in_us, period_in_us + 100);
114 mali_pm_get_dvfs_utilisation(mdev, &total_time, &busy_time);
115
116 /* 'devfreq_dev_profile' instance registered to devfreq
117 * also uses mali_pm_reset_dvfs_utilisation()
118 * and mali_pm_get_dvfs_utilisation().
119 * So, it's better to disable GPU DVFS before reading this node.
120 */
121 D("total_time : %lu, busy_time : %lu.", total_time, busy_time);
122
123 utilisation = busy_time / (total_time / 100);
124 ret += snprintf(buf, PAGE_SIZE, "%lu\n", utilisation);
125
126 return ret;
127 }
128
129 static DEVICE_ATTR_RW(utilisation_period);
130 static DEVICE_ATTR_RO(utilisation);
131 #endif
132
rk_context_create_sysfs_files(struct device * dev)133 static int rk_context_create_sysfs_files(struct device *dev)
134 {
135 #ifdef CONFIG_MALI_DEVFREQ
136 int ret;
137
138 ret = device_create_file(dev, &dev_attr_utilisation_period);
139 if (ret) {
140 E("fail to create sysfs file 'utilisation_period'.");
141 goto out;
142 }
143
144 ret = device_create_file(dev, &dev_attr_utilisation);
145 if (ret) {
146 E("fail to create sysfs file 'utilisation'.");
147 goto remove_utilisation_period;
148 }
149
150 return 0;
151
152 remove_utilisation_period:
153 device_remove_file(dev, &dev_attr_utilisation_period);
154 out:
155 return ret;
156 #else
157 return 0;
158 #endif
159 }
160
rk_context_remove_sysfs_files(struct device * dev)161 static void rk_context_remove_sysfs_files(struct device *dev)
162 {
163 #ifdef CONFIG_MALI_DEVFREQ
164 device_remove_file(dev, &dev_attr_utilisation_period);
165 device_remove_file(dev, &dev_attr_utilisation);
166 #endif
167 }
168
169 /*---------------------------------------------------------------------------*/
170
171 /*
172 * Init rk_platform_context of mali_device.
173 */
rk_context_init(struct platform_device * pdev)174 static int rk_context_init(struct platform_device *pdev)
175 {
176 int ret = 0;
177 struct device *dev = &pdev->dev;
178 struct rk_context *platform; /* platform_context */
179
180 platform = kzalloc(sizeof(*platform), GFP_KERNEL);
181 if (!platform) {
182 E("no mem.");
183 return _MALI_OSK_ERR_NOMEM;
184 }
185
186 platform->dev = dev;
187 platform->is_powered = false;
188
189 platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS;
190
191 ret = rk_context_create_sysfs_files(dev);
192 if (ret) {
193 E("fail to create sysfs files, ret = %d", ret);
194 goto EXIT;
195 }
196
197 s_rk_context = platform;
198
199 pm_runtime_set_autosuspend_delay(dev, 1000);
200 pm_runtime_use_autosuspend(dev);
201 pm_runtime_enable(dev);
202
203 EXIT:
204 return ret;
205 }
206
rk_context_deinit(struct platform_device * pdev)207 static void rk_context_deinit(struct platform_device *pdev)
208 {
209 struct device *dev = &pdev->dev;
210 struct rk_context *platform = s_rk_context;
211
212 pm_runtime_disable(dev);
213
214 s_rk_context = NULL;
215
216 rk_context_remove_sysfs_files(dev);
217
218 if (platform) {
219 platform->is_powered = false;
220 platform->dev = NULL;
221 kfree(platform);
222 }
223 }
224
225 /*---------------------------------------------------------------------------*/
226 /* for devfreq cooling. */
227
228 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
229
230 #define FALLBACK_STATIC_TEMPERATURE 55000
231
232 static u32 dynamic_coefficient;
233 static u32 static_coefficient;
234 static s32 ts[4];
235 static struct thermal_zone_device *gpu_tz;
236 static struct ipa_power_model_data *model_data;
237
238 /* Calculate gpu static power example for reference */
rk_model_static_power(struct devfreq * devfreq,unsigned long voltage)239 static unsigned long rk_model_static_power(struct devfreq *devfreq,
240 unsigned long voltage)
241 {
242 int temperature, temp;
243 int temp_squared, temp_cubed, temp_scaling_factor;
244 const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10;
245 unsigned long static_power;
246
247 if (gpu_tz) {
248 int ret;
249
250 ret = gpu_tz->ops->get_temp(gpu_tz, &temperature);
251 if (ret) {
252 MALI_DEBUG_PRINT(2, ("fail to read temp: %d\n", ret));
253 temperature = FALLBACK_STATIC_TEMPERATURE;
254 }
255 } else {
256 temperature = FALLBACK_STATIC_TEMPERATURE;
257 }
258
259 /* Calculate the temperature scaling factor. To be applied to the
260 * voltage scaled power.
261 */
262 temp = temperature / 1000;
263 temp_squared = temp * temp;
264 temp_cubed = temp_squared * temp;
265 temp_scaling_factor =
266 (ts[3] * temp_cubed)
267 + (ts[2] * temp_squared)
268 + (ts[1] * temp)
269 + ts[0];
270
271 static_power = (((static_coefficient * voltage_cubed) >> 20)
272 * temp_scaling_factor)
273 / 1000000;
274
275 return static_power;
276 }
277
278 /* Calculate gpu dynamic power example for reference */
rk_model_dynamic_power(struct devfreq * devfreq,unsigned long freq,unsigned long voltage)279 static unsigned long rk_model_dynamic_power(struct devfreq *devfreq,
280 unsigned long freq,
281 unsigned long voltage)
282 {
283 /* The inputs: freq (f) is in Hz, and voltage (v) in mV.
284 * The coefficient (c) is in mW/(MHz mV mV).
285 *
286 * This function calculates the dynamic power after this formula:
287 * Pdyn (mW) = c (mW/(MHz*mV*mV)) * v (mV) * v (mV) * f (MHz)
288 */
289 const unsigned long v2 = (voltage * voltage) / 1000; /* m*(V*V) */
290 const unsigned long f_mhz = freq / 1000000; /* MHz */
291 unsigned long dynamic_power;
292
293 dynamic_power = (dynamic_coefficient * v2 * f_mhz) / 1000000; /* mW */
294
295 return dynamic_power;
296 }
297
298 static struct devfreq_cooling_power rk_cooling_ops = {
299 .get_static_power = rk_model_static_power,
300 .get_dynamic_power = rk_model_dynamic_power,
301 };
302
mali_devfreq_get_static_power(struct devfreq * devfreq,unsigned long voltage)303 static unsigned long mali_devfreq_get_static_power(struct devfreq *devfreq,
304 unsigned long voltage)
305 {
306 return rockchip_ipa_get_static_power(model_data, voltage);
307 }
308
power_model_simple_init(struct platform_device * pdev)309 static int power_model_simple_init(struct platform_device *pdev)
310 {
311 struct device_node *power_model_node;
312 const char *tz_name;
313 u32 static_power, dynamic_power;
314 u32 voltage, voltage_squared, voltage_cubed, frequency;
315
316 if (of_find_compatible_node(pdev->dev.of_node, NULL, "simple-power-model")) {
317 of_property_read_u32(pdev->dev.of_node,
318 "dynamic-power-coefficient",
319 (u32 *)&rk_cooling_ops.dyn_power_coeff);
320 model_data = rockchip_ipa_power_model_init(&pdev->dev,
321 "gpu_leakage");
322 if (IS_ERR_OR_NULL(model_data)) {
323 model_data = NULL;
324 dev_err(&pdev->dev, "failed to initialize power model\n");
325 } else if (model_data->dynamic_coefficient) {
326 rk_cooling_ops.dyn_power_coeff =
327 model_data->dynamic_coefficient;
328 rk_cooling_ops.get_dynamic_power = NULL;
329 rk_cooling_ops.get_static_power = mali_devfreq_get_static_power;
330 }
331 if (!rk_cooling_ops.dyn_power_coeff) {
332 dev_err(&pdev->dev, "failed to get dynamic-coefficient\n");
333 return -EINVAL;
334 }
335
336 return 0;
337 }
338
339 power_model_node = of_get_child_by_name(pdev->dev.of_node,
340 "power_model");
341 if (!power_model_node) {
342 dev_err(&pdev->dev, "could not find power_model node\n");
343 return -ENODEV;
344 }
345 if (!of_device_is_compatible(power_model_node,
346 "arm,mali-simple-power-model")) {
347 dev_err(&pdev->dev, "power_model incompatible with simple power model\n");
348 return -ENODEV;
349 }
350
351 if (of_property_read_string(power_model_node, "thermal-zone",
352 &tz_name)) {
353 dev_err(&pdev->dev, "ts in power_model not available\n");
354 return -EINVAL;
355 }
356
357 gpu_tz = thermal_zone_get_zone_by_name(tz_name);
358 if (IS_ERR(gpu_tz)) {
359 pr_warn_ratelimited("Error getting gpu thermal zone '%s'(%ld), not yet ready?\n",
360 tz_name,
361 PTR_ERR(gpu_tz));
362 gpu_tz = NULL;
363 }
364
365 if (of_property_read_u32(power_model_node, "static-power",
366 &static_power)) {
367 dev_err(&pdev->dev, "static-power in power_model not available\n");
368 return -EINVAL;
369 }
370 if (of_property_read_u32(power_model_node, "dynamic-power",
371 &dynamic_power)) {
372 dev_err(&pdev->dev, "dynamic-power in power_model not available\n");
373 return -EINVAL;
374 }
375 if (of_property_read_u32(power_model_node, "voltage",
376 &voltage)) {
377 dev_err(&pdev->dev, "voltage in power_model not available\n");
378 return -EINVAL;
379 }
380 if (of_property_read_u32(power_model_node, "frequency",
381 &frequency)) {
382 dev_err(&pdev->dev, "frequency in power_model not available\n");
383 return -EINVAL;
384 }
385 voltage_squared = (voltage * voltage) / 1000;
386 voltage_cubed = voltage * voltage * voltage;
387 static_coefficient = (static_power << 20) / (voltage_cubed >> 10);
388 dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared)
389 * 1000) / frequency;
390
391 if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) {
392 dev_err(&pdev->dev, "ts in power_model not available\n");
393 return -EINVAL;
394 }
395
396 return 0;
397 }
398
399 #endif
400
401 /*---------------------------------------------------------------------------*/
402
403 #ifdef CONFIG_PM
404
rk_platform_enable_clk_gpu(struct device * dev)405 static int rk_platform_enable_clk_gpu(struct device *dev)
406 {
407 int ret = 0;
408 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
409 struct mali_device *mdev = dev_get_drvdata(dev);
410
411 ret = clk_bulk_enable(mdev->num_clks, mdev->clks);
412 #endif
413 return ret;
414 }
415
rk_platform_disable_clk_gpu(struct device * dev)416 static void rk_platform_disable_clk_gpu(struct device *dev)
417 {
418 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
419 struct mali_device *mdev = dev_get_drvdata(dev);
420
421 clk_bulk_disable(mdev->num_clks, mdev->clks);
422 #endif
423 }
424
rk_platform_enable_gpu_regulator(struct device * dev)425 static int rk_platform_enable_gpu_regulator(struct device *dev)
426 {
427 int ret = 0;
428 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
429 struct mali_device *mdev = dev_get_drvdata(dev);
430
431 if (mdev->regulator)
432 ret = regulator_enable(mdev->regulator);
433 #endif
434 return ret;
435 }
436
rk_platform_disable_gpu_regulator(struct device * dev)437 static void rk_platform_disable_gpu_regulator(struct device *dev)
438 {
439 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_REGULATOR)
440 struct mali_device *mdev = dev_get_drvdata(dev);
441
442 if (mdev->regulator)
443 regulator_disable(mdev->regulator);
444 #endif
445 }
446
rk_platform_power_on_gpu(struct device * dev)447 static int rk_platform_power_on_gpu(struct device *dev)
448 {
449 struct rk_context *platform = s_rk_context;
450 int ret = 0;
451
452 if (!(platform->is_powered)) {
453 ret = rk_platform_enable_clk_gpu(dev);
454 if (ret) {
455 E("fail to enable clk_gpu, ret : %d.", ret);
456 goto fail_to_enable_clk;
457 }
458
459 ret = rk_platform_enable_gpu_regulator(dev);
460 if (ret) {
461 E("fail to enable vdd_gpu, ret : %d.", ret);
462 goto fail_to_enable_regulator;
463 }
464
465 if (cpu_is_rk3528()) {
466 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
467 struct mali_device *mdev = dev_get_drvdata(dev);
468
469 clk_set_rate(mdev->clock, mdev->current_freq);
470 #endif
471 }
472 platform->is_powered = true;
473 }
474
475 return 0;
476
477 fail_to_enable_regulator:
478 rk_platform_disable_clk_gpu(dev);
479
480 fail_to_enable_clk:
481 return ret;
482 }
483
rk_platform_power_off_gpu(struct device * dev)484 static void rk_platform_power_off_gpu(struct device *dev)
485 {
486 struct rk_context *platform = s_rk_context;
487
488 if (platform->is_powered) {
489 if (cpu_is_rk3528()) {
490 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK)
491 struct mali_device *mdev = dev_get_drvdata(dev);
492
493 //use normal pll 200M for gpu when suspend
494 clk_set_rate(mdev->clock, 200000000);
495 #endif
496 }
497 rk_platform_disable_clk_gpu(dev);
498 rk_platform_disable_gpu_regulator(dev);
499
500 platform->is_powered = false;
501 }
502 }
503
rk_platform_init_opp_table(struct device * dev)504 int rk_platform_init_opp_table(struct device *dev)
505 {
506 return rockchip_init_opp_table(dev, NULL, "gpu_leakage", "mali");
507 }
508
mali_runtime_suspend(struct device * device)509 static int mali_runtime_suspend(struct device *device)
510 {
511 int ret = 0;
512
513 MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
514
515 if (device->driver &&
516 device->driver->pm &&
517 device->driver->pm->runtime_suspend) {
518 /* Need to notify Mali driver about this event */
519 ret = device->driver->pm->runtime_suspend(device);
520 }
521
522 if (!ret)
523 rk_platform_power_off_gpu(device);
524
525 return ret;
526 }
527
mali_runtime_resume(struct device * device)528 static int mali_runtime_resume(struct device *device)
529 {
530 int ret = 0;
531
532 MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
533
534 rk_platform_power_on_gpu(device);
535
536 if (device->driver &&
537 device->driver->pm &&
538 device->driver->pm->runtime_resume) {
539 /* Need to notify Mali driver about this event */
540 ret = device->driver->pm->runtime_resume(device);
541 }
542
543 return ret;
544 }
545
mali_runtime_idle(struct device * device)546 static int mali_runtime_idle(struct device *device)
547 {
548 int ret = 0;
549
550 MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
551
552 if (device->driver &&
553 device->driver->pm &&
554 device->driver->pm->runtime_idle) {
555 /* Need to notify Mali driver about this event */
556 ret = device->driver->pm->runtime_idle(device);
557 if (ret)
558 return ret;
559 }
560
561 return 0;
562 }
563 #endif
564
mali_os_suspend(struct device * device)565 static int mali_os_suspend(struct device *device)
566 {
567 int ret = 0;
568
569 MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
570
571 if (device->driver &&
572 device->driver->pm &&
573 device->driver->pm->suspend) {
574 /* Need to notify Mali driver about this event */
575 ret = device->driver->pm->suspend(device);
576 }
577
578 if (!ret)
579 rk_platform_power_off_gpu(device);
580
581 return ret;
582 }
583
mali_os_resume(struct device * device)584 static int mali_os_resume(struct device *device)
585 {
586 int ret = 0;
587
588 MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
589
590 rk_platform_power_on_gpu(device);
591
592 if (device->driver &&
593 device->driver->pm &&
594 device->driver->pm->resume) {
595 /* Need to notify Mali driver about this event */
596 ret = device->driver->pm->resume(device);
597 }
598
599 return ret;
600 }
601
mali_os_freeze(struct device * device)602 static int mali_os_freeze(struct device *device)
603 {
604 int ret = 0;
605
606 MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
607
608 if (device->driver &&
609 device->driver->pm &&
610 device->driver->pm->freeze) {
611 /* Need to notify Mali driver about this event */
612 ret = device->driver->pm->freeze(device);
613 }
614
615 return ret;
616 }
617
mali_os_thaw(struct device * device)618 static int mali_os_thaw(struct device *device)
619 {
620 int ret = 0;
621
622 MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
623
624 if (device->driver &&
625 device->driver->pm &&
626 device->driver->pm->thaw) {
627 /* Need to notify Mali driver about this event */
628 ret = device->driver->pm->thaw(device);
629 }
630
631 return ret;
632 }
633
634 static const struct dev_pm_ops mali_gpu_device_type_pm_ops = {
635 .suspend = mali_os_suspend,
636 .resume = mali_os_resume,
637 .freeze = mali_os_freeze,
638 .thaw = mali_os_thaw,
639 #ifdef CONFIG_PM
640 .runtime_suspend = mali_runtime_suspend,
641 .runtime_resume = mali_runtime_resume,
642 .runtime_idle = mali_runtime_idle,
643 #endif
644 };
645
646 static const struct device_type mali_gpu_device_device_type = {
647 .pm = &mali_gpu_device_type_pm_ops,
648 };
649
650 /*
651 * platform_specific_data of platform_device of mali_gpu.
652 */
653 static const struct mali_gpu_device_data mali_gpu_data = {
654 .shared_mem_size = 1024 * 1024 * 1024, /* 1GB */
655 .max_job_runtime = 60000, /* 60 seconds */
656 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
657 .gpu_cooling_ops = &rk_cooling_ops,
658 #endif
659 };
660
mali_platform_device_add_config(struct platform_device * pdev)661 static void mali_platform_device_add_config(struct platform_device *pdev)
662 {
663 pdev->name = MALI_GPU_NAME_UTGARD,
664 pdev->id = 0;
665 pdev->dev.type = &mali_gpu_device_device_type;
666 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask,
667 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
668 }
669
670 /*---------------------------------------------------------------------------*/
671 /* platform_device_functions called by common_part. */
672
mali_platform_device_init(struct platform_device * pdev)673 int mali_platform_device_init(struct platform_device *pdev)
674 {
675 int err = 0;
676
677 mali_platform_device_add_config(pdev);
678
679 D("to add platform_specific_data to platform_device_of_mali.");
680 err = platform_device_add_data(pdev,
681 &mali_gpu_data,
682 sizeof(mali_gpu_data));
683 if (err) {
684 E("fail to add platform_specific_data. err : %d.", err);
685 goto add_data_failed;
686 }
687
688 err = rk_context_init(pdev);
689 if (err) {
690 E("fail to init rk_context. err : %d.", err);
691 goto init_rk_context_failed;
692 }
693
694 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
695 if (of_machine_is_compatible("rockchip,rk3036"))
696 return 0;
697
698 err = power_model_simple_init(pdev);
699 if (err) {
700 E("fail to init simple_power_model, err : %d.", err);
701 goto init_power_model_failed;
702 }
703 #endif
704
705 return 0;
706
707 #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
708 init_power_model_failed:
709 rk_context_deinit(pdev);
710 #endif
711 init_rk_context_failed:
712 add_data_failed:
713 return err;
714 }
715
mali_platform_device_deinit(struct platform_device * pdev)716 void mali_platform_device_deinit(struct platform_device *pdev)
717 {
718 MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
719
720 rk_context_deinit(pdev);
721 }
722