Commit 1efc80b5 authored by Michael Hennerich's avatar Michael Hennerich Committed by Bryan Wu

Blackfin arch: Functional power management support

Enable: PM_SUSPEND_MEM -> Blackfin Hibernate to SDRAM
This feature requires a special bootloader (u-boot)
supporting return from hibernate.
Signed-off-by: default avatarMichael Hennerich <michael.hennerich@analog.com>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent 4f13f548
...@@ -880,7 +880,7 @@ config ARCH_SUSPEND_POSSIBLE ...@@ -880,7 +880,7 @@ config ARCH_SUSPEND_POSSIBLE
depends on !SMP depends on !SMP
choice choice
prompt "Default Power Saving Mode" prompt "Standby Power Saving Mode"
depends on PM depends on PM
default PM_BFIN_SLEEP_DEEPER default PM_BFIN_SLEEP_DEEPER
config PM_BFIN_SLEEP_DEEPER config PM_BFIN_SLEEP_DEEPER
...@@ -899,6 +899,8 @@ config PM_BFIN_SLEEP_DEEPER ...@@ -899,6 +899,8 @@ config PM_BFIN_SLEEP_DEEPER
normal during Sleep Deeper, due to the reduced SCLK frequency. normal during Sleep Deeper, due to the reduced SCLK frequency.
When in the sleep mode, system DMA access to L1 memory is not supported. When in the sleep mode, system DMA access to L1 memory is not supported.
If unsure, select "Sleep Deeper".
config PM_BFIN_SLEEP config PM_BFIN_SLEEP
bool "Sleep" bool "Sleep"
help help
...@@ -906,15 +908,17 @@ config PM_BFIN_SLEEP ...@@ -906,15 +908,17 @@ config PM_BFIN_SLEEP
dissipation by disabling the clock to the processor core (CCLK). dissipation by disabling the clock to the processor core (CCLK).
The PLL and system clock (SCLK), however, continue to operate in The PLL and system clock (SCLK), however, continue to operate in
this mode. Typically an external event or RTC activity will wake this mode. Typically an external event or RTC activity will wake
up the processor. When in the sleep mode, up the processor. When in the sleep mode, system DMA access to L1
system DMA access to L1 memory is not supported. memory is not supported.
If unsure, select "Sleep Deeper".
endchoice endchoice
config PM_WAKEUP_BY_GPIO config PM_WAKEUP_BY_GPIO
bool "Cause Wakeup Event by GPIO" bool "Allow Wakeup from Standby by GPIO"
config PM_WAKEUP_GPIO_NUMBER config PM_WAKEUP_GPIO_NUMBER
int "Wakeup GPIO number" int "GPIO number"
range 0 47 range 0 47
depends on PM_WAKEUP_BY_GPIO depends on PM_WAKEUP_BY_GPIO
default 2 if BFIN537_STAMP default 2 if BFIN537_STAMP
...@@ -935,6 +939,58 @@ config PM_WAKEUP_GPIO_POLAR_EDGE_B ...@@ -935,6 +939,58 @@ config PM_WAKEUP_GPIO_POLAR_EDGE_B
bool "Both EDGE" bool "Both EDGE"
endchoice endchoice
comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
depends on PM
config PM_BFIN_WAKE_RTC
bool "Allow Wake-Up from RESET and on-chip RTC"
depends on PM
default n
help
Enable RTC Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_PH6
bool "Allow Wake-Up from on-chip PHY or PH6 GP"
depends on PM && (BF52x || BF534 || BF536 || BF537)
default n
help
Enable PHY and PH6 GP Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_CAN
bool "Allow Wake-Up from on-chip CAN0/1"
depends on PM && (BF54x || BF534 || BF536 || BF537)
default n
help
Enable CAN0/1 Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_GP
bool "Allow Wake-Up from GPIOs"
depends on PM && BF54x
default n
help
Enable General-Purpose Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_USB
bool "Allow Wake-Up from on-chip USB"
depends on PM && (BF54x || BF52x)
default n
help
Enable USB Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_KEYPAD
bool "Allow Wake-Up from on-chip Keypad"
depends on PM && BF54x
default n
help
Enable Keypad Wake-Up (Voltage Regulator Power-Up)
config PM_BFIN_WAKE_ROTARY
bool "Allow Wake-Up from on-chip Rotary"
depends on PM && BF54x
default n
help
Enable Rotary Wake-Up (Voltage Regulator Power-Up)
endmenu endmenu
menu "CPU Frequency scaling" menu "CPU Frequency scaling"
......
...@@ -472,6 +472,32 @@ unsigned long get_dma_curr_addr(unsigned int channel) ...@@ -472,6 +472,32 @@ unsigned long get_dma_curr_addr(unsigned int channel)
} }
EXPORT_SYMBOL(get_dma_curr_addr); EXPORT_SYMBOL(get_dma_curr_addr);
#ifdef CONFIG_PM
int blackfin_dma_suspend(void)
{
int i;
for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
return -EBUSY;
}
dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
}
return 0;
}
void blackfin_dma_resume(void)
{
int i;
for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
}
#endif
static void *__dma_memcpy(void *dest, const void *src, size_t size) static void *__dma_memcpy(void *dest, const void *src, size_t size)
{ {
int direction; /* 1 - address decrease, 0 - address increase */ int direction; /* 1 - address decrease, 0 - address increase */
......
...@@ -186,7 +186,10 @@ static struct str_ident { ...@@ -186,7 +186,10 @@ static struct str_ident {
char name[RESOURCE_LABEL_SIZE]; char name[RESOURCE_LABEL_SIZE];
} str_ident[MAX_RESOURCES]; } str_ident[MAX_RESOURCES];
#if defined(CONFIG_PM) && !defined(CONFIG_BF54x) #if defined(CONFIG_PM)
#if defined(CONFIG_BF54x)
static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
#else
static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)]; static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
...@@ -206,7 +209,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INT ...@@ -206,7 +209,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INT
#ifdef BF561_FAMILY #ifdef BF561_FAMILY
static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
#endif #endif
#endif
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#if defined(BF548_FAMILY) #if defined(BF548_FAMILY)
...@@ -667,7 +670,7 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type) ...@@ -667,7 +670,7 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
return 0; return 0;
} }
u32 bfin_pm_setup(void) u32 bfin_pm_standby_setup(void)
{ {
u16 bank, mask, i, gpio; u16 bank, mask, i, gpio;
...@@ -679,7 +682,7 @@ u32 bfin_pm_setup(void) ...@@ -679,7 +682,7 @@ u32 bfin_pm_setup(void)
gpio_bankb[bank]->maskb = 0; gpio_bankb[bank]->maskb = 0;
if (mask) { if (mask) {
#ifdef BF537_FAMILY #if defined(BF527_FAMILY) || defined(BF537_FAMILY)
gpio_bank_saved[bank].fer = *port_fer[bank]; gpio_bank_saved[bank].fer = *port_fer[bank];
#endif #endif
gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
...@@ -715,7 +718,7 @@ u32 bfin_pm_setup(void) ...@@ -715,7 +718,7 @@ u32 bfin_pm_setup(void)
return 0; return 0;
} }
void bfin_pm_restore(void) void bfin_pm_standby_restore(void)
{ {
u16 bank, mask, i; u16 bank, mask, i;
...@@ -724,7 +727,7 @@ void bfin_pm_restore(void) ...@@ -724,7 +727,7 @@ void bfin_pm_restore(void)
bank = gpio_bank(i); bank = gpio_bank(i);
if (mask) { if (mask) {
#ifdef BF537_FAMILY #if defined(BF527_FAMILY) || defined(BF537_FAMILY)
*port_fer[bank] = gpio_bank_saved[bank].fer; *port_fer[bank] = gpio_bank_saved[bank].fer;
#endif #endif
gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
...@@ -743,8 +746,111 @@ void bfin_pm_restore(void) ...@@ -743,8 +746,111 @@ void bfin_pm_restore(void)
AWA_DUMMY_READ(maskb); AWA_DUMMY_READ(maskb);
} }
void bfin_gpio_pm_hibernate_suspend(void)
{
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
gpio_bank_saved[bank].fer = *port_fer[bank];
#ifdef BF527_FAMILY
gpio_bank_saved[bank].mux = *port_mux[bank];
#else
if (bank == 0)
gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
#endif
#endif
gpio_bank_saved[bank].data = gpio_bankb[bank]->data;
gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska;
}
AWA_DUMMY_READ(maska);
}
void bfin_gpio_pm_hibernate_restore(void)
{
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
#ifdef BF527_FAMILY
*port_mux[bank] = gpio_bank_saved[bank].mux;
#else
if (bank == 0)
bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
#endif
*port_fer[bank] = gpio_bank_saved[bank].fer;
#endif
gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
| gpio_bank_saved[bank].dir;
gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
}
AWA_DUMMY_READ(maska);
}
#endif #endif
#else /* BF548_FAMILY */ #else /* BF548_FAMILY */
#ifdef CONFIG_PM
u32 bfin_pm_standby_setup(void)
{
return 0;
}
void bfin_pm_standby_restore(void)
{
}
void bfin_gpio_pm_hibernate_suspend(void)
{
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen;
gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set;
}
}
void bfin_gpio_pm_hibernate_restore(void)
{
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen;
gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir;
gpio_array[bank]->port_set = gpio_bank_saved[bank].data
| gpio_bank_saved[bank].dir;
}
}
#endif
unsigned short get_gpio_dir(unsigned gpio) unsigned short get_gpio_dir(unsigned gpio)
{ {
......
This diff is collapsed.
...@@ -38,8 +38,9 @@ ...@@ -38,8 +38,9 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/dpmc.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/dma.h>
#include <asm/dpmc.h>
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H #ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
#define WAKEUP_TYPE PM_WAKE_HIGH #define WAKEUP_TYPE PM_WAKE_HIGH
...@@ -61,16 +62,17 @@ ...@@ -61,16 +62,17 @@
#define WAKEUP_TYPE PM_WAKE_BOTH_EDGES #define WAKEUP_TYPE PM_WAKE_BOTH_EDGES
#endif #endif
void bfin_pm_suspend_standby_enter(void) void bfin_pm_suspend_standby_enter(void)
{ {
unsigned long flags;
#ifdef CONFIG_PM_WAKEUP_BY_GPIO #ifdef CONFIG_PM_WAKEUP_BY_GPIO
gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
#endif #endif
u32 flags;
local_irq_save(flags); local_irq_save(flags);
bfin_pm_setup(); bfin_pm_standby_setup();
#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
...@@ -78,7 +80,7 @@ void bfin_pm_suspend_standby_enter(void) ...@@ -78,7 +80,7 @@ void bfin_pm_suspend_standby_enter(void)
sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#endif #endif
bfin_pm_restore(); bfin_pm_standby_restore();
#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
bfin_write_SIC_IWR0(IWR_ENABLE_ALL); bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
...@@ -93,6 +95,195 @@ void bfin_pm_suspend_standby_enter(void) ...@@ -93,6 +95,195 @@ void bfin_pm_suspend_standby_enter(void)
local_irq_restore(flags); local_irq_restore(flags);
} }
int bf53x_suspend_l1_mem(unsigned char *memptr)
{
dma_memcpy(memptr, (const void *) L1_CODE_START, L1_CODE_LENGTH);
dma_memcpy(memptr + L1_CODE_LENGTH, (const void *) L1_DATA_A_START,
L1_DATA_A_LENGTH);
dma_memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
(const void *) L1_DATA_B_START, L1_DATA_B_LENGTH);
memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH +
L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START,
L1_SCRATCH_LENGTH);
return 0;
}
int bf53x_resume_l1_mem(unsigned char *memptr)
{
dma_memcpy((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
dma_memcpy((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
L1_DATA_A_LENGTH);
dma_memcpy((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
L1_DATA_A_LENGTH, L1_DATA_B_LENGTH);
memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH +
L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH);
return 0;
}
#ifdef CONFIG_BFIN_WB
static void flushinv_all_dcache(void)
{
u32 way, bank, subbank, set;
u32 status, addr;
u32 dmem_ctl = bfin_read_DMEM_CONTROL();
for (bank = 0; bank < 2; ++bank) {
if (!(dmem_ctl & (1 << (DMC1_P - bank))))
continue;
for (way = 0; way < 2; ++way)
for (subbank = 0; subbank < 4; ++subbank)
for (set = 0; set < 64; ++set) {
bfin_write_DTEST_COMMAND(
way << 26 |
bank << 23 |
subbank << 16 |
set << 5
);
CSYNC();
status = bfin_read_DTEST_DATA0();
/* only worry about valid/dirty entries */
if ((status & 0x3) != 0x3)
continue;
/* construct the address using the tag */
addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
/* flush it */
__asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
}
}
}
#endif
static inline void dcache_disable(void)
{
#ifdef CONFIG_BFIN_DCACHE
unsigned long ctrl;
#ifdef CONFIG_BFIN_WB
flushinv_all_dcache();
#endif
SSYNC();
ctrl = bfin_read_DMEM_CONTROL();
ctrl &= ~ENDCPLB;
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
#endif
}
static inline void dcache_enable(void)
{
#ifdef CONFIG_BFIN_DCACHE
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_DMEM_CONTROL();
ctrl |= ENDCPLB;
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
#endif
}
static inline void icache_disable(void)
{
#ifdef CONFIG_BFIN_ICACHE
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_IMEM_CONTROL();
ctrl &= ~ENICPLB;
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
#endif
}
static inline void icache_enable(void)
{
#ifdef CONFIG_BFIN_ICACHE
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= ENICPLB;
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
#endif
}
int bfin_pm_suspend_mem_enter(void)
{
unsigned long flags;
int wakeup, ret;
unsigned char *memptr = kmalloc(L1_CODE_LENGTH + L1_DATA_A_LENGTH
+ L1_DATA_B_LENGTH + L1_SCRATCH_LENGTH,
GFP_KERNEL);
if (memptr == NULL) {
panic("bf53x_suspend_l1_mem malloc failed");
return -ENOMEM;
}
wakeup = bfin_read_VR_CTL() & ~FREQ;
wakeup |= SCKELOW;
/* FIXME: merge this somehow with set_irq_wake */
#ifdef CONFIG_PM_BFIN_WAKE_RTC
wakeup |= WAKE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_PH6
wakeup |= PHYWE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_CAN
wakeup |= CANWE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_GP
wakeup |= GPWE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_USB
wakeup |= USBWE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_KEYPAD
wakeup |= KPADWE;
#endif
#ifdef CONFIG_PM_BFIN_WAKE_ROTARY
wakeup |= ROTWE;
#endif
local_irq_save(flags);
ret = blackfin_dma_suspend();
if (ret) {
local_irq_restore(flags);
kfree(memptr);
return ret;
}
bfin_gpio_pm_hibernate_suspend();
dcache_disable();
icache_disable();
bf53x_suspend_l1_mem(memptr);
do_hibernate(wakeup); /* Goodbye */
bf53x_resume_l1_mem(memptr);
icache_enable();
dcache_enable();
bfin_gpio_pm_hibernate_restore();
blackfin_dma_resume();
local_irq_restore(flags);
kfree(memptr);
return 0;
}
/* /*
* bfin_pm_valid - Tell the PM core that we only support the standby sleep * bfin_pm_valid - Tell the PM core that we only support the standby sleep
* state * state
...@@ -101,7 +292,24 @@ void bfin_pm_suspend_standby_enter(void) ...@@ -101,7 +292,24 @@ void bfin_pm_suspend_standby_enter(void)
*/ */
static int bfin_pm_valid(suspend_state_t state) static int bfin_pm_valid(suspend_state_t state)
{ {
return (state == PM_SUSPEND_STANDBY); return (state == PM_SUSPEND_STANDBY
#ifndef BF533_FAMILY
/*
* On BF533/2/1:
* If we enter Hibernate the SCKE Pin is driven Low,
* so that the SDRAM enters Self Refresh Mode.
* However when the reset sequence that follows hibernate
* state is executed, SCKE is driven High, taking the
* SDRAM out of Self Refresh.
*
* If you reconfigure and access the SDRAM "very quickly",
* you are likely to avoid errors, otherwise the SDRAM
* start losing its contents.
* An external HW workaround is possible using logic gates.
*/
|| state == PM_SUSPEND_MEM
#endif
);
} }
/* /*
...@@ -115,10 +323,9 @@ static int bfin_pm_enter(suspend_state_t state) ...@@ -115,10 +323,9 @@ static int bfin_pm_enter(suspend_state_t state)
case PM_SUSPEND_STANDBY: case PM_SUSPEND_STANDBY:
bfin_pm_suspend_standby_enter(); bfin_pm_suspend_standby_enter();
break; break;
case PM_SUSPEND_MEM: case PM_SUSPEND_MEM:
return -ENOTSUPP; bfin_pm_suspend_mem_enter();
break;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -144,8 +144,16 @@ struct dma_channel { ...@@ -144,8 +144,16 @@ struct dma_channel {
void *data; void *data;
unsigned int dma_enable_flag; unsigned int dma_enable_flag;
unsigned int loopback_flag; unsigned int loopback_flag;
#ifdef CONFIG_PM
unsigned short saved_peripheral_map;
#endif
}; };
#ifdef CONFIG_PM
int blackfin_dma_suspend(void);
void blackfin_dma_resume(void);
#endif
/******************************************************************************* /*******************************************************************************
* DMA API's * DMA API's
*******************************************************************************/ *******************************************************************************/
......
...@@ -7,63 +7,18 @@ ...@@ -7,63 +7,18 @@
#ifndef _BLACKFIN_DPMC_H_ #ifndef _BLACKFIN_DPMC_H_
#define _BLACKFIN_DPMC_H_ #define _BLACKFIN_DPMC_H_
#define SLEEP_MODE 1
#define DEEP_SLEEP_MODE 2
#define ACTIVE_PLL_DISABLED 3
#define FULLON_MODE 4
#define ACTIVE_PLL_ENABLED 5
#define HIBERNATE_MODE 6
#define IOCTL_FULL_ON_MODE _IO('s', 0xA0)
#define IOCTL_ACTIVE_MODE _IO('s', 0xA1)
#define IOCTL_SLEEP_MODE _IO('s', 0xA2)
#define IOCTL_DEEP_SLEEP_MODE _IO('s', 0xA3)
#define IOCTL_HIBERNATE_MODE _IO('s', 0xA4)
#define IOCTL_CHANGE_FREQUENCY _IOW('s', 0xA5, unsigned long)
#define IOCTL_CHANGE_VOLTAGE _IOW('s', 0xA6, unsigned long)
#define IOCTL_SET_CCLK _IOW('s', 0xA7, unsigned long)
#define IOCTL_SET_SCLK _IOW('s', 0xA8, unsigned long)
#define IOCTL_GET_PLLSTATUS _IOW('s', 0xA9, unsigned long)
#define IOCTL_GET_CORECLOCK _IOW('s', 0xAA, unsigned long)
#define IOCTL_GET_SYSTEMCLOCK _IOW('s', 0xAB, unsigned long)
#define IOCTL_GET_VCO _IOW('s', 0xAC, unsigned long)
#define IOCTL_DISABLE_WDOG_TIMER _IO('s', 0xAD)
#define IOCTL_UNMASK_WDOG_WAKEUP_EVENT _IO('s',0xAE)
#define IOCTL_PROGRAM_WDOG_TIMER _IOW('s',0xAF,unsigned long)
#define IOCTL_CLEAR_WDOG_WAKEUP_EVENT _IO('s',0xB0)
#define IOCTL_SLEEP_DEEPER_MODE _IO('s',0xB1)
#define DPMC_MINOR 254
#define ON 0
#define OFF 1
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASSEMBLY__
unsigned long calc_volt(void);
int calc_vlev(int vlt);
unsigned long change_voltage(unsigned long volt);
int calc_msel(int vco_hz);
unsigned long change_frequency(unsigned long vco_mhz);
int set_pll_div(unsigned short sel, unsigned char flag);
int get_vco(void);
unsigned long change_system_clock(unsigned long clock);
unsigned long change_core_clock(unsigned long clock);
unsigned long get_pll_status(void);
void change_baud(int baud);
void fullon_mode(void);
void active_mode(void);
void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2); void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void deep_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2); void deep_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void hibernate_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2); void hibernate_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void sleep_deeper(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2); void sleep_deeper(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void program_wdog_timer(unsigned long); void do_hibernate(int wakeup);
void unmask_wdog_wakeup_evt(void); void set_dram_srfs(void);
void clear_wdog_wakeup_evt(void); void unset_dram_srfs(void);
void disable_wdog_timer(void);
extern unsigned long get_cclk(void); #define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
extern unsigned long get_sclk(void);
struct bfin_dpmc_platform_data { struct bfin_dpmc_platform_data {
const unsigned int *tuple_tab; const unsigned int *tuple_tab;
...@@ -71,8 +26,33 @@ struct bfin_dpmc_platform_data { ...@@ -71,8 +26,33 @@ struct bfin_dpmc_platform_data {
unsigned short vr_settling_time; /* in us */ unsigned short vr_settling_time; /* in us */
}; };
#define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16)) #else
#define PM_PUSH(x) \
R0 = [P0 + (x - SRAM_BASE_ADDRESS)];\
[--SP] = R0;\
#define PM_POP(x) \
R0 = [SP++];\
[P0 + (x - SRAM_BASE_ADDRESS)] = R0;\
#define PM_SYS_PUSH(x) \
R0 = [P0 + (x - PLL_CTL)];\
[--SP] = R0;\
#define PM_SYS_POP(x) \
R0 = [SP++];\
[P0 + (x - PLL_CTL)] = R0;\
#define PM_SYS_PUSH16(x) \
R0 = w[P0 + (x - PLL_CTL)];\
[--SP] = R0;\
#define PM_SYS_POP16(x) \
R0 = [SP++];\
w[P0 + (x - PLL_CTL)] = R0;\
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /*_BLACKFIN_DPMC_H_*/ #endif /*_BLACKFIN_DPMC_H_*/
...@@ -376,8 +376,12 @@ struct gpio_port_t { ...@@ -376,8 +376,12 @@ struct gpio_port_t {
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
unsigned int bfin_pm_setup(void);
void bfin_pm_restore(void); unsigned int bfin_pm_standby_setup(void);
void bfin_pm_standby_restore(void);
void bfin_gpio_pm_hibernate_restore(void);
void bfin_gpio_pm_hibernate_suspend(void);
#ifndef CONFIG_BF54x #ifndef CONFIG_BF54x
#define PM_WAKE_RISING 0x1 #define PM_WAKE_RISING 0x1
...@@ -392,17 +396,8 @@ void gpio_pm_wakeup_free(unsigned gpio); ...@@ -392,17 +396,8 @@ void gpio_pm_wakeup_free(unsigned gpio);
struct gpio_port_s { struct gpio_port_s {
unsigned short data; unsigned short data;
unsigned short data_clear;
unsigned short data_set;
unsigned short toggle;
unsigned short maska; unsigned short maska;
unsigned short maska_clear;
unsigned short maska_set;
unsigned short maska_toggle;
unsigned short maskb; unsigned short maskb;
unsigned short maskb_clear;
unsigned short maskb_set;
unsigned short maskb_toggle;
unsigned short dir; unsigned short dir;
unsigned short polar; unsigned short polar;
unsigned short edge; unsigned short edge;
...@@ -411,10 +406,10 @@ struct gpio_port_s { ...@@ -411,10 +406,10 @@ struct gpio_port_s {
unsigned short fer; unsigned short fer;
unsigned short reserved; unsigned short reserved;
unsigned short mux;
}; };
#endif /*CONFIG_BF54x*/ #endif /*CONFIG_BF54x*/
#endif /*CONFIG_PM*/ #endif /*CONFIG_PM*/
/*********************************************************** /***********************************************************
* *
* FUNCTIONS: Blackfin GPIO Driver * FUNCTIONS: Blackfin GPIO Driver
......
...@@ -209,3 +209,11 @@ struct gpio_port_t { ...@@ -209,3 +209,11 @@ struct gpio_port_t {
unsigned short dummy7; unsigned short dummy7;
unsigned int port_mux; unsigned int port_mux;
}; };
struct gpio_port_s {
unsigned short fer;
unsigned short data;
unsigned short dir;
unsigned short inen;
unsigned int mux;
};
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