fix mali for ttab
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / platform / platform_pmm.c
CommitLineData
db9a41fa 1
6fa3eb70
S
2#include <linux/mali/mali_utgard.h>
3#include "mali_kernel_common.h"
4#include "mali_osk.h"
5#include "platform_pmm.h"
db9a41fa 6#include <linux/kernel.h>
6fa3eb70
S
7#include <asm/atomic.h>
8#include "arm_core_scaling.h"
db9a41fa
S
9#include <linux/clk.h>
10#include <linux/io.h>
11#include <linux/regulator/consumer.h>
6fa3eb70
S
12
13#if defined(CONFIG_MALI400_PROFILING)
14#include "mali_osk_profiling.h"
15#endif
16
db9a41fa
S
17#ifdef CONFIG_MALI_DT
18#include <linux/module.h>
19#include <linux/clk.h>
20#include <linux/clk-private.h>
21#include <linux/pm_runtime.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/of_platform.h>
25#include <linux/init.h>
26#include <linux/pm_runtime.h>
27#include <linux/platform_device.h>
28#include <linux/of_irq.h>
29#include "mt-plat/mt_smi.h"
30#include <linux/proc_fs.h>
31#else
32#include "mach/mt_gpufreq.h"
765691f5 33#include "mach/mt_clkmgr.h"
db9a41fa 34#endif
6fa3eb70 35
765691f5 36
db9a41fa
S
37extern unsigned long (*mtk_thermal_get_gpu_loading_fp) (void);
38extern unsigned long (*mtk_get_gpu_loading_fp) (void);
765691f5 39
6fa3eb70
S
40
41static int bPoweroff;
db9a41fa 42unsigned int current_sample_utilization;
6fa3eb70 43
db9a41fa
S
44extern u32 get_devinfo_with_index(u32 index);
45static int _need_univpll;
46
765691f5
S
47#define MFG_SPD_MASK 0x80000
48
49#define mfg_pwr_unlock(flags) \
50do { \
51 spin_unlock_irqrestore(&mali_pwr_lock, flags); \
52} while(0)
53
db9a41fa
S
54#ifdef CONFIG_MALI_DT
55
56/* MFG begin
57 * GPU controller.
58 *
59 * If GPU power domain needs to be enabled after disp, we will break flow
60 * of mfg_enable_gpu to be 2 functions like mfg_prepare/mfg_enable.
61 *
62 * Currently no lock for mfg, Mali driver will take .
63 */
64
65#define MFG_CG_CON 0x0
66#define MFG_CG_SET 0x4
67#define MFG_CG_CLR 0x8
68#define MFG_DEBUG_SEL 0x180
69#define MFG_DEBUG_STAT 0x184
765691f5 70//#define MFG_SPD_MASK 0x80000
db9a41fa
S
71#define MFG_GPU_QUAL_MASK 0x3
72
73#define MFG_READ32(r) __raw_readl((void __iomem *)((unsigned long)mfg_start + (r)))
74#define MFG_WRITE32(v, r) __raw_writel((v), (void __iomem *)((unsigned long)mfg_start + (r)))
6fa3eb70 75
db9a41fa
S
76static struct platform_device *mfg_dev;
77static void __iomem *mfg_start;
78static void __iomem * scp_start;
6fa3eb70 79
db9a41fa
S
80#ifdef CONFIG_OF
81static const struct of_device_id mfg_dt_ids[] = {
82 {.compatible = "mediatek,mt8127-mfg"},
83 { /* sentinel */ }
84};
85
86MODULE_DEVICE_TABLE(of, mfg_dt_ids);
6fa3eb70
S
87#endif
88
db9a41fa
S
89static int mfg_device_probe(struct platform_device *pdev)
90{
91
92 /* Make sure disp pm is ready to operate .. */
93 if(!mtk_smi_larb_get_base(0)) {
94 pr_warn("MFG is defer for disp domain ready\n");
95 mfg_dev = NULL;
96 return -EPROBE_DEFER;
97 }else
98 pr_info("MFG domain ready\n");
6fa3eb70 99
db9a41fa
S
100 mfg_start = of_iomap(pdev->dev.of_node, 0);
101 if (IS_ERR_OR_NULL(mfg_start)) {
102 mfg_start = NULL;
103 goto error_out;
104 }
105 pr_info("MFG start is mapped %p\n", mfg_start);
6fa3eb70 106
db9a41fa
S
107 pm_runtime_set_autosuspend_delay(&(pdev->dev), 300);
108 pm_runtime_use_autosuspend(&(pdev->dev));
6fa3eb70 109
db9a41fa
S
110 pm_runtime_enable(&pdev->dev);
111
112 {
113 struct device_node * node;
114 static const struct of_device_id scp_ids[] = {
115 {.compatible = "mediatek,mt8127-scpsys"},
116 { /* sentinel */ }
117 };
118 node = of_find_matching_node(NULL, scp_ids);
119 if (node)
120 scp_start = of_iomap(node, 0);
121 pr_info("MFG scp_start is mapped %p\n", scp_ids);
122 }
123 mfg_dev = pdev;
124 pr_info("MFG device probed done\n");
125 return 0;
126error_out:
127 if (mfg_start)
128 iounmap(mfg_start);
129 if(scp_start)
130 iounmap(scp_start);
131
132 return -1;
133}
134
135static int mfg_device_remove(struct platform_device *pdev)
136{
137 pm_runtime_disable(&pdev->dev);
138
139 if (mfg_start)
140 iounmap(mfg_start);
141 if(scp_start)
142 iounmap(scp_start);
143
144 return 0;
6fa3eb70 145}
db9a41fa
S
146
147static struct platform_driver mtk_mfg_driver = {
148 .probe = mfg_device_probe,
149 .remove = mfg_device_remove,
150 .driver = {
151 .name = "mfg",
152 .owner = THIS_MODULE,
153 .of_match_table = of_match_ptr(mfg_dt_ids),
154 },
155};
156
157#define MFG_DUMP_FOR(base, off) \
158do {\
159 u32 val;\
160 val = __raw_readl(base + off);\
161 pr_info("pwr_dump %s [%#x]: 0x%x\n", #base, (u32)off, val); \
162 }while(0)
163
164#define DEBUG_MFG_STAT \
165do {\
166 u32 con = 0xDEAC;\
167 con = MFG_READ32(MFG_CG_CON);\
168 pr_debug("MFG %s #%d CON: 0x%x\n", __func__, __LINE__, con); \
169} while (0)
170
171static int mfg_enable_gpu(void)
172{
173 int ret = -1, i = 10;
174 u32 con;
175 if (mfg_start == NULL)
176 return ret;
177 ret = pm_runtime_get_sync(&mfg_dev->dev);
178 if (ret < 0){
179 /*
180 pm_runtime_enable(&mfg_dev->dev);
181 ret = pm_runtime_get_sync(&mfg_dev->dev);
182 */
183 pr_warn("MFG %s #%d get DISP[%d] \n", __func__, __LINE__, ret);
184 }
185 ret = mtk_smi_larb_clock_on(0, false);
186
187 i = 10;
188 DEBUG_MFG_STAT;
189 do{
190 MFG_WRITE32(0x1, MFG_CG_CLR);
191 con = MFG_READ32(MFG_CG_CON);
192 if (con == 0)
193 break;
194 else
195 pr_warn("MFG MFG_CG_CON[0x%x]", con);
196 }while(i--);
197 DEBUG_MFG_STAT;
198
199 return ret;
6fa3eb70
S
200}
201
db9a41fa 202static void mfg_disable_gpu(void)
6fa3eb70 203{
db9a41fa
S
204 if (mfg_start == NULL)
205 return;
6fa3eb70 206
db9a41fa
S
207 DEBUG_MFG_STAT;
208 MFG_WRITE32(0x1, MFG_CG_SET);
209 DEBUG_MFG_STAT;
210 mtk_smi_larb_clock_off(0, false);
211 pm_runtime_mark_last_busy(&mfg_dev->dev);
212 pm_runtime_put_autosuspend(&mfg_dev->dev);
6fa3eb70
S
213}
214
db9a41fa 215static int __init mfg_driver_init(void)
6fa3eb70 216{
db9a41fa
S
217 int ret;
218
219 ret = platform_driver_register(&mtk_mfg_driver);
220 return ret;
221}
222
223bool mtk_mfg_is_ready(void)
224{
225 return (mfg_dev !=NULL && mfg_start != NULL);
226}
227
228/* We need make mfg probed before GPU */
229late_initcall(mfg_driver_init);
230
231/* MFG end */
232
233struct _mfg_base
234{
235 void __iomem *g3d_base;
236 struct clk *mm_smi;
237 struct clk *mfg_pll;
238 struct clk *mfg_sel;
239 /*struct regulator *vdd_g3d;*/
240};
241
242static struct _mfg_base mfg_base;
243
244#define REG_MFG_G3D BIT(0)
245
246#define REG_MFG_CG_STA 0x00
247#define REG_MFG_CG_SET 0x04
248#define REG_MFG_CG_CLR 0x08
249
250int mali_mfgsys_init(struct platform_device *device)
251{
252 int err = 0;
253 struct clk *parent;
254 unsigned long freq;
255
256 mfg_base.g3d_base = mfg_start;
257
258 mfg_base.mm_smi = devm_clk_get(&device->dev, "mm_smi");
259 if (IS_ERR(mfg_base.mm_smi)) {
260 err = PTR_ERR(mfg_base.mm_smi);
261 dev_err(&device->dev, "devm_clk_get mm_smi failed\n");
262 goto err_iounmap_reg_base;
263 }
264 if(!_need_univpll){
265 mfg_base.mfg_pll = devm_clk_get(&device->dev, "mfg_pll");
266 if (IS_ERR(mfg_base.mfg_pll)) {
267 err = PTR_ERR(mfg_base.mfg_pll);
268 dev_err(&device->dev, "devm_clk_get mfg_pll failed\n");
269 goto err_iounmap_reg_base;
270 }
271 }else{
272 mfg_base.mfg_pll = devm_clk_get(&device->dev, "mfg_pll_univ");
273 if (IS_ERR(mfg_base.mfg_pll)) {
274 err = PTR_ERR(mfg_base.mfg_pll);
275 dev_err(&device->dev, "devm_clk_get mfg_pll_univ failed\n");
276 goto err_iounmap_reg_base;
277 }
278 }
279 mfg_base.mfg_sel = devm_clk_get(&device->dev, "mfg_sel");
280 if (IS_ERR(mfg_base.mfg_sel)) {
281 err = PTR_ERR(mfg_base.mfg_sel);
282 dev_err(&device->dev, "devm_clk_get mfg_sel failed\n");
283 goto err_iounmap_reg_base;
284 }
285 clk_prepare_enable(mfg_base.mfg_sel);
286
287 err = clk_set_parent(mfg_base.mfg_sel, mfg_base.mfg_pll);
288 if (err != 0) {
289 dev_err(&device->dev, "failed to clk_set_parent\n");
290 goto err_iounmap_reg_base;
291 }
292 parent = clk_get_parent(mfg_base.mfg_sel);
293 if (!IS_ERR_OR_NULL(parent)) {
294 pr_info("0MFG is now selected to %s\n", parent->name);
295 freq = clk_get_rate(parent);
296 pr_info("MFG parent rate %lu\n", freq);
297 /* Don't set rate here, gpufreq will do this */
298 } else {
299 pr_err("Failed to select mfg\n");
300 }
301
302 /*
303 clk_disable_unprepare(mfg_base.mfg_sel);
304
305 mfg_base.vdd_g3d = devm_regulator_get(&device->dev, "vdd_g3d");
306 if (IS_ERR(mfg_base.vdd_g3d)) {
307 err = PTR_ERR(mfg_base.vdd_g3d);
308 goto err_iounmap_reg_base;
6fa3eb70 309 }
db9a41fa
S
310
311 err = regulator_enable(mfg_base.vdd_g3d);
312 if (err != 0) {
313 dev_err(&device->dev, "failed to enable regulator vdd_g3d\n");
314 goto err_iounmap_reg_base;
315 }
316 */
317
318 return 0;
319
320err_iounmap_reg_base:
321
322 return err;
6fa3eb70
S
323}
324
db9a41fa 325void mali_mfgsys_deinit(struct platform_device *device)
6fa3eb70 326{
db9a41fa
S
327 MALI_IGNORE(device);
328 pm_runtime_disable(&device->dev);
329 /*regulator_disable(mfg_base.vdd_g3d);*/
6fa3eb70 330}
db9a41fa
S
331void dump_clk_state(void)
332{
333 MALI_DEBUG_PRINT(2, ("mali platform_mmt dump_clk_state smi_ref[%d], smi_enabled[%d]\n",
334 __clk_get_enable_count(mfg_base.mm_smi), __clk_is_enabled(mfg_base.mm_smi)));
335 MALI_DEBUG_PRINT(2, ("MFG %s #%d MFG_DEBUG_SEL: 0x%x\n", __func__, __LINE__, MFG_READ32(MFG_DEBUG_SEL)));
336 MALI_DEBUG_PRINT(2, ("MFG %s #%d MFG_DEBUG_CON: %x\n", __func__, __LINE__, MFG_READ32(MFG_CG_CON)));
337 if(scp_start) {
338 MFG_DUMP_FOR(scp_start, 0x060c); /*SPM_PWR_STATUS*/
339 MFG_DUMP_FOR(scp_start, 0x0610); /*SPM_PWR_STATUS_2ND*/
340 }
341 mali_platform_power_mode_change(NULL, MALI_POWER_MODE_ON);
342}
343int mali_clk_enable(struct device *device)
344{
345 int ret;
346 /*clk_prepare_enable(mfg_base.mfg_sel);*/
6fa3eb70 347
db9a41fa 348 ret = mfg_enable_gpu();
6fa3eb70 349
db9a41fa
S
350 MALI_DEBUG_PRINT(3, ("MFG %s #%d MFG_DEBUG_SEL: 0x%x\n", __func__, __LINE__, MFG_READ32(MFG_DEBUG_SEL)));
351 MALI_DEBUG_PRINT(3, ("MFG %s #%d MFG_DEBUG_CON: %x\n", __func__, __LINE__, MFG_READ32(MFG_CG_CON)));
352 MALI_DEBUG_PRINT(2, ("mali_clk_enable![%d]\n", ret));
353
354 return 0;
355}
6fa3eb70 356
db9a41fa 357int mali_clk_disable(struct device *device)
6fa3eb70 358{
db9a41fa
S
359 mfg_disable_gpu();
360 /*clk_disable_unprepare(mfg_base.mfg_sel);*/
361 MALI_DEBUG_PRINT(2, ("mali_clk_disable done\n"));
362
363 return 0;
364}
365#endif
366
765691f5
S
367static u32 check_need_univpll() {
368 u32 info = *(volatile u32 *)0xf0206174;
369 /*get_devinfo_with_index (15);*/
370 /*if(0x0 == (info & (0x1 << 31))) { t or b?*/
371 /*T*/
372 u32 devinfo = *(volatile u32* )0xf0206040;/*get_devinfo_with_index(3);*/
373 if(devinfo & 0x80000) {
374 MALI_DEBUG_PRINT(1, ("GPU use univ with devinfo 0x%x\n", devinfo));
375 return 1;
376 } else {
377#ifdef MTK_MALI_UNIV
378 MALI_DEBUG_PRINT(1, ("GPU use univ with MTK_MALI_UNIV\n"));
379 return 1;
380#else
381 return 0;
382#endif
383 }
384
385}
386
db9a41fa
S
387int mali_pmm_init(struct platform_device *device)
388{
389 int err = 0;
765691f5 390
db9a41fa 391 MALI_DEBUG_PRINT(1, ("%s\n", __FUNCTION__));
765691f5
S
392
393 _need_univpll = check_need_univpll();
394
395 MALI_DEBUG_PRINT(1, ("need univ src pll %d\n", _need_univpll));
db9a41fa
S
396
397 /* Because clkmgr may do 'default on' for some clock.
398 We check the clock state on init and set power state atomic.
399 */
400
401 MALI_DEBUG_PRINT(1, ("MFG G3D init enable if it is on0621\n"));
765691f5 402
db9a41fa
S
403 mtk_thermal_get_gpu_loading_fp = gpu_get_current_utilization;
404 mtk_get_gpu_loading_fp = gpu_get_current_utilization;
405 if (clock_is_on(MT_CG_MFG_G3D)) {
406 MALI_DEBUG_PRINT(1, ("MFG G3D default on\n"));
407 atomic_set((atomic_t *) & bPoweroff, 0);
408 /* Need call enable first for 'default on' clocks.
409 * Canbe removed if clkmgr remove this requirement.
410 */
411 enable_clock(MT_CG_DISP0_SMI_COMMON, "MFG");
412 enable_clock(MT_CG_MFG_G3D, "MFG");
413 } else {
414 MALI_DEBUG_PRINT(1, ("MFG G3D init default off\n"));
415 atomic_set((atomic_t *) & bPoweroff, 1);
416 }
765691f5 417
db9a41fa
S
418 mali_platform_power_mode_change(&(device->dev), MALI_POWER_MODE_ON);
419
420 return err;
6fa3eb70
S
421}
422
db9a41fa
S
423void mali_pmm_deinit(struct platform_device *device)
424{
425 MALI_DEBUG_PRINT(1, ("%s\n", __FUNCTION__));
426
427 mali_platform_power_mode_change(&device->dev, MALI_POWER_MODE_DEEP_SLEEP);
765691f5 428#ifdef CONFIG_MALI_DT
db9a41fa 429 mali_mfgsys_deinit(device);
765691f5 430#endif
db9a41fa 431}
6fa3eb70 432
db9a41fa
S
433unsigned int gpu_get_current_utilization(void)
434{
435 return (current_sample_utilization * 100) / 256;
436}
6fa3eb70 437
db9a41fa
S
438void mali_platform_power_mode_change(struct device *device,
439 mali_power_mode power_mode)
440{
441 switch (power_mode) {
442 case MALI_POWER_MODE_ON:
443 MALI_DEBUG_PRINT(3,
444 ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n",
445 atomic_read((atomic_t *) & bPoweroff) ?
446 "powering on" : "already on"));
447 if (atomic_read((atomic_t *) & bPoweroff) == 1) {
448 /*Leave this to undepend ref count of clkmgr */
449 #ifndef CONFIG_MALI_DT
450 if (!clock_is_on(MT_CG_MFG_G3D)) {
451 MALI_DEBUG_PRINT(3, ("MFG enable_clock \n"));
452 if (_need_univpll) {
453 enable_pll(UNIVPLL, "GPU");
6fa3eb70 454 }
db9a41fa
S
455 enable_clock(MT_CG_DISP0_SMI_COMMON, "MFG");
456 enable_clock(MT_CG_MFG_G3D, "MFG");
457 if (_need_univpll) {
6fa3eb70
S
458 clkmux_sel(MT_MUX_MFG, 6, "GPU");
459 }
db9a41fa
S
460 atomic_set((atomic_t *) & bPoweroff, 0);
461 }
462 #else
463 if (!mali_clk_enable(device))
464 atomic_set((atomic_t *) & bPoweroff, 0);
465 #endif
6fa3eb70 466#if defined(CONFIG_MALI400_PROFILING)
db9a41fa
S
467 _mali_osk_profiling_add_event
468 (MALI_PROFILING_EVENT_TYPE_SINGLE |
469 MALI_PROFILING_EVENT_CHANNEL_GPU |
470 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
471 500, 1200 / 1000, 0, 0, 0);
6fa3eb70
S
472
473#endif
db9a41fa
S
474 }
475 break;
476 case MALI_POWER_MODE_LIGHT_SLEEP:
477 case MALI_POWER_MODE_DEEP_SLEEP:
478 MALI_DEBUG_PRINT(3,
479 ("Mali platform: Got %s event, %s\n",
480 power_mode ==
481 MALI_POWER_MODE_LIGHT_SLEEP ?
482 "MALI_POWER_MODE_LIGHT_SLEEP" :
483 "MALI_POWER_MODE_DEEP_SLEEP",
484 atomic_read((atomic_t *) & bPoweroff) ?
485 "already off" : "powering off"));
6fa3eb70 486
db9a41fa
S
487 if (atomic_read((atomic_t *) & bPoweroff) == 0) {
488 #ifndef CONFIG_MALI_DT
489 if (clock_is_on(MT_CG_MFG_G3D)) {
490 MALI_DEBUG_PRINT(3, ("MFG disable_clock \n"));
491 disable_clock(MT_CG_MFG_G3D, "MFG");
492 disable_clock(MT_CG_DISP0_SMI_COMMON, "MFG");
493 if (_need_univpll) {
494 disable_pll(UNIVPLL, "GPU");
495 }
496 atomic_set((atomic_t *) & bPoweroff, 1);
497 }
498 #else
499 if (!mali_clk_disable(device))
500 atomic_set((atomic_t *) & bPoweroff, 1);
501 #endif
6fa3eb70 502#if defined(CONFIG_MALI400_PROFILING)
db9a41fa
S
503 _mali_osk_profiling_add_event
504 (MALI_PROFILING_EVENT_TYPE_SINGLE |
505 MALI_PROFILING_EVENT_CHANNEL_GPU |
506 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
507 0, 0, 0, 0, 0);
6fa3eb70 508#endif
db9a41fa
S
509 }
510 break;
511 }
6fa3eb70 512}