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>
9 #include <mach/mt_spm.h>
10 #include <mach/wd_api.h>
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
22 static const pcm_desc_t pcm_normal
= {
29 /**************************************
30 * SW code for general and normal
31 **************************************/
32 #define WAKE_SRC_FOR_NORMAL (WAKE_SRC_THERM)
34 DEFINE_SPINLOCK(spm_lock
);
36 static twam_handler_t spm_twam_handler
= NULL
;
38 void spm_go_to_normal(void)
42 spin_lock_irqsave(&spm_lock
, flags
);
44 spm_write(SPM_PCM_CON0
, CON0_CFG_KEY
| CON0_PCM_SW_RESET
);
45 spm_write(SPM_PCM_CON0
, CON0_CFG_KEY
);
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
);
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);
55 /* unmask wakeup source */
56 spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK
, ~WAKE_SRC_FOR_NORMAL
);
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
);
64 static irqreturn_t
spm_irq_handler(int irq
, void *dev_id
)
71 isr
= spm_read(SPM_SLEEP_ISR_STATUS
);
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
);
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
);
83 udelay(100); /* need 3T TWAM clock */
84 spm_write(SPM_PCM_SW_INT_CLEAR
, PCM_SW_INT0
);
85 spin_unlock(&spm_lock
);
87 if (isr
== ISR_TWAM
&& spm_twam_handler
)
88 spm_twam_handler(&twamsig
);
90 spm_error("ISR SHOULD NOT BE EXECUTED (0x%x)\n", isr
);
95 void spm_module_init(void)
99 struct wd_api
*wd_api
;
101 spin_lock_irqsave(&spm_lock
, flags
);
102 /* enable register control */
103 spm_write(SPM_POWERON_CONFIG_SET
, (SPM_PROJECT_CODE
<< 16) | (1U << 0));
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);
111 spm_write(SPM_PCM_CON0
, CON0_CFG_KEY
| CON0_PCM_SW_RESET
);
112 spm_write(SPM_PCM_CON0
, CON0_CFG_KEY
);
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);
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));
127 /* clean wakeup event raw status */
128 spm_write(SPM_SLEEP_WAKEUP_EVENT_MASK
, 0xffffffff);
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
);
136 r
= request_irq(MT_SPM_IRQ_ID
, spm_irq_handler
, IRQF_TRIGGER_LOW
| IRQF_NO_SUSPEND
,
139 spm_error("FAILED TO REQUEST SPM IRQ (%d)\n", r
);
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
);
148 spm_error("FAILED TO GET WD API\n");
152 spm_go_to_normal(); /* let PCM help to do thermal protection */
156 /**************************************
157 * for TWAM to integrate with MET
158 **************************************/
159 void spm_twam_register_handler(twam_handler_t handler
)
161 spm_twam_handler
= handler
;
163 EXPORT_SYMBOL(spm_twam_register_handler
);
165 void spm_twam_enable_monitor(twam_sig_t
*twamsig
, bool speed_mode
)
167 u32 con
= TWAM_CON_EN
;
171 con
|= TWAM_CON_SPEED_EN
;
174 con
|= (twamsig
->sig0
& 0xf) << 16;
175 con
|= (twamsig
->sig1
& 0xf) << 20;
176 con
|= (twamsig
->sig2
& 0xf) << 24;
177 con
|= (twamsig
->sig3
& 0xf) << 28;
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
);
185 EXPORT_SYMBOL(spm_twam_enable_monitor
);
187 void spm_twam_disable_monitor(void)
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
);
197 EXPORT_SYMBOL(spm_twam_disable_monitor
);
200 /**************************************
201 * for PCM WDT to replace RGU WDT
202 **************************************/
203 int spm_wdt_register_fiq(fiq_isr_handler rgu_wdt_handler
)
207 #ifdef CONFIG_FIQ_GLUE
208 r
= request_fiq(MT_SPM1_IRQ_ID
, rgu_wdt_handler
, IRQF_TRIGGER_FALLING
, NULL
);
216 int spm_wdt_register_irq(irq_handler_t rgu_wdt_handler
)
220 r
= request_irq(MT_SPM1_IRQ_ID
, rgu_wdt_handler
, IRQF_TRIGGER_FALLING
,
226 void spm_wdt_set_timeout(u32 sec
)
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
);
236 void spm_wdt_enable_timer(void)
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
);
246 void spm_wdt_restart_timer(void)
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
);
256 void spm_wdt_restart_timer_nolock(void)
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
);
262 void spm_wdt_disable_timer(void)
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
);
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
);
276 /**************************************
278 **************************************/
279 #define MAX_RETRY_COUNT (100)
281 int spm_dvfs_ctrl_volt(u32 value
)
286 #ifdef MTK_ALPS_BOX_SUPPORT
289 ap_dvfs_con
= spm_read(SPM_AP_DVFS_CON_SET
);
290 spm_write(SPM_AP_DVFS_CON_SET
, (ap_dvfs_con
& ~(0x7)) | value
);
293 while ((spm_read(SPM_AP_DVFS_CON_SET
) & (0x1 << 31)) == 0)
295 if (retry
>= MAX_RETRY_COUNT
)
297 printk("FAIL: no response from PMIC wrapper\n");
302 printk("wait for ACK signal from PMIC wrapper, retry = %d\n", retry
);
310 MODULE_DESCRIPTION("SPM Driver v0.6");