ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
/*
* Suspend / resume support . Currently supporting Armada XP only .
*
* Copyright ( C ) 2014 Marvell
*
* Thomas Petazzoni < thomas . petazzoni @ free - electrons . com >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/cpu_pm.h>
# include <linux/delay.h>
# include <linux/gpio.h>
# include <linux/io.h>
# include <linux/kernel.h>
# include <linux/mbus.h>
# include <linux/of_address.h>
# include <linux/suspend.h>
# include <asm/cacheflush.h>
# include <asm/outercache.h>
# include <asm/suspend.h>
# include "coherency.h"
2016-06-07 22:03:46 +03:00
# include "common.h"
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
# include "pmsu.h"
# define SDRAM_CONFIG_OFFS 0x0
# define SDRAM_CONFIG_SR_MODE_BIT BIT(24)
# define SDRAM_OPERATION_OFFS 0x18
# define SDRAM_OPERATION_SELF_REFRESH 0x7
# define SDRAM_DLB_EVICTION_OFFS 0x30c
# define SDRAM_DLB_EVICTION_THRESHOLD_MASK 0xff
static void ( * mvebu_board_pm_enter ) ( void __iomem * sdram_reg , u32 srcmd ) ;
static void __iomem * sdram_ctrl ;
static int mvebu_pm_powerdown ( unsigned long data )
{
u32 reg , srcmd ;
flush_cache_all ( ) ;
outer_flush_all ( ) ;
/*
* Issue a Data Synchronization Barrier instruction to ensure
* that all state saving has been completed .
*/
dsb ( ) ;
/* Flush the DLB and wait ~7 usec */
reg = readl ( sdram_ctrl + SDRAM_DLB_EVICTION_OFFS ) ;
reg & = ~ SDRAM_DLB_EVICTION_THRESHOLD_MASK ;
writel ( reg , sdram_ctrl + SDRAM_DLB_EVICTION_OFFS ) ;
udelay ( 7 ) ;
/* Set DRAM in battery backup mode */
reg = readl ( sdram_ctrl + SDRAM_CONFIG_OFFS ) ;
reg & = ~ SDRAM_CONFIG_SR_MODE_BIT ;
writel ( reg , sdram_ctrl + SDRAM_CONFIG_OFFS ) ;
/* Prepare to go to self-refresh */
srcmd = readl ( sdram_ctrl + SDRAM_OPERATION_OFFS ) ;
srcmd & = ~ 0x1F ;
srcmd | = SDRAM_OPERATION_SELF_REFRESH ;
mvebu_board_pm_enter ( sdram_ctrl + SDRAM_OPERATION_OFFS , srcmd ) ;
return 0 ;
}
# define BOOT_INFO_ADDR 0x3000
# define BOOT_MAGIC_WORD 0xdeadb002
# define BOOT_MAGIC_LIST_END 0xffffffff
/*
* Those registers are accessed before switching the internal register
* base , which is why we hardcode the 0xd0000000 base address , the one
* used by the SoC out of reset .
*/
# define MBUS_WINDOW_12_CTRL 0xd00200b0
# define MBUS_INTERNAL_REG_ADDRESS 0xd0020080
# define SDRAM_WIN_BASE_REG(x) (0x20180 + (0x8*x))
# define SDRAM_WIN_CTRL_REG(x) (0x20184 + (0x8*x))
static phys_addr_t mvebu_internal_reg_base ( void )
{
struct device_node * np ;
__be32 in_addr [ 2 ] ;
np = of_find_node_by_name ( NULL , " internal-regs " ) ;
BUG_ON ( ! np ) ;
/*
* Ask the DT what is the internal register address on this
* platform . In the mvebu - mbus DT binding , 0xf0010000
* corresponds to the internal register window .
*/
in_addr [ 0 ] = cpu_to_be32 ( 0xf0010000 ) ;
in_addr [ 1 ] = 0x0 ;
return of_translate_address ( np , in_addr ) ;
}
2015-07-08 18:02:32 +03:00
static void mvebu_pm_store_armadaxp_bootinfo ( u32 * store_addr )
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
{
phys_addr_t resume_pc ;
2017-01-15 05:59:29 +03:00
resume_pc = __pa_symbol ( armada_370_xp_cpu_resume ) ;
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
/*
* The bootloader expects the first two words to be a magic
* value ( BOOT_MAGIC_WORD ) , followed by the address of the
* resume code to jump to . Then , it expects a sequence of
* ( address , value ) pairs , which can be used to restore the
* value of certain registers . This sequence must end with the
* BOOT_MAGIC_LIST_END magic value .
*/
writel ( BOOT_MAGIC_WORD , store_addr + + ) ;
writel ( resume_pc , store_addr + + ) ;
/*
* Some platforms remap their internal register base address
* to 0xf1000000 . However , out of reset , window 12 starts at
* 0xf0000000 and ends at 0xf7ffffff , which would overlap with
* the internal registers . Therefore , disable window 12.
*/
writel ( MBUS_WINDOW_12_CTRL , store_addr + + ) ;
writel ( 0x0 , store_addr + + ) ;
/*
* Set the internal register base address to the value
* expected by Linux , as read from the Device Tree .
*/
writel ( MBUS_INTERNAL_REG_ADDRESS , store_addr + + ) ;
writel ( mvebu_internal_reg_base ( ) , store_addr + + ) ;
/*
* Ask the mvebu - mbus driver to store the SDRAM window
* configuration , which has to be restored by the bootloader
* before re - entering the kernel on resume .
*/
store_addr + = mvebu_mbus_save_cpu_target ( store_addr ) ;
writel ( BOOT_MAGIC_LIST_END , store_addr ) ;
}
2015-07-08 18:02:32 +03:00
static int mvebu_pm_store_bootinfo ( void )
{
u32 * store_addr ;
store_addr = phys_to_virt ( BOOT_INFO_ADDR ) ;
if ( of_machine_is_compatible ( " marvell,armadaxp " ) )
mvebu_pm_store_armadaxp_bootinfo ( store_addr ) ;
else
return - ENODEV ;
return 0 ;
}
2015-07-03 14:55:51 +03:00
static int mvebu_enter_suspend ( void )
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
{
2015-07-08 18:02:32 +03:00
int ret ;
ret = mvebu_pm_store_bootinfo ( ) ;
if ( ret )
return ret ;
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
cpu_pm_enter ( ) ;
cpu_suspend ( 0 , mvebu_pm_powerdown ) ;
outer_resume ( ) ;
mvebu_v7_pmsu_idle_exit ( ) ;
set_cpu_coherent ( ) ;
cpu_pm_exit ( ) ;
2015-07-03 14:55:51 +03:00
return 0 ;
}
static int mvebu_pm_enter ( suspend_state_t state )
{
switch ( state ) {
case PM_SUSPEND_STANDBY :
cpu_do_idle ( ) ;
break ;
case PM_SUSPEND_MEM :
2015-07-03 14:55:53 +03:00
pr_warn ( " Entering suspend to RAM. Only special wake-up sources will resume the system \n " ) ;
2015-07-03 14:55:51 +03:00
return mvebu_enter_suspend ( ) ;
default :
return - EINVAL ;
}
return 0 ;
}
static int mvebu_pm_valid ( suspend_state_t state )
{
if ( state = = PM_SUSPEND_STANDBY )
return 1 ;
if ( state = = PM_SUSPEND_MEM & & mvebu_board_pm_enter ! = NULL )
return 1 ;
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
return 0 ;
}
static const struct platform_suspend_ops mvebu_pm_ops = {
. enter = mvebu_pm_enter ,
2015-07-03 14:55:51 +03:00
. valid = mvebu_pm_valid ,
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
} ;
2015-07-03 14:55:51 +03:00
static int __init mvebu_pm_init ( void )
{
if ( ! of_machine_is_compatible ( " marvell,armadaxp " ) & &
! of_machine_is_compatible ( " marvell,armada370 " ) & &
! of_machine_is_compatible ( " marvell,armada380 " ) & &
! of_machine_is_compatible ( " marvell,armada390 " ) )
return - ENODEV ;
suspend_set_ops ( & mvebu_pm_ops ) ;
return 0 ;
}
late_initcall ( mvebu_pm_init ) ;
int __init mvebu_pm_suspend_init ( void ( * board_pm_enter ) ( void __iomem * sdram_reg ,
u32 srcmd ) )
ARM: mvebu: implement suspend/resume support for Armada XP
This commit implements the core of the platform code to enable
suspend/resume on Armada XP. It registers the platform_suspend_ops
structure, and implements the ->enter() hook of this structure.
It is worth mentioning that this commit only provides the SoC-level
part of suspend/resume, which calls into some board-specific code
provided in a follow-up commit.
The most important thing that this SoC-level code has to do is to
build an in-memory structure that contains a magic number, the return
address in the kernel after resume, and a set of address/value
pairs. This structure is used by the bootloader to restore a certain
number of registers (according to the set of address/value pairs) and
then jump back into the kernel at the provided location.
The code also puts the SDRAM into self-refresh mode, before calling
into board-specific code to actually enter the suspend to RAM state.
[ jac - add email exchange between Andrew Lunn and Thomas Petazzoni to better
describe who consumes the address/value pairs ]
> > Is this a well defined mechanism supported by mainline uboot, barebox
> > etc. Or is it some Marvell extension to their uboot?
>
> As far as I know, it is a Marvell extension to their "binary header",
> so it's done even before U-Boot starts. Since the hardware needs
> assistance from the bootloader to do suspend/resume, there is
> necessarily a certain amount of cooperation/agreement needed by what
> the kernel does and what the bootloader expects. I'm not sure there's
> any "standard" mechanism here. Do you know of any?
>
> I know the suspend/resume on the Blackfin architecture works the same
> way (at least it used to work that way years ago when I did a bit of
> Blackfin stuff). And here as well, there was some cooperation between
> the kernel and the bootloader. See
> arch/blackfin/mach-common/dpmc_modes.S, function do_hibernate() at the
> end.
>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1416585613-2113-10-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-11-21 19:00:06 +03:00
{
struct device_node * np ;
struct resource res ;
np = of_find_compatible_node ( NULL , NULL ,
" marvell,armada-xp-sdram-controller " ) ;
if ( ! np )
return - ENODEV ;
if ( of_address_to_resource ( np , 0 , & res ) ) {
of_node_put ( np ) ;
return - ENODEV ;
}
if ( ! request_mem_region ( res . start , resource_size ( & res ) ,
np - > full_name ) ) {
of_node_put ( np ) ;
return - EBUSY ;
}
sdram_ctrl = ioremap ( res . start , resource_size ( & res ) ) ;
if ( ! sdram_ctrl ) {
release_mem_region ( res . start , resource_size ( & res ) ) ;
of_node_put ( np ) ;
return - ENOMEM ;
}
of_node_put ( np ) ;
mvebu_board_pm_enter = board_pm_enter ;
return 0 ;
}