forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c
....@@ -13,19 +13,31 @@
1313 #include <mali_kbase.h>
1414 #include <mali_kbase_defs.h>
1515 #include <mali_kbase_config.h>
16
+#include <backend/gpu/mali_kbase_devfreq.h>
1617 #include <backend/gpu/mali_kbase_pm_internal.h>
1718 #include <backend/gpu/mali_kbase_pm_defs.h>
1819
20
+#if MALI_USE_CSF
21
+#include <asm/arch_timer.h>
22
+#endif
23
+
24
+#include <linux/clk.h>
1925 #include <linux/pm_runtime.h>
2026 #include <linux/suspend.h>
2127 #include <linux/of.h>
2228 #include <linux/delay.h>
29
+#include <linux/mfd/syscon.h>
2330 #include <linux/nvmem-consumer.h>
31
+#include <linux/regmap.h>
2432 #include <linux/soc/rockchip/pvtm.h>
2533 #include <linux/thermal.h>
2634 #include <soc/rockchip/rockchip_opp_select.h>
35
+#include <soc/rockchip/rockchip_system_monitor.h>
2736
37
+#include "mali_kbase_config_platform.h"
2838 #include "mali_kbase_rk.h"
39
+
40
+#define POWER_DOWN_FREQ 200000000
2941
3042 /**
3143 * @file mali_kbase_config_rk.c
....@@ -45,6 +57,13 @@
4557 */
4658
4759 /*---------------------------------------------------------------------------*/
60
+#ifndef CONFIG_MALI_BIFROST_DEVFREQ
61
+static inline void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
62
+ struct kbasep_pm_metrics *last,
63
+ struct kbasep_pm_metrics *diff)
64
+{
65
+}
66
+#endif
4867
4968 #ifdef CONFIG_REGULATOR
5069 static int rk_pm_enable_regulator(struct kbase_device *kbdev);
....@@ -76,20 +95,32 @@
7695 container_of(to_delayed_work(work), struct rk_context, work);
7796 struct kbase_device *kbdev = platform->kbdev;
7897
98
+ mutex_lock(&platform->lock);
99
+
79100 if (!platform->is_powered) {
80101 D("mali_dev is already powered off.");
102
+ mutex_unlock(&platform->lock);
81103 return;
82104 }
83105
106
+ rockchip_monitor_volt_adjust_lock(kbdev->mdev_info);
84107 if (pm_runtime_enabled(kbdev->dev)) {
85108 D("to put_sync_suspend mali_dev.");
86109 pm_runtime_put_sync_suspend(kbdev->dev);
87110 }
111
+ rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info);
88112
89
- rk_pm_disable_regulator(kbdev);
113
+ rk_pm_disable_clk(kbdev);
114
+
115
+ if (pm_runtime_suspended(kbdev->dev)) {
116
+ rk_pm_disable_regulator(kbdev);
117
+ platform->is_regulator_on = false;
118
+ }
90119
91120 platform->is_powered = false;
92121 wake_unlock(&platform->wake_lock);
122
+
123
+ mutex_unlock(&platform->lock);
93124 }
94125
95126 static int kbase_platform_rk_init(struct kbase_device *kbdev)
....@@ -117,7 +148,7 @@
117148 ret = -ENOMEM;
118149 goto err_wq;
119150 }
120
- INIT_DELAYED_WORK(&platform->work, rk_pm_power_off_delay_work);
151
+ INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work);
121152
122153 wake_lock_init(&platform->wake_lock, WAKE_LOCK_SUSPEND, "gpu");
123154
....@@ -131,6 +162,8 @@
131162
132163 kbdev->platform_context = (void *)platform;
133164 pm_runtime_enable(kbdev->dev);
165
+
166
+ mutex_init(&platform->lock);
134167
135168 return 0;
136169
....@@ -169,11 +202,39 @@
169202
170203 static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
171204 {
205
+ struct rockchip_opp_info *opp_info = &kbdev->opp_info;
206
+ int ret = 0;
207
+
208
+ if (!kbdev->current_nominal_freq)
209
+ return 0;
210
+
211
+ ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks);
212
+ if (ret) {
213
+ dev_err(kbdev->dev, "failed to enable opp clks\n");
214
+ return ret;
215
+ }
216
+ if (opp_info->data && opp_info->data->set_read_margin)
217
+ opp_info->data->set_read_margin(kbdev->dev, opp_info,
218
+ opp_info->target_rm);
219
+ if (opp_info->scmi_clk) {
220
+ if (clk_set_rate(opp_info->scmi_clk,
221
+ kbdev->current_nominal_freq))
222
+ dev_err(kbdev->dev, "failed to restore clk rate\n");
223
+ }
224
+ clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
225
+
172226 return 0;
173227 }
174228
175229 static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
176230 {
231
+ struct rockchip_opp_info *opp_info = &kbdev->opp_info;
232
+
233
+ if (opp_info->scmi_clk) {
234
+ if (clk_set_rate(opp_info->scmi_clk, POWER_DOWN_FREQ))
235
+ dev_err(kbdev->dev, "failed to set power down rate\n");
236
+ }
237
+ opp_info->current_rm = UINT_MAX;
177238 }
178239
179240 static int rk_pm_callback_power_on(struct kbase_device *kbdev)
....@@ -184,24 +245,33 @@
184245
185246 cancel_delayed_work_sync(&platform->work);
186247
187
- err = rk_pm_enable_clk(kbdev);
188
- if (err) {
189
- E("failed to enable clk: %d", err);
190
- return err;
191
- }
248
+ mutex_lock(&platform->lock);
192249
193250 if (platform->is_powered) {
194251 D("mali_device is already powered.");
195
- return 0;
252
+ ret = 0;
253
+ goto out;
196254 }
197255
198256 /* we must enable vdd_gpu before pd_gpu_in_chip. */
199
- err = rk_pm_enable_regulator(kbdev);
200
- if (err) {
201
- E("fail to enable regulator, err : %d.", err);
202
- return err;
257
+ if (!platform->is_regulator_on) {
258
+ err = rk_pm_enable_regulator(kbdev);
259
+ if (err) {
260
+ E("fail to enable regulator, err : %d.", err);
261
+ ret = err;
262
+ goto out;
263
+ }
264
+ platform->is_regulator_on = true;
203265 }
204266
267
+ err = rk_pm_enable_clk(kbdev);
268
+ if (err) {
269
+ E("failed to enable clk: %d", err);
270
+ ret = err;
271
+ goto out;
272
+ }
273
+
274
+ rockchip_monitor_volt_adjust_lock(kbdev->mdev_info);
205275 /* 若 mali_dev 的 runtime_pm 是 enabled 的, 则... */
206276 if (pm_runtime_enabled(kbdev->dev)) {
207277 D("to resume mali_dev syncly.");
....@@ -211,16 +281,20 @@
211281 err = pm_runtime_get_sync(kbdev->dev);
212282 if (err < 0) {
213283 E("failed to runtime resume device: %d.", err);
214
- return err;
284
+ ret = err;
285
+ goto out;
215286 } else if (err == 1) { /* runtime_pm_status is still active */
216287 D("chip has NOT been powered off, no need to re-init.");
217288 ret = 0;
218289 }
219290 }
291
+ rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info);
220292
221293 platform->is_powered = true;
222294 wake_lock(&platform->wake_lock);
223295
296
+out:
297
+ mutex_unlock(&platform->lock);
224298 return ret;
225299 }
226300
....@@ -228,17 +302,18 @@
228302 {
229303 struct rk_context *platform = get_rk_context(kbdev);
230304
231
- rk_pm_disable_clk(kbdev);
305
+ D("enter");
306
+
232307 queue_delayed_work(platform->power_off_wq, &platform->work,
233308 msecs_to_jiffies(platform->delay_ms));
234309 }
235310
236
-int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
311
+static int rk_kbase_device_runtime_init(struct kbase_device *kbdev)
237312 {
238313 return 0;
239314 }
240315
241
-void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
316
+static void rk_kbase_device_runtime_disable(struct kbase_device *kbdev)
242317 {
243318 }
244319
....@@ -257,20 +332,6 @@
257332 .power_runtime_off_callback = NULL,
258333 #endif /* CONFIG_PM */
259334 };
260
-
261
-int kbase_platform_early_init(void)
262
-{
263
- /* Nothing needed at this stage */
264
- return 0;
265
-}
266
-
267
-/*---------------------------------------------------------------------------*/
268
-
269
-void kbase_platform_rk_shutdown(struct kbase_device *kbdev)
270
-{
271
- I("to make vdd_gpu enabled for turning off pd_gpu in pm_framework.");
272
- rk_pm_enable_regulator(kbdev);
273
-}
274335
275336 /*---------------------------------------------------------------------------*/
276337
....@@ -398,7 +459,7 @@
398459 unsigned long period_in_us = platform->utilisation_period * 1000;
399460 u32 utilisation;
400461 struct kbasep_pm_metrics metrics_when_start;
401
- struct kbasep_pm_metrics metrics_diff; /* between start and end. */
462
+ struct kbasep_pm_metrics metrics_diff = {}; /* between start and end. */
402463 u32 total_time = 0;
403464 u32 busy_time = 0;
404465
....@@ -452,8 +513,180 @@
452513 device_remove_file(dev, &dev_attr_utilisation);
453514 }
454515
516
+static int rk3588_gpu_get_soc_info(struct device *dev, struct device_node *np,
517
+ int *bin, int *process)
518
+{
519
+ int ret = 0;
520
+ u8 value = 0;
521
+
522
+ if (!bin)
523
+ return 0;
524
+
525
+ if (of_property_match_string(np, "nvmem-cell-names",
526
+ "specification_serial_number") >= 0) {
527
+ ret = rockchip_nvmem_cell_read_u8(np,
528
+ "specification_serial_number",
529
+ &value);
530
+ if (ret) {
531
+ dev_err(dev,
532
+ "Failed to get specification_serial_number\n");
533
+ return ret;
534
+ }
535
+ /* RK3588M */
536
+ if (value == 0xd)
537
+ *bin = 1;
538
+ /* RK3588J */
539
+ else if (value == 0xa)
540
+ *bin = 2;
541
+ }
542
+ if (*bin < 0)
543
+ *bin = 0;
544
+ dev_info(dev, "bin=%d\n", *bin);
545
+
546
+ return ret;
547
+}
548
+
549
+static int rk3588_gpu_set_soc_info(struct device *dev, struct device_node *np,
550
+ int bin, int process, int volt_sel)
551
+{
552
+ struct opp_table *opp_table;
553
+ u32 supported_hw[2];
554
+
555
+ if (volt_sel < 0)
556
+ return 0;
557
+ if (bin < 0)
558
+ bin = 0;
559
+
560
+ if (!of_property_read_bool(np, "rockchip,supported-hw"))
561
+ return 0;
562
+
563
+ /* SoC Version */
564
+ supported_hw[0] = BIT(bin);
565
+ /* Speed Grade */
566
+ supported_hw[1] = BIT(volt_sel);
567
+ opp_table = dev_pm_opp_set_supported_hw(dev, supported_hw, 2);
568
+ if (IS_ERR(opp_table)) {
569
+ dev_err(dev, "failed to set supported opp\n");
570
+ return PTR_ERR(opp_table);
571
+ }
572
+
573
+ return 0;
574
+}
575
+
576
+static int rk3588_gpu_set_read_margin(struct device *dev,
577
+ struct rockchip_opp_info *opp_info,
578
+ u32 rm)
579
+{
580
+ int ret = 0;
581
+ u32 val;
582
+
583
+ if (!opp_info->grf || !opp_info->volt_rm_tbl)
584
+ return 0;
585
+ if (rm == opp_info->current_rm || rm == UINT_MAX)
586
+ return 0;
587
+
588
+ dev_dbg(dev, "set rm to %d\n", rm);
589
+
590
+ ret = regmap_read(opp_info->grf, 0x24, &val);
591
+ if (ret < 0) {
592
+ dev_err(dev, "failed to get rm from 0x24\n");
593
+ return ret;
594
+ }
595
+ val &= ~0x1c;
596
+ regmap_write(opp_info->grf, 0x24, val | (rm << 2));
597
+
598
+ ret = regmap_read(opp_info->grf, 0x28, &val);
599
+ if (ret < 0) {
600
+ dev_err(dev, "failed to get rm from 0x28\n");
601
+ return ret;
602
+ }
603
+ val &= ~0x1c;
604
+ regmap_write(opp_info->grf, 0x28, val | (rm << 2));
605
+
606
+ opp_info->current_rm = rm;
607
+
608
+ return 0;
609
+}
610
+
611
+static const struct rockchip_opp_data rk3588_gpu_opp_data = {
612
+ .get_soc_info = rk3588_gpu_get_soc_info,
613
+ .set_soc_info = rk3588_gpu_set_soc_info,
614
+ .set_read_margin = rk3588_gpu_set_read_margin,
615
+};
616
+
617
+static const struct of_device_id rockchip_mali_of_match[] = {
618
+ {
619
+ .compatible = "rockchip,rk3588",
620
+ .data = (void *)&rk3588_gpu_opp_data,
621
+ },
622
+ {},
623
+};
624
+
455625 int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev)
456626 {
457
- return rockchip_init_opp_table(kbdev->dev, NULL,
627
+ rockchip_get_opp_data(rockchip_mali_of_match, &kbdev->opp_info);
628
+
629
+ return rockchip_init_opp_table(kbdev->dev, &kbdev->opp_info,
458630 "gpu_leakage", "mali");
459631 }
632
+
633
+int kbase_platform_rk_enable_regulator(struct kbase_device *kbdev)
634
+{
635
+ struct rk_context *platform = get_rk_context(kbdev);
636
+ int err = 0;
637
+
638
+ if (!platform->is_regulator_on) {
639
+ err = rk_pm_enable_regulator(kbdev);
640
+ if (err) {
641
+ E("fail to enable regulator, err : %d.", err);
642
+ return err;
643
+ }
644
+ platform->is_regulator_on = true;
645
+ }
646
+
647
+ return 0;
648
+}
649
+
650
+/*---------------------------------------------------------------------------*/
651
+
652
+static void *enumerate_gpu_clk(struct kbase_device *kbdev,
653
+ unsigned int index)
654
+{
655
+ if (index >= kbdev->nr_clocks)
656
+ return NULL;
657
+
658
+ return kbdev->clocks[index];
659
+}
660
+
661
+static unsigned long get_gpu_clk_rate(struct kbase_device *kbdev,
662
+ void *gpu_clk_handle)
663
+{
664
+ return clk_get_rate((struct clk *)gpu_clk_handle);
665
+}
666
+
667
+static int gpu_clk_notifier_register(struct kbase_device *kbdev,
668
+ void *gpu_clk_handle, struct notifier_block *nb)
669
+{
670
+ compiletime_assert(offsetof(struct clk_notifier_data, clk) ==
671
+ offsetof(struct kbase_gpu_clk_notifier_data, gpu_clk_handle),
672
+ "mismatch in the offset of clk member");
673
+
674
+ compiletime_assert(sizeof(((struct clk_notifier_data *)0)->clk) ==
675
+ sizeof(((struct kbase_gpu_clk_notifier_data *)0)->gpu_clk_handle),
676
+ "mismatch in the size of clk member");
677
+
678
+ return clk_notifier_register((struct clk *)gpu_clk_handle, nb);
679
+}
680
+
681
+static void gpu_clk_notifier_unregister(struct kbase_device *kbdev,
682
+ void *gpu_clk_handle, struct notifier_block *nb)
683
+{
684
+ clk_notifier_unregister((struct clk *)gpu_clk_handle, nb);
685
+}
686
+
687
+struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops = {
688
+ .get_gpu_clk_rate = get_gpu_clk_rate,
689
+ .enumerate_gpu_clk = enumerate_gpu_clk,
690
+ .gpu_clk_notifier_register = gpu_clk_notifier_register,
691
+ .gpu_clk_notifier_unregister = gpu_clk_notifier_unregister,
692
+};