mvebu soc changes for v4.3 (part #1)

- Extend suspend to RAM support in order to add new mvebu SoC
 - Add standby support for all Armada 3xx/XP SoCs
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iEYEABECAAYFAlW7OiYACgkQCwYYjhRyO9WEIgCglOTwI09tYdDRxrW3gETI8RbM
 cX8An3XYyaPavLOh58x9UMmiXwTBU5EM
 =YmnC
 -----END PGP SIGNATURE-----

Merge tag 'mvebu-soc-4.3-1' of git://git.infradead.org/linux-mvebu into next/soc

mvebu soc changes for v4.3 (part #1)

- Extend suspend to RAM support in order to add new mvebu SoC
- Add standby support for all Armada 3xx/XP SoCs

* tag 'mvebu-soc-4.3-1' of git://git.infradead.org/linux-mvebu:
  ARM: mvebu: Warn about the wake-up sources not taken into account in suspend
  ARM: mvebu: Add standby support
  ARM: mvebu: Use __init for the PM initialization functions
  ARM: mvebu: prepare pm-board.c for the introduction of Armada 38x support
  ARM: mvebu: prepare mvebu_pm_store_bootinfo() to support multiple SoCs
  ARM: mvebu: do not check machine in mvebu_pm_init()
  ARM: mvebu: prepare set_cpu_coherent() for future extension

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2015-08-05 11:09:02 +02:00
commit f9fa55b970
4 changed files with 103 additions and 39 deletions

View File

@ -65,18 +65,6 @@ static const struct of_device_id of_coherency_table[] = {
int ll_enable_coherency(void); int ll_enable_coherency(void);
void ll_add_cpu_to_smp_group(void); void ll_add_cpu_to_smp_group(void);
int set_cpu_coherent(void)
{
if (!coherency_base) {
pr_warn("Can't make current CPU cache coherent.\n");
pr_warn("Coherency fabric is not initialized\n");
return 1;
}
ll_add_cpu_to_smp_group();
return ll_enable_coherency();
}
static int mvebu_hwcc_notifier(struct notifier_block *nb, static int mvebu_hwcc_notifier(struct notifier_block *nb,
unsigned long event, void *__dev) unsigned long event, void *__dev)
{ {
@ -206,6 +194,23 @@ static int coherency_type(void)
return type; return type;
} }
int set_cpu_coherent(void)
{
int type = coherency_type();
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) {
if (!coherency_base) {
pr_warn("Can't make current CPU cache coherent.\n");
pr_warn("Coherency fabric is not initialized\n");
return 1;
}
ll_add_cpu_to_smp_group();
return ll_enable_coherency();
}
return 0;
}
int coherency_available(void) int coherency_available(void)
{ {
return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; return coherency_type() != COHERENCY_FABRIC_TYPE_NONE;

View File

@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
void __iomem *mvebu_get_scu_base(void); void __iomem *mvebu_get_scu_base(void);
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)); int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
u32 srcmd));
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Board-level suspend/resume support. * Board-level suspend/resume support.
* *
* Copyright (C) 2014 Marvell * Copyright (C) 2014-2015 Marvell
* *
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
* *
@ -20,27 +20,27 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "common.h" #include "common.h"
#define ARMADA_XP_GP_PIC_NR_GPIOS 3 #define ARMADA_PIC_NR_GPIOS 3
static void __iomem *gpio_ctrl; static void __iomem *gpio_ctrl;
static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; static int pic_gpios[ARMADA_PIC_NR_GPIOS];
static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS];
static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd)
{ {
u32 reg, ackcmd; u32 reg, ackcmd;
int i; int i;
/* Put 001 as value on the GPIOs */ /* Put 001 as value on the GPIOs */
reg = readl(gpio_ctrl); reg = readl(gpio_ctrl);
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
reg &= ~BIT(pic_raw_gpios[i]); reg &= ~BIT(pic_raw_gpios[i]);
reg |= BIT(pic_raw_gpios[0]); reg |= BIT(pic_raw_gpios[0]);
writel(reg, gpio_ctrl); writel(reg, gpio_ctrl);
/* Prepare writing 111 to the GPIOs */ /* Prepare writing 111 to the GPIOs */
ackcmd = readl(gpio_ctrl); ackcmd = readl(gpio_ctrl);
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
ackcmd |= BIT(pic_raw_gpios[i]); ackcmd |= BIT(pic_raw_gpios[i]);
srcmd = cpu_to_le32(srcmd); srcmd = cpu_to_le32(srcmd);
@ -76,7 +76,7 @@ static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
[ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1"); [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
} }
static int mvebu_armada_xp_gp_pm_init(void) static int __init mvebu_armada_pm_init(void)
{ {
struct device_node *np; struct device_node *np;
struct device_node *gpio_ctrl_np; struct device_node *gpio_ctrl_np;
@ -89,7 +89,7 @@ static int mvebu_armada_xp_gp_pm_init(void)
if (!np) if (!np)
return -ENODEV; return -ENODEV;
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) { for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) {
char *name; char *name;
struct of_phandle_args args; struct of_phandle_args args;
@ -134,11 +134,19 @@ static int mvebu_armada_xp_gp_pm_init(void)
if (!gpio_ctrl) if (!gpio_ctrl)
return -ENOMEM; return -ENOMEM;
mvebu_pm_init(mvebu_armada_xp_gp_pm_enter); mvebu_pm_suspend_init(mvebu_armada_pm_enter);
out: out:
of_node_put(np); of_node_put(np);
return ret; return ret;
} }
late_initcall(mvebu_armada_xp_gp_pm_init); /*
* Registering the mvebu_board_pm_enter callback must be done before
* the platform_suspend_ops will be registered. In the same time we
* also need to have the gpio devices registered. That's why we use a
* device_initcall_sync which is called after all the device_initcall
* (used by the gpio device) but before the late_initcall (used to
* register the platform_suspend_ops)
*/
device_initcall_sync(mvebu_armada_pm_init);

View File

@ -105,12 +105,10 @@ static phys_addr_t mvebu_internal_reg_base(void)
return of_translate_address(np, in_addr); return of_translate_address(np, in_addr);
} }
static void mvebu_pm_store_bootinfo(void) static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr)
{ {
u32 *store_addr;
phys_addr_t resume_pc; phys_addr_t resume_pc;
store_addr = phys_to_virt(BOOT_INFO_ADDR);
resume_pc = virt_to_phys(armada_370_xp_cpu_resume); resume_pc = virt_to_phys(armada_370_xp_cpu_resume);
/* /*
@ -151,14 +149,30 @@ static void mvebu_pm_store_bootinfo(void)
writel(BOOT_MAGIC_LIST_END, store_addr); writel(BOOT_MAGIC_LIST_END, store_addr);
} }
static int mvebu_pm_enter(suspend_state_t state) static int mvebu_pm_store_bootinfo(void)
{ {
if (state != PM_SUSPEND_MEM) u32 *store_addr;
return -EINVAL;
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;
}
static int mvebu_enter_suspend(void)
{
int ret;
ret = mvebu_pm_store_bootinfo();
if (ret)
return ret;
cpu_pm_enter(); cpu_pm_enter();
mvebu_pm_store_bootinfo();
cpu_suspend(0, mvebu_pm_powerdown); cpu_suspend(0, mvebu_pm_powerdown);
outer_resume(); outer_resume();
@ -168,23 +182,62 @@ static int mvebu_pm_enter(suspend_state_t state)
set_cpu_coherent(); set_cpu_coherent();
cpu_pm_exit(); cpu_pm_exit();
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:
pr_warn("Entering suspend to RAM. Only special wake-up sources will resume the system\n");
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;
return 0; return 0;
} }
static const struct platform_suspend_ops mvebu_pm_ops = { static const struct platform_suspend_ops mvebu_pm_ops = {
.enter = mvebu_pm_enter, .enter = mvebu_pm_enter,
.valid = suspend_valid_only_mem, .valid = mvebu_pm_valid,
}; };
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) 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))
{ {
struct device_node *np; struct device_node *np;
struct resource res; struct resource res;
if (!of_machine_is_compatible("marvell,armadaxp"))
return -ENODEV;
np = of_find_compatible_node(NULL, NULL, np = of_find_compatible_node(NULL, NULL,
"marvell,armada-xp-sdram-controller"); "marvell,armada-xp-sdram-controller");
if (!np) if (!np)
@ -212,7 +265,5 @@ int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
mvebu_board_pm_enter = board_pm_enter; mvebu_board_pm_enter = board_pm_enter;
suspend_set_ops(&mvebu_pm_ops);
return 0; return 0;
} }