Commit 93f89519 authored by Steven Miao's avatar Steven Miao Committed by Bob Liu

blackfin: bf60x: add power management support

Add bf60x cpu pm callbacks and change blackfin pm framework to support bf60x.
Signed-off-by: default avatarSteven Miao <realmz6@gmail.com>
Signed-off-by: default avatarBob Liu <lliubbo@gmail.com>
parent b2cfc653
......@@ -9,6 +9,637 @@
#ifndef _BLACKFIN_DPMC_H_
#define _BLACKFIN_DPMC_H_
#ifdef __ASSEMBLY__
#define PM_REG0 R7
#define PM_REG1 R6
#define PM_REG2 R5
#define PM_REG3 R4
#define PM_REG4 R3
#define PM_REG5 R2
#define PM_REG6 R1
#define PM_REG7 R0
#define PM_REG8 P5
#define PM_REG9 P4
#define PM_REG10 P3
#define PM_REG11 P2
#define PM_REG12 P1
#define PM_REG13 P0
#define PM_REGSET0 R7:7
#define PM_REGSET1 R7:6
#define PM_REGSET2 R7:5
#define PM_REGSET3 R7:4
#define PM_REGSET4 R7:3
#define PM_REGSET5 R7:2
#define PM_REGSET6 R7:1
#define PM_REGSET7 R7:0
#define PM_REGSET8 R7:0, P5:5
#define PM_REGSET9 R7:0, P5:4
#define PM_REGSET10 R7:0, P5:3
#define PM_REGSET11 R7:0, P5:2
#define PM_REGSET12 R7:0, P5:1
#define PM_REGSET13 R7:0, P5:0
#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n;
#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n);
#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++];
#define PM_PUSH(n, x) PM_REG##n = [FP++];
#define PM_POP(n, x) [FP--] = PM_REG##n;
#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE)
#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE)
#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE)
#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE)
#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE)
#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE)
.macro bfin_cpu_reg_save
/*
* Save the core regs early so we can blow them away when
* saving/restoring MMR states
*/
[--sp] = (R7:0, P5:0);
[--sp] = fp;
[--sp] = usp;
[--sp] = i0;
[--sp] = i1;
[--sp] = i2;
[--sp] = i3;
[--sp] = m0;
[--sp] = m1;
[--sp] = m2;
[--sp] = m3;
[--sp] = l0;
[--sp] = l1;
[--sp] = l2;
[--sp] = l3;
[--sp] = b0;
[--sp] = b1;
[--sp] = b2;
[--sp] = b3;
[--sp] = a0.x;
[--sp] = a0.w;
[--sp] = a1.x;
[--sp] = a1.w;
[--sp] = LC0;
[--sp] = LC1;
[--sp] = LT0;
[--sp] = LT1;
[--sp] = LB0;
[--sp] = LB1;
/* We can't push RETI directly as that'll change IPEND[4] */
r7 = RETI;
[--sp] = RETS;
[--sp] = ASTAT;
[--sp] = CYCLES;
[--sp] = CYCLES2;
[--sp] = SYSCFG;
[--sp] = RETX;
[--sp] = SEQSTAT;
[--sp] = r7;
/* Save first func arg in M3 */
M3 = R0;
.endm
.macro bfin_cpu_reg_restore
/* Restore Core Registers */
RETI = [sp++];
SEQSTAT = [sp++];
RETX = [sp++];
SYSCFG = [sp++];
CYCLES2 = [sp++];
CYCLES = [sp++];
ASTAT = [sp++];
RETS = [sp++];
LB1 = [sp++];
LB0 = [sp++];
LT1 = [sp++];
LT0 = [sp++];
LC1 = [sp++];
LC0 = [sp++];
a1.w = [sp++];
a1.x = [sp++];
a0.w = [sp++];
a0.x = [sp++];
b3 = [sp++];
b2 = [sp++];
b1 = [sp++];
b0 = [sp++];
l3 = [sp++];
l2 = [sp++];
l1 = [sp++];
l0 = [sp++];
m3 = [sp++];
m2 = [sp++];
m1 = [sp++];
m0 = [sp++];
i3 = [sp++];
i2 = [sp++];
i1 = [sp++];
i0 = [sp++];
usp = [sp++];
fp = [sp++];
(R7:0, P5:0) = [sp++];
.endm
.macro bfin_sys_mmr_save
/* Save system MMRs */
FP.H = hi(SYSMMR_BASE);
FP.L = lo(SYSMMR_BASE);
#ifdef SIC_IMASK0
PM_SYS_PUSH(0, SIC_IMASK0)
PM_SYS_PUSH(1, SIC_IMASK1)
# ifdef SIC_IMASK2
PM_SYS_PUSH(2, SIC_IMASK2)
# endif
#else
# ifdef SIC_IMASK
PM_SYS_PUSH(0, SIC_IMASK)
# endif
#endif
#ifdef SIC_IAR0
PM_SYS_PUSH(3, SIC_IAR0)
PM_SYS_PUSH(4, SIC_IAR1)
PM_SYS_PUSH(5, SIC_IAR2)
#endif
#ifdef SIC_IAR3
PM_SYS_PUSH(6, SIC_IAR3)
#endif
#ifdef SIC_IAR4
PM_SYS_PUSH(7, SIC_IAR4)
PM_SYS_PUSH(8, SIC_IAR5)
PM_SYS_PUSH(9, SIC_IAR6)
#endif
#ifdef SIC_IAR7
PM_SYS_PUSH(10, SIC_IAR7)
#endif
#ifdef SIC_IAR8
PM_SYS_PUSH(11, SIC_IAR8)
PM_SYS_PUSH(12, SIC_IAR9)
PM_SYS_PUSH(13, SIC_IAR10)
#endif
PM_PUSH_SYNC(13)
#ifdef SIC_IAR11
PM_SYS_PUSH(0, SIC_IAR11)
#endif
#ifdef SIC_IWR
PM_SYS_PUSH(1, SIC_IWR)
#endif
#ifdef SIC_IWR0
PM_SYS_PUSH(1, SIC_IWR0)
#endif
#ifdef SIC_IWR1
PM_SYS_PUSH(2, SIC_IWR1)
#endif
#ifdef SIC_IWR2
PM_SYS_PUSH(3, SIC_IWR2)
#endif
#ifdef PINT0_ASSIGN
PM_SYS_PUSH(4, PINT0_MASK_SET)
PM_SYS_PUSH(5, PINT1_MASK_SET)
PM_SYS_PUSH(6, PINT2_MASK_SET)
PM_SYS_PUSH(7, PINT3_MASK_SET)
PM_SYS_PUSH(8, PINT0_ASSIGN)
PM_SYS_PUSH(9, PINT1_ASSIGN)
PM_SYS_PUSH(10, PINT2_ASSIGN)
PM_SYS_PUSH(11, PINT3_ASSIGN)
PM_SYS_PUSH(12, PINT0_INVERT_SET)
PM_SYS_PUSH(13, PINT1_INVERT_SET)
PM_PUSH_SYNC(13)
PM_SYS_PUSH(0, PINT2_INVERT_SET)
PM_SYS_PUSH(1, PINT3_INVERT_SET)
PM_SYS_PUSH(2, PINT0_EDGE_SET)
PM_SYS_PUSH(3, PINT1_EDGE_SET)
PM_SYS_PUSH(4, PINT2_EDGE_SET)
PM_SYS_PUSH(5, PINT3_EDGE_SET)
#endif
#ifdef SYSCR
PM_SYS_PUSH16(6, SYSCR)
#endif
#ifdef EBIU_AMGCTL
PM_SYS_PUSH16(7, EBIU_AMGCTL)
PM_SYS_PUSH(8, EBIU_AMBCTL0)
PM_SYS_PUSH(9, EBIU_AMBCTL1)
#endif
#ifdef EBIU_FCTL
PM_SYS_PUSH(10, EBIU_MBSCTL)
PM_SYS_PUSH(11, EBIU_MODE)
PM_SYS_PUSH(12, EBIU_FCTL)
PM_PUSH_SYNC(12)
#else
PM_PUSH_SYNC(9)
#endif
.endm
.macro bfin_sys_mmr_restore
/* Restore System MMRs */
FP.H = hi(SYSMMR_BASE);
FP.L = lo(SYSMMR_BASE);
#ifdef EBIU_FCTL
PM_POP_SYNC(12)
PM_SYS_POP(12, EBIU_FCTL)
PM_SYS_POP(11, EBIU_MODE)
PM_SYS_POP(10, EBIU_MBSCTL)
#else
PM_POP_SYNC(9)
#endif
#ifdef EBIU_AMBCTL
PM_SYS_POP(9, EBIU_AMBCTL1)
PM_SYS_POP(8, EBIU_AMBCTL0)
PM_SYS_POP16(7, EBIU_AMGCTL)
#endif
#ifdef SYSCR
PM_SYS_POP16(6, SYSCR)
#endif
#ifdef PINT0_ASSIGN
PM_SYS_POP(5, PINT3_EDGE_SET)
PM_SYS_POP(4, PINT2_EDGE_SET)
PM_SYS_POP(3, PINT1_EDGE_SET)
PM_SYS_POP(2, PINT0_EDGE_SET)
PM_SYS_POP(1, PINT3_INVERT_SET)
PM_SYS_POP(0, PINT2_INVERT_SET)
PM_POP_SYNC(13)
PM_SYS_POP(13, PINT1_INVERT_SET)
PM_SYS_POP(12, PINT0_INVERT_SET)
PM_SYS_POP(11, PINT3_ASSIGN)
PM_SYS_POP(10, PINT2_ASSIGN)
PM_SYS_POP(9, PINT1_ASSIGN)
PM_SYS_POP(8, PINT0_ASSIGN)
PM_SYS_POP(7, PINT3_MASK_SET)
PM_SYS_POP(6, PINT2_MASK_SET)
PM_SYS_POP(5, PINT1_MASK_SET)
PM_SYS_POP(4, PINT0_MASK_SET)
#endif
#ifdef SIC_IWR2
PM_SYS_POP(3, SIC_IWR2)
#endif
#ifdef SIC_IWR1
PM_SYS_POP(2, SIC_IWR1)
#endif
#ifdef SIC_IWR0
PM_SYS_POP(1, SIC_IWR0)
#endif
#ifdef SIC_IWR
PM_SYS_POP(1, SIC_IWR)
#endif
#ifdef SIC_IAR11
PM_SYS_POP(0, SIC_IAR11)
#endif
PM_POP_SYNC(13)
#ifdef SIC_IAR8
PM_SYS_POP(13, SIC_IAR10)
PM_SYS_POP(12, SIC_IAR9)
PM_SYS_POP(11, SIC_IAR8)
#endif
#ifdef SIC_IAR7
PM_SYS_POP(10, SIC_IAR7)
#endif
#ifdef SIC_IAR6
PM_SYS_POP(9, SIC_IAR6)
PM_SYS_POP(8, SIC_IAR5)
PM_SYS_POP(7, SIC_IAR4)
#endif
#ifdef SIC_IAR3
PM_SYS_POP(6, SIC_IAR3)
#endif
#ifdef SIC_IAR0
PM_SYS_POP(5, SIC_IAR2)
PM_SYS_POP(4, SIC_IAR1)
PM_SYS_POP(3, SIC_IAR0)
#endif
#ifdef SIC_IMASK0
# ifdef SIC_IMASK2
PM_SYS_POP(2, SIC_IMASK2)
# endif
PM_SYS_POP(1, SIC_IMASK1)
PM_SYS_POP(0, SIC_IMASK0)
#else
# ifdef SIC_IMASK
PM_SYS_POP(0, SIC_IMASK)
# endif
#endif
.endm
.macro bfin_core_mmr_save
/* Save Core MMRs */
I0.H = hi(COREMMR_BASE);
I0.L = lo(COREMMR_BASE);
I1 = I0;
I2 = I0;
I3 = I0;
B0 = I0;
B1 = I0;
B2 = I0;
B3 = I0;
I1.L = lo(DCPLB_ADDR0);
I2.L = lo(DCPLB_DATA0);
I3.L = lo(ICPLB_ADDR0);
B0.L = lo(ICPLB_DATA0);
B1.L = lo(EVT2);
B2.L = lo(IMASK);
B3.L = lo(TCNTL);
/* Event Vectors */
FP = B1;
PM_PUSH(0, EVT2)
PM_PUSH(1, EVT3)
FP += 4; /* EVT4 */
PM_PUSH(2, EVT5)
PM_PUSH(3, EVT6)
PM_PUSH(4, EVT7)
PM_PUSH(5, EVT8)
PM_PUSH_SYNC(5)
PM_PUSH(0, EVT9)
PM_PUSH(1, EVT10)
PM_PUSH(2, EVT11)
PM_PUSH(3, EVT12)
PM_PUSH(4, EVT13)
PM_PUSH(5, EVT14)
PM_PUSH(6, EVT15)
/* CEC */
FP = B2;
PM_PUSH(7, IMASK)
FP += 4; /* IPEND */
PM_PUSH(8, ILAT)
PM_PUSH(9, IPRIO)
/* Core Timer */
FP = B3;
PM_PUSH(10, TCNTL)
PM_PUSH(11, TPERIOD)
PM_PUSH(12, TSCALE)
PM_PUSH(13, TCOUNT)
PM_PUSH_SYNC(13)
/* Misc non-contiguous registers */
FP = I0;
PM_CORE_PUSH(0, DMEM_CONTROL);
PM_CORE_PUSH(1, IMEM_CONTROL);
PM_CORE_PUSH(2, TBUFCTL);
PM_PUSH_SYNC(2)
/* DCPLB Addr */
FP = I1;
PM_PUSH(0, DCPLB_ADDR0)
PM_PUSH(1, DCPLB_ADDR1)
PM_PUSH(2, DCPLB_ADDR2)
PM_PUSH(3, DCPLB_ADDR3)
PM_PUSH(4, DCPLB_ADDR4)
PM_PUSH(5, DCPLB_ADDR5)
PM_PUSH(6, DCPLB_ADDR6)
PM_PUSH(7, DCPLB_ADDR7)
PM_PUSH(8, DCPLB_ADDR8)
PM_PUSH(9, DCPLB_ADDR9)
PM_PUSH(10, DCPLB_ADDR10)
PM_PUSH(11, DCPLB_ADDR11)
PM_PUSH(12, DCPLB_ADDR12)
PM_PUSH(13, DCPLB_ADDR13)
PM_PUSH_SYNC(13)
PM_PUSH(0, DCPLB_ADDR14)
PM_PUSH(1, DCPLB_ADDR15)
/* DCPLB Data */
FP = I2;
PM_PUSH(2, DCPLB_DATA0)
PM_PUSH(3, DCPLB_DATA1)
PM_PUSH(4, DCPLB_DATA2)
PM_PUSH(5, DCPLB_DATA3)
PM_PUSH(6, DCPLB_DATA4)
PM_PUSH(7, DCPLB_DATA5)
PM_PUSH(8, DCPLB_DATA6)
PM_PUSH(9, DCPLB_DATA7)
PM_PUSH(10, DCPLB_DATA8)
PM_PUSH(11, DCPLB_DATA9)
PM_PUSH(12, DCPLB_DATA10)
PM_PUSH(13, DCPLB_DATA11)
PM_PUSH_SYNC(13)
PM_PUSH(0, DCPLB_DATA12)
PM_PUSH(1, DCPLB_DATA13)
PM_PUSH(2, DCPLB_DATA14)
PM_PUSH(3, DCPLB_DATA15)
/* ICPLB Addr */
FP = I3;
PM_PUSH(4, ICPLB_ADDR0)
PM_PUSH(5, ICPLB_ADDR1)
PM_PUSH(6, ICPLB_ADDR2)
PM_PUSH(7, ICPLB_ADDR3)
PM_PUSH(8, ICPLB_ADDR4)
PM_PUSH(9, ICPLB_ADDR5)
PM_PUSH(10, ICPLB_ADDR6)
PM_PUSH(11, ICPLB_ADDR7)
PM_PUSH(12, ICPLB_ADDR8)
PM_PUSH(13, ICPLB_ADDR9)
PM_PUSH_SYNC(13)
PM_PUSH(0, ICPLB_ADDR10)
PM_PUSH(1, ICPLB_ADDR11)
PM_PUSH(2, ICPLB_ADDR12)
PM_PUSH(3, ICPLB_ADDR13)
PM_PUSH(4, ICPLB_ADDR14)
PM_PUSH(5, ICPLB_ADDR15)
/* ICPLB Data */
FP = B0;
PM_PUSH(6, ICPLB_DATA0)
PM_PUSH(7, ICPLB_DATA1)
PM_PUSH(8, ICPLB_DATA2)
PM_PUSH(9, ICPLB_DATA3)
PM_PUSH(10, ICPLB_DATA4)
PM_PUSH(11, ICPLB_DATA5)
PM_PUSH(12, ICPLB_DATA6)
PM_PUSH(13, ICPLB_DATA7)
PM_PUSH_SYNC(13)
PM_PUSH(0, ICPLB_DATA8)
PM_PUSH(1, ICPLB_DATA9)
PM_PUSH(2, ICPLB_DATA10)
PM_PUSH(3, ICPLB_DATA11)
PM_PUSH(4, ICPLB_DATA12)
PM_PUSH(5, ICPLB_DATA13)
PM_PUSH(6, ICPLB_DATA14)
PM_PUSH(7, ICPLB_DATA15)
PM_PUSH_SYNC(7)
.endm
.macro bfin_core_mmr_restore
/* Restore Core MMRs */
I0.H = hi(COREMMR_BASE);
I0.L = lo(COREMMR_BASE);
I1 = I0;
I2 = I0;
I3 = I0;
B0 = I0;
B1 = I0;
B2 = I0;
B3 = I0;
I1.L = lo(DCPLB_ADDR15);
I2.L = lo(DCPLB_DATA15);
I3.L = lo(ICPLB_ADDR15);
B0.L = lo(ICPLB_DATA15);
B1.L = lo(EVT15);
B2.L = lo(IPRIO);
B3.L = lo(TCOUNT);
/* ICPLB Data */
FP = B0;
PM_POP_SYNC(7)
PM_POP(7, ICPLB_DATA15)
PM_POP(6, ICPLB_DATA14)
PM_POP(5, ICPLB_DATA13)
PM_POP(4, ICPLB_DATA12)
PM_POP(3, ICPLB_DATA11)
PM_POP(2, ICPLB_DATA10)
PM_POP(1, ICPLB_DATA9)
PM_POP(0, ICPLB_DATA8)
PM_POP_SYNC(13)
PM_POP(13, ICPLB_DATA7)
PM_POP(12, ICPLB_DATA6)
PM_POP(11, ICPLB_DATA5)
PM_POP(10, ICPLB_DATA4)
PM_POP(9, ICPLB_DATA3)
PM_POP(8, ICPLB_DATA2)
PM_POP(7, ICPLB_DATA1)
PM_POP(6, ICPLB_DATA0)
/* ICPLB Addr */
FP = I3;
PM_POP(5, ICPLB_ADDR15)
PM_POP(4, ICPLB_ADDR14)
PM_POP(3, ICPLB_ADDR13)
PM_POP(2, ICPLB_ADDR12)
PM_POP(1, ICPLB_ADDR11)
PM_POP(0, ICPLB_ADDR10)
PM_POP_SYNC(13)
PM_POP(13, ICPLB_ADDR9)
PM_POP(12, ICPLB_ADDR8)
PM_POP(11, ICPLB_ADDR7)
PM_POP(10, ICPLB_ADDR6)
PM_POP(9, ICPLB_ADDR5)
PM_POP(8, ICPLB_ADDR4)
PM_POP(7, ICPLB_ADDR3)
PM_POP(6, ICPLB_ADDR2)
PM_POP(5, ICPLB_ADDR1)
PM_POP(4, ICPLB_ADDR0)
/* DCPLB Data */
FP = I2;
PM_POP(3, DCPLB_DATA15)
PM_POP(2, DCPLB_DATA14)
PM_POP(1, DCPLB_DATA13)
PM_POP(0, DCPLB_DATA12)
PM_POP_SYNC(13)
PM_POP(13, DCPLB_DATA11)
PM_POP(12, DCPLB_DATA10)
PM_POP(11, DCPLB_DATA9)
PM_POP(10, DCPLB_DATA8)
PM_POP(9, DCPLB_DATA7)
PM_POP(8, DCPLB_DATA6)
PM_POP(7, DCPLB_DATA5)
PM_POP(6, DCPLB_DATA4)
PM_POP(5, DCPLB_DATA3)
PM_POP(4, DCPLB_DATA2)
PM_POP(3, DCPLB_DATA1)
PM_POP(2, DCPLB_DATA0)
/* DCPLB Addr */
FP = I1;
PM_POP(1, DCPLB_ADDR15)
PM_POP(0, DCPLB_ADDR14)
PM_POP_SYNC(13)
PM_POP(13, DCPLB_ADDR13)
PM_POP(12, DCPLB_ADDR12)
PM_POP(11, DCPLB_ADDR11)
PM_POP(10, DCPLB_ADDR10)
PM_POP(9, DCPLB_ADDR9)
PM_POP(8, DCPLB_ADDR8)
PM_POP(7, DCPLB_ADDR7)
PM_POP(6, DCPLB_ADDR6)
PM_POP(5, DCPLB_ADDR5)
PM_POP(4, DCPLB_ADDR4)
PM_POP(3, DCPLB_ADDR3)
PM_POP(2, DCPLB_ADDR2)
PM_POP(1, DCPLB_ADDR1)
PM_POP(0, DCPLB_ADDR0)
/* Misc non-contiguous registers */
/* icache & dcache will enable later
drop IMEM_CONTROL, DMEM_CONTROL pop
*/
FP = I0;
PM_POP_SYNC(2)
PM_CORE_POP(2, TBUFCTL)
PM_CORE_POP(1, IMEM_CONTROL)
PM_CORE_POP(0, DMEM_CONTROL)
/* Core Timer */
FP = B3;
R0 = 0x1;
[FP - 0xC] = R0;
PM_POP_SYNC(13)
FP = B3;
PM_POP(13, TCOUNT)
PM_POP(12, TSCALE)
PM_POP(11, TPERIOD)
PM_POP(10, TCNTL)
/* CEC */
FP = B2;
PM_POP(9, IPRIO)
PM_POP(8, ILAT)
FP += -4; /* IPEND */
PM_POP(7, IMASK)
/* Event Vectors */
FP = B1;
PM_POP(6, EVT15)
PM_POP(5, EVT14)
PM_POP(4, EVT13)
PM_POP(3, EVT12)
PM_POP(2, EVT11)
PM_POP(1, EVT10)
PM_POP(0, EVT9)
PM_POP_SYNC(5)
PM_POP(5, EVT8)
PM_POP(4, EVT7)
PM_POP(3, EVT6)
PM_POP(2, EVT5)
FP += -4; /* EVT4 */
PM_POP(1, EVT3)
PM_POP(0, EVT2)
.endm
#endif
#include <mach/pll.h>
/* PLL_CTL Masks */
......@@ -114,6 +745,7 @@
#define USBWE 0x0800 /* Enable USB Wakeup From Hibernate */
#endif
#ifndef __ASSEMBLY__
void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
......
/*
* Blackfin bf609 power management
*
* Copyright 2011 Analog Devices Inc.
*
* Licensed under the GPL-2
*/
#ifndef __PM_H__
#define __PM_H__
#include <mach/pm.h>
#include <linux/suspend.h>
struct bfin_cpu_pm_fns {
void (*save)(unsigned long *);
void (*restore)(unsigned long *);
int (*valid)(suspend_state_t state);
void (*enter)(suspend_state_t state);
int (*prepare)(void);
void (*finish)(void);
};
extern struct bfin_cpu_pm_fns *bfin_cpu_pm;
# ifdef CONFIG_BFIN_COREB
void bfin_coreb_start(void);
void bfin_coreb_stop(void);
void bfin_coreb_reset(void);
# endif
#endif
#include <linux/linkage.h>
#include <asm/blackfin.h>
#include <asm/dpmc.h>
#define PM_STACK (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
.section .l1.text
ENTRY(_enter_hibernate)
/* switch stack to L1 scratch, prepare for ddr srfr */
P0.H = HI(PM_STACK);
P0.L = LO(PM_STACK);
SP = P0;
call _bf609_ddr_sr;
call _bfin_hibernate_syscontrol;
P0.H = HI(DPM0_RESTORE4);
P0.L = LO(DPM0_RESTORE4);
P1.H = _bf609_pm_data;
P1.L = _bf609_pm_data;
[P0] = P1;
P0.H = HI(DPM0_CTL);
P0.L = LO(DPM0_CTL);
R3.H = HI(0x00000010);
R3.L = LO(0x00000010);
[P0] = R3;
SSYNC;
ENDPROC(_enter_hibernate_mode)
.section .text
ENTRY(_bf609_hibernate)
bfin_cpu_reg_save;
bfin_core_mmr_save;
P0.H = _bf609_pm_data;
P0.L = _bf609_pm_data;
R1.H = 0xDEAD;
R1.L = 0xBEEF;
R2.H = .Lpm_resume_here;
R2.L = .Lpm_resume_here;
[P0++] = R1;
[P0++] = R2;
[P0++] = SP;
P1.H = _enter_hibernate;
P1.L = _enter_hibernate;
call (P1);
.Lpm_resume_here:
bfin_core_mmr_restore;
bfin_cpu_reg_restore;
[--sp] = RETI; /* Clear Global Interrupt Disable */
SP += 4;
RTS;
ENDPROC(_bf609_hibernate)
/*
* Blackfin bf609 power management
*
* Copyright 2011 Analog Devices Inc.
*
* Licensed under the GPL-2
*/
#ifndef __MACH_BF609_PM_H__
#define __MACH_BF609_PM_H__
#include <linux/suspend.h>
int bfin609_pm_enter(suspend_state_t state);
int bf609_pm_prepare(void);
void bf609_pm_finish(void);
void bf609_hibernate(void);
void bfin_sec_raise_irq(unsigned int sid);
void coreb_enable(void);
#endif
/*
* Blackfin bf609 power management
*
* Copyright 2011 Analog Devices Inc.
*
* Licensed under the GPL-2
*/
#include <linux/suspend.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <asm/dpmc.h>
#include <asm/pm.h>
#include <mach/pm.h>
#include <asm/blackfin.h>
/***********************************************************/
/* */
/* Wakeup Actions for DPM_RESTORE */
/* */
/***********************************************************/
#define BITP_ROM_WUA_CHKHDR 24
#define BITP_ROM_WUA_DDRLOCK 7
#define BITP_ROM_WUA_DDRDLLEN 6
#define BITP_ROM_WUA_DDR 5
#define BITP_ROM_WUA_CGU 4
#define BITP_ROM_WUA_MEMBOOT 2
#define BITP_ROM_WUA_EN 1
#define BITM_ROM_WUA_CHKHDR (0xFF000000)
#define ENUM_ROM_WUA_CHKHDR_AD 0xAD000000
#define BITM_ROM_WUA_DDRLOCK (0x00000080)
#define BITM_ROM_WUA_DDRDLLEN (0x00000040)
#define BITM_ROM_WUA_DDR (0x00000020)
#define BITM_ROM_WUA_CGU (0x00000010)
#define BITM_ROM_WUA_MEMBOOT (0x00000002)
#define BITM_ROM_WUA_EN (0x00000001)
/***********************************************************/
/* */
/* Syscontrol */
/* */
/***********************************************************/
#define BITP_ROM_SYSCTRL_CGU_LOCKINGEN 28 /* unlocks CGU_CTL register */
#define BITP_ROM_SYSCTRL_WUA_OVERRIDE 24
#define BITP_ROM_SYSCTRL_WUA_DDRDLLEN 20 /* Saves the DDR DLL and PADS registers to the DPM registers */
#define BITP_ROM_SYSCTRL_WUA_DDR 19 /* Saves the DDR registers to the DPM registers */
#define BITP_ROM_SYSCTRL_WUA_CGU 18 /* Saves the CGU registers into DPM registers */
#define BITP_ROM_SYSCTRL_WUA_DPMWRITE 17 /* Saves the Syscontrol structure structure contents into DPM registers */
#define BITP_ROM_SYSCTRL_WUA_EN 16 /* reads current PLL and DDR configuration into structure */
#define BITP_ROM_SYSCTRL_DDR_WRITE 13 /* writes the DDR registers from Syscontrol structure for wakeup initialization of DDR */
#define BITP_ROM_SYSCTRL_DDR_READ 12 /* Read the DDR registers into the Syscontrol structure for storing prior to hibernate */
#define BITP_ROM_SYSCTRL_CGU_AUTODIS 11 /* Disables auto handling of UPDT and ALGN fields */
#define BITP_ROM_SYSCTRL_CGU_CLKOUTSEL 7 /* access CGU_CLKOUTSEL register */
#define BITP_ROM_SYSCTRL_CGU_DIV 6 /* access CGU_DIV register */
#define BITP_ROM_SYSCTRL_CGU_STAT 5 /* access CGU_STAT register */
#define BITP_ROM_SYSCTRL_CGU_CTL 4 /* access CGU_CTL register */
#define BITP_ROM_SYSCTRL_CGU_RTNSTAT 2 /* Update structure STAT field upon error */
#define BITP_ROM_SYSCTRL_WRITE 1 /* write registers */
#define BITP_ROM_SYSCTRL_READ 0 /* read registers */
#define BITM_ROM_SYSCTRL_CGU_READ (0x00000001) /* Read CGU registers */
#define BITM_ROM_SYSCTRL_CGU_WRITE (0x00000002) /* Write registers */
#define BITM_ROM_SYSCTRL_CGU_RTNSTAT (0x00000004) /* Update structure STAT field upon error or after a write operation */
#define BITM_ROM_SYSCTRL_CGU_CTL (0x00000010) /* Access CGU_CTL register */
#define BITM_ROM_SYSCTRL_CGU_STAT (0x00000020) /* Access CGU_STAT register */
#define BITM_ROM_SYSCTRL_CGU_DIV (0x00000040) /* Access CGU_DIV register */
#define BITM_ROM_SYSCTRL_CGU_CLKOUTSEL (0x00000080) /* Access CGU_CLKOUTSEL register */
#define BITM_ROM_SYSCTRL_CGU_AUTODIS (0x00000800) /* Disables auto handling of UPDT and ALGN fields */
#define BITM_ROM_SYSCTRL_DDR_READ (0x00001000) /* Reads the contents of the DDR registers and stores them into the structure */
#define BITM_ROM_SYSCTRL_DDR_WRITE (0x00002000) /* Writes the DDR registers from the structure, only really intented for wakeup functionality and not for full DDR configuration */
#define BITM_ROM_SYSCTRL_WUA_EN (0x00010000) /* Wakeup entry or exit opertation enable */
#define BITM_ROM_SYSCTRL_WUA_DPMWRITE (0x00020000) /* When set indicates a restore of the PLL and DDR is to be performed otherwise a save is required */
#define BITM_ROM_SYSCTRL_WUA_CGU (0x00040000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
#define BITM_ROM_SYSCTRL_WUA_DDR (0x00080000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
#define BITM_ROM_SYSCTRL_WUA_DDRDLLEN (0x00100000) /* Enables saving/restoring of the DDR DLLCTL register */
#define BITM_ROM_SYSCTRL_WUA_OVERRIDE (0x01000000)
#define BITM_ROM_SYSCTRL_CGU_LOCKINGEN (0x10000000) /* Unlocks the CGU_CTL register */
/* Structures for the syscontrol() function */
struct STRUCT_ROM_SYSCTRL {
uint32_t ulCGU_CTL;
uint32_t ulCGU_STAT;
uint32_t ulCGU_DIV;
uint32_t ulCGU_CLKOUTSEL;
uint32_t ulWUA_Flags;
uint32_t ulWUA_BootAddr;
uint32_t ulWUA_User;
uint32_t ulDDR_CTL;
uint32_t ulDDR_CFG;
uint32_t ulDDR_TR0;
uint32_t ulDDR_TR1;
uint32_t ulDDR_TR2;
uint32_t ulDDR_MR;
uint32_t ulDDR_EMR1;
uint32_t ulDDR_EMR2;
uint32_t ulDDR_PADCTL;
uint32_t ulDDR_DLLCTL;
uint32_t ulReserved;
};
struct bfin_pm_data {
uint32_t magic;
uint32_t resume_addr;
uint32_t sp;
};
struct bfin_pm_data bf609_pm_data;
struct STRUCT_ROM_SYSCTRL configvalues;
uint32_t dactionflags;
#define FUNC_ROM_SYSCONTROL 0xC8000080
__attribute__((l1_data))
static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, struct STRUCT_ROM_SYSCTRL *settings, void *reserved) = (void *)FUNC_ROM_SYSCONTROL;
__attribute__((l1_text))
void bfin_cpu_suspend(void)
{
__asm__ __volatile__( \
".align 8;" \
"idle;" \
: : \
);
}
__attribute__((l1_text))
void bfin_deepsleep(unsigned long mask)
{
uint32_t dpm0_ctl;
bfin_write32(DPM0_WAKE_EN, 0x10);
bfin_write32(DPM0_WAKE_POL, 0x10);
dpm0_ctl = bfin_read32(DPM0_CTL);
dpm0_ctl = 0x00000008;
bfin_write32(DPM0_CTL, dpm0_ctl);
SSYNC();
__asm__ __volatile__( \
".align 8;" \
"idle;" \
: : \
);
}
__attribute__((l1_text))
void bf609_ddr_sr(void)
{
uint32_t reg;
reg = bfin_read_DDR0_CTL();
reg |= 0x8;
bfin_write_DDR0_CTL(reg);
while (!(bfin_read_DDR0_STAT() & 0x8))
continue;
}
__attribute__((l1_text))
void bf609_ddr_sr_exit(void)
{
uint32_t reg;
while (!(bfin_read_DDR0_STAT() & 0x1))
continue;
reg = bfin_read_DDR0_CTL();
reg &= ~0x8;
bfin_write_DDR0_CTL(reg);
while ((bfin_read_DDR0_STAT() & 0x8))
continue;
}
__attribute__((l1_text))
void bfin_hibernate_syscontrol(void)
{
configvalues.ulWUA_Flags = (0xAD000000 | BITM_ROM_WUA_EN
| BITM_ROM_WUA_CGU | BITM_ROM_WUA_DDR | BITM_ROM_WUA_DDRDLLEN);
dactionflags = (BITM_ROM_SYSCTRL_WUA_EN
| BITM_ROM_SYSCTRL_WUA_DPMWRITE | BITM_ROM_SYSCTRL_WUA_CGU
| BITM_ROM_SYSCTRL_WUA_DDR | BITM_ROM_SYSCTRL_WUA_DDRDLLEN);
bfrom_SysControl(dactionflags, &configvalues, NULL);
bfin_write32(DPM0_RESTORE5, bfin_read32(DPM0_RESTORE5) | 4);
}
#ifndef CONFIG_BF60x
# define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
#else
# define SIC_SYSIRQ(irq) ((irq) - IVG15)
#endif
void bfin_hibernate(unsigned long mask)
{
bfin_write32(DPM0_WAKE_EN, 0x10);
bfin_write32(DPM0_WAKE_POL, 0x10);
bfin_write32(DPM0_PGCNTR, 0x0000FFFF);
bfin_write32(DPM0_HIB_DIS, 0xFFFF);
printk(KERN_DEBUG "hibernate: restore %x pgcnt %x\n", bfin_read32(DPM0_RESTORE0), bfin_read32(DPM0_PGCNTR));
bf609_hibernate();
}
void bf609_cpu_pm_enter(suspend_state_t state)
{
int error;
error = irq_set_irq_wake(255, 1);
if(error < 0)
printk(KERN_DEBUG "Unable to get irq wake\n");
error = irq_set_irq_wake(231, 1);
if (error < 0)
printk(KERN_DEBUG "Unable to get irq wake\n");
if (state == PM_SUSPEND_STANDBY)
bfin_deepsleep(0xffff);
else {
bfin_hibernate(0xffff);
}
}
int bf609_cpu_pm_prepare(void)
{
return 0;
}
void bf609_cpu_pm_finish(void)
{
}
static struct bfin_cpu_pm_fns bf609_cpu_pm = {
.enter = bf609_cpu_pm_enter,
.prepare = bf609_cpu_pm_prepare,
.finish = bf609_cpu_pm_finish,
};
static irqreturn_t test_isr(int irq, void *dev_id)
{
printk(KERN_DEBUG "gpio irq %d\n", irq);
return IRQ_HANDLED;
}
static irqreturn_t dpm0_isr(int irq, void *dev_id)
{
uint32_t wake_stat;
wake_stat = bfin_read32(DPM0_WAKE_STAT);
printk(KERN_DEBUG "enter %s wake stat %08x\n", __func__, wake_stat);
bfin_write32(DPM0_WAKE_STAT, wake_stat);
return IRQ_HANDLED;
}
static int __init bf609_init_pm(void)
{
int irq;
int error;
error = gpio_request(GPIO_PG4, "gpiopg4");
if (error < 0) {
printk(KERN_DEBUG "failed to request GPIO %d, error %d\n",
GPIO_PG4, error);
}
irq = gpio_to_irq(GPIO_PG4);
if (irq < 0) {
error = irq;
printk(KERN_DEBUG "Unable to get irq number for GPIO %d, error %d\n",
GPIO_PG4, error);
}
printk(KERN_DEBUG "%s gpio %d irq %d\n", __func__, GPIO_PG4, irq);
error = request_irq(irq, test_isr, IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND, "gpiopg4", NULL);
if(error < 0)
printk(KERN_DEBUG "Unable to get irq\n");
#if 1
irq = gpio_to_irq(GPIO_PE12);
if (irq < 0) {
error = irq;
printk(KERN_DEBUG "Unable to get irq number for GPIO %d, error %d\n",
GPIO_PE12, error);
}
error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "gpiope12", NULL);
if(error < 0)
printk(KERN_DEBUG "Unable to get irq\n");
#endif
error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND, "cgu0 event", NULL);
if(error < 0)
printk(KERN_DEBUG "Unable to get irq\n");
error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND, "dpm0 event", NULL);
if (error < 0)
printk(KERN_DEBUG "Unable to get irq\n");
bfin_cpu_pm = &bf609_cpu_pm;
return 0;
}
late_initcall(bf609_init_pm);
......@@ -6,7 +6,10 @@ obj-y := \
cache.o cache-c.o entry.o head.o \
interrupt.o arch_checks.o ints-priority.o
obj-$(CONFIG_PM) += pm.o dpmc_modes.o
obj-$(CONFIG_PM) += pm.o
ifneq ($(CONFIG_BF60x),y)
obj-$(CONFIG_PM) += dpmc_modes.o
endif
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
obj-$(CONFIG_SMP) += smp.o
......
......@@ -10,7 +10,7 @@
#include <asm/dpmc.h>
.section .l1.text
#ifndef CONFIG_BF60x
ENTRY(_sleep_mode)
[--SP] = (R7:4, P5:3);
[--SP] = RETS;
......@@ -49,6 +49,7 @@ ENTRY(_sleep_mode)
(R7:4, P5:3) = [SP++];
RTS;
ENDPROC(_sleep_mode)
#endif
/*
* This func never returns as it puts the part into hibernate, and
......@@ -58,12 +59,14 @@ ENDPROC(_sleep_mode)
*
* We accept just one argument -- the value to write to VR_CTL.
*/
ENTRY(_hibernate_mode)
/* Save/setup the regs we need early for minor pipeline optimization */
R4 = R0;
#ifndef CONFIG_BF60x
P3.H = hi(VR_CTL);
P3.L = lo(VR_CTL);
/* Disable all wakeup sources */
R0 = IWR_DISABLE_ALL;
R1 = IWR_DISABLE_ALL;
......@@ -71,6 +74,7 @@ ENTRY(_hibernate_mode)
call _set_sic_iwr;
call _set_dram_srfs;
SSYNC;
#endif
/* Finally, we climb into our cave to hibernate */
W[P3] = R4.L;
......@@ -80,6 +84,7 @@ ENTRY(_hibernate_mode)
jump .Lforever;
ENDPROC(_hibernate_mode)
#ifndef CONFIG_BF60x
ENTRY(_sleep_deeper)
[--SP] = (R7:4, P5:3);
[--SP] = RETS;
......@@ -274,329 +279,13 @@ ENTRY(_test_pll_locked)
IF !CC JUMP 1b;
RTS;
ENDPROC(_test_pll_locked)
#endif
.section .text
#define PM_REG0 R7
#define PM_REG1 R6
#define PM_REG2 R5
#define PM_REG3 R4
#define PM_REG4 R3
#define PM_REG5 R2
#define PM_REG6 R1
#define PM_REG7 R0
#define PM_REG8 P5
#define PM_REG9 P4
#define PM_REG10 P3
#define PM_REG11 P2
#define PM_REG12 P1
#define PM_REG13 P0
#define PM_REGSET0 R7:7
#define PM_REGSET1 R7:6
#define PM_REGSET2 R7:5
#define PM_REGSET3 R7:4
#define PM_REGSET4 R7:3
#define PM_REGSET5 R7:2
#define PM_REGSET6 R7:1
#define PM_REGSET7 R7:0
#define PM_REGSET8 R7:0, P5:5
#define PM_REGSET9 R7:0, P5:4
#define PM_REGSET10 R7:0, P5:3
#define PM_REGSET11 R7:0, P5:2
#define PM_REGSET12 R7:0, P5:1
#define PM_REGSET13 R7:0, P5:0
#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
#define _PM_POP(n, x, w, base) w[FP + ((x) - (base))] = PM_REG##n;
#define PM_PUSH_SYNC(n) [--sp] = (PM_REGSET##n);
#define PM_POP_SYNC(n) (PM_REGSET##n) = [sp++];
#define PM_PUSH(n, x) PM_REG##n = [FP++];
#define PM_POP(n, x) [FP--] = PM_REG##n;
#define PM_CORE_PUSH(n, x) _PM_PUSH(n, x, , COREMMR_BASE)
#define PM_CORE_POP(n, x) _PM_POP(n, x, , COREMMR_BASE)
#define PM_SYS_PUSH(n, x) _PM_PUSH(n, x, , SYSMMR_BASE)
#define PM_SYS_POP(n, x) _PM_POP(n, x, , SYSMMR_BASE)
#define PM_SYS_PUSH16(n, x) _PM_PUSH(n, x, w, SYSMMR_BASE)
#define PM_SYS_POP16(n, x) _PM_POP(n, x, w, SYSMMR_BASE)
ENTRY(_do_hibernate)
/*
* Save the core regs early so we can blow them away when
* saving/restoring MMR states
*/
[--sp] = (R7:0, P5:0);
[--sp] = fp;
[--sp] = usp;
[--sp] = i0;
[--sp] = i1;
[--sp] = i2;
[--sp] = i3;
[--sp] = m0;
[--sp] = m1;
[--sp] = m2;
[--sp] = m3;
[--sp] = l0;
[--sp] = l1;
[--sp] = l2;
[--sp] = l3;
[--sp] = b0;
[--sp] = b1;
[--sp] = b2;
[--sp] = b3;
[--sp] = a0.x;
[--sp] = a0.w;
[--sp] = a1.x;
[--sp] = a1.w;
[--sp] = LC0;
[--sp] = LC1;
[--sp] = LT0;
[--sp] = LT1;
[--sp] = LB0;
[--sp] = LB1;
/* We can't push RETI directly as that'll change IPEND[4] */
r7 = RETI;
[--sp] = RETS;
[--sp] = ASTAT;
[--sp] = CYCLES;
[--sp] = CYCLES2;
[--sp] = SYSCFG;
[--sp] = RETX;
[--sp] = SEQSTAT;
[--sp] = r7;
/* Save first func arg in M3 */
M3 = R0;
/* Save system MMRs */
FP.H = hi(SYSMMR_BASE);
FP.L = lo(SYSMMR_BASE);
#ifdef SIC_IMASK0
PM_SYS_PUSH(0, SIC_IMASK0)
PM_SYS_PUSH(1, SIC_IMASK1)
# ifdef SIC_IMASK2
PM_SYS_PUSH(2, SIC_IMASK2)
# endif
#else
PM_SYS_PUSH(0, SIC_IMASK)
#endif
#ifdef SIC_IAR0
PM_SYS_PUSH(3, SIC_IAR0)
PM_SYS_PUSH(4, SIC_IAR1)
PM_SYS_PUSH(5, SIC_IAR2)
#endif
#ifdef SIC_IAR3
PM_SYS_PUSH(6, SIC_IAR3)
#endif
#ifdef SIC_IAR4
PM_SYS_PUSH(7, SIC_IAR4)
PM_SYS_PUSH(8, SIC_IAR5)
PM_SYS_PUSH(9, SIC_IAR6)
#endif
#ifdef SIC_IAR7
PM_SYS_PUSH(10, SIC_IAR7)
#endif
#ifdef SIC_IAR8
PM_SYS_PUSH(11, SIC_IAR8)
PM_SYS_PUSH(12, SIC_IAR9)
PM_SYS_PUSH(13, SIC_IAR10)
#endif
PM_PUSH_SYNC(13)
#ifdef SIC_IAR11
PM_SYS_PUSH(0, SIC_IAR11)
#endif
#ifdef SIC_IWR
PM_SYS_PUSH(1, SIC_IWR)
#endif
#ifdef SIC_IWR0
PM_SYS_PUSH(1, SIC_IWR0)
#endif
#ifdef SIC_IWR1
PM_SYS_PUSH(2, SIC_IWR1)
#endif
#ifdef SIC_IWR2
PM_SYS_PUSH(3, SIC_IWR2)
#endif
#ifdef PINT0_ASSIGN
PM_SYS_PUSH(4, PINT0_MASK_SET)
PM_SYS_PUSH(5, PINT1_MASK_SET)
PM_SYS_PUSH(6, PINT2_MASK_SET)
PM_SYS_PUSH(7, PINT3_MASK_SET)
PM_SYS_PUSH(8, PINT0_ASSIGN)
PM_SYS_PUSH(9, PINT1_ASSIGN)
PM_SYS_PUSH(10, PINT2_ASSIGN)
PM_SYS_PUSH(11, PINT3_ASSIGN)
PM_SYS_PUSH(12, PINT0_INVERT_SET)
PM_SYS_PUSH(13, PINT1_INVERT_SET)
PM_PUSH_SYNC(13)
PM_SYS_PUSH(0, PINT2_INVERT_SET)
PM_SYS_PUSH(1, PINT3_INVERT_SET)
PM_SYS_PUSH(2, PINT0_EDGE_SET)
PM_SYS_PUSH(3, PINT1_EDGE_SET)
PM_SYS_PUSH(4, PINT2_EDGE_SET)
PM_SYS_PUSH(5, PINT3_EDGE_SET)
#endif
PM_SYS_PUSH16(6, SYSCR)
PM_SYS_PUSH16(7, EBIU_AMGCTL)
PM_SYS_PUSH(8, EBIU_AMBCTL0)
PM_SYS_PUSH(9, EBIU_AMBCTL1)
#ifdef EBIU_FCTL
PM_SYS_PUSH(10, EBIU_MBSCTL)
PM_SYS_PUSH(11, EBIU_MODE)
PM_SYS_PUSH(12, EBIU_FCTL)
PM_PUSH_SYNC(12)
#else
PM_PUSH_SYNC(9)
#endif
/* Save Core MMRs */
I0.H = hi(COREMMR_BASE);
I0.L = lo(COREMMR_BASE);
I1 = I0;
I2 = I0;
I3 = I0;
B0 = I0;
B1 = I0;
B2 = I0;
B3 = I0;
I1.L = lo(DCPLB_ADDR0);
I2.L = lo(DCPLB_DATA0);
I3.L = lo(ICPLB_ADDR0);
B0.L = lo(ICPLB_DATA0);
B1.L = lo(EVT2);
B2.L = lo(IMASK);
B3.L = lo(TCNTL);
/* DCPLB Addr */
FP = I1;
PM_PUSH(0, DCPLB_ADDR0)
PM_PUSH(1, DCPLB_ADDR1)
PM_PUSH(2, DCPLB_ADDR2)
PM_PUSH(3, DCPLB_ADDR3)
PM_PUSH(4, DCPLB_ADDR4)
PM_PUSH(5, DCPLB_ADDR5)
PM_PUSH(6, DCPLB_ADDR6)
PM_PUSH(7, DCPLB_ADDR7)
PM_PUSH(8, DCPLB_ADDR8)
PM_PUSH(9, DCPLB_ADDR9)
PM_PUSH(10, DCPLB_ADDR10)
PM_PUSH(11, DCPLB_ADDR11)
PM_PUSH(12, DCPLB_ADDR12)
PM_PUSH(13, DCPLB_ADDR13)
PM_PUSH_SYNC(13)
PM_PUSH(0, DCPLB_ADDR14)
PM_PUSH(1, DCPLB_ADDR15)
/* DCPLB Data */
FP = I2;
PM_PUSH(2, DCPLB_DATA0)
PM_PUSH(3, DCPLB_DATA1)
PM_PUSH(4, DCPLB_DATA2)
PM_PUSH(5, DCPLB_DATA3)
PM_PUSH(6, DCPLB_DATA4)
PM_PUSH(7, DCPLB_DATA5)
PM_PUSH(8, DCPLB_DATA6)
PM_PUSH(9, DCPLB_DATA7)
PM_PUSH(10, DCPLB_DATA8)
PM_PUSH(11, DCPLB_DATA9)
PM_PUSH(12, DCPLB_DATA10)
PM_PUSH(13, DCPLB_DATA11)
PM_PUSH_SYNC(13)
PM_PUSH(0, DCPLB_DATA12)
PM_PUSH(1, DCPLB_DATA13)
PM_PUSH(2, DCPLB_DATA14)
PM_PUSH(3, DCPLB_DATA15)
/* ICPLB Addr */
FP = I3;
PM_PUSH(4, ICPLB_ADDR0)
PM_PUSH(5, ICPLB_ADDR1)
PM_PUSH(6, ICPLB_ADDR2)
PM_PUSH(7, ICPLB_ADDR3)
PM_PUSH(8, ICPLB_ADDR4)
PM_PUSH(9, ICPLB_ADDR5)
PM_PUSH(10, ICPLB_ADDR6)
PM_PUSH(11, ICPLB_ADDR7)
PM_PUSH(12, ICPLB_ADDR8)
PM_PUSH(13, ICPLB_ADDR9)
PM_PUSH_SYNC(13)
PM_PUSH(0, ICPLB_ADDR10)
PM_PUSH(1, ICPLB_ADDR11)
PM_PUSH(2, ICPLB_ADDR12)
PM_PUSH(3, ICPLB_ADDR13)
PM_PUSH(4, ICPLB_ADDR14)
PM_PUSH(5, ICPLB_ADDR15)
/* ICPLB Data */
FP = B0;
PM_PUSH(6, ICPLB_DATA0)
PM_PUSH(7, ICPLB_DATA1)
PM_PUSH(8, ICPLB_DATA2)
PM_PUSH(9, ICPLB_DATA3)
PM_PUSH(10, ICPLB_DATA4)
PM_PUSH(11, ICPLB_DATA5)
PM_PUSH(12, ICPLB_DATA6)
PM_PUSH(13, ICPLB_DATA7)
PM_PUSH_SYNC(13)
PM_PUSH(0, ICPLB_DATA8)
PM_PUSH(1, ICPLB_DATA9)
PM_PUSH(2, ICPLB_DATA10)
PM_PUSH(3, ICPLB_DATA11)
PM_PUSH(4, ICPLB_DATA12)
PM_PUSH(5, ICPLB_DATA13)
PM_PUSH(6, ICPLB_DATA14)
PM_PUSH(7, ICPLB_DATA15)
/* Event Vectors */
FP = B1;
PM_PUSH(8, EVT2)
PM_PUSH(9, EVT3)
FP += 4; /* EVT4 */
PM_PUSH(10, EVT5)
PM_PUSH(11, EVT6)
PM_PUSH(12, EVT7)
PM_PUSH(13, EVT8)
PM_PUSH_SYNC(13)
PM_PUSH(0, EVT9)
PM_PUSH(1, EVT10)
PM_PUSH(2, EVT11)
PM_PUSH(3, EVT12)
PM_PUSH(4, EVT13)
PM_PUSH(5, EVT14)
PM_PUSH(6, EVT15)
/* CEC */
FP = B2;
PM_PUSH(7, IMASK)
FP += 4; /* IPEND */
PM_PUSH(8, ILAT)
PM_PUSH(9, IPRIO)
/* Core Timer */
FP = B3;
PM_PUSH(10, TCNTL)
PM_PUSH(11, TPERIOD)
PM_PUSH(12, TSCALE)
PM_PUSH(13, TCOUNT)
PM_PUSH_SYNC(13)
/* Misc non-contiguous registers */
FP = I0;
PM_CORE_PUSH(0, DMEM_CONTROL);
PM_CORE_PUSH(1, IMEM_CONTROL);
PM_CORE_PUSH(2, TBUFCTL);
PM_PUSH_SYNC(2)
bfin_cpu_reg_save;
bfin_sys_mmr_save;
bfin_core_mmr_save;
/* Setup args to hibernate mode early for pipeline optimization */
R0 = M3;
......@@ -618,274 +307,9 @@ ENTRY(_do_hibernate)
.Lpm_resume_here:
/* Restore Core MMRs */
I0.H = hi(COREMMR_BASE);
I0.L = lo(COREMMR_BASE);
I1 = I0;
I2 = I0;
I3 = I0;
B0 = I0;
B1 = I0;
B2 = I0;
B3 = I0;
I1.L = lo(DCPLB_ADDR15);
I2.L = lo(DCPLB_DATA15);
I3.L = lo(ICPLB_ADDR15);
B0.L = lo(ICPLB_DATA15);
B1.L = lo(EVT15);
B2.L = lo(IPRIO);
B3.L = lo(TCOUNT);
/* Misc non-contiguous registers */
FP = I0;
PM_POP_SYNC(2)
PM_CORE_POP(2, TBUFCTL)
PM_CORE_POP(1, IMEM_CONTROL)
PM_CORE_POP(0, DMEM_CONTROL)
/* Core Timer */
PM_POP_SYNC(13)
FP = B3;
PM_POP(13, TCOUNT)
PM_POP(12, TSCALE)
PM_POP(11, TPERIOD)
PM_POP(10, TCNTL)
/* CEC */
FP = B2;
PM_POP(9, IPRIO)
PM_POP(8, ILAT)
FP += -4; /* IPEND */
PM_POP(7, IMASK)
/* Event Vectors */
FP = B1;
PM_POP(6, EVT15)
PM_POP(5, EVT14)
PM_POP(4, EVT13)
PM_POP(3, EVT12)
PM_POP(2, EVT11)
PM_POP(1, EVT10)
PM_POP(0, EVT9)
PM_POP_SYNC(13)
PM_POP(13, EVT8)
PM_POP(12, EVT7)
PM_POP(11, EVT6)
PM_POP(10, EVT5)
FP += -4; /* EVT4 */
PM_POP(9, EVT3)
PM_POP(8, EVT2)
/* ICPLB Data */
FP = B0;
PM_POP(7, ICPLB_DATA15)
PM_POP(6, ICPLB_DATA14)
PM_POP(5, ICPLB_DATA13)
PM_POP(4, ICPLB_DATA12)
PM_POP(3, ICPLB_DATA11)
PM_POP(2, ICPLB_DATA10)
PM_POP(1, ICPLB_DATA9)
PM_POP(0, ICPLB_DATA8)
PM_POP_SYNC(13)
PM_POP(13, ICPLB_DATA7)
PM_POP(12, ICPLB_DATA6)
PM_POP(11, ICPLB_DATA5)
PM_POP(10, ICPLB_DATA4)
PM_POP(9, ICPLB_DATA3)
PM_POP(8, ICPLB_DATA2)
PM_POP(7, ICPLB_DATA1)
PM_POP(6, ICPLB_DATA0)
/* ICPLB Addr */
FP = I3;
PM_POP(5, ICPLB_ADDR15)
PM_POP(4, ICPLB_ADDR14)
PM_POP(3, ICPLB_ADDR13)
PM_POP(2, ICPLB_ADDR12)
PM_POP(1, ICPLB_ADDR11)
PM_POP(0, ICPLB_ADDR10)
PM_POP_SYNC(13)
PM_POP(13, ICPLB_ADDR9)
PM_POP(12, ICPLB_ADDR8)
PM_POP(11, ICPLB_ADDR7)
PM_POP(10, ICPLB_ADDR6)
PM_POP(9, ICPLB_ADDR5)
PM_POP(8, ICPLB_ADDR4)
PM_POP(7, ICPLB_ADDR3)
PM_POP(6, ICPLB_ADDR2)
PM_POP(5, ICPLB_ADDR1)
PM_POP(4, ICPLB_ADDR0)
/* DCPLB Data */
FP = I2;
PM_POP(3, DCPLB_DATA15)
PM_POP(2, DCPLB_DATA14)
PM_POP(1, DCPLB_DATA13)
PM_POP(0, DCPLB_DATA12)
PM_POP_SYNC(13)
PM_POP(13, DCPLB_DATA11)
PM_POP(12, DCPLB_DATA10)
PM_POP(11, DCPLB_DATA9)
PM_POP(10, DCPLB_DATA8)
PM_POP(9, DCPLB_DATA7)
PM_POP(8, DCPLB_DATA6)
PM_POP(7, DCPLB_DATA5)
PM_POP(6, DCPLB_DATA4)
PM_POP(5, DCPLB_DATA3)
PM_POP(4, DCPLB_DATA2)
PM_POP(3, DCPLB_DATA1)
PM_POP(2, DCPLB_DATA0)
/* DCPLB Addr */
FP = I1;
PM_POP(1, DCPLB_ADDR15)
PM_POP(0, DCPLB_ADDR14)
PM_POP_SYNC(13)
PM_POP(13, DCPLB_ADDR13)
PM_POP(12, DCPLB_ADDR12)
PM_POP(11, DCPLB_ADDR11)
PM_POP(10, DCPLB_ADDR10)
PM_POP(9, DCPLB_ADDR9)
PM_POP(8, DCPLB_ADDR8)
PM_POP(7, DCPLB_ADDR7)
PM_POP(6, DCPLB_ADDR6)
PM_POP(5, DCPLB_ADDR5)
PM_POP(4, DCPLB_ADDR4)
PM_POP(3, DCPLB_ADDR3)
PM_POP(2, DCPLB_ADDR2)
PM_POP(1, DCPLB_ADDR1)
PM_POP(0, DCPLB_ADDR0)
/* Restore System MMRs */
FP.H = hi(SYSMMR_BASE);
FP.L = lo(SYSMMR_BASE);
#ifdef EBIU_FCTL
PM_POP_SYNC(12)
PM_SYS_POP(12, EBIU_FCTL)
PM_SYS_POP(11, EBIU_MODE)
PM_SYS_POP(10, EBIU_MBSCTL)
#else
PM_POP_SYNC(9)
#endif
PM_SYS_POP(9, EBIU_AMBCTL1)
PM_SYS_POP(8, EBIU_AMBCTL0)
PM_SYS_POP16(7, EBIU_AMGCTL)
PM_SYS_POP16(6, SYSCR)
#ifdef PINT0_ASSIGN
PM_SYS_POP(5, PINT3_EDGE_SET)
PM_SYS_POP(4, PINT2_EDGE_SET)
PM_SYS_POP(3, PINT1_EDGE_SET)
PM_SYS_POP(2, PINT0_EDGE_SET)
PM_SYS_POP(1, PINT3_INVERT_SET)
PM_SYS_POP(0, PINT2_INVERT_SET)
PM_POP_SYNC(13)
PM_SYS_POP(13, PINT1_INVERT_SET)
PM_SYS_POP(12, PINT0_INVERT_SET)
PM_SYS_POP(11, PINT3_ASSIGN)
PM_SYS_POP(10, PINT2_ASSIGN)
PM_SYS_POP(9, PINT1_ASSIGN)
PM_SYS_POP(8, PINT0_ASSIGN)
PM_SYS_POP(7, PINT3_MASK_SET)
PM_SYS_POP(6, PINT2_MASK_SET)
PM_SYS_POP(5, PINT1_MASK_SET)
PM_SYS_POP(4, PINT0_MASK_SET)
#endif
#ifdef SIC_IWR2
PM_SYS_POP(3, SIC_IWR2)
#endif
#ifdef SIC_IWR1
PM_SYS_POP(2, SIC_IWR1)
#endif
#ifdef SIC_IWR0
PM_SYS_POP(1, SIC_IWR0)
#endif
#ifdef SIC_IWR
PM_SYS_POP(1, SIC_IWR)
#endif
#ifdef SIC_IAR11
PM_SYS_POP(0, SIC_IAR11)
#endif
PM_POP_SYNC(13)
#ifdef SIC_IAR8
PM_SYS_POP(13, SIC_IAR10)
PM_SYS_POP(12, SIC_IAR9)
PM_SYS_POP(11, SIC_IAR8)
#endif
#ifdef SIC_IAR7
PM_SYS_POP(10, SIC_IAR7)
#endif
#ifdef SIC_IAR6
PM_SYS_POP(9, SIC_IAR6)
PM_SYS_POP(8, SIC_IAR5)
PM_SYS_POP(7, SIC_IAR4)
#endif
#ifdef SIC_IAR3
PM_SYS_POP(6, SIC_IAR3)
#endif
#ifdef SIC_IAR0
PM_SYS_POP(5, SIC_IAR2)
PM_SYS_POP(4, SIC_IAR1)
PM_SYS_POP(3, SIC_IAR0)
#endif
#ifdef SIC_IMASK0
# ifdef SIC_IMASK2
PM_SYS_POP(2, SIC_IMASK2)
# endif
PM_SYS_POP(1, SIC_IMASK1)
PM_SYS_POP(0, SIC_IMASK0)
#else
PM_SYS_POP(0, SIC_IMASK)
#endif
/* Restore Core Registers */
RETI = [sp++];
SEQSTAT = [sp++];
RETX = [sp++];
SYSCFG = [sp++];
CYCLES2 = [sp++];
CYCLES = [sp++];
ASTAT = [sp++];
RETS = [sp++];
LB1 = [sp++];
LB0 = [sp++];
LT1 = [sp++];
LT0 = [sp++];
LC1 = [sp++];
LC0 = [sp++];
a1.w = [sp++];
a1.x = [sp++];
a0.w = [sp++];
a0.x = [sp++];
b3 = [sp++];
b2 = [sp++];
b1 = [sp++];
b0 = [sp++];
l3 = [sp++];
l2 = [sp++];
l1 = [sp++];
l0 = [sp++];
m3 = [sp++];
m2 = [sp++];
m1 = [sp++];
m0 = [sp++];
i3 = [sp++];
i2 = [sp++];
i1 = [sp++];
i0 = [sp++];
usp = [sp++];
fp = [sp++];
(R7:0, P5:0) = [sp++];
bfin_core_mmr_restore;
bfin_sys_mmr_restore;
bfin_cpu_reg_restore;
[--sp] = RETI; /* Clear Global Interrupt Disable */
SP += 4;
......
......@@ -19,20 +19,33 @@
#include <asm/gpio.h>
#include <asm/dma.h>
#include <asm/dpmc.h>
#include <asm/pm.h>
#ifdef CONFIG_BF60x
struct bfin_cpu_pm_fns *bfin_cpu_pm;
#endif
void bfin_pm_suspend_standby_enter(void)
{
#ifndef CONFIG_BF60x
bfin_pm_standby_setup();
#endif
#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#ifdef CONFIG_BF60x
bfin_cpu_pm->enter(PM_SUSPEND_STANDBY);
#else
# ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
# else
sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
# endif
#endif
#ifndef CONFIG_BF60x
bfin_pm_standby_restore();
#endif
#ifndef CONFIG_BF60x
#ifdef SIC_IWR0
bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
# ifdef SIC_IWR1
......@@ -52,6 +65,8 @@ void bfin_pm_suspend_standby_enter(void)
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
#endif
}
int bf53x_suspend_l1_mem(unsigned char *memptr)
......@@ -83,10 +98,13 @@ int bf53x_resume_l1_mem(unsigned char *memptr)
}
#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
# ifdef CONFIG_BF60x
__attribute__((l1_text))
# endif
static void flushinv_all_dcache(void)
{
u32 way, bank, subbank, set;
u32 status, addr;
register u32 way, bank, subbank, set;
register u32 status, addr;
u32 dmem_ctl = bfin_read_DMEM_CONTROL();
for (bank = 0; bank < 2; ++bank) {
......@@ -133,7 +151,11 @@ int bfin_pm_suspend_mem_enter(void)
return -ENOMEM;
}
#ifndef CONFIG_BF60x
wakeup = bfin_read_VR_CTL() & ~FREQ;
#else
#endif
wakeup |= SCKELOW;
#ifdef CONFIG_PM_BFIN_WAKE_PH6
......@@ -159,7 +181,11 @@ int bfin_pm_suspend_mem_enter(void)
_disable_icplb();
bf53x_suspend_l1_mem(memptr);
#ifndef CONFIG_BF60x
do_hibernate(wakeup | vr_wakeup); /* See you later! */
#else
bfin_cpu_pm->enter(PM_SUSPEND_MEM);
#endif
bf53x_resume_l1_mem(memptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment