Initial commit
[kernel/linux-3.0.git] / drivers / gpu / vithar_rev0 / kbase / src / platform / mali_kbase_runtime_pm.c
1 /* drivers/gpu/vithar/kbase/src/platform/mali_kbase_runtime_pm.c
2  *
3  * Copyright 2011 by S.LSI. Samsung Electronics Inc.
4  * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea
5  *
6  * Samsung SoC Mali-T604 runtime pm driver
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software FoundatIon.
11  */
12
13 /**
14  * @file mali_kbase_runtime_pm.c
15  * Runtime PM
16  */
17
18 #include <osk/mali_osk.h>
19 #include <kbase/src/common/mali_kbase.h>
20 #include <kbase/src/common/mali_kbase_uku.h>
21 #include <kbase/src/common/mali_kbase_mem.h>
22 #include <kbase/src/common/mali_midg_regmap.h>
23 #include <kbase/src/linux/mali_kbase_mem_linux.h>
24 #include <uk/mali_ukk.h>
25
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/poll.h>
29 #include <linux/kernel.h>
30 #include <linux/errno.h>
31 #include <linux/platform_device.h>
32 #include <linux/pci.h>
33 #include <linux/miscdevice.h>
34 #include <linux/list.h>
35 #include <linux/semaphore.h>
36 #include <linux/fs.h>
37 #include <linux/uaccess.h>
38 #include <linux/interrupt.h>
39 #include <linux/io.h>
40 #include <linux/timer.h>
41 #include <kbase/src/platform/mali_kbase_platform.h>
42 #include <kbase/src/platform/mali_kbase_runtime_pm.h>
43 #include <linux/pm_runtime.h>
44 #include <linux/workqueue.h>
45
46 /** Indicator to use suspended power off scheme.
47  *
48  * if SUSPENDED_OFF is defined, power gating to mali-t604 is RUNTIME_PM_RUNTIME_DELAY_TIME delayed.
49  */
50 #define SUSPENDED_OFF
51 #define RUNTIME_PM_DELAY_TIME 10
52 static void kbase_device_runtime_workqueue_callback(struct work_struct *work)
53 {
54 #ifdef SUSPENDED_OFF
55         struct kbase_device *kbdev;
56         kbdev = container_of(work, struct kbase_device, runtime_pm_workqueue.work);
57
58         kbase_pm_wait_for_power_down(kbdev);
59         kbase_platform_cmu_pmu_control(kbdev->osdev.dev, 0);
60 #endif
61 }
62
63 void kbase_device_runtime_init_workqueue(struct device *dev)
64 {
65 #ifdef SUSPENDED_OFF
66         struct kbase_device *kbdev;
67         kbdev = dev_get_drvdata(dev);
68         INIT_DELAYED_WORK(&kbdev->runtime_pm_workqueue, kbase_device_runtime_workqueue_callback);
69 #endif
70 }
71
72 /** Suspend callback from the OS.
73  *
74  * This is called by Linux runtime PM when the device should suspend.
75  *
76  * @param dev   The device to suspend
77  *
78  * @return A standard Linux error code
79  */
80 int kbase_device_runtime_suspend(struct device *dev)
81 {
82 #ifdef SUSPENDED_OFF
83         struct kbase_device *kbdev;
84         kbdev = dev_get_drvdata(dev);
85
86         if(delayed_work_pending(&kbdev->runtime_pm_workqueue)) {
87                 cancel_delayed_work_sync(&kbdev->runtime_pm_workqueue);
88         }
89         schedule_delayed_work(&kbdev->runtime_pm_workqueue, RUNTIME_PM_DELAY_TIME);
90         return 0;
91 #else
92         return kbase_platform_cmu_pmu_control(dev, 0);
93 #endif
94 }
95
96 /** Resume callback from the OS.
97  *
98  * This is called by Linux runtime PM when the device should resume from suspension.
99  *
100  * @param dev   The device to resume
101  *
102  * @return A standard Linux error code
103  */
104 int kbase_device_runtime_resume(struct device *dev)
105 {
106 #ifdef SUSPENDED_OFF
107         struct kbase_device *kbdev;
108         kbdev = dev_get_drvdata(dev);
109
110         if(delayed_work_pending(&kbdev->runtime_pm_workqueue)) {
111                 cancel_delayed_work_sync(&kbdev->runtime_pm_workqueue);
112         }
113 #endif
114         return kbase_platform_cmu_pmu_control(dev, 1);
115 }
116
117 /** Disable runtime pm
118  *
119  * @param dev   The device to enable rpm
120  *
121  * @return A standard Linux error code
122  */
123 void kbase_device_runtime_disable(struct device *dev)
124 {
125     pm_runtime_disable(dev);
126 }
127
128 /** Initialize runtiem pm fields in given device 
129  *
130  * @param dev   The device to initialize
131  *
132  * @return A standard Linux error code
133  */
134 static void kbase_device_runtime_init(struct device *dev)
135 {
136         pm_suspend_ignore_children(dev, true);
137         pm_runtime_enable(dev);
138 }
139
140 static int rp_started = 1;
141 void kbase_device_runtime_get_sync(struct device *dev)
142 {
143         int result;
144
145         if(rp_started) {
146                 kbase_device_runtime_init(dev);
147                 rp_started = 0;
148         }
149
150         result = pm_runtime_get_sync(dev);
151         //OSK_PRINT_ERROR(OSK_BASE_PM, "get_sync, usage_count=%d  \n", atomic_read(&dev->power.usage_count));
152         if(result < 0)
153                 OSK_PRINT_ERROR(OSK_BASE_PM, "pm_runtime_get_sync failed (%d)\n", result);
154 }
155
156 void kbase_device_runtime_put_sync(struct device *dev)
157 {
158         int result;
159
160         if(rp_started) {
161                 return;
162         }
163
164         result = pm_runtime_put_sync(dev);
165         //OSK_PRINT_ERROR(OSK_BASE_PM, "put_sync, usage_count=%d  \n", atomic_read(&dev->power.usage_count));
166         if(result < 0)
167                 OSK_PRINT_ERROR(OSK_BASE_PM, "pm_runtime_put_sync failed (%d)\n", result);
168 }