import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_spm.c
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/spinlock.h>
5 #include <linux/interrupt.h>
6 #include <linux/delay.h>
7
8 #include <mach/irqs.h>
9 #include <mach/mt_spm.h>
10 #include <mach/wd_api.h>
11
12 /**********************************************************
13 * PCM code for normal (v2 @ 2013-04-26)
14 **********************************************************/
15 static const u32 __pcm_normal[] = {
16 0x1840001f, 0x00000001, 0x1b00001f, 0x00202000, 0x1b80001f, 0x80001000,
17 0x8880000c, 0x00200000, 0xd80001e2, 0x17c07c1f, 0xe8208000, 0x100063e0,
18 0x00000002, 0x1b80001f, 0x00001000, 0x809c840d, 0xd8200042, 0x17c07c1f,
19 0xa1d78407, 0x1890001f, 0x10006014, 0x18c0001f, 0x10006014, 0xa0978402,
20 0xe0c00002, 0x1b80001f, 0x00001000, 0xf0000000
21 };
22 static const pcm_desc_t pcm_normal = {
23 .base = __pcm_normal,
24 .size = 28,
25 .sess = 1,
26 };
27
28
29 /**************************************
30 * SW code for general and normal
31 **************************************/
32 #define WAKE_SRC_FOR_NORMAL (WAKE_SRC_THERM)
33
34 DEFINE_SPINLOCK(spm_lock);
35
36 static twam_handler_t spm_twam_handler = NULL;
37
38 void spm_go_to_normal(void)
39 {
40 unsigned long flags;
41
42 spin_lock_irqsave(&spm_lock, flags);
43 /* reset PCM */
44 spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
45 spm_write(SPM_PCM_CON0, CON0_CFG_KEY);
46
47 /* init PCM_CON1 (disable non-replace mode) */
48 spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_SPM_SRAM_ISO_B |
49 CON1_SPM_SRAM_SLP_B | CON1_MIF_APBEN);
50
51 /* tell IM where is PCM code */
52 spm_write(SPM_PCM_IM_PTR, spm_get_base_phys(pcm_normal.base));
53 spm_write(SPM_PCM_IM_LEN, pcm_normal.size - 1);
54
55 /* unmask wakeup source */
56 spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, ~WAKE_SRC_FOR_NORMAL);
57
58 /* kick IM and PCM to run */
59 spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_KICK | CON0_PCM_KICK);
60 spm_write(SPM_PCM_CON0, CON0_CFG_KEY);
61 spin_unlock_irqrestore(&spm_lock, flags);
62 }
63
64 static irqreturn_t spm_irq_handler(int irq, void *dev_id)
65 {
66 u32 isr;
67 twam_sig_t twamsig;
68
69 spin_lock(&spm_lock);
70 /* get ISR status */
71 isr = spm_read(SPM_SLEEP_ISR_STATUS);
72 if (isr & ISR_TWAM) {
73 twamsig.sig0 = spm_read(SPM_SLEEP_TWAM_STATUS0);
74 twamsig.sig1 = spm_read(SPM_SLEEP_TWAM_STATUS1);
75 twamsig.sig2 = spm_read(SPM_SLEEP_TWAM_STATUS2);
76 twamsig.sig3 = spm_read(SPM_SLEEP_TWAM_STATUS3);
77 }
78
79 /* clean ISR status */
80 spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) | ISRM_ALL_EXC_TWAM);
81 spm_write(SPM_SLEEP_ISR_STATUS, isr);
82 if (isr & ISR_TWAM)
83 udelay(100); /* need 3T TWAM clock */
84 spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT0);
85 spin_unlock(&spm_lock);
86
87 if (isr == ISR_TWAM && spm_twam_handler)
88 spm_twam_handler(&twamsig);
89 else
90 spm_error("ISR SHOULD NOT BE EXECUTED (0x%x)\n", isr);
91
92 return IRQ_HANDLED;
93 }
94
95 void spm_module_init(void)
96 {
97 int r;
98 unsigned long flags;
99 struct wd_api *wd_api;
100
101 spin_lock_irqsave(&spm_lock, flags);
102 /* enable register control */
103 spm_write(SPM_POWERON_CONFIG_SET, (SPM_PROJECT_CODE << 16) | (1U << 0));
104
105 /* init power control register (select PCM clock to 26M) */
106 spm_write(SPM_POWER_ON_VAL0, 0);
107 spm_write(SPM_POWER_ON_VAL1, 0x00015820);
108 spm_write(SPM_PCM_PWR_IO_EN, 0);
109
110 /* reset PCM */
111 spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
112 spm_write(SPM_PCM_CON0, CON0_CFG_KEY);
113
114 /* init PCM control register */
115 spm_write(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);
116 spm_write(SPM_PCM_CON1, CON1_CFG_KEY | CON1_SPM_SRAM_ISO_B |
117 CON1_SPM_SRAM_SLP_B | CON1_IM_NONRP_EN | CON1_MIF_APBEN);
118 spm_write(SPM_PCM_IM_PTR, 0);
119 spm_write(SPM_PCM_IM_LEN, 0);
120
121 /* SRCLKENA: POWER_ON_VAL1 (PWR_IO_EN[7]=0) or POWER_ON_VAL1|r7 (PWR_IO_EN[7]=1) */
122 /* CLKSQ: POWER_ON_VAL0 (PWR_IO_EN[0]=0) or r0 (PWR_IO_EN[0]=1) */
123 /* SRCLKENAI will trigger 26M-wake/sleep event */
124 spm_write(SPM_CLK_CON, CC_CXO32K_RM_EN_MD);
125 spm_write(SPM_PCM_SRC_REQ, (1U << 1));
126
127 /* clean wakeup event raw status */
128 spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK, 0xffffffff);
129
130 /* clean ISR status */
131 spm_write(SPM_SLEEP_ISR_MASK, ISRM_ALL);
132 spm_write(SPM_SLEEP_ISR_STATUS, ISRC_ALL);
133 spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT_ALL);
134 spin_unlock_irqrestore(&spm_lock, flags);
135
136 r = request_irq(MT_SPM_IRQ_ID, spm_irq_handler, IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND,
137 "mt-spm", NULL);
138 if (r) {
139 spm_error("FAILED TO REQUEST SPM IRQ (%d)\n", r);
140 WARN_ON(1);
141 }
142
143 get_wd_api(&wd_api);
144 if (wd_api->wd_spmwdt_mode_config && wd_api->wd_thermal_mode_config) {
145 wd_api->wd_spmwdt_mode_config(WD_REQ_EN, WD_REQ_RST_MODE);
146 wd_api->wd_thermal_mode_config(WD_REQ_EN, WD_REQ_RST_MODE);
147 } else {
148 spm_error("FAILED TO GET WD API\n");
149 WARN_ON(1);
150 }
151
152 spm_go_to_normal(); /* let PCM help to do thermal protection */
153 }
154
155
156 /**************************************
157 * for TWAM to integrate with MET
158 **************************************/
159 void spm_twam_register_handler(twam_handler_t handler)
160 {
161 spm_twam_handler = handler;
162 }
163 EXPORT_SYMBOL(spm_twam_register_handler);
164
165 void spm_twam_enable_monitor(twam_sig_t *twamsig, bool speed_mode)
166 {
167 u32 con = TWAM_CON_EN;
168 unsigned long flags;
169
170 if (speed_mode)
171 con |= TWAM_CON_SPEED_EN;
172
173 if (twamsig) {
174 con |= (twamsig->sig0 & 0xf) << 16;
175 con |= (twamsig->sig1 & 0xf) << 20;
176 con |= (twamsig->sig2 & 0xf) << 24;
177 con |= (twamsig->sig3 & 0xf) << 28;
178 }
179
180 spin_lock_irqsave(&spm_lock, flags);
181 spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) & ~ISR_TWAM);
182 spm_write(SPM_SLEEP_TWAM_CON, con);
183 spin_unlock_irqrestore(&spm_lock, flags);
184 }
185 EXPORT_SYMBOL(spm_twam_enable_monitor);
186
187 void spm_twam_disable_monitor(void)
188 {
189 unsigned long flags;
190
191 spin_lock_irqsave(&spm_lock, flags);
192 spm_write(SPM_SLEEP_TWAM_CON, spm_read(SPM_SLEEP_TWAM_CON) & ~TWAM_CON_EN);
193 spm_write(SPM_SLEEP_ISR_MASK, spm_read(SPM_SLEEP_ISR_MASK) | ISR_TWAM);
194 spm_write(SPM_SLEEP_ISR_STATUS, ISR_TWAM);
195 spin_unlock_irqrestore(&spm_lock, flags);
196 }
197 EXPORT_SYMBOL(spm_twam_disable_monitor);
198
199
200 /**************************************
201 * for PCM WDT to replace RGU WDT
202 **************************************/
203 int spm_wdt_register_fiq(fiq_isr_handler rgu_wdt_handler)
204 {
205 int r;
206
207 #ifdef CONFIG_FIQ_GLUE
208 r = request_fiq(MT_SPM1_IRQ_ID, rgu_wdt_handler, IRQF_TRIGGER_FALLING, NULL);
209 #else
210 r = -EPERM;
211 #endif
212
213 return r;
214 }
215
216 int spm_wdt_register_irq(irq_handler_t rgu_wdt_handler)
217 {
218 int r;
219
220 r = request_irq(MT_SPM1_IRQ_ID, rgu_wdt_handler, IRQF_TRIGGER_FALLING,
221 "mt-spm1", NULL);
222
223 return r;
224 }
225
226 void spm_wdt_set_timeout(u32 sec)
227 {
228 unsigned long flags;
229
230 spin_lock_irqsave(&spm_lock, flags);
231 BUG_ON(sec > 36 * 3600);
232 spm_write(SPM_PCM_WDT_TIMER_VAL, sec * 32768);
233 spin_unlock_irqrestore(&spm_lock, flags);
234 }
235
236 void spm_wdt_enable_timer(void)
237 {
238 unsigned long flags;
239
240 spin_lock_irqsave(&spm_lock, flags);
241 spm_write(SPM_PCM_CON1, spm_read(SPM_PCM_CON1) | CON1_CFG_KEY |
242 CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
243 spin_unlock_irqrestore(&spm_lock, flags);
244 }
245
246 void spm_wdt_restart_timer(void)
247 {
248 unsigned long flags;
249
250 spin_lock_irqsave(&spm_lock, flags);
251 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) | R7_WDT_KICK_P);
252 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) & ~R7_WDT_KICK_P);
253 spin_unlock_irqrestore(&spm_lock, flags);
254 }
255
256 void spm_wdt_restart_timer_nolock(void)
257 {
258 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) | R7_WDT_KICK_P);
259 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) & ~R7_WDT_KICK_P);
260 }
261
262 void spm_wdt_disable_timer(void)
263 {
264 unsigned long flags;
265
266 spin_lock_irqsave(&spm_lock, flags);
267 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) | R7_WDT_KICK_P);
268 spm_write(SPM_POWER_ON_VAL1, spm_read(SPM_POWER_ON_VAL1) & ~R7_WDT_KICK_P);
269
270 spm_write(SPM_PCM_CON1, CON1_CFG_KEY | (spm_read(SPM_PCM_CON1) & ~CON1_PCM_WDT_EN));
271 spm_write(SPM_PCM_SW_INT_CLEAR, PCM_SW_INT1);
272 spin_unlock_irqrestore(&spm_lock, flags);
273 }
274
275
276 /**************************************
277 * for CPU DVFS
278 **************************************/
279 #define MAX_RETRY_COUNT (100)
280
281 int spm_dvfs_ctrl_volt(u32 value)
282 {
283 u32 ap_dvfs_con;
284 int retry = 0;
285
286 #ifdef MTK_ALPS_BOX_SUPPORT
287 return 0;
288 #endif
289 ap_dvfs_con = spm_read(SPM_AP_DVFS_CON_SET);
290 spm_write(SPM_AP_DVFS_CON_SET, (ap_dvfs_con & ~(0x7)) | value);
291 udelay(5);
292
293 while ((spm_read(SPM_AP_DVFS_CON_SET) & (0x1 << 31)) == 0)
294 {
295 if (retry >= MAX_RETRY_COUNT)
296 {
297 printk("FAIL: no response from PMIC wrapper\n");
298 return -1;
299 }
300
301 retry++;
302 printk("wait for ACK signal from PMIC wrapper, retry = %d\n", retry);
303
304 udelay(5);
305 }
306
307 return 0;
308 }
309
310 MODULE_DESCRIPTION("SPM Driver v0.6");