3 * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
5 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
8 * A copy of the licence is included with the program, and can also be obtained from Free Software
9 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/poll.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/platform_device.h>
19 #include <linux/pci.h>
20 #include <linux/miscdevice.h>
21 #include <linux/list.h>
22 #include <linux/semaphore.h>
24 #include <linux/uaccess.h>
25 #include <linux/interrupt.h>
27 #include <linux/ioport.h>
28 #include <linux/spinlock.h>
32 #include <linux/clk.h>
33 #include <mach/regs-clock.h>
35 #include <mach/regs-pmu.h>
36 #include <asm/delay.h>
38 #include <generated/autoconf.h>
40 #include <linux/timer.h>
41 #include <linux/pm_runtime.h>
42 #include <linux/workqueue.h>
43 #include <linux/regulator/consumer.h>
44 #include <linux/regulator/driver.h>
46 #include <osk/mali_osk.h>
47 #include <kbase/src/common/mali_kbase.h>
48 #include <kbase/src/common/mali_kbase_pm.h>
49 #include <kbase/src/common/mali_kbase_uku.h>
50 #include <kbase/src/common/mali_kbase_mem.h>
51 #include <kbase/src/common/mali_midg_regmap.h>
52 #include <kbase/src/linux/mali_kbase_mem_linux.h>
53 #include <kbase/src/common/mali_kbase_defs.h>
54 #include <kbase/src/linux/mali_kbase_config_linux.h>
56 #include <kbase/src/linux/mali_linux_dvfs_trace.h>
58 #if CONFIG_MALI_UNCACHED == 0
59 #error CONFIG_MALI_UNCACHED should equal 1 for Exynos5 support, your scons commandline should contain 'no_syncsets=1'
62 #define MALI_DVFS_DEBUG 0
63 #define MALI_DVFS_STEP 7
64 #define MALI_DVFS_KEEP_STAY_CNT 10
66 #ifdef CONFIG_T6XX_DVFS
67 #ifdef CONFIG_CPU_FREQ
68 #define MALI_DVFS_ASV_ENABLE
72 #ifdef MALI_DVFS_ASV_ENABLE
73 #include <mach/busfreq_exynos5.h>
74 #define MALI_DVFS_ASV_GROUP_SPECIAL_NUM 10
75 #define MALI_DVFS_ASV_GROUP_NUM 12
78 #define HZ_IN_MHZ (1000000)
79 #define MALI_RTPM_DEBUG 0
80 #define VITHAR_DEFAULT_CLOCK 533000000
81 #define RUNTIME_PM_DELAY_TIME 10
82 #define CONFIG_T6XX_HWVER_R0P0 1
84 struct regulator *kbase_platform_get_regulator(void);
85 int kbase_platform_regulator_init(void);
86 int kbase_platform_regulator_disable(void);
87 int kbase_platform_regulator_enable(void);
88 int kbase_platform_get_default_voltage(struct device *dev, int *vol);
89 int kbase_platform_get_voltage(struct device *dev, int *vol);
90 int kbase_platform_set_voltage(struct device *dev, int vol);
91 void kbase_platform_dvfs_set_clock(kbase_device *kbdev, int freq);
92 void kbase_platform_dvfs_set_level(kbase_device *kbdev, int level);
93 int kbase_platform_dvfs_get_level(int freq);
95 #ifdef CONFIG_T6XX_DVFS
96 int kbase_platform_dvfs_init(kbase_device *kbdev);
97 void kbase_platform_dvfs_term(void);
98 int kbase_platform_dvfs_get_control_status(void);
99 int kbase_platform_dvfs_get_utilisation(void);
100 #ifdef MALI_DVFS_ASV_ENABLE
101 static int kbase_platform_asv_set(int enable);
102 static int kbase_platform_dvfs_sprint_avs_table(char *buf);
103 #endif /* MALI_DVFS_ASV_ENABLE */
104 #endif /* CONFIG_T6XX_DVFS */
106 int kbase_platform_cmu_pmu_control(struct kbase_device *kbdev, int control);
107 void kbase_platform_remove_sysfs_file(struct device *dev);
108 mali_error kbase_platform_init(struct kbase_device *kbdev);
109 static int kbase_platform_is_power_on(void);
110 void kbase_platform_term(struct kbase_device *kbdev);
112 #ifdef CONFIG_T6XX_DEBUG_SYS
113 static int kbase_platform_create_sysfs_file(struct device *dev);
114 #endif /* CONFIG_T6XX_DEBUG_SYS */
116 static int mali_setup_system_tracing(struct device *dev);
117 static void mali_cleanup_system_tracing(struct device *dev);
119 struct exynos_context
121 /** Indicator if system clock to mail-t604 is active */
123 /** cmd & pmu lock */
124 spinlock_t cmu_pmu_lock;
125 struct clk *sclk_g3d;
128 static kbase_io_resources io_resources =
130 .job_irq_number = EXYNOS5_JOB_IRQ_NUMBER,
131 .mmu_irq_number = EXYNOS5_MMU_IRQ_NUMBER,
132 .gpu_irq_number = EXYNOS5_GPU_IRQ_NUMBER,
135 .start = EXYNOS5_PA_G3D,
136 .end = EXYNOS5_PA_G3D + (4096 * 5) - 1
141 * Read the CPU clock speed
143 int get_cpu_clock_speed(u32* cpu_clock)
145 struct clk * cpu_clk;
147 cpu_clk = clk_get(NULL, "armclk");
150 freq = clk_get_rate(cpu_clk);
151 *cpu_clock = (freq/HZ_IN_MHZ);
156 * Power Management callback - power ON
158 static int pm_callback_power_on(kbase_device *kbdev)
160 #ifdef CONFIG_PM_RUNTIME
161 pm_runtime_resume(kbdev->osdev.dev);
162 #endif /* CONFIG_PM_RUNTIME */
167 * Power Management callback - power OFF
169 static void pm_callback_power_off(kbase_device *kbdev)
171 #ifdef CONFIG_PM_RUNTIME
172 pm_schedule_suspend(kbdev->osdev.dev, RUNTIME_PM_DELAY_TIME);
173 #endif /* CONFIG_PM_RUNTIME */
177 * Power Management callback - runtime power ON
179 #ifdef CONFIG_PM_RUNTIME
180 static int pm_callback_runtime_power_on(kbase_device *kbdev)
183 printk("kbase_device_runtime_resume\n");
184 #endif /* MALI_RTPM_DEBUG */
185 return kbase_platform_cmu_pmu_control(kbdev, 1);
187 #endif /* CONFIG_PM_RUNTIME */
190 * Power Management callback - runtime power OFF
192 #ifdef CONFIG_PM_RUNTIME
193 static void pm_callback_runtime_power_off(kbase_device *kbdev)
196 printk("kbase_device_runtime_suspend\n");
197 #endif /* MALI_RTPM_DEBUG */
198 kbase_platform_cmu_pmu_control(kbdev, 0);
200 #endif /* CONFIG_PM_RUNTIME */
202 static kbase_pm_callback_conf pm_callbacks =
204 .power_on_callback = pm_callback_power_on,
205 .power_off_callback = pm_callback_power_off,
209 * Exynos5 hardware specific initialization
211 mali_bool kbase_platform_exynos5_init(kbase_device *kbdev)
213 if(MALI_ERROR_NONE == kbase_platform_init(kbdev))
215 #ifdef CONFIG_T6XX_DEBUG_SYS
216 if(kbase_platform_create_sysfs_file(kbdev->osdev.dev))
220 #endif /* CONFIG_T6XX_DEBUG_SYS */
228 * Exynos5 hardware specific termination
230 void kbase_platform_exynos5_term(kbase_device *kbdev)
232 #ifdef CONFIG_T6XX_DEBUG_SYS
233 kbase_platform_remove_sysfs_file(kbdev->osdev.dev);
234 #endif /* CONFIG_T6XX_DEBUG_SYS */
235 kbase_platform_term(kbdev);
238 kbase_platform_funcs_conf platform_funcs =
240 .platform_init_func = &kbase_platform_exynos5_init,
241 .platform_term_func = &kbase_platform_exynos5_term,
244 static kbase_attribute config_attributes[] = {
246 KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_MAX,
247 2048 * 1024 * 1024UL /* 2048MB */
251 KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_PERF_GPU,
255 KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS,
256 (uintptr_t)&pm_callbacks
259 KBASE_CONFIG_ATTR_PLATFORM_FUNCS,
260 (uintptr_t)&platform_funcs
264 KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX,
268 KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN,
272 KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS,
273 500 /* 500ms before cancelling stuck jobs */
276 KBASE_CONFIG_ATTR_CPU_SPEED_FUNC,
277 (uintptr_t)&get_cpu_clock_speed
280 KBASE_CONFIG_ATTR_END,
285 kbase_platform_config platform_config =
287 .attributes = config_attributes,
288 .io_resources = &io_resources,
289 .midgard_type = KBASE_MALI_T604
292 static struct clk *clk_g3d = NULL;
295 * Initialize GPU clocks
297 static int kbase_platform_power_clock_init(kbase_device *kbdev)
299 struct device *dev = kbdev->osdev.dev;
301 struct exynos_context *platform;
303 platform = (struct exynos_context *) kbdev->platform_context;
309 /* Turn on G3D power */
310 __raw_writel(0x7, EXYNOS5_G3D_CONFIGURATION);
312 /* Wait for G3D power stability for 1ms */
314 while((__raw_readl(EXYNOS5_G3D_STATUS) & 0x7) != 0x7) {
316 /* need to call panic */
317 panic("failed to turn on g3d power\n");
324 /* Turn on G3D clock */
325 clk_g3d = clk_get(dev, "g3d");
326 if(IS_ERR(clk_g3d)) {
328 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_get [clk_g3d]\n");
329 /* chrome linux does not have this clock */
333 /* android_v4 support */
335 printk("v4 support\n");
338 #ifdef CONFIG_T6XX_HWVER_R0P0
339 platform->sclk_g3d = clk_get(dev, "aclk_400_g3d");
340 if(IS_ERR(platform->sclk_g3d)) {
341 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_get [sclk_g3d]\n");
344 #else /* CONFIG_T6XX_HWVER_R0P0 */
346 struct clk *mpll = NULL;
347 mpll = clk_get(dev, "mout_mpll_user");
349 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_get [mout_mpll_user]\n");
353 platform->sclk_g3d = clk_get(dev, "sclk_g3d");
354 if(IS_ERR(platform->sclk_g3d)) {
355 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_get [sclk_g3d]\n");
359 clk_set_parent(platform->sclk_g3d, mpll);
360 if(IS_ERR(platform->sclk_g3d)) {
361 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_set_parent\n");
365 clk_set_rate(platform->sclk_g3d, VITHAR_DEFAULT_CLOCK);
366 if(IS_ERR(platform->sclk_g3d)) {
367 OSK_PRINT_ERROR(OSK_BASE_PM, "failed to clk_set_rate [sclk_g3d] = %d\n", VITHAR_DEFAULT_CLOCK);
371 #endif /* CONFIG_T6XX_HWVER_R0P0 */
372 (void) clk_enable(platform->sclk_g3d);
381 static int kbase_platform_clock_on(struct kbase_device *kbdev)
383 struct exynos_context *platform;
387 platform = (struct exynos_context *) kbdev->platform_context;
393 /* android_v4 support */
394 (void) clk_enable(clk_g3d);
399 (void) clk_enable(platform->sclk_g3d);
408 static int kbase_platform_clock_off(struct kbase_device *kbdev)
410 struct exynos_context *platform;
414 platform = (struct exynos_context *) kbdev->platform_context;
420 /* android_v4 support */
421 (void)clk_disable(clk_g3d);
426 (void)clk_disable(platform->sclk_g3d);
432 * Report GPU power status
434 static inline int kbase_platform_is_power_on(void)
436 return ((__raw_readl(EXYNOS5_G3D_STATUS) & 0x7) == 0x7) ? 1 : 0;
442 static int kbase_platform_power_on(void)
447 __raw_writel(0x7, EXYNOS5_G3D_CONFIGURATION);
449 /* Wait for G3D power stability */
452 while((__raw_readl(EXYNOS5_G3D_STATUS) & 0x7) != 0x7) {
454 /* need to call panic */
455 panic("failed to turn on g3d via g3d_configuration\n");
468 static int kbase_platform_power_off(void)
473 __raw_writel(0x0, EXYNOS5_G3D_CONFIGURATION);
475 /* Wait for G3D power stability */
478 while(__raw_readl(EXYNOS5_G3D_STATUS) & 0x7) {
480 /* need to call panic */
481 panic( "failed to turn off g3d via g3d_configuration\n");
492 * Power Management unit control. Enable/disable power and clocks to GPU
494 int kbase_platform_cmu_pmu_control(struct kbase_device *kbdev, int control)
497 struct exynos_context *platform;
503 platform = (struct exynos_context *) kbdev->platform_context;
509 spin_lock_irqsave(&platform->cmu_pmu_lock, flags);
514 if(platform->cmu_pmu_status == 0)
516 spin_unlock_irqrestore(&platform->cmu_pmu_lock, flags);
520 if(kbase_platform_power_off())
521 panic("failed to turn off g3d power\n");
522 if(kbase_platform_clock_off(kbdev))
524 panic("failed to turn off sclk_g3d\n");
526 platform->cmu_pmu_status = 0;
528 printk( KERN_ERR "3D cmu_pmu_control - off\n" );
529 #endif /* MALI_RTPM_DEBUG */
534 if(platform->cmu_pmu_status == 1)
536 spin_unlock_irqrestore(&platform->cmu_pmu_lock, flags);
540 if(kbase_platform_clock_on(kbdev))
541 panic("failed to turn on sclk_g3d\n");
542 if(kbase_platform_power_on())
543 panic("failed to turn on g3d power\n");
545 platform->cmu_pmu_status = 1;
547 printk( KERN_ERR "3D cmu_pmu_control - on\n");
548 #endif /* MALI_RTPM_DEBUG */
551 spin_unlock_irqrestore(&platform->cmu_pmu_lock, flags);
556 #ifdef CONFIG_T6XX_DEBUG_SYS
557 /** The sysfs file @c clock, fbdev.
559 * This is used for obtaining information about the vithar
560 * operating clock & framebuffer address,
563 static ssize_t mali_sysfs_show_clock(struct device *dev,
564 struct device_attribute *attr, char *buf)
566 struct kbase_device *kbdev;
567 struct exynos_context *platform;
569 unsigned int clkrate;
571 kbdev = dev_get_drvdata(dev);
576 platform = (struct exynos_context *) kbdev->platform_context;
580 if(!platform->sclk_g3d)
583 clkrate = clk_get_rate(platform->sclk_g3d);
584 ret += snprintf(buf+ret, PAGE_SIZE-ret, "Current sclk_g3d[G3D_BLK] = %dMhz", clkrate/1000000);
587 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\nPossible settings : 533, 450, 400, 350, 266, 160, 100Mhz");
588 if (ret < PAGE_SIZE - 1)
589 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
592 buf[PAGE_SIZE-2] = '\n';
593 buf[PAGE_SIZE-1] = '\0';
600 static ssize_t mali_sysfs_set_clock(struct device *dev,
601 struct device_attribute *attr, const char *buf, size_t count)
603 struct kbase_device *kbdev = dev_get_drvdata(dev);
604 struct exynos_context *platform;
605 unsigned int tmp = 0, freq = 0 ;
608 pr_err("%s: no kbdev\n", __func__);
612 platform = (struct exynos_context *) kbdev->platform_context;
613 if (platform == NULL) {
614 pr_err("%s: no platform\n", __func__);
617 if (!platform->sclk_g3d) {
618 pr_info("%s: clkout not 3d\n", __func__);
622 /* TODO(dianders) need to be more careful fiddling voltage+clock */
623 if (sysfs_streq("533", buf)) {
625 } else if (sysfs_streq("450", buf)) {
627 } else if (sysfs_streq("400", buf)) {
629 } else if (sysfs_streq("350", buf)) {
631 } else if (sysfs_streq("266", buf)) {
633 } else if (sysfs_streq("160", buf)) {
635 } else if (sysfs_streq("100", buf)) {
638 pr_err("%s: invalid value\n", __func__);
642 pr_info("aclk400 %u\n", (unsigned int)clk_get_rate(platform->sclk_g3d));
643 kbase_platform_dvfs_set_level(kbdev,
644 kbase_platform_dvfs_get_level(freq));
645 /* Waiting for clock is stable */
647 tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_TOP0);
648 } while (tmp & 0x1000000);
652 DEVICE_ATTR(clock, S_IRUGO|S_IWUSR, mali_sysfs_show_clock,
653 mali_sysfs_set_clock);
655 static ssize_t mali_sysfs_show_fbdev(struct device *dev,
656 struct device_attribute *attr, char *buf)
658 struct kbase_device *kbdev;
662 kbdev = dev_get_drvdata(dev);
667 for(i = 0 ; i < num_registered_fb ; i++) {
668 ret += snprintf(buf+ret, PAGE_SIZE-ret, "fb[%d] xres=%d, yres=%d, addr=0x%lx\n", i, registered_fb[i]->var.xres, registered_fb[i]->var.yres, registered_fb[i]->fix.smem_start);
671 if (ret < PAGE_SIZE - 1)
672 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
675 buf[PAGE_SIZE-2] = '\n';
676 buf[PAGE_SIZE-1] = '\0';
682 DEVICE_ATTR(fbdev, S_IRUGO, mali_sysfs_show_fbdev, NULL);
686 L1_I_data_RAM = 0x01,
690 L1_I_indirect_predictor_RAM = 0x05,
692 L1_D_data_RAM = 0x09,
693 L1_D_load_TLB_array = 0x0A,
694 L1_D_store_TLB_array = 0x0B,
697 L2_snoop_tag_RAM = 0x12,
698 L2_data_ECC_RAM = 0x13,
703 static inline void asm_ramindex_mrc(u32 *DL1Data0, u32 *DL1Data1,
704 u32 *DL1Data2, u32 *DL1Data3)
710 asm volatile("mrc p15, 0, %0, c15, c1, 0" : "=r" (val));
715 asm volatile("mrc p15, 0, %0, c15, c1, 1" : "=r" (val));
720 asm volatile("mrc p15, 0, %0, c15, c1, 2" : "=r" (val));
725 asm volatile("mrc p15, 0, %0, c15, c1, 3" : "=r" (val));
730 static inline void asm_ramindex_mcr(u32 val)
732 asm volatile("mcr p15, 0, %0, c15, c4, 0" : : "r" (val));
737 static void get_tlb_array(u32 val, u32 *DL1Data0, u32 *DL1Data1,
738 u32 *DL1Data2, u32 *DL1Data3)
740 asm_ramindex_mcr(val);
741 asm_ramindex_mrc(DL1Data0, DL1Data1, DL1Data2, DL1Data3);
744 static RAMID_type ramindex = L1_D_load_TLB_array;
745 static ssize_t mali_sysfs_show_dtlb(struct device *dev,
746 struct device_attribute *attr, char *buf)
748 struct kbase_device *kbdev;
751 u32 DL1Data0 = 0, DL1Data1 = 0, DL1Data2 = 0, DL1Data3 = 0;
753 kbdev = dev_get_drvdata(dev);
759 if(ramindex == L1_I_tag_RAM)
761 printk("Not implemented yet\n");
764 else if(ramindex == L1_I_data_RAM)
766 printk("Not implemented yet\n");
769 else if(ramindex == L1_I_BTB_RAM)
771 printk("Not implemented yet\n");
774 else if(ramindex == L1_I_GHB_RAM)
776 printk("Not implemented yet\n");
779 else if(ramindex == L1_I_TLB_RAM)
781 printk("L1-I TLB RAM\n");
782 for(entries = 0 ; entries < 32 ; entries++)
784 get_tlb_array((((u8)ramindex) << 24) + entries, &DL1Data0, &DL1Data1, &DL1Data2, NULL);
785 printk("entries[%d], DL1Data0=%08x, DL1Data1=%08x DL1Data2=%08x\n", entries, DL1Data0, DL1Data1 & 0xffff, 0x0);
788 /* L1-I indirect predictor RAM */
789 else if(ramindex == L1_I_indirect_predictor_RAM)
791 printk("Not implemented yet\n");
794 else if(ramindex == L1_D_tag_RAM)
796 printk("Not implemented yet\n");
799 else if(ramindex == L1_D_data_RAM)
801 printk("Not implemented yet\n");
803 /* L1-D load TLB array */
804 else if(ramindex == L1_D_load_TLB_array)
806 printk("L1-D load TLB array\n");
807 for(entries = 0 ; entries < 32 ; entries++)
809 get_tlb_array((((u8)ramindex) << 24) + entries, &DL1Data0, &DL1Data1, &DL1Data2, &DL1Data3);
810 printk("entries[%d], DL1Data0=%08x, DL1Data1=%08x, DL1Data2=%08x, DL1Data3=%08x\n", entries, DL1Data0, DL1Data1, DL1Data2, DL1Data3 & 0x3f);
813 /* L1-D store TLB array */
814 else if(ramindex == L1_D_store_TLB_array)
816 printk("\nL1-D store TLB array\n");
817 for(entries = 0 ; entries < 32 ; entries++)
819 get_tlb_array((((u8)ramindex) << 24) + entries, &DL1Data0, &DL1Data1, &DL1Data2, &DL1Data3);
820 printk("entries[%d], DL1Data0=%08x, DL1Data1=%08x, DL1Data2=%08x, DL1Data3=%08x\n", entries, DL1Data0, DL1Data1, DL1Data2, DL1Data3 & 0x3f);
824 else if(ramindex == L2_tag_RAM)
826 printk("Not implemented yet\n");
829 else if(ramindex == L2_data_RAM)
831 printk("Not implemented yet\n");
833 /* L2 snoop tag RAM */
834 else if(ramindex == L2_snoop_tag_RAM)
836 printk("Not implemented yet\n");
838 /* L2 data ECC RAM */
839 else if(ramindex == L2_data_ECC_RAM)
841 printk("Not implemented yet\n");
844 else if(ramindex == L2_dirty_RAM)
846 printk("Not implemented yet\n");
849 else if(ramindex == L2_TLB_RAM)
851 printk("\nL2 TLB array\n");
852 for(ways = 0 ; ways < 4 ; ways++)
854 for(entries = 0 ; entries < 512 ; entries++)
856 get_tlb_array((ramindex << 24) + (ways << 18) + entries, &DL1Data0, &DL1Data1, &DL1Data2, &DL1Data3);
857 printk("ways[%d]:entries[%d], DL1Data0=%08x, DL1Data1=%08x, DL1Data2=%08x, DL1Data3=%08x\n", ways, entries, DL1Data0, DL1Data1, DL1Data2, DL1Data3);
862 ret += snprintf(buf+ret, PAGE_SIZE-ret, "Succeeded...\n");
864 if (ret < PAGE_SIZE - 1)
865 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
868 buf[PAGE_SIZE-2] = '\n';
869 buf[PAGE_SIZE-1] = '\0';
875 static ssize_t mali_sysfs_set_dtlb(struct device *dev,
876 struct device_attribute *attr, const char *buf, size_t count)
878 struct kbase_device *kbdev;
879 kbdev = dev_get_drvdata(dev);
884 if (sysfs_streq("L1_I_tag_RAM", buf)) {
885 ramindex = L1_I_tag_RAM;
886 } else if (sysfs_streq("L1_I_data_RAM", buf)) {
887 ramindex = L1_I_data_RAM;
888 } else if (sysfs_streq("L1_I_BTB_RAM", buf)) {
889 ramindex = L1_I_BTB_RAM;
890 } else if (sysfs_streq("L1_I_GHB_RAM", buf)) {
891 ramindex = L1_I_GHB_RAM;
892 } else if (sysfs_streq("L1_I_TLB_RAM", buf)) {
893 ramindex = L1_I_TLB_RAM;
894 } else if (sysfs_streq("L1_I_indirect_predictor_RAM", buf)) {
895 ramindex = L1_I_indirect_predictor_RAM;
896 } else if (sysfs_streq("L1_D_tag_RAM", buf)) {
897 ramindex = L1_D_tag_RAM;
898 } else if (sysfs_streq("L1_D_data_RAM", buf)) {
899 ramindex = L1_D_data_RAM;
900 } else if (sysfs_streq("L1_D_load_TLB_array", buf)) {
901 ramindex = L1_D_load_TLB_array;
902 } else if (sysfs_streq("L1_D_store_TLB_array", buf)) {
903 ramindex = L1_D_store_TLB_array;
904 } else if (sysfs_streq("L2_tag_RAM", buf)) {
905 ramindex = L2_tag_RAM;
906 } else if (sysfs_streq("L2_data_RAM", buf)) {
907 ramindex = L2_data_RAM;
908 } else if (sysfs_streq("L2_snoop_tag_RAM", buf)) {
909 ramindex = L2_snoop_tag_RAM;
910 } else if (sysfs_streq("L2_data_ECC_RAM", buf)) {
911 ramindex = L2_data_ECC_RAM;
912 } else if (sysfs_streq("L2_dirty_RAM", buf)) {
913 ramindex = L2_dirty_RAM;
914 } else if (sysfs_streq("L2_TLB_RAM", buf)) {
915 ramindex = L2_TLB_RAM;
917 printk("Invalid value....\n\n");
918 printk("Available options are one of below\n");
919 printk("L1_I_tag_RAM, L1_I_data_RAM, L1_I_BTB_RAM\n");
920 printk("L1_I_GHB_RAM, L1_I_TLB_RAM, L1_I_indirect_predictor_RAM\n");
921 printk("L1_D_tag_RAM, L1_D_data_RAM, L1_D_load_TLB_array, L1_D_store_TLB_array\n");
922 printk("L2_tag_RAM, L2_data_RAM, L2_snoop_tag_RAM, L2_data_ECC_RAM\n");
923 printk("L2_dirty_RAM, L2_TLB_RAM\n");
928 DEVICE_ATTR(dtlb, S_IRUGO|S_IWUSR, mali_sysfs_show_dtlb, mali_sysfs_set_dtlb);
930 static ssize_t mali_sysfs_show_vol(struct device *dev,
931 struct device_attribute *attr, char *buf)
933 struct kbase_device *kbdev;
937 kbdev = dev_get_drvdata(dev);
942 kbase_platform_get_voltage(dev, &vol);
943 ret += snprintf(buf+ret, PAGE_SIZE-ret, "Current operating voltage for mali t6xx = %d", vol);
945 if (ret < PAGE_SIZE - 1)
946 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
949 buf[PAGE_SIZE-2] = '\n';
950 buf[PAGE_SIZE-1] = '\0';
956 DEVICE_ATTR(vol, S_IRUGO|S_IWUSR, mali_sysfs_show_vol, NULL);
958 static int get_clkout_cmu_top(int *val)
960 *val = __raw_readl(/*EXYNOS5_CLKOUT_CMU_TOP*/EXYNOS_CLKREG(0x10A00));
961 if((*val & 0x1f) == 0xB) /* CLKOUT is ACLK_400 in CLKOUT_CMU_TOP */
967 static void set_clkout_for_3d(void)
972 tmp |= 0x1000B; /* ACLK_400 selected */
973 tmp |= 9 << 8; /* divided by (9 + 1) */
974 __raw_writel(tmp, /*EXYNOS5_CLKOUT_CMU_TOP*/EXYNOS_CLKREG(0x10A00));
976 #ifdef PMU_XCLKOUT_SET
977 exynos5_pmu_xclkout_set(1, XCLKOUT_CMU_TOP);
978 #else /* PMU_XCLKOUT_SET */
980 tmp |= 7 << 8; /* CLKOUT_CMU_TOP selected */
981 __raw_writel(tmp, /*S5P_PMU_DEBUG*/S5P_PMUREG(0x0A00));
982 #endif /* PMU_XCLKOUT_SET */
985 static ssize_t mali_sysfs_show_clkout(struct device *dev,
986 struct device_attribute *attr, char *buf)
988 struct kbase_device *kbdev;
992 kbdev = dev_get_drvdata(dev);
997 if(get_clkout_cmu_top(&val))
998 ret += snprintf(buf+ret, PAGE_SIZE-ret, "Current CLKOUT is g3d divided by 10, CLKOUT_CMU_TOP=0x%x", val);
1000 ret += snprintf(buf+ret, PAGE_SIZE-ret, "Current CLKOUT is not g3d, CLKOUT_CMU_TOP=0x%x", val);
1002 if (ret < PAGE_SIZE - 1)
1003 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
1006 buf[PAGE_SIZE-2] = '\n';
1007 buf[PAGE_SIZE-1] = '\0';
1014 static ssize_t mali_sysfs_set_clkout(struct device *dev,
1015 struct device_attribute *attr, const char *buf, size_t count)
1017 struct kbase_device *kbdev = dev_get_drvdata(dev);
1022 set_clkout_for_3d();
1023 pr_info("clkout set to 3d\n");
1026 DEVICE_ATTR(clkout, S_IRUGO|S_IWUSR, mali_sysfs_show_clkout,
1027 mali_sysfs_set_clkout);
1029 #ifdef CONFIG_T6XX_DVFS
1030 static ssize_t mali_sysfs_show_dvfs(struct device *dev,
1031 struct device_attribute *attr, char *buf)
1033 struct kbase_device *kbdev;
1036 kbdev = dev_get_drvdata(dev);
1041 if (!kbasep_pm_metrics_isactive(kbdev))
1042 ret += snprintf(buf+ret, PAGE_SIZE-ret, "G3D DVFS is off\n");
1044 ret += snprintf(buf+ret, PAGE_SIZE-ret, "G3D DVFS is on\n");
1049 static ssize_t mali_sysfs_set_dvfs(struct device *dev,
1050 struct device_attribute *attr, const char *buf, size_t count)
1053 struct kbase_device *kbdev;
1054 kbdev = dev_get_drvdata(dev);
1059 if (sysfs_streq("off", buf)) {
1060 if (kbasep_pm_metrics_isactive(kbdev)) {
1061 kbasep_pm_metrics_term(kbdev);
1062 kbase_platform_dvfs_set_level(kbdev,
1063 kbase_platform_dvfs_get_level(VITHAR_DEFAULT_CLOCK / 1000000));
1064 pr_info("G3D DVFS is disabled\n");
1066 } else if (sysfs_streq("on", buf)) {
1067 if (!kbasep_pm_metrics_isactive(kbdev)) {
1068 ret = kbasep_pm_metrics_init(kbdev);
1069 if (ret != MALI_ERROR_NONE)
1070 pr_warning("kbase_pm_metrics_init failed,"
1071 " error %u\n", ret);
1073 pr_info("G3D DVFS is enabled\n");
1076 pr_info("%s: invalid, only [on, off] is accepted\n", buf);
1081 DEVICE_ATTR(dvfs, S_IRUGO|S_IWUSR, mali_sysfs_show_dvfs, mali_sysfs_set_dvfs);
1082 #endif /* CONFIG_T6XX_DVFS */
1084 #ifdef MALI_DVFS_ASV_ENABLE
1085 static ssize_t mali_sysfs_show_asv(struct device *dev,
1086 struct device_attribute *attr, char *buf)
1089 struct kbase_device *kbdev;
1091 kbdev = dev_get_drvdata(dev);
1096 ret = kbase_platform_dvfs_sprint_avs_table(buf);
1101 static ssize_t mali_sysfs_set_asv(struct device *dev,
1102 struct device_attribute *attr, const char *buf, size_t count)
1104 if (sysfs_streq("off", buf))
1105 kbase_platform_asv_set(0);
1106 else if (sysfs_streq("on", buf))
1107 kbase_platform_asv_set(1);
1109 printk(KERN_ERR "invalid val -only [on, off] is accepted\n");
1113 DEVICE_ATTR(asv, S_IRUGO|S_IWUSR, mali_sysfs_show_asv, mali_sysfs_set_asv);
1116 static int kbase_platform_create_sysfs_file(struct device *dev)
1118 if (device_create_file(dev, &dev_attr_clock))
1120 dev_err(dev, "Couldn't create sysfs file [clock]\n");
1124 if (device_create_file(dev, &dev_attr_fbdev))
1126 dev_err(dev, "Couldn't create sysfs file [fbdev]\n");
1130 if (device_create_file(dev, &dev_attr_dtlb))
1132 dev_err(dev, "Couldn't create sysfs file [dtlb]\n");
1136 if (device_create_file(dev, &dev_attr_vol))
1138 dev_err(dev, "Couldn't create sysfs file [vol]\n");
1142 if (device_create_file(dev, &dev_attr_clkout))
1144 dev_err(dev, "Couldn't create sysfs file [clkout]\n");
1147 #ifdef CONFIG_T6XX_DVFS
1148 if (device_create_file(dev, &dev_attr_dvfs))
1150 dev_err(dev, "Couldn't create sysfs file [dvfs]\n");
1153 #ifdef MALI_DVFS_ASV_ENABLE
1154 if (device_create_file(dev, &dev_attr_asv)) {
1155 dev_err(dev, "Couldn't create sysfs file [asv]\n");
1159 #endif /* CONFIG_T6XX_DVFS */
1160 if (!mali_setup_system_tracing(dev))
1169 void kbase_platform_remove_sysfs_file(struct device *dev)
1171 device_remove_file(dev, &dev_attr_clock);
1172 device_remove_file(dev, &dev_attr_fbdev);
1173 device_remove_file(dev, &dev_attr_dtlb);
1174 device_remove_file(dev, &dev_attr_vol);
1175 device_remove_file(dev, &dev_attr_clkout);
1176 #ifdef CONFIG_T6XX_DVFS
1177 device_remove_file(dev, &dev_attr_dvfs);
1178 #ifdef MALI_DVFS_ASV_ENABLE
1179 device_remove_file(dev, &dev_attr_asv);
1181 #endif /* CONFIG_T6XX_DVFS */
1182 mali_cleanup_system_tracing(dev);
1184 #endif /* CONFIG_T6XX_DEBUG_SYS */
1186 #include "osk/include/mali_osk_lock_order.h"
1188 #ifdef CONFIG_PM_RUNTIME
1189 static void kbase_platform_runtime_term(struct kbase_device *kbdev)
1191 pm_runtime_disable(kbdev->osdev.dev);
1193 #endif /* CONFIG_PM_RUNTIME */
1195 #ifdef CONFIG_PM_RUNTIME
1196 extern void pm_runtime_init(struct device *dev);
1198 static mali_error kbase_platform_runtime_init(struct kbase_device *kbdev)
1200 pm_runtime_init(kbdev->osdev.dev);
1201 pm_suspend_ignore_children(kbdev->osdev.dev, true);
1202 pm_runtime_enable(kbdev->osdev.dev);
1203 return MALI_ERROR_NONE;
1205 #endif /* CONFIG_PM_RUNTIME */
1207 mali_error kbase_platform_init(kbase_device *kbdev)
1209 struct exynos_context *platform;
1211 platform = osk_malloc(sizeof(struct exynos_context));
1213 if(NULL == platform)
1215 return MALI_ERROR_OUT_OF_MEMORY;
1218 kbdev->platform_context = (void *) platform;
1220 platform->cmu_pmu_status = 0;
1221 spin_lock_init(&platform->cmu_pmu_lock);
1223 if(kbase_platform_power_clock_init(kbdev))
1225 goto clock_init_fail;
1228 #ifdef CONFIG_REGULATOR
1229 if(kbase_platform_regulator_init())
1231 goto regulator_init_fail;
1233 #endif /* CONFIG_REGULATOR */
1235 #ifdef CONFIG_T6XX_DVFS
1236 kbase_platform_dvfs_init(kbdev);
1237 #endif /* CONFIG_T6XX_DVFS */
1240 kbase_platform_cmu_pmu_control(kbdev, 1);
1241 return MALI_ERROR_NONE;
1243 #ifdef CONFIG_REGULATOR
1244 kbase_platform_regulator_disable();
1245 #endif /* CONFIG_REGULATOR */
1246 regulator_init_fail:
1250 return MALI_ERROR_FUNCTION_FAILED;
1253 void kbase_platform_term(kbase_device *kbdev)
1255 struct exynos_context *platform;
1257 platform = (struct exynos_context *) kbdev->platform_context;
1259 #ifdef CONFIG_T6XX_DVFS
1260 kbase_platform_dvfs_term();
1261 #endif /* CONFIG_T6XX_DVFS */
1264 kbase_platform_cmu_pmu_control(kbdev, 0);
1265 #ifdef CONFIG_REGULATOR
1266 kbase_platform_regulator_disable();
1267 #endif /* CONFIG_REGULATOR */
1268 osk_free(kbdev->platform_context);
1269 kbdev->platform_context = 0;
1273 #ifdef CONFIG_REGULATOR
1274 static struct regulator *g3d_regulator=NULL;
1275 #ifdef CONFIG_T6XX_HWVER_R0P0
1276 static int mali_gpu_vol = 1250000; /* 1.25V @ 533 MHz */
1278 static int mali_gpu_vol = 1050000; /* 1.05V @ 266 MHz */
1279 #endif /* CONFIG_T6XX_HWVER_R0P0 */
1280 #endif /* CONFIG_REGULATOR */
1282 #ifdef CONFIG_T6XX_DVFS
1284 * Weighted moving average support for signed integer data
1285 * with 7-bits of precision (not currently used; all data
1288 #define DVFS_AVG_DUMMY_MARKER (~0)
1289 #define DVFS_AVG_LPF_LEN 4 /* NB: best to be pow2 */
1290 #define DVFS_AVG_EP_MULTIPLIER (1<<7) /* 7 fractional bits */
1292 #define DVFS_AVG_RESET(x) ((x) = DVFS_AVG_DUMMY_MARKER)
1293 #define _DVFS_AVG_IN(x) ((x) * DVFS_AVG_EP_MULTIPLIER)
1294 #define _DVFS_LPF_UTIL(x, y, len) \
1295 ((x != DVFS_AVG_DUMMY_MARKER) ? \
1296 (((x) * ((len) - 1) + (y)) / (len)) : (y))
1297 #define DVFS_AVG_LPF(x, y) do { \
1298 x = _DVFS_LPF_UTIL((x), _DVFS_AVG_IN((y)), DVFS_AVG_LPF_LEN); \
1300 #define DVFS_TO_AVG(x) DIV_ROUND_CLOSEST(x, DVFS_AVG_EP_MULTIPLIER)
1302 #ifdef MALI_DVFS_ASV_ENABLE
1303 enum asv_update_val {
1304 DVFS_NOT_UPDATE_ASV_TBL = 0,
1305 DVFS_UPDATE_ASV_TBL = 1,
1306 DVFS_UPDATE_ASV_DEFAULT_TBL = 2,
1308 #endif /* MALI_DVFS_ASV_ENABLE */
1310 struct mali_dvfs_status {
1311 kbase_device *kbdev;
1315 u32 avg_utilisation;
1316 #ifdef MALI_DVFS_ASV_ENABLE
1317 enum asv_update_val asv_need_update;
1322 static struct workqueue_struct *mali_dvfs_wq = 0;
1323 int mali_dvfs_control=0;
1324 osk_spinlock_irq mali_dvfs_spinlock;
1327 static struct mali_dvfs_status mali_dvfs_status_current;
1329 * Governor parameters. The governor gets periodic samples of the
1330 * GPU utilisation (%busy) and maintains a weighted average over the
1331 * last DVFS_AVG_LPF_LEN values. When the average is in the range
1332 * [min_threshold..max_threshold] we maintain the current clock+voltage.
1333 * If the utilisation drops below min for down_cnt_threshold samples
1334 * we step down. If the utilisation exceeds max_threshold for
1335 * up_cnt_threshold samples we step up.
1337 * The up/down thresholds are chosen to enable fast step up under
1338 * load with a longer step down; this optimizes for performance over
1339 * power consumption. 266MHz is the "sweet spot"; it has the best
1340 * performance/power ratio. For this reason it has slightly extended
1341 * up/down thresholds to make it "sticky".
1343 struct mali_dvfs_info {
1344 unsigned int voltage;
1348 int up_cnt_threshold;
1349 int down_cnt_threshold;
1352 /* TODO(sleffler) round or verify time is a multiple of frequency */
1353 /* convert a time in milliseconds to a dvfs sample count */
1354 #define DVFS_TIME_TO_CNT(t) ((t) / KBASE_PM_DVFS_FREQUENCY)
1356 /* TODO(sleffler) should be const but for voltage */
1357 static struct mali_dvfs_info mali_dvfs_infotbl[MALI_DVFS_STEP] = {
1358 #if (MALI_DVFS_STEP == 7)
1359 { 912500, 100, 0, 60, DVFS_TIME_TO_CNT(750), DVFS_TIME_TO_CNT(2000)},
1360 { 925000, 160, 40, 75, DVFS_TIME_TO_CNT(750), DVFS_TIME_TO_CNT(2000)},
1361 {1025000, 266, 65, 85, DVFS_TIME_TO_CNT(1000), DVFS_TIME_TO_CNT(3000)},
1362 {1075000, 350, 65, 85, DVFS_TIME_TO_CNT(750), DVFS_TIME_TO_CNT(1500)},
1363 {1125000, 400, 65, 85, DVFS_TIME_TO_CNT(750), DVFS_TIME_TO_CNT(1500)},
1364 {1150000, 450, 65, 90, DVFS_TIME_TO_CNT(1000), DVFS_TIME_TO_CNT(1500)},
1365 {1250000, 533, 75, 100, DVFS_TIME_TO_CNT(750), DVFS_TIME_TO_CNT(1500)}
1371 #ifdef MALI_DVFS_ASV_ENABLE
1372 static const unsigned int mali_dvfs_asv_vol_tbl_special
1373 [MALI_DVFS_ASV_GROUP_SPECIAL_NUM][MALI_DVFS_STEP] = {
1374 /* 100Mh 160Mh 266Mh 350Mh 400Mh 450Mh 533Mh*/
1376 912500, 925000, 1025000, 1075000, 1100000, 1150000, 1225000,
1379 900000, 900000, 1000000, 1037500, 1087500, 1125000, 1200000,
1382 912500, 925000, 1025000, 1037500, 1100000, 1150000, 1225000,
1385 900000, 900000, 1000000, 1025000, 1087500, 1125000, 1200000,
1388 912500, 925000, 1000000, 1000000, 1125000, 1150000, 1250000,
1391 900000, 912500, 987500, 987500, 1112500, 1150000, 1237500,
1394 900000, 900000, 975000, 987500, 1100000, 1137500, 1225000,
1397 900000, 900000, 975000, 987500, 1100000, 1137500, 1225000,
1400 887500, 900000, 962500, 975000, 1087500, 1125000, 1212500,
1403 887500, 900000, 962500, 962500, 1087500, 1125000, 1212500,
1407 static const unsigned int mali_dvfs_asv_vol_tbl
1408 [MALI_DVFS_ASV_GROUP_NUM][MALI_DVFS_STEP] = {
1409 /* 100Mh 160Mh 266Mh 350Mh, 400Mh 450Mh 533Mh*/
1411 925000, 925000, 1025000, 1075000, 1125000, 1150000, 1200000,
1414 900000, 900000, 1000000, 1037500, 1087500, 1137500, 1187500,
1417 900000, 900000, 950000, 1037500, 1075000, 1125000, 1187500,
1420 900000, 900000, 950000, 1037500, 1075000, 1125000, 1187500,
1423 900000, 900000, 937500, 1025000, 1075000, 1112500, 1175000,
1426 900000, 900000, 937500, 1000000, 1050000, 1100000, 1150000,
1429 900000, 900000, 925000, 987500, 1037500, 1087500, 1137500,
1432 900000, 900000, 912500, 987500, 1025000, 1075000, 1125000,
1435 900000, 900000, 912500, 987500, 1012500, 1075000, 1125000,
1438 900000, 900000, 900000, 975000, 1012500, 1050000, 1125000,
1441 875000, 900000, 900000, 962500, 1000000, 1050000, 1112500,
1444 875000, 900000, 900000, 962500, 1000000, 1050000, 1112500,
1448 static const unsigned int mali_dvfs_vol_default[MALI_DVFS_STEP] = {
1449 925000, 925000, 1025000, 1075000, 1125000, 1150000, 120000
1452 static int mali_dvfs_update_asv(int group)
1456 /* TODO(Shariq): Replace exynos_lot_id with api call once ASV code is rebased */
1457 if (exynos_lot_id && group == 0) {
1458 /* wrong group: Use default table to keep the system running smoothly */
1459 for (i = 0; i < MALI_DVFS_STEP; i++)
1460 mali_dvfs_infotbl[i].voltage = mali_dvfs_vol_default[i];
1461 pr_err("exynos_lot_id has group 0. Using default gpu asv table\n");
1466 for (i = 0; i < MALI_DVFS_STEP; i++)
1467 mali_dvfs_infotbl[i].voltage = mali_dvfs_vol_default[i];
1468 pr_err("mali_dvfs_update_asv use default table\n");
1471 if (group > MALI_DVFS_ASV_GROUP_NUM) {
1472 /* unknown group: Use default table to keep the system running smoothly */
1473 for (i = 0; i < MALI_DVFS_STEP; i++)
1474 mali_dvfs_infotbl[i].voltage = mali_dvfs_vol_default[i];
1475 OSK_PRINT_ERROR(OSK_BASE_PM, "invalid asv group (%d)\n", group);
1478 for (i = 0; i < MALI_DVFS_STEP; i++) {
1480 mali_dvfs_infotbl[i].voltage =
1481 mali_dvfs_asv_vol_tbl_special[group-1][i];
1483 mali_dvfs_infotbl[i].voltage =
1484 mali_dvfs_asv_vol_tbl[group][i];
1489 #endif /* MALI_DVFS_ASV_ENABLE */
1491 static void mali_dvfs_event_proc(struct work_struct *w)
1493 struct mali_dvfs_status dvfs_status;
1494 const struct mali_dvfs_info *info;
1495 int avg_utilisation;
1497 osk_spinlock_irq_lock(&mali_dvfs_spinlock);
1498 dvfs_status = mali_dvfs_status_current;
1499 #ifdef MALI_DVFS_ASV_ENABLE
1500 if (dvfs_status.asv_need_update == DVFS_UPDATE_ASV_DEFAULT_TBL) {
1501 mali_dvfs_update_asv(-1);
1502 dvfs_status.asv_need_update = DVFS_NOT_UPDATE_ASV_TBL;
1503 } else if (dvfs_status.asv_need_update == DVFS_UPDATE_ASV_TBL) {
1504 if (mali_dvfs_update_asv(exynos_result_of_asv&0xf) == 0)
1505 dvfs_status.asv_group = (exynos_result_of_asv&0xf);
1506 dvfs_status.asv_need_update = DVFS_NOT_UPDATE_ASV_TBL;
1509 osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
1511 info = &mali_dvfs_infotbl[dvfs_status.step];
1513 OSK_ASSERT(dvfs_status.utilisation <= 100);
1514 dvfs_status.nsamples++;
1515 DVFS_AVG_LPF(dvfs_status.avg_utilisation, dvfs_status.utilisation);
1516 OSK_ASSERT(dvfs_status.nsamples > 0);
1517 avg_utilisation = DVFS_TO_AVG(dvfs_status.avg_utilisation);
1519 pr_debug("%s: step %d utilisation %d avg %d max %d min %d "
1520 "nsamples %u up_cnt %d down_cnt %d\n", __func__,
1521 dvfs_status.step, dvfs_status.utilisation,
1522 avg_utilisation, info->max_threshold, info->min_threshold,
1523 dvfs_status.nsamples, allow_up_cnt, allow_down_cnt);
1525 trace_mali_dvfs_event(dvfs_status.utilisation, avg_utilisation);
1527 if (avg_utilisation > info->max_threshold &&
1528 dvfs_status.nsamples >= info->up_cnt_threshold) {
1531 * NB: max clock should have max_threshold of 100
1532 * so this should never trip.
1534 OSK_ASSERT(dvfs_status.step < MALI_DVFS_STEP);
1535 DVFS_AVG_RESET(dvfs_status.avg_utilisation);
1536 dvfs_status.nsamples = 0;
1537 } else if (dvfs_status.step > 0 &&
1538 avg_utilisation < info->min_threshold &&
1539 dvfs_status.nsamples >= info->down_cnt_threshold) {
1540 OSK_ASSERT(dvfs_status.step > 0);
1542 DVFS_AVG_RESET(dvfs_status.avg_utilisation);
1543 dvfs_status.nsamples = 0;
1546 if (kbasep_pm_metrics_isactive(dvfs_status.kbdev))
1547 kbase_platform_dvfs_set_level(dvfs_status.kbdev,
1550 osk_spinlock_irq_lock(&mali_dvfs_spinlock);
1551 mali_dvfs_status_current = dvfs_status;
1552 osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
1556 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_event_proc);
1559 * Exynos5 alternative dvfs_callback imlpementation.
1561 * action = kbase_pm_get_dvfs_action(kbdev);
1563 * kbase_platform_dvfs_event(kbdev);
1566 int kbase_platform_dvfs_get_control_status(void)
1568 return mali_dvfs_control;
1571 int kbase_platform_dvfs_init(kbase_device *kbdev)
1574 add here with the right function to get initilization value.
1577 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
1579 osk_spinlock_irq_init(&mali_dvfs_spinlock, OSK_LOCK_ORDER_PM_METRICS);
1581 /*add a error handling here*/
1582 osk_spinlock_irq_lock(&mali_dvfs_spinlock);
1583 mali_dvfs_status_current.kbdev = kbdev;
1584 mali_dvfs_status_current.step = MALI_DVFS_STEP-1;
1585 mali_dvfs_status_current.utilisation = 100;
1586 DVFS_AVG_RESET(mali_dvfs_status_current.avg_utilisation);
1587 #ifdef MALI_DVFS_ASV_ENABLE
1588 mali_dvfs_status_current.asv_need_update = DVFS_UPDATE_ASV_TBL;
1589 mali_dvfs_status_current.asv_group = -1;
1591 mali_dvfs_control = 1;
1592 osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
1597 void kbase_platform_dvfs_term(void)
1600 destroy_workqueue(mali_dvfs_wq);
1602 mali_dvfs_wq = NULL;
1604 #endif /* CONFIG_T6XX_DVFS */
1607 int kbase_platform_dvfs_event(struct kbase_device *kbdev)
1609 #ifdef CONFIG_T6XX_DVFS
1610 int utilisation = kbase_pm_get_dvfs_utilisation(kbdev);
1612 osk_spinlock_irq_lock(&mali_dvfs_spinlock);
1613 mali_dvfs_status_current.utilisation = utilisation;
1614 osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
1615 queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
1617 /*add error handle here*/
1624 int kbase_platform_regulator_init(void)
1626 #ifdef CONFIG_REGULATOR
1627 g3d_regulator = regulator_get(NULL, "vdd_g3d");
1628 if(IS_ERR(g3d_regulator))
1630 printk("[kbase_platform_regulator_init] failed to get mali t6xx regulator\n");
1634 if(regulator_enable(g3d_regulator) != 0)
1636 printk("[kbase_platform_regulator_init] failed to enable mali t6xx regulator\n");
1640 if(regulator_set_voltage(g3d_regulator, mali_gpu_vol, mali_gpu_vol) != 0)
1642 printk("[kbase_platform_regulator_init] failed to set mali t6xx operating voltage [%d]\n", mali_gpu_vol);
1645 #endif /* CONFIG_REGULATOR */
1650 int kbase_platform_regulator_disable(void)
1652 #ifdef CONFIG_REGULATOR
1655 printk("[kbase_platform_regulator_disable] g3d_regulator is not initialized\n");
1659 if(regulator_disable(g3d_regulator) != 0)
1661 printk("[kbase_platform_regulator_disable] failed to disable g3d regulator\n");
1664 #endif /* CONFIG_REGULATOR */
1668 int kbase_platform_regulator_enable(void)
1670 #ifdef CONFIG_REGULATOR
1673 printk("[kbase_platform_regulator_enable] g3d_regulator is not initialized\n");
1677 if(regulator_enable(g3d_regulator) != 0)
1679 printk("[kbase_platform_regulator_enable] failed to enable g3d regulator\n");
1682 #endif /* CONFIG_REGULATOR */
1686 int kbase_platform_get_default_voltage(struct device *dev, int *vol)
1688 #ifdef CONFIG_REGULATOR
1689 *vol = mali_gpu_vol;
1690 #else /* CONFIG_REGULATOR */
1692 #endif /* CONFIG_REGULATOR */
1696 #ifdef CONFIG_T6XX_DEBUG_SYS
1697 int kbase_platform_get_voltage(struct device *dev, int *vol)
1699 #ifdef CONFIG_REGULATOR
1702 printk("[kbase_platform_get_voltage] g3d_regulator is not initialized\n");
1706 *vol = regulator_get_voltage(g3d_regulator);
1707 #else /* CONFIG_REGULATOR */
1709 #endif /* CONFIG_REGULATOR */
1712 #endif /* CONFIG_T6XX_DEBUG_SYS */
1714 #if defined CONFIG_T6XX_DEBUG_SYS || defined CONFIG_T6XX_DVFS
1715 int kbase_platform_set_voltage(struct device *dev, int vol)
1717 #ifdef CONFIG_REGULATOR
1720 printk("[kbase_platform_set_voltage] g3d_regulator is not initialized\n");
1724 if(regulator_set_voltage(g3d_regulator, vol, vol) != 0)
1726 printk("[kbase_platform_set_voltage] failed to set voltage\n");
1729 #endif /* CONFIG_REGULATOR */
1732 #endif /* CONFIG_T6XX_DEBUG_SYS */
1734 void kbase_platform_dvfs_set_clock(kbase_device *kbdev, int freq)
1736 static struct clk * mout_gpll = NULL;
1737 static struct clk * fin_gpll = NULL;
1738 static struct clk * fout_gpll = NULL;
1739 static int _freq = -1;
1740 static unsigned long gpll_rate_prev = 0;
1741 unsigned long gpll_rate = 0, aclk_400_rate = 0;
1742 unsigned long tmp = 0;
1743 struct exynos_context *platform;
1749 platform = (struct exynos_context *) kbdev->platform_context;
1750 if (NULL == platform)
1751 panic("no platform");
1753 if (platform->sclk_g3d == 0)
1756 if (mout_gpll == NULL) {
1757 mout_gpll = clk_get(kbdev->osdev.dev, "mout_gpll");
1758 fin_gpll = clk_get(kbdev->osdev.dev, "ext_xtal");
1759 fout_gpll = clk_get(kbdev->osdev.dev, "fout_gpll");
1760 if (IS_ERR(mout_gpll) || IS_ERR(fin_gpll) || IS_ERR(fout_gpll))
1761 panic("clk_get ERROR");
1767 trace_mali_dvfs_set_clock(freq);
1772 gpll_rate = 533000000;
1773 aclk_400_rate = 533000000;
1776 gpll_rate = 450000000;
1777 aclk_400_rate = 450000000;
1780 gpll_rate = 800000000;
1781 aclk_400_rate = 400000000;
1784 gpll_rate = 1400000000;
1785 aclk_400_rate = 350000000;
1788 gpll_rate = 800000000;
1789 aclk_400_rate = 267000000;
1792 gpll_rate = 800000000;
1793 aclk_400_rate = 160000000;
1796 gpll_rate = 800000000;
1797 aclk_400_rate = 100000000;
1803 /* if changed the GPLL rate, set rate for GPLL and wait for lock time */
1804 if( gpll_rate != gpll_rate_prev) {
1805 /*for stable clock input.*/
1806 clk_set_rate(platform->sclk_g3d, 100000000);
1807 clk_set_parent(mout_gpll, fin_gpll);
1810 clk_set_rate( fout_gpll, gpll_rate );
1813 clk_set_parent(mout_gpll, fout_gpll);
1814 gpll_rate_prev = gpll_rate;
1818 clk_set_rate(platform->sclk_g3d, aclk_400_rate);
1820 /* Waiting for clock is stable */
1822 tmp = __raw_readl(/*EXYNOS5_CLKDIV_STAT_TOP0*/EXYNOS_CLKREG(0x10610));
1823 } while (tmp & 0x1000000);
1824 #ifdef CONFIG_T6XX_DVFS
1826 printk("aclk400 %u[%d]\n", (unsigned int)clk_get_rate(platform->sclk_g3d),mali_dvfs_status_current.utilisation);
1827 printk("dvfs_set_clock GPLL : %lu, ACLK_400 : %luMhz\n", gpll_rate, aclk_400_rate );
1828 #endif /* MALI_DVFS_DEBUG */
1829 #endif /* CONFIG_T6XX_DVFS */
1833 static void kbase_platform_dvfs_set_vol(unsigned int vol)
1835 static int _vol = -1;
1839 trace_mali_dvfs_set_voltage(vol);
1841 kbase_platform_set_voltage(NULL, vol);
1845 printk(KERN_DEBUG "dvfs_set_vol %dmV\n", vol);
1850 int kbase_platform_dvfs_get_level(int freq)
1853 for (i = 0; i < MALI_DVFS_STEP; i++) {
1854 if (mali_dvfs_infotbl[i].clock == freq)
1860 #if defined CONFIG_T6XX_DVFS || defined CONFIG_T6XX_DEBUG_SYS
1861 void kbase_platform_dvfs_set_level(kbase_device *kbdev, int level)
1863 static int level_prev = -1;
1865 if (level == level_prev)
1867 if (WARN_ON((level >= MALI_DVFS_STEP) || (level < 0)))
1868 panic("invalid level");
1870 if (level > level_prev) {
1871 kbase_platform_dvfs_set_vol(mali_dvfs_infotbl[level].voltage);
1872 kbase_platform_dvfs_set_clock(kbdev,
1873 mali_dvfs_infotbl[level].clock);
1875 kbase_platform_dvfs_set_clock(kbdev,
1876 mali_dvfs_infotbl[level].clock);
1877 kbase_platform_dvfs_set_vol(mali_dvfs_infotbl[level].voltage);
1883 #ifdef MALI_DVFS_ASV_ENABLE
1884 static int kbase_platform_dvfs_sprint_avs_table(char *buf)
1890 cnt += sprintf(buf, "asv group:%d exynos_lot_id:%d\n",
1891 exynos_result_of_asv&0xf, exynos_lot_id);
1892 for (i = MALI_DVFS_STEP-1; i >= 0; i--) {
1893 cnt += sprintf(buf+cnt, "%dMhz:%d\n",
1894 mali_dvfs_infotbl[i].clock, mali_dvfs_infotbl[i].voltage);
1899 static int kbase_platform_asv_set(int enable)
1901 osk_spinlock_irq_lock(&mali_dvfs_spinlock);
1903 mali_dvfs_status_current.asv_need_update = DVFS_UPDATE_ASV_TBL;
1904 mali_dvfs_status_current.asv_group = -1;
1906 mali_dvfs_status_current.asv_need_update = DVFS_UPDATE_ASV_DEFAULT_TBL;
1908 osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
1911 #endif /* MALI_DVFS_ASV_ENABLE */
1914 * Exynos5 alternative dvfs_callback imlpementation.
1916 * action = kbase_pm_get_dvfs_action(kbdev);
1918 * kbase_platform_dvfs_event(kbdev);
1921 #ifdef CONFIG_T6XX_DVFS
1922 int kbase_pm_get_dvfs_utilisation(kbase_device *kbdev)
1924 unsigned long flags;
1926 ktime_t now = ktime_get();
1929 OSK_ASSERT(kbdev != NULL);
1931 spin_lock_irqsave(&kbdev->pm.metrics.lock, flags);
1933 if (kbdev->pm.metrics.gpu_active)
1935 diff = ktime_sub(now, kbdev->pm.metrics.time_period_start);
1936 kbdev->pm.metrics.time_busy += (u32)(ktime_to_ns( diff ) >> KBASE_PM_TIME_SHIFT);
1937 kbdev->pm.metrics.time_period_start = now;
1941 diff = ktime_sub(now, kbdev->pm.metrics.time_period_start);
1942 kbdev->pm.metrics.time_idle += (u32)(ktime_to_ns( diff ) >> KBASE_PM_TIME_SHIFT);
1943 kbdev->pm.metrics.time_period_start = now;
1946 if (kbdev->pm.metrics.time_idle + kbdev->pm.metrics.time_busy == 0)
1948 /* No data - so we return NOP */
1952 utilisation = (100*kbdev->pm.metrics.time_busy) / (kbdev->pm.metrics.time_idle + kbdev->pm.metrics.time_busy);
1956 kbdev->pm.metrics.time_idle = 0;
1957 kbdev->pm.metrics.time_busy = 0;
1959 spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags);
1965 #ifdef CONFIG_MALI_HWC_TRACE
1967 * Mali hardware performance counter trace support. Each counter
1968 * has a corresponding trace event. To use, enable events and write
1969 * 1 to the hwc_enable sysfs file to start polling for counter data
1970 * at vblank. An event is dispatched each time a counter's value
1971 * changes. Note system event tracing must be enabled to get the
1972 * events; otherwise the polling will not generate events. When done
1973 * turn off polling. Note also that the GPU_ACTIVE counter causes
1974 * the GPU to never be idle; this causes the governor to push the
1975 * clock to max (since it sees 100% utilization).
1977 * This code is derived from ARM's gator driver.
1979 #include <drm/drm_notifier.h>
1980 #include <kbase/src/linux/mali_linux_hwc_trace.h>
1983 * Mali hw counters by block. Note that each hw counter enable bit
1984 * covers 4 counters. There are 64 counters / block for 256 total
1987 #define MALI_HWC_TOTAL (4*64) /* total # hw counters */
1989 #define hwc_off(x) ((x) & 0x3f) /* offset in block */
1990 #define hwc_bit(x) (hwc_off(x) >> 2) /* block bm enable bit */
1992 #define BLOCK_OFF(b) ((b) << 6)
1994 /* Job Manager (Block 0) */
1995 #define BLOCK_JM_OFF BLOCK_OFF(0)
1996 #define MALI_HW_MESSAGES_SENT (BLOCK_JM_OFF + 4)
1997 #define MALI_HW_MESSAGES_RECEIVED (BLOCK_JM_OFF + 5)
1998 /* NB: if GPU_ACTIVE is enabled the GPU will stay active when idle */
1999 #define MALI_HW_GPU_ACTIVE (BLOCK_JM_OFF + 6)
2000 #define MALI_HW_IRQ_ACTIVE (BLOCK_JM_OFF + 7)
2002 #define MALI_HW_JS0_JOBS (BLOCK_JM_OFF + 8*0 + 8)
2003 #define MALI_HW_JS0_TASKS (BLOCK_JM_OFF + 8*0 + 9)
2004 #define MALI_HW_JS0_ACTIVE (BLOCK_JM_OFF + 8*0 + 10)
2005 #define MALI_HW_JS0_WAIT_READ (BLOCK_JM_OFF + 8*0 + 11)
2006 #define MALI_HW_JS0_WAIT_ISSUE (BLOCK_JM_OFF + 8*0 + 12)
2007 #define MALI_HW_JS0_WAIT_DEPEND (BLOCK_JM_OFF + 8*0 + 13)
2008 #define MALI_HW_JS0_WAIT_FINISH (BLOCK_JM_OFF + 8*0 + 14)
2010 #define MALI_HW_JS1_JOBS (BLOCK_JM_OFF + 8*1 + 8)
2011 #define MALI_HW_JS1_TASKS (BLOCK_JM_OFF + 8*1 + 9)
2012 #define MALI_HW_JS1_ACTIVE (BLOCK_JM_OFF + 8*1 + 10)
2013 #define MALI_HW_JS1_WAIT_READ (BLOCK_JM_OFF + 8*1 + 11)
2014 #define MALI_HW_JS1_WAIT_ISSUE (BLOCK_JM_OFF + 8*1 + 12)
2015 #define MALI_HW_JS1_WAIT_DEPEND (BLOCK_JM_OFF + 8*1 + 13)
2016 #define MALI_HW_JS1_WAIT_FINISH (BLOCK_JM_OFF + 8*1 + 14)
2018 #define MALI_HW_JS2_JOBS (BLOCK_JM_OFF + 8*2 + 8)
2019 #define MALI_HW_JS2_TASKS (BLOCK_JM_OFF + 8*2 + 9)
2020 #define MALI_HW_JS2_ACTIVE (BLOCK_JM_OFF + 8*2 + 10)
2021 #define MALI_HW_JS2_WAIT_READ (BLOCK_JM_OFF + 8*2 + 11)
2022 #define MALI_HW_JS2_WAIT_ISSUE (BLOCK_JM_OFF + 8*2 + 12)
2023 #define MALI_HW_JS2_WAIT_DEPEND (BLOCK_JM_OFF + 8*2 + 13)
2024 #define MALI_HW_JS2_WAIT_FINISH (BLOCK_JM_OFF + 8*2 + 14)
2026 #define MALI_HW_JS3_JOBS (BLOCK_JM_OFF + 8*3 + 8)
2027 #define MALI_HW_JS3_TASKS (BLOCK_JM_OFF + 8*3 + 9)
2028 #define MALI_HW_JS3_ACTIVE (BLOCK_JM_OFF + 8*3 + 10)
2029 #define MALI_HW_JS3_WAIT_READ (BLOCK_JM_OFF + 8*3 + 11)
2030 #define MALI_HW_JS3_WAIT_ISSUE (BLOCK_JM_OFF + 8*3 + 12)
2031 #define MALI_HW_JS3_WAIT_DEPEND (BLOCK_JM_OFF + 8*3 + 13)
2032 #define MALI_HW_JS3_WAIT_FINISH (BLOCK_JM_OFF + 8*3 + 14)
2034 #define MALI_HW_JS4_JOBS (BLOCK_JM_OFF + 8*4 + 8)
2035 #define MALI_HW_JS4_TASKS (BLOCK_JM_OFF + 8*4 + 9)
2036 #define MALI_HW_JS4_ACTIVE (BLOCK_JM_OFF + 8*4 + 10)
2037 #define MALI_HW_JS4_WAIT_READ (BLOCK_JM_OFF + 8*4 + 11)
2038 #define MALI_HW_JS4_WAIT_ISSUE (BLOCK_JM_OFF + 8*4 + 12)
2039 #define MALI_HW_JS4_WAIT_DEPEND (BLOCK_JM_OFF + 8*4 + 13)
2040 #define MALI_HW_JS4_WAIT_FINISH (BLOCK_JM_OFF + 8*4 + 14)
2042 #define MALI_HW_JS5_JOBS (BLOCK_JM_OFF + 8*5 + 8)
2043 #define MALI_HW_JS5_TASKS (BLOCK_JM_OFF + 8*5 + 9)
2044 #define MALI_HW_JS5_ACTIVE (BLOCK_JM_OFF + 8*5 + 10)
2045 #define MALI_HW_JS5_WAIT_READ (BLOCK_JM_OFF + 8*5 + 11)
2046 #define MALI_HW_JS5_WAIT_ISSUE (BLOCK_JM_OFF + 8*5 + 12)
2047 #define MALI_HW_JS5_WAIT_DEPEND (BLOCK_JM_OFF + 8*5 + 13)
2048 #define MALI_HW_JS5_WAIT_FINISH (BLOCK_JM_OFF + 8*5 + 14)
2050 #define MALI_HW_JS6_JOBS (BLOCK_JM_OFF + 8*6 + 8)
2051 #define MALI_HW_JS6_TASKS (BLOCK_JM_OFF + 8*6 + 9)
2052 #define MALI_HW_JS6_ACTIVE (BLOCK_JM_OFF + 8*6 + 10)
2053 #define MALI_HW_JS6_WAIT_READ (BLOCK_JM_OFF + 8*6 + 11)
2054 #define MALI_HW_JS6_WAIT_ISSUE (BLOCK_JM_OFF + 8*6 + 12)
2055 #define MALI_HW_JS6_WAIT_DEPEND (BLOCK_JM_OFF + 8*6 + 13)
2056 #define MALI_HW_JS6_WAIT_FINISH (BLOCK_JM_OFF + 8*6 + 14)
2058 #define MALI_HW_JM_FIRST MALI_HW_GPU_ACTIVE
2059 #define MALI_HW_JM_LAST MALI_HW_JS6_WAIT_FINISH
2061 /* Tiler (Block 1) */
2062 #define BLOCK_TILER_OFF BLOCK_OFF(1)
2063 #define MALI_HW_JOBS_PROCESSED (BLOCK_TILER_OFF + 3)
2064 #define MALI_HW_TRIANGLES (BLOCK_TILER_OFF + 4)
2065 #define MALI_HW_QUADS (BLOCK_TILER_OFF + 5)
2066 #define MALI_HW_POLYGONS (BLOCK_TILER_OFF + 6)
2067 #define MALI_HW_POINTS (BLOCK_TILER_OFF + 7)
2068 #define MALI_HW_LINES (BLOCK_TILER_OFF + 8)
2069 #define MALI_HW_VCACHE_HIT (BLOCK_TILER_OFF + 9)
2070 #define MALI_HW_VCACHE_MISS (BLOCK_TILER_OFF + 10)
2071 #define MALI_HW_FRONT_FACING (BLOCK_TILER_OFF + 11)
2072 #define MALI_HW_BACK_FACING (BLOCK_TILER_OFF + 12)
2073 #define MALI_HW_PRIM_VISIBLE (BLOCK_TILER_OFF + 13)
2074 #define MALI_HW_PRIM_CULLED (BLOCK_TILER_OFF + 14)
2075 #define MALI_HW_PRIM_CLIPPED (BLOCK_TILER_OFF + 15)
2077 #define MALI_HW_COMPRESS_IN (BLOCK_TILER_OFF + 32)
2078 #define MALI_HW_COMPRESS_OUT (BLOCK_TILER_OFF + 33)
2079 #define MALI_HW_COMPRESS_FLUSH (BLOCK_TILER_OFF + 34)
2080 #define MALI_HW_TIMESTAMPS (BLOCK_TILER_OFF + 35)
2081 #define MALI_HW_PCACHE_HIT (BLOCK_TILER_OFF + 36)
2082 #define MALI_HW_PCACHE_MISS (BLOCK_TILER_OFF + 37)
2083 #define MALI_HW_PCACHE_LINE (BLOCK_TILER_OFF + 38)
2084 #define MALI_HW_PCACHE_STALL (BLOCK_TILER_OFF + 39)
2085 #define MALI_HW_WRBUF_HIT (BLOCK_TILER_OFF + 40)
2086 #define MALI_HW_WRBUF_MISS (BLOCK_TILER_OFF + 41)
2087 #define MALI_HW_WRBUF_LINE (BLOCK_TILER_OFF + 42)
2088 #define MALI_HW_WRBUF_PARTIAL (BLOCK_TILER_OFF + 43)
2089 #define MALI_HW_WRBUF_STALL (BLOCK_TILER_OFF + 44)
2090 #define MALI_HW_ACTIVE (BLOCK_TILER_OFF + 45)
2091 #define MALI_HW_LOADING_DESC (BLOCK_TILER_OFF + 46)
2092 #define MALI_HW_INDEX_WAIT (BLOCK_TILER_OFF + 47)
2093 #define MALI_HW_INDEX_RANGE_WAIT (BLOCK_TILER_OFF + 48)
2094 #define MALI_HW_VERTEX_WAIT (BLOCK_TILER_OFF + 49)
2095 #define MALI_HW_PCACHE_WAIT (BLOCK_TILER_OFF + 50)
2096 #define MALI_HW_WRBUF_WAIT (BLOCK_TILER_OFF + 51)
2097 #define MALI_HW_BUS_READ (BLOCK_TILER_OFF + 52)
2098 #define MALI_HW_BUS_WRITE (BLOCK_TILER_OFF + 53)
2100 #define MALI_HW_TILER_UTLB_STALL (BLOCK_TILER_OFF + 59)
2101 #define MALI_HW_TILER_UTLB_REPLAY_MISS (BLOCK_TILER_OFF + 60)
2102 #define MALI_HW_TILER_UTLB_REPLAY_FULL (BLOCK_TILER_OFF + 61)
2103 #define MALI_HW_TILER_UTLB_NEW_MISS (BLOCK_TILER_OFF + 62)
2104 #define MALI_HW_TILER_UTLB_HIT (BLOCK_TILER_OFF + 63)
2106 #define MALI_HW_TILER_FIRST MALI_HW_JOBS_PROCESSED
2107 #define MALI_HW_TILER_LAST MALI_HW_TILER_UTLB_HIT
2109 /* Shader Core (Block 2) */
2110 #define BLOCK_SHADER_OFF BLOCK_OFF(2)
2111 #define MALI_HW_SHADER_CORE_ACTIVE (BLOCK_SHADER_OFF + 3)
2112 #define MALI_HW_FRAG_ACTIVE (BLOCK_SHADER_OFF + 4)
2113 #define MALI_HW_FRAG_PRIMATIVES (BLOCK_SHADER_OFF + 5)
2114 #define MALI_HW_FRAG_PRIMATIVES_DROPPED (BLOCK_SHADER_OFF + 6)
2115 #define MALI_HW_FRAG_CYCLE_DESC (BLOCK_SHADER_OFF + 7)
2116 #define MALI_HW_FRAG_CYCLES_PLR (BLOCK_SHADER_OFF + 8)
2117 #define MALI_HW_FRAG_CYCLES_VERT (BLOCK_SHADER_OFF + 9)
2118 #define MALI_HW_FRAG_CYCLES_TRISETUP (BLOCK_SHADER_OFF + 10)
2119 #define MALI_HW_FRAG_CYCLES_RAST (BLOCK_SHADER_OFF + 11)
2120 #define MALI_HW_FRAG_THREADS (BLOCK_SHADER_OFF + 12)
2121 #define MALI_HW_FRAG_DUMMY_THREADS (BLOCK_SHADER_OFF + 13)
2122 #define MALI_HW_FRAG_QUADS_RAST (BLOCK_SHADER_OFF + 14)
2123 #define MALI_HW_FRAG_QUADS_EZS_TEST (BLOCK_SHADER_OFF + 15)
2124 #define MALI_HW_FRAG_QUADS_EZS_KILLED (BLOCK_SHADER_OFF + 16)
2125 #define MALI_HW_FRAG_QUADS_LZS_TEST (BLOCK_SHADER_OFF + 17)
2126 #define MALI_HW_FRAG_QUADS_LZS_KILLED (BLOCK_SHADER_OFF + 18)
2127 #define MALI_HW_FRAG_CYCLE_NO_TILE (BLOCK_SHADER_OFF + 19)
2128 #define MALI_HW_FRAG_NUM_TILES (BLOCK_SHADER_OFF + 20)
2129 #define MALI_HW_FRAG_TRANS_ELIM (BLOCK_SHADER_OFF + 21)
2130 #define MALI_HW_COMPUTE_ACTIVE (BLOCK_SHADER_OFF + 22)
2131 #define MALI_HW_COMPUTE_TASKS (BLOCK_SHADER_OFF + 23)
2132 #define MALI_HW_COMPUTE_THREADS (BLOCK_SHADER_OFF + 24)
2133 #define MALI_HW_COMPUTE_CYCLES_DESC (BLOCK_SHADER_OFF + 25)
2134 #define MALI_HW_TRIPIPE_ACTIVE (BLOCK_SHADER_OFF + 26)
2135 #define MALI_HW_ARITH_WORDS (BLOCK_SHADER_OFF + 27)
2136 #define MALI_HW_ARITH_CYCLES_REG (BLOCK_SHADER_OFF + 28)
2137 #define MALI_HW_ARITH_CYCLES_L0 (BLOCK_SHADER_OFF + 29)
2138 #define MALI_HW_ARITH_FRAG_DEPEND (BLOCK_SHADER_OFF + 30)
2139 #define MALI_HW_LS_WORDS (BLOCK_SHADER_OFF + 31)
2140 #define MALI_HW_LS_ISSUES (BLOCK_SHADER_OFF + 32)
2141 #define MALI_HW_LS_RESTARTS (BLOCK_SHADER_OFF + 33)
2142 #define MALI_HW_LS_REISSUES_MISS (BLOCK_SHADER_OFF + 34)
2143 #define MALI_HW_LS_REISSUES_VD (BLOCK_SHADER_OFF + 35)
2144 #define MALI_HW_LS_REISSUE_ATTRIB_MISS (BLOCK_SHADER_OFF + 36)
2145 #define MALI_HW_LS_NO_WB (BLOCK_SHADER_OFF + 37)
2146 #define MALI_HW_TEX_WORDS (BLOCK_SHADER_OFF + 38)
2147 #define MALI_HW_TEX_BUBBLES (BLOCK_SHADER_OFF + 39)
2148 #define MALI_HW_TEX_WORDS_L0 (BLOCK_SHADER_OFF + 40)
2149 #define MALI_HW_TEX_WORDS_DESC (BLOCK_SHADER_OFF + 41)
2150 #define MALI_HW_TEX_THREADS (BLOCK_SHADER_OFF + 42)
2151 #define MALI_HW_TEX_RECIRC_FMISS (BLOCK_SHADER_OFF + 43)
2152 #define MALI_HW_TEX_RECIRC_DESC (BLOCK_SHADER_OFF + 44)
2153 #define MALI_HW_TEX_RECIRC_MULTI (BLOCK_SHADER_OFF + 45)
2154 #define MALI_HW_TEX_RECIRC_PMISS (BLOCK_SHADER_OFF + 46)
2155 #define MALI_HW_TEX_RECIRC_CONF (BLOCK_SHADER_OFF + 47)
2156 #define MALI_HW_LSC_READ_HITS (BLOCK_SHADER_OFF + 48)
2157 #define MALI_HW_LSC_READ_MISSES (BLOCK_SHADER_OFF + 49)
2158 #define MALI_HW_LSC_WRITE_HITS (BLOCK_SHADER_OFF + 50)
2159 #define MALI_HW_LSC_WRITE_MISSES (BLOCK_SHADER_OFF + 51)
2160 #define MALI_HW_LSC_ATOMIC_HITS (BLOCK_SHADER_OFF + 52)
2161 #define MALI_HW_LSC_ATOMIC_MISSES (BLOCK_SHADER_OFF + 53)
2162 #define MALI_HW_LSC_LINE_FETCHES (BLOCK_SHADER_OFF + 54)
2163 #define MALI_HW_LSC_DIRTY_LINE (BLOCK_SHADER_OFF + 55)
2164 #define MALI_HW_LSC_SNOOPS (BLOCK_SHADER_OFF + 56)
2165 #define MALI_HW_AXI_TLB_STALL (BLOCK_SHADER_OFF + 57)
2166 #define MALI_HW_AXI_TLB_MISS (BLOCK_SHADER_OFF + 58)
2167 #define MALI_HW_AXI_TLB_TRANSACTION (BLOCK_SHADER_OFF + 59)
2168 #define MALI_HW_LS_TLB_MISS (BLOCK_SHADER_OFF + 60)
2169 #define MALI_HW_LS_TLB_HIT (BLOCK_SHADER_OFF + 61)
2170 #define MALI_HW_AXI_BEATS_READ (BLOCK_SHADER_OFF + 62)
2171 #define MALI_HW_AXI_BEATS_WRITE (BLOCK_SHADER_OFF + 63)
2173 #define MALI_HW_SHADER_FIRST MALI_HW_SHADER_CORE_ACTIVE
2174 #define MALI_HW_SHADER_LAST MALI_HW_AXI_BEATS_WRITE
2176 /* L2 and MMU (Block 3) */
2177 #define BLOCK_MMU_OFF BLOCK_OFF(3)
2178 #define MALI_HW_MMU_TABLE_WALK (BLOCK_MMU_OFF + 4)
2179 #define MALI_HW_MMU_REPLAY_MISS (BLOCK_MMU_OFF + 5)
2180 #define MALI_HW_MMU_REPLAY_FULL (BLOCK_MMU_OFF + 6)
2181 #define MALI_HW_MMU_NEW_MISS (BLOCK_MMU_OFF + 7)
2182 #define MALI_HW_MMU_HIT (BLOCK_MMU_OFF + 8)
2184 #define MALI_HW_UTLB_STALL (BLOCK_MMU_OFF + 16)
2185 #define MALI_HW_UTLB_REPLAY_MISS (BLOCK_MMU_OFF + 17)
2186 #define MALI_HW_UTLB_REPLAY_FULL (BLOCK_MMU_OFF + 18)
2187 #define MALI_HW_UTLB_NEW_MISS (BLOCK_MMU_OFF + 19)
2188 #define MALI_HW_UTLB_HIT (BLOCK_MMU_OFF + 20)
2190 #define MALI_HW_L2_WRITE_BEATS (BLOCK_MMU_OFF + 30)
2191 #define MALI_HW_L2_READ_BEATS (BLOCK_MMU_OFF + 31)
2192 #define MALI_HW_L2_ANY_LOOKUP (BLOCK_MMU_OFF + 32)
2193 #define MALI_HW_L2_READ_LOOKUP (BLOCK_MMU_OFF + 33)
2194 #define MALI_HW_L2_SREAD_LOOKUP (BLOCK_MMU_OFF + 34)
2195 #define MALI_HW_L2_READ_REPLAY (BLOCK_MMU_OFF + 35)
2196 #define MALI_HW_L2_READ_SNOOP (BLOCK_MMU_OFF + 36)
2197 #define MALI_HW_L2_READ_HIT (BLOCK_MMU_OFF + 37)
2198 #define MALI_HW_L2_CLEAN_MISS (BLOCK_MMU_OFF + 38)
2199 #define MALI_HW_L2_WRITE_LOOKUP (BLOCK_MMU_OFF + 39)
2200 #define MALI_HW_L2_SWRITE_LOOKUP (BLOCK_MMU_OFF + 40)
2201 #define MALI_HW_L2_WRITE_REPLAY (BLOCK_MMU_OFF + 41)
2202 #define MALI_HW_L2_WRITE_SNOOP (BLOCK_MMU_OFF + 42)
2203 #define MALI_HW_L2_WRITE_HIT (BLOCK_MMU_OFF + 43)
2204 #define MALI_HW_L2_EXT_READ_FULL (BLOCK_MMU_OFF + 44)
2205 #define MALI_HW_L2_EXT_READ_HALF (BLOCK_MMU_OFF + 45)
2206 #define MALI_HW_L2_EXT_WRITE_FULL (BLOCK_MMU_OFF + 46)
2207 #define MALI_HW_L2_EXT_WRITE_HALF (BLOCK_MMU_OFF + 47)
2208 #define MALI_HW_L2_EXT_READ (BLOCK_MMU_OFF + 48)
2209 #define MALI_HW_L2_EXT_READ_LINE (BLOCK_MMU_OFF + 49)
2210 #define MALI_HW_L2_EXT_WRITE (BLOCK_MMU_OFF + 50)
2211 #define MALI_HW_L2_EXT_WRITE_LINE (BLOCK_MMU_OFF + 51)
2212 #define MALI_HW_L2_EXT_WRITE_SMALL (BLOCK_MMU_OFF + 52)
2213 #define MALI_HW_L2_EXT_BARRIER (BLOCK_MMU_OFF + 53)
2214 #define MALI_HW_L2_EXT_AR_STALL (BLOCK_MMU_OFF + 54)
2215 #define MALI_HW_L2_EXT_R_BUF_FULL (BLOCK_MMU_OFF + 55)
2216 #define MALI_HW_L2_EXT_RD_BUF_FULL (BLOCK_MMU_OFF + 56)
2217 #define MALI_HW_L2_EXT_R_RAW (BLOCK_MMU_OFF + 57)
2218 #define MALI_HW_L2_EXT_W_STALL (BLOCK_MMU_OFF + 58)
2219 #define MALI_HW_L2_EXT_W_BUF_FULL (BLOCK_MMU_OFF + 59)
2220 #define MALI_HW_L2_EXT_R_W_HAZARD (BLOCK_MMU_OFF + 60)
2221 #define MALI_HW_L2_TAG_HAZARD (BLOCK_MMU_OFF + 61)
2222 #define MALI_HW_L2_SNOOP_FULL (BLOCK_MMU_OFF + 62)
2223 #define MALI_HW_L2_REPLAY_FULL (BLOCK_MMU_OFF + 63)
2225 #define MALI_HW_MMU_FIRST MALI_HW_MMU_TABLE_WALK
2226 #define MALI_HW_MMU_LAST MALI_HW_L2_REPLAY_FULL
2229 * The amount of memory required to store a hwc dump is:
2230 * # "core groups" (1)
2231 * x # blocks (always 8 for midgard arch)
2232 * x # counters / block (always 64)
2233 * x # bytes / counter (4 for 32-bit counters)
2235 #define MALI_HWC_DUMP_SIZE (1*8*64*4)
2237 struct mali_hwcounter_state {
2238 struct workqueue_struct *wq; /* collection context */
2239 struct kbase_context *ctx; /* kbase device context */
2240 void *buf; /* counter data buffer */
2241 kbase_uk_hwcnt_setup setup; /* hwcounter setup block */
2242 bool active; /* collecting data */
2243 u32 last_read[MALI_HWC_TOTAL]; /* last counter value read */
2245 static struct mali_hwcounter_state mali_hwcs;
2246 static osk_spinlock mali_hwcounter_spinlock;
2249 * Support for mapping between hw counters and trace events.
2251 struct mali_hwcounter_trace_map {
2252 void (*do_trace)(unsigned int val); /* NB: all the same prototype */
2253 struct static_key *key;
2255 #define HWC_EVENT_MAP(event) \
2256 [MALI_HW_##event] = { \
2257 .do_trace = &trace_mali_hwc_##event, \
2258 .key = &__tracepoint_mali_hwc_##event.key \
2261 static struct mali_hwcounter_trace_map mali_hwcounter_map[256] = {
2263 HWC_EVENT_MAP(MESSAGES_SENT),
2264 HWC_EVENT_MAP(MESSAGES_RECEIVED),
2266 HWC_EVENT_MAP(GPU_ACTIVE),
2267 HWC_EVENT_MAP(IRQ_ACTIVE),
2269 HWC_EVENT_MAP(JS0_JOBS),
2270 HWC_EVENT_MAP(JS0_TASKS),
2271 HWC_EVENT_MAP(JS0_ACTIVE),
2272 HWC_EVENT_MAP(JS0_WAIT_READ),
2273 HWC_EVENT_MAP(JS0_WAIT_ISSUE),
2274 HWC_EVENT_MAP(JS0_WAIT_DEPEND),
2275 HWC_EVENT_MAP(JS0_WAIT_FINISH),
2276 HWC_EVENT_MAP(JS1_JOBS),
2277 HWC_EVENT_MAP(JS1_TASKS),
2278 HWC_EVENT_MAP(JS1_ACTIVE),
2279 HWC_EVENT_MAP(JS1_WAIT_READ),
2280 HWC_EVENT_MAP(JS1_WAIT_ISSUE),
2281 HWC_EVENT_MAP(JS1_WAIT_DEPEND),
2282 HWC_EVENT_MAP(JS1_WAIT_FINISH),
2283 HWC_EVENT_MAP(JS2_JOBS),
2284 HWC_EVENT_MAP(JS2_TASKS),
2285 HWC_EVENT_MAP(JS2_ACTIVE),
2286 HWC_EVENT_MAP(JS2_WAIT_READ),
2287 HWC_EVENT_MAP(JS2_WAIT_ISSUE),
2288 HWC_EVENT_MAP(JS2_WAIT_DEPEND),
2289 HWC_EVENT_MAP(JS2_WAIT_FINISH),
2290 HWC_EVENT_MAP(JS3_JOBS),
2291 HWC_EVENT_MAP(JS3_TASKS),
2292 HWC_EVENT_MAP(JS3_ACTIVE),
2293 HWC_EVENT_MAP(JS3_WAIT_READ),
2294 HWC_EVENT_MAP(JS3_WAIT_ISSUE),
2295 HWC_EVENT_MAP(JS3_WAIT_DEPEND),
2296 HWC_EVENT_MAP(JS3_WAIT_FINISH),
2297 HWC_EVENT_MAP(JS4_JOBS),
2298 HWC_EVENT_MAP(JS4_TASKS),
2299 HWC_EVENT_MAP(JS4_ACTIVE),
2300 HWC_EVENT_MAP(JS4_WAIT_READ),
2301 HWC_EVENT_MAP(JS4_WAIT_ISSUE),
2302 HWC_EVENT_MAP(JS4_WAIT_DEPEND),
2303 HWC_EVENT_MAP(JS4_WAIT_FINISH),
2304 HWC_EVENT_MAP(JS5_JOBS),
2305 HWC_EVENT_MAP(JS5_TASKS),
2306 HWC_EVENT_MAP(JS5_ACTIVE),
2307 HWC_EVENT_MAP(JS5_WAIT_READ),
2308 HWC_EVENT_MAP(JS5_WAIT_ISSUE),
2309 HWC_EVENT_MAP(JS5_WAIT_DEPEND),
2310 HWC_EVENT_MAP(JS5_WAIT_FINISH),
2311 HWC_EVENT_MAP(JS6_JOBS),
2312 HWC_EVENT_MAP(JS6_TASKS),
2313 HWC_EVENT_MAP(JS6_ACTIVE),
2314 HWC_EVENT_MAP(JS6_WAIT_READ),
2315 HWC_EVENT_MAP(JS6_WAIT_ISSUE),
2316 HWC_EVENT_MAP(JS6_WAIT_DEPEND),
2317 HWC_EVENT_MAP(JS6_WAIT_FINISH),
2320 HWC_EVENT_MAP(JOBS_PROCESSED),
2321 HWC_EVENT_MAP(TRIANGLES),
2322 HWC_EVENT_MAP(QUADS),
2323 HWC_EVENT_MAP(POLYGONS),
2324 HWC_EVENT_MAP(POINTS),
2325 HWC_EVENT_MAP(LINES),
2326 HWC_EVENT_MAP(VCACHE_HIT),
2327 HWC_EVENT_MAP(VCACHE_MISS),
2328 HWC_EVENT_MAP(FRONT_FACING),
2329 HWC_EVENT_MAP(BACK_FACING),
2330 HWC_EVENT_MAP(PRIM_VISIBLE),
2331 HWC_EVENT_MAP(PRIM_CULLED),
2332 HWC_EVENT_MAP(PRIM_CLIPPED),
2334 HWC_EVENT_MAP(COMPRESS_IN),
2335 HWC_EVENT_MAP(COMPRESS_OUT),
2336 HWC_EVENT_MAP(COMPRESS_FLUSH),
2337 HWC_EVENT_MAP(TIMESTAMPS),
2338 HWC_EVENT_MAP(PCACHE_HIT),
2339 HWC_EVENT_MAP(PCACHE_MISS),
2340 HWC_EVENT_MAP(PCACHE_LINE),
2341 HWC_EVENT_MAP(PCACHE_STALL),
2342 HWC_EVENT_MAP(WRBUF_HIT),
2343 HWC_EVENT_MAP(WRBUF_MISS),
2344 HWC_EVENT_MAP(WRBUF_LINE),
2345 HWC_EVENT_MAP(WRBUF_PARTIAL),
2346 HWC_EVENT_MAP(WRBUF_STALL),
2347 HWC_EVENT_MAP(ACTIVE),
2348 HWC_EVENT_MAP(LOADING_DESC),
2349 HWC_EVENT_MAP(INDEX_WAIT),
2350 HWC_EVENT_MAP(INDEX_RANGE_WAIT),
2351 HWC_EVENT_MAP(VERTEX_WAIT),
2352 HWC_EVENT_MAP(PCACHE_WAIT),
2353 HWC_EVENT_MAP(WRBUF_WAIT),
2354 HWC_EVENT_MAP(BUS_READ),
2355 HWC_EVENT_MAP(BUS_WRITE),
2357 HWC_EVENT_MAP(TILER_UTLB_STALL),
2358 HWC_EVENT_MAP(TILER_UTLB_REPLAY_MISS),
2359 HWC_EVENT_MAP(TILER_UTLB_REPLAY_FULL),
2360 HWC_EVENT_MAP(TILER_UTLB_NEW_MISS),
2361 HWC_EVENT_MAP(TILER_UTLB_HIT),
2364 HWC_EVENT_MAP(SHADER_CORE_ACTIVE),
2365 HWC_EVENT_MAP(FRAG_ACTIVE),
2366 HWC_EVENT_MAP(FRAG_PRIMATIVES),
2367 HWC_EVENT_MAP(FRAG_PRIMATIVES_DROPPED),
2368 HWC_EVENT_MAP(FRAG_CYCLE_DESC),
2369 HWC_EVENT_MAP(FRAG_CYCLES_PLR),
2370 HWC_EVENT_MAP(FRAG_CYCLES_VERT),
2371 HWC_EVENT_MAP(FRAG_CYCLES_TRISETUP),
2372 HWC_EVENT_MAP(FRAG_CYCLES_RAST),
2373 HWC_EVENT_MAP(FRAG_THREADS),
2374 HWC_EVENT_MAP(FRAG_DUMMY_THREADS),
2375 HWC_EVENT_MAP(FRAG_QUADS_RAST),
2376 HWC_EVENT_MAP(FRAG_QUADS_EZS_TEST),
2377 HWC_EVENT_MAP(FRAG_QUADS_EZS_KILLED),
2378 HWC_EVENT_MAP(FRAG_QUADS_LZS_TEST),
2379 HWC_EVENT_MAP(FRAG_QUADS_LZS_KILLED),
2380 HWC_EVENT_MAP(FRAG_CYCLE_NO_TILE),
2381 HWC_EVENT_MAP(FRAG_NUM_TILES),
2382 HWC_EVENT_MAP(FRAG_TRANS_ELIM),
2383 HWC_EVENT_MAP(COMPUTE_ACTIVE),
2384 HWC_EVENT_MAP(COMPUTE_TASKS),
2385 HWC_EVENT_MAP(COMPUTE_THREADS),
2386 HWC_EVENT_MAP(COMPUTE_CYCLES_DESC),
2387 HWC_EVENT_MAP(TRIPIPE_ACTIVE),
2388 HWC_EVENT_MAP(ARITH_WORDS),
2389 HWC_EVENT_MAP(ARITH_CYCLES_REG),
2390 HWC_EVENT_MAP(ARITH_CYCLES_L0),
2391 HWC_EVENT_MAP(ARITH_FRAG_DEPEND),
2392 HWC_EVENT_MAP(LS_WORDS),
2393 HWC_EVENT_MAP(LS_ISSUES),
2394 HWC_EVENT_MAP(LS_RESTARTS),
2395 HWC_EVENT_MAP(LS_REISSUES_MISS),
2396 HWC_EVENT_MAP(LS_REISSUES_VD),
2397 HWC_EVENT_MAP(LS_REISSUE_ATTRIB_MISS),
2398 HWC_EVENT_MAP(LS_NO_WB),
2399 HWC_EVENT_MAP(TEX_WORDS),
2400 HWC_EVENT_MAP(TEX_BUBBLES),
2401 HWC_EVENT_MAP(TEX_WORDS_L0),
2402 HWC_EVENT_MAP(TEX_WORDS_DESC),
2403 HWC_EVENT_MAP(TEX_THREADS),
2404 HWC_EVENT_MAP(TEX_RECIRC_FMISS),
2405 HWC_EVENT_MAP(TEX_RECIRC_DESC),
2406 HWC_EVENT_MAP(TEX_RECIRC_MULTI),
2407 HWC_EVENT_MAP(TEX_RECIRC_PMISS),
2408 HWC_EVENT_MAP(TEX_RECIRC_CONF),
2409 HWC_EVENT_MAP(LSC_READ_HITS),
2410 HWC_EVENT_MAP(LSC_READ_MISSES),
2411 HWC_EVENT_MAP(LSC_WRITE_HITS),
2412 HWC_EVENT_MAP(LSC_WRITE_MISSES),
2413 HWC_EVENT_MAP(LSC_ATOMIC_HITS),
2414 HWC_EVENT_MAP(LSC_ATOMIC_MISSES),
2415 HWC_EVENT_MAP(LSC_LINE_FETCHES),
2416 HWC_EVENT_MAP(LSC_DIRTY_LINE),
2417 HWC_EVENT_MAP(LSC_SNOOPS),
2418 HWC_EVENT_MAP(AXI_TLB_STALL),
2419 HWC_EVENT_MAP(AXI_TLB_MISS),
2420 HWC_EVENT_MAP(AXI_TLB_TRANSACTION),
2421 HWC_EVENT_MAP(LS_TLB_MISS),
2422 HWC_EVENT_MAP(LS_TLB_HIT),
2423 HWC_EVENT_MAP(AXI_BEATS_READ),
2424 HWC_EVENT_MAP(AXI_BEATS_WRITE),
2427 HWC_EVENT_MAP(MMU_TABLE_WALK),
2428 HWC_EVENT_MAP(MMU_REPLAY_MISS),
2429 HWC_EVENT_MAP(MMU_REPLAY_FULL),
2430 HWC_EVENT_MAP(MMU_NEW_MISS),
2431 HWC_EVENT_MAP(MMU_HIT),
2433 HWC_EVENT_MAP(UTLB_STALL),
2434 HWC_EVENT_MAP(UTLB_REPLAY_MISS),
2435 HWC_EVENT_MAP(UTLB_REPLAY_FULL),
2436 HWC_EVENT_MAP(UTLB_NEW_MISS),
2437 HWC_EVENT_MAP(UTLB_HIT),
2439 HWC_EVENT_MAP(L2_WRITE_BEATS),
2440 HWC_EVENT_MAP(L2_READ_BEATS),
2441 HWC_EVENT_MAP(L2_ANY_LOOKUP),
2442 HWC_EVENT_MAP(L2_READ_LOOKUP),
2443 HWC_EVENT_MAP(L2_SREAD_LOOKUP),
2444 HWC_EVENT_MAP(L2_READ_REPLAY),
2445 HWC_EVENT_MAP(L2_READ_SNOOP),
2446 HWC_EVENT_MAP(L2_READ_HIT),
2447 HWC_EVENT_MAP(L2_CLEAN_MISS),
2448 HWC_EVENT_MAP(L2_WRITE_LOOKUP),
2449 HWC_EVENT_MAP(L2_SWRITE_LOOKUP),
2450 HWC_EVENT_MAP(L2_WRITE_REPLAY),
2451 HWC_EVENT_MAP(L2_WRITE_SNOOP),
2452 HWC_EVENT_MAP(L2_WRITE_HIT),
2453 HWC_EVENT_MAP(L2_EXT_READ_FULL),
2454 HWC_EVENT_MAP(L2_EXT_READ_HALF),
2455 HWC_EVENT_MAP(L2_EXT_WRITE_FULL),
2456 HWC_EVENT_MAP(L2_EXT_WRITE_HALF),
2457 HWC_EVENT_MAP(L2_EXT_READ),
2458 HWC_EVENT_MAP(L2_EXT_READ_LINE),
2459 HWC_EVENT_MAP(L2_EXT_WRITE),
2460 HWC_EVENT_MAP(L2_EXT_WRITE_LINE),
2461 HWC_EVENT_MAP(L2_EXT_WRITE_SMALL),
2462 HWC_EVENT_MAP(L2_EXT_BARRIER),
2463 HWC_EVENT_MAP(L2_EXT_AR_STALL),
2464 HWC_EVENT_MAP(L2_EXT_R_BUF_FULL),
2465 HWC_EVENT_MAP(L2_EXT_RD_BUF_FULL),
2466 HWC_EVENT_MAP(L2_EXT_R_RAW),
2467 HWC_EVENT_MAP(L2_EXT_W_STALL),
2468 HWC_EVENT_MAP(L2_EXT_W_BUF_FULL),
2469 HWC_EVENT_MAP(L2_EXT_R_W_HAZARD),
2470 HWC_EVENT_MAP(L2_TAG_HAZARD),
2471 HWC_EVENT_MAP(L2_SNOOP_FULL),
2472 HWC_EVENT_MAP(L2_REPLAY_FULL),
2476 * Support for building hw counter enable bitmaps from enabled trace events.
2478 #define __BLOCK_CHECK_ENABLED(block, bm_name) do { \
2480 for (ev = block##_FIRST; ev <= block##_LAST; ev++) { \
2481 const struct mali_hwcounter_trace_map *map = \
2482 &mali_hwcounter_map[ev]; \
2483 if (map->key != NULL && static_key_false(map->key)) { \
2484 mali_hwcs.setup.bm_name |= 1<<hwc_bit(ev); \
2489 #define JM_CHECK_ENABLED() __BLOCK_CHECK_ENABLED(MALI_HW_JM, jm_bm)
2490 #define TILER_CHECK_ENABLED() __BLOCK_CHECK_ENABLED(MALI_HW_TILER, tiler_bm)
2491 #define SHADER_CHECK_ENABLED() __BLOCK_CHECK_ENABLED(MALI_HW_SHADER, shader_bm)
2492 #define MMU_CHECK_ENABLED() __BLOCK_CHECK_ENABLED(MALI_HW_MMU, mmu_l2_bm)
2495 * Support for dispatching trace events based on hw counter data.
2496 * Note we dispatch an event only when a counter changes value.
2498 static int block_update(const int boff, const int event_num)
2500 const u32 *block = ((const u32 *)((uintptr_t)mali_hwcs.buf + boff));
2501 u32 value = block[hwc_off(event_num)];
2502 if (value != mali_hwcs.last_read[event_num]) {
2503 mali_hwcs.last_read[event_num] = value;
2509 #define __BLOCK_DISPATCH_EVENTS(block, bm_name, boff) do { \
2511 for (ev = block##_FIRST; ev <= block##_LAST; ev++) { \
2512 const struct mali_hwcounter_trace_map *map = \
2513 &mali_hwcounter_map[ev]; \
2514 /* NB: each enable bit covers 4 counters */ \
2515 if ((mali_hwcs.setup.bm_name & (1<<hwc_bit(ev))) && \
2516 map->key != NULL && static_key_false(map->key) && \
2517 block_update(boff, ev)) \
2518 map->do_trace(mali_hwcs.last_read[ev]); \
2521 #define JM_DISPATCH_EVENTS() \
2522 __BLOCK_DISPATCH_EVENTS(MALI_HW_JM, jm_bm, 0x700)
2523 #define TILER_DISPATCH_EVENTS() \
2524 __BLOCK_DISPATCH_EVENTS(MALI_HW_TILER, tiler_bm, 0x400)
2525 #define MMU_DISPATCH_EVENTS() \
2526 __BLOCK_DISPATCH_EVENTS(MALI_HW_MMU, mmu_l2_bm, 0x500)
2528 static int shader_block_update(const int event_num)
2530 const u32 *block = ((const u32 *)((uintptr_t)mali_hwcs.buf + 0x000));
2531 u32 value = block[hwc_off(event_num)]
2532 + block[hwc_off(event_num) + 0x100]
2533 + block[hwc_off(event_num) + 0x200]
2534 + block[hwc_off(event_num) + 0x300]
2536 if (value != mali_hwcs.last_read[event_num]) {
2537 mali_hwcs.last_read[event_num] = value;
2543 #define SHADER_DISPATCH_EVENTS() do { \
2545 for (ev = MALI_HW_SHADER_FIRST; ev <= MALI_HW_SHADER_LAST; ev++) {\
2546 const struct mali_hwcounter_trace_map *map = \
2547 &mali_hwcounter_map[ev]; \
2548 /* NB: each enable bit covers 4 counters */ \
2549 if ((mali_hwcs.setup.shader_bm & (1<<hwc_bit(ev))) && \
2550 map->key != NULL && static_key_false(map->key) && \
2551 shader_block_update(ev)) \
2552 map->do_trace(mali_hwcs.last_read[ev]); \
2557 * Collect hw counter data and dispatch trace events.
2558 * This runs from the workqueue so it can block when
2559 * fetching hw counter data.
2561 static void mali_hwcounter_collect(struct work_struct *w)
2565 osk_spinlock_lock(&mali_hwcounter_spinlock);
2566 if (!mali_hwcs.active) {
2567 osk_spinlock_unlock(&mali_hwcounter_spinlock);
2570 error = kbase_instr_hwcnt_dump(mali_hwcs.ctx);
2571 osk_spinlock_unlock(&mali_hwcounter_spinlock);
2572 if (error == MALI_ERROR_NONE) {
2573 /* extract data and generate trace events */
2574 JM_DISPATCH_EVENTS();
2575 TILER_DISPATCH_EVENTS();
2576 SHADER_DISPATCH_EVENTS();
2577 MMU_DISPATCH_EVENTS();
2579 pr_err("%s: failed to dump hw counters\n", __func__);
2581 static DECLARE_WORK(mali_hwcounter_work, mali_hwcounter_collect);
2584 * drm vblank notifier; used to trigger hw counter polling.
2586 static int mali_hwcounter_vblank(struct notifier_block *nb,
2587 unsigned long unused, void *data)
2589 /* punt to work queue where we can block */
2590 queue_work_on(0, mali_hwcs.wq, &mali_hwcounter_work);
2593 static struct notifier_block mali_vblank_notifier = {
2594 .notifier_call = mali_hwcounter_vblank,
2598 * Start hw counter polling. Construct the counter enable bitmaps
2599 * based on the enabled trace events, call kbase to turn on counters,
2600 * and arrange polling at vblank.
2602 static int mali_hwcounter_polling_start(struct kbase_device *kbdev)
2606 if (mali_hwcs.active)
2609 /* Construct hw counter bitmaps from enabled trace events */
2610 memset(&mali_hwcs.setup, 0, sizeof(mali_hwcs.setup));
2613 TILER_CHECK_ENABLED();
2614 SHADER_CHECK_ENABLED();
2615 MMU_CHECK_ENABLED();
2617 if (ncounters > 0) {
2620 mali_hwcs.ctx = kbase_create_context(kbdev);
2621 if (mali_hwcs.ctx == NULL) {
2622 pr_err("%s: cannot create context\n", __func__);
2625 mali_hwcs.buf = kbase_va_alloc(mali_hwcs.ctx,
2626 MALI_HWC_DUMP_SIZE);
2627 mali_hwcs.setup.dump_buffer = (uintptr_t) mali_hwcs.buf;
2629 error = kbase_instr_hwcnt_enable(mali_hwcs.ctx,
2631 if (error != MALI_ERROR_NONE) {
2632 pr_err("%s: cannot enable hw counters\n", __func__);
2634 kbase_va_free(mali_hwcs.ctx, mali_hwcs.buf);
2635 mali_hwcs.buf = NULL;
2637 kbase_destroy_context(mali_hwcs.ctx);
2638 mali_hwcs.ctx = NULL;
2640 return -EIO;/*TODO make unique*/
2642 kbase_instr_hwcnt_clear(mali_hwcs.ctx);
2643 mali_hwcs.active = true;
2644 /* NB: use 0 to minimize meaningless events */
2645 memset(mali_hwcs.last_read, 0, sizeof(mali_hwcs.last_read));
2647 drm_vblank_register_notifier(&mali_vblank_notifier);
2653 * Stop hw counter polling. Disable polling, turn off hw counters,
2654 * and release our resources.
2656 static void mali_hwcounter_polling_stop(struct kbase_device *kbdev)
2658 osk_spinlock_lock(&mali_hwcounter_spinlock);
2659 if (mali_hwcs.active) {
2660 drm_vblank_unregister_notifier(&mali_vblank_notifier);
2662 kbase_instr_hwcnt_disable(mali_hwcs.ctx);
2664 kbase_va_free(mali_hwcs.ctx, mali_hwcs.buf);
2665 mali_hwcs.buf = NULL;
2667 kbase_destroy_context(mali_hwcs.ctx);
2668 mali_hwcs.ctx = NULL;
2670 mali_hwcs.active = false;
2672 osk_spinlock_unlock(&mali_hwcounter_spinlock);
2675 static ssize_t mali_sysfs_show_hwc_enable(struct device *dev,
2676 struct device_attribute *attr, char *buf)
2678 return snprintf(buf, PAGE_SIZE, "%d\n", (mali_hwcs.active == true));
2681 static ssize_t mali_sysfs_set_hwc_enable(struct device *dev,
2682 struct device_attribute *attr, const char *buf, size_t count)
2684 struct kbase_device *kbdev = dev_get_drvdata(dev);
2688 if (strtobool(buf, &enable) < 0)
2691 error = mali_hwcounter_polling_start(kbdev);
2695 mali_hwcounter_polling_stop(kbdev);
2698 DEVICE_ATTR(hwc_enable, S_IRUGO|S_IWUSR, mali_sysfs_show_hwc_enable,
2699 mali_sysfs_set_hwc_enable);
2701 static int mali_setup_system_tracing(struct device *dev)
2703 osk_spinlock_init(&mali_hwcounter_spinlock, OSK_LOCK_ORDER_PM_METRICS);
2704 mali_hwcs.wq = create_singlethread_workqueue("mali_hwc");
2705 mali_hwcs.active = false;
2707 if (device_create_file(dev, &dev_attr_hwc_enable)) {
2708 dev_err(dev, "Couldn't create sysfs file [hwc_enable]\n");
2714 static void mali_cleanup_system_tracing(struct device *dev)
2716 struct kbase_device *kbdev = dev_get_drvdata(dev);
2718 mali_hwcounter_polling_stop(kbdev);
2719 destroy_workqueue(mali_hwcs.wq);
2720 device_remove_file(dev, &dev_attr_hwc_enable);
2722 #else /* CONFIG_MALI_HWC_TRACE */
2723 static int mali_setup_system_tracing(struct device *dev)
2728 static void mali_cleanup_system_tracing(struct device *dev)
2731 #endif /* CONFIG_MALI_HWC_TRACE */