Commit b3c20e98 authored by Olof Johansson's avatar Olof Johansson

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

Merge "mvebu SoC changes for v3.17" from Jason Cooper:

- kirkwood
  * add setup file for netxbig LEDs (non-trivial DT binding doesn't exist yet)

- mvebu
  * staticize where needed
  * add CPU hotplug for Armada XP
  * add public datasheet for Armada 370
  * don't apply thermal quirk by default
  * get SoC ID from the system controller when possible

* tag 'mvebu-soc-3.17' of git://git.infradead.org/linux-mvebu:
  ARM: mvebu: Staticize mvebu_cpu_reset_init
  ARM: mvebu: Staticize armada_370_xp_cpu_pm_init
  ARM: mvebu: Staticize armada_375_smp_cpu1_enable_wa
  ARM: mvebu: Use system controller to get the soc id when possible
  ARM: mvebu: Use the a standard errno in mvebu_get_soc_id
  ARM: mvebu: Don't apply the thermal quirk if the SoC revision is unknown
  Documentation: arm: add URLs to public datasheets for the Marvell Armada 370 SoC
  ARM: mvebu: implement CPU hotplug support for Armada XP
  ARM: mvebu: export PMSU idle enter/exit functions
  ARM: mvebu: slightly refactor/rename PMSU idle related functions
  ARM: mvebu: remove stub implementation of CPU hotplug on Armada 375/38x
  ARM: Kirkwood: Add setup file for netxbig LEDs
  ARM: mvebu: mark armada_370_xp_pmsu_idle_prepare() as static
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 98abaf13 e6571474
...@@ -83,7 +83,9 @@ EBU Armada family ...@@ -83,7 +83,9 @@ EBU Armada family
88F6710 88F6710
88F6707 88F6707
88F6W11 88F6W11
Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
Hardware Spec: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-datasheet.pdf
Functional Spec: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
Armada 375 Flavors: Armada 375 Flavors:
88F6720 88F6720
......
...@@ -96,4 +96,11 @@ config MACH_KIRKWOOD ...@@ -96,4 +96,11 @@ config MACH_KIRKWOOD
Say 'Y' here if you want your kernel to support boards based Say 'Y' here if you want your kernel to support boards based
on the Marvell Kirkwood device tree. on the Marvell Kirkwood device tree.
config MACH_NETXBIG
bool "LaCie 2Big and 5Big Network v2"
depends on MACH_KIRKWOOD
help
Say 'Y' here if you want your kernel to support the
LaCie 2Big and 5Big Network v2
endif endif
...@@ -9,8 +9,8 @@ obj-y += system-controller.o mvebu-soc-id.o ...@@ -9,8 +9,8 @@ obj-y += system-controller.o mvebu-soc-id.o
ifeq ($(CONFIG_MACH_MVEBU_V7),y) ifeq ($(CONFIG_MACH_MVEBU_V7),y)
obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif endif
obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o
obj-$(CONFIG_MACH_NETXBIG) += netxbig.o
...@@ -24,4 +24,7 @@ void armada_xp_secondary_startup(void); ...@@ -24,4 +24,7 @@ void armada_xp_secondary_startup(void);
extern struct smp_operations armada_xp_smp_ops; extern struct smp_operations armada_xp_smp_ops;
#endif #endif
int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
void armada_370_xp_pmsu_idle_exit(void);
#endif /* __MACH_ARMADA_370_XP_H */ #endif /* __MACH_ARMADA_370_XP_H */
...@@ -118,8 +118,16 @@ static void __init thermal_quirk(void) ...@@ -118,8 +118,16 @@ static void __init thermal_quirk(void)
{ {
struct device_node *np; struct device_node *np;
u32 dev, rev; u32 dev, rev;
int res;
if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > ARMADA_375_Z1_REV) /*
* The early SoC Z1 revision needs a quirk to be applied in order
* for the thermal controller to work properly. This quirk breaks
* the thermal support if applied on a SoC that doesn't need it,
* so we enforce the SoC revision to be known.
*/
res = mvebu_get_soc_id(&dev, &rev);
if (res < 0 || (res == 0 && rev > ARMADA_375_Z1_REV))
return; return;
for_each_compatible_node(np, NULL, "marvell,armada375-thermal") { for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
...@@ -153,7 +161,8 @@ static void __init thermal_quirk(void) ...@@ -153,7 +161,8 @@ static void __init thermal_quirk(void)
/* /*
* The thermal controller needs some quirk too, so let's change * The thermal controller needs some quirk too, so let's change
* the compatible string to reflect this. * the compatible string to reflect this and allow the driver
* the take the necessary action.
*/ */
prop = kzalloc(sizeof(*prop), GFP_KERNEL); prop = kzalloc(sizeof(*prop), GFP_KERNEL);
prop->name = kstrdup("compatible", GFP_KERNEL); prop->name = kstrdup("compatible", GFP_KERNEL);
......
...@@ -13,4 +13,9 @@ ...@@ -13,4 +13,9 @@
#ifndef __ARCH_MVEBU_BOARD_H #ifndef __ARCH_MVEBU_BOARD_H
#define __ARCH_MVEBU_BOARD_H #define __ARCH_MVEBU_BOARD_H
#ifdef CONFIG_MACH_NETXBIG
void netxbig_init(void);
#else
static inline void netxbig_init(void) {};
#endif
#endif #endif
...@@ -21,7 +21,6 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd); ...@@ -21,7 +21,6 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd);
int mvebu_cpu_reset_deassert(int cpu); int mvebu_cpu_reset_deassert(int cpu);
void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr); void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr);
void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr); void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr);
int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
void armada_xp_cpu_die(unsigned int cpu);
#endif #endif
...@@ -67,7 +67,7 @@ static int mvebu_cpu_reset_map(struct device_node *np, int res_idx) ...@@ -67,7 +67,7 @@ static int mvebu_cpu_reset_map(struct device_node *np, int res_idx)
return 0; return 0;
} }
int __init mvebu_cpu_reset_init(void) static int __init mvebu_cpu_reset_init(void)
{ {
struct device_node *np; struct device_node *np;
int res_idx; int res_idx;
......
/*
* Symmetric Multi Processing (SMP) support for Armada XP
*
* Copyright (C) 2012 Marvell
*
* Lior Amsalem <alior@marvell.com>
* Gregory CLEMENT <gregory.clement@free-electrons.com>
* 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/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <asm/proc-fns.h>
#include "common.h"
/*
* platform-specific code to shutdown a CPU
*
* Called with IRQs disabled
*/
void __ref armada_xp_cpu_die(unsigned int cpu)
{
cpu_do_idle();
/* We should never return from idle */
panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
}
...@@ -180,6 +180,9 @@ static void __init kirkwood_dt_init(void) ...@@ -180,6 +180,9 @@ static void __init kirkwood_dt_init(void)
kirkwood_pm_init(); kirkwood_pm_init();
kirkwood_dt_eth_fixup(); kirkwood_dt_eth_fixup();
if (of_machine_is_compatible("lacie,netxbig"))
netxbig_init();
of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL); of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sys_soc.h> #include <linux/sys_soc.h>
#include "common.h"
#include "mvebu-soc-id.h" #include "mvebu-soc-id.h"
#define PCIE_DEV_ID_OFF 0x0 #define PCIE_DEV_ID_OFF 0x0
...@@ -51,10 +52,10 @@ int mvebu_get_soc_id(u32 *dev, u32 *rev) ...@@ -51,10 +52,10 @@ int mvebu_get_soc_id(u32 *dev, u32 *rev)
*rev = soc_rev; *rev = soc_rev;
return 0; return 0;
} else } else
return -1; return -ENODEV;
} }
static int __init mvebu_soc_id_init(void) static int __init get_soc_id_by_pci(void)
{ {
struct device_node *np; struct device_node *np;
int ret = 0; int ret = 0;
...@@ -129,6 +130,22 @@ static int __init mvebu_soc_id_init(void) ...@@ -129,6 +130,22 @@ static int __init mvebu_soc_id_init(void)
return ret; return ret;
} }
static int __init mvebu_soc_id_init(void)
{
/*
* First try to get the ID and the revision by the system
* register and use PCI registers only if it is not possible
*/
if (!mvebu_system_controller_get_soc_id(&soc_dev_id, &soc_rev)) {
is_id_valid = true;
pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
return 0;
}
return get_soc_id_by_pci();
}
early_initcall(mvebu_soc_id_init); early_initcall(mvebu_soc_id_init);
static int __init mvebu_soc_device(void) static int __init mvebu_soc_device(void)
......
/*
* arch/arm/mach-mvbu/board-netxbig.c
*
* LaCie 2Big and 5Big Network v2 board setup
*
* Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/leds-kirkwood-netxbig.h>
#include "common.h"
/*****************************************************************************
* GPIO extension LEDs
****************************************************************************/
/*
* The LEDs are controlled by a CPLD and can be configured through a GPIO
* extension bus:
*
* - address register : bit [0-2] -> GPIO [47-49]
* - data register : bit [0-2] -> GPIO [44-46]
* - enable register : GPIO 29
*/
static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
.addr = netxbig_v2_gpio_ext_addr,
.num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
.data = netxbig_v2_gpio_ext_data,
.num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
.enable = 29,
};
/*
* Address register selection:
*
* addr | register
* ----------------------------
* 0 | front LED
* 1 | front LED brightness
* 2 | SATA LED brightness
* 3 | SATA0 LED
* 4 | SATA1 LED
* 5 | SATA2 LED
* 6 | SATA3 LED
* 7 | SATA4 LED
*
* Data register configuration:
*
* data | LED brightness
* -------------------------------------------------
* 0 | min (off)
* - | -
* 7 | max
*
* data | front LED mode
* -------------------------------------------------
* 0 | fix off
* 1 | fix blue on
* 2 | fix red on
* 3 | blink blue on=1 sec and blue off=1 sec
* 4 | blink red on=1 sec and red off=1 sec
* 5 | blink blue on=2.5 sec and red on=0.5 sec
* 6 | blink blue on=1 sec and red on=1 sec
* 7 | blink blue on=0.5 sec and blue off=2.5 sec
*
* data | SATA LED mode
* -------------------------------------------------
* 0 | fix off
* 1 | SATA activity blink
* 2 | fix red on
* 3 | blink blue on=1 sec and blue off=1 sec
* 4 | blink red on=1 sec and red off=1 sec
* 5 | blink blue on=2.5 sec and red on=0.5 sec
* 6 | blink blue on=1 sec and red on=1 sec
* 7 | fix blue on
*/
static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 2,
[NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
[NETXBIG_LED_TIMER1] = 4,
[NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
};
static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 1,
[NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
[NETXBIG_LED_TIMER1] = 3,
[NETXBIG_LED_TIMER2] = 7,
};
static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
[NETXBIG_LED_OFF] = 0,
[NETXBIG_LED_ON] = 7,
[NETXBIG_LED_SATA] = 1,
[NETXBIG_LED_TIMER1] = 3,
[NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
};
static struct netxbig_led_timer netxbig_v2_led_timer[] = {
[0] = {
.delay_on = 500,
.delay_off = 500,
.mode = NETXBIG_LED_TIMER1,
},
[1] = {
.delay_on = 500,
.delay_off = 1000,
.mode = NETXBIG_LED_TIMER2,
},
};
#define NETXBIG_LED(_name, maddr, mval, baddr) \
{ .name = _name, \
.mode_addr = maddr, \
.mode_val = mval, \
.bright_addr = baddr }
static struct netxbig_led net2big_v2_leds_ctrl[] = {
NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
};
static struct netxbig_led_platform_data net2big_v2_leds_data = {
.gpio_ext = &netxbig_v2_gpio_ext,
.timer = netxbig_v2_led_timer,
.num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
.leds = net2big_v2_leds_ctrl,
.num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
};
static struct netxbig_led net5big_v2_leds_ctrl[] = {
NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
NETXBIG_LED("net5big-v2:red:sata4", 7, netxbig_v2_red_mled, 2),
};
static struct netxbig_led_platform_data net5big_v2_leds_data = {
.gpio_ext = &netxbig_v2_gpio_ext,
.timer = netxbig_v2_led_timer,
.num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
.leds = net5big_v2_leds_ctrl,
.num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
};
static struct platform_device netxbig_v2_leds = {
.name = "leds-netxbig",
.id = -1,
.dev = {
.platform_data = &net2big_v2_leds_data,
},
};
void __init netxbig_init(void)
{
if (of_machine_is_compatible("lacie,net5big_v2"))
netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
platform_device_register(&netxbig_v2_leds);
}
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
extern unsigned char armada_375_smp_cpu1_enable_code_end; extern unsigned char armada_375_smp_cpu1_enable_code_end;
extern unsigned char armada_375_smp_cpu1_enable_code_start; extern unsigned char armada_375_smp_cpu1_enable_code_start;
void armada_375_smp_cpu1_enable_wa(void) static void armada_375_smp_cpu1_enable_wa(void)
{ {
void __iomem *sram_virt_base; void __iomem *sram_virt_base;
...@@ -91,9 +91,6 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, ...@@ -91,9 +91,6 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
.smp_boot_secondary = mvebu_cortex_a9_boot_secondary, .smp_boot_secondary = mvebu_cortex_a9_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = armada_xp_cpu_die,
#endif
}; };
CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp", CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
......
...@@ -78,6 +78,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -78,6 +78,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
hw_cpu = cpu_logical_map(cpu); hw_cpu = cpu_logical_map(cpu);
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
/*
* This is needed to wake up CPUs in the offline state after
* using CPU hotplug.
*/
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
/*
* This is needed to take secondary CPUs out of reset on the
* initial boot.
*/
ret = mvebu_cpu_reset_deassert(hw_cpu); ret = mvebu_cpu_reset_deassert(hw_cpu);
if (ret) { if (ret) {
pr_warn("unable to boot CPU: %d\n", ret); pr_warn("unable to boot CPU: %d\n", ret);
...@@ -87,6 +98,19 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -87,6 +98,19 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
return 0; return 0;
} }
/*
* When a CPU is brought back online, either through CPU hotplug, or
* because of the boot of a kexec'ed kernel, the PMSU configuration
* for this CPU might be in the deep idle state, preventing this CPU
* from receiving interrupts. Here, we therefore take out the current
* CPU from this state, which was entered by armada_xp_cpu_die()
* below.
*/
static void armada_xp_secondary_init(unsigned int cpu)
{
armada_370_xp_pmsu_idle_exit();
}
static void __init armada_xp_smp_init_cpus(void) static void __init armada_xp_smp_init_cpus(void)
{ {
unsigned int ncores = num_possible_cpus(); unsigned int ncores = num_possible_cpus();
...@@ -122,12 +146,36 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) ...@@ -122,12 +146,36 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
panic("The address for the BootROM is incorrect"); panic("The address for the BootROM is incorrect");
} }
#ifdef CONFIG_HOTPLUG_CPU
static void armada_xp_cpu_die(unsigned int cpu)
{
/*
* CPU hotplug is implemented by putting offline CPUs into the
* deep idle sleep state.
*/
armada_370_xp_pmsu_idle_enter(true);
}
/*
* We need a dummy function, so that platform_can_cpu_hotplug() knows
* we support CPU hotplug. However, the function does not need to do
* anything, because CPUs going offline can enter the deep idle state
* by themselves, without any help from a still alive CPU.
*/
static int armada_xp_cpu_kill(unsigned int cpu)
{
return 1;
}
#endif
struct smp_operations armada_xp_smp_ops __initdata = { struct smp_operations armada_xp_smp_ops __initdata = {
.smp_init_cpus = armada_xp_smp_init_cpus, .smp_init_cpus = armada_xp_smp_init_cpus,
.smp_prepare_cpus = armada_xp_smp_prepare_cpus, .smp_prepare_cpus = armada_xp_smp_prepare_cpus,
.smp_boot_secondary = armada_xp_boot_secondary, .smp_boot_secondary = armada_xp_boot_secondary,
.smp_secondary_init = armada_xp_secondary_init,
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
.cpu_die = armada_xp_cpu_die, .cpu_die = armada_xp_cpu_die,
.cpu_kill = armada_xp_cpu_kill,
#endif #endif
}; };
......
...@@ -148,13 +148,13 @@ static void armada_370_xp_cpu_resume(void) ...@@ -148,13 +148,13 @@ static void armada_370_xp_cpu_resume(void)
} }
/* No locking is needed because we only access per-CPU registers */ /* No locking is needed because we only access per-CPU registers */
void armada_370_xp_pmsu_idle_prepare(bool deepidle) int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
{ {
unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
u32 reg; u32 reg;
if (pmsu_mp_base == NULL) if (pmsu_mp_base == NULL)
return; return -EINVAL;
/* /*
* Adjust the PMSU configuration to wait for WFI signal, enable * Adjust the PMSU configuration to wait for WFI signal, enable
...@@ -183,11 +183,6 @@ void armada_370_xp_pmsu_idle_prepare(bool deepidle) ...@@ -183,11 +183,6 @@ void armada_370_xp_pmsu_idle_prepare(bool deepidle)
reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu)); reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP; reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu)); writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
}
static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle)
{
armada_370_xp_pmsu_idle_prepare(deepidle);
v7_exit_coherency_flush(all); v7_exit_coherency_flush(all);
...@@ -220,11 +215,11 @@ static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle) ...@@ -220,11 +215,11 @@ static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle)
static int armada_370_xp_cpu_suspend(unsigned long deepidle) static int armada_370_xp_cpu_suspend(unsigned long deepidle)
{ {
return cpu_suspend(deepidle, do_armada_370_xp_cpu_suspend); return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
} }
/* No locking is needed because we only access per-CPU registers */ /* No locking is needed because we only access per-CPU registers */
static noinline void armada_370_xp_pmsu_idle_restore(void) void armada_370_xp_pmsu_idle_exit(void)
{ {
unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
u32 reg; u32 reg;
...@@ -253,7 +248,7 @@ static int armada_370_xp_cpu_pm_notify(struct notifier_block *self, ...@@ -253,7 +248,7 @@ static int armada_370_xp_cpu_pm_notify(struct notifier_block *self,
unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume); mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume);
} else if (action == CPU_PM_EXIT) { } else if (action == CPU_PM_EXIT) {
armada_370_xp_pmsu_idle_restore(); armada_370_xp_pmsu_idle_exit();
} }
return NOTIFY_OK; return NOTIFY_OK;
...@@ -263,7 +258,7 @@ static struct notifier_block armada_370_xp_cpu_pm_notifier = { ...@@ -263,7 +258,7 @@ static struct notifier_block armada_370_xp_cpu_pm_notifier = {
.notifier_call = armada_370_xp_cpu_pm_notify, .notifier_call = armada_370_xp_cpu_pm_notify,
}; };
int __init armada_370_xp_cpu_pm_init(void) static int __init armada_370_xp_cpu_pm_init(void)
{ {
struct device_node *np; struct device_node *np;
......
...@@ -39,6 +39,9 @@ struct mvebu_system_controller { ...@@ -39,6 +39,9 @@ struct mvebu_system_controller {
u32 system_soft_reset; u32 system_soft_reset;
u32 resume_boot_addr; u32 resume_boot_addr;
u32 dev_id;
u32 rev_id;
}; };
static struct mvebu_system_controller *mvebu_sc; static struct mvebu_system_controller *mvebu_sc;
...@@ -47,6 +50,8 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = { ...@@ -47,6 +50,8 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = {
.system_soft_reset_offset = 0x64, .system_soft_reset_offset = 0x64,
.rstoutn_mask_reset_out_en = 0x1, .rstoutn_mask_reset_out_en = 0x1,
.system_soft_reset = 0x1, .system_soft_reset = 0x1,
.dev_id = 0x38,
.rev_id = 0x3c,
}; };
static const struct mvebu_system_controller armada_375_system_controller = { static const struct mvebu_system_controller armada_375_system_controller = {
...@@ -55,6 +60,8 @@ static const struct mvebu_system_controller armada_375_system_controller = { ...@@ -55,6 +60,8 @@ static const struct mvebu_system_controller armada_375_system_controller = {
.rstoutn_mask_reset_out_en = 0x1, .rstoutn_mask_reset_out_en = 0x1,
.system_soft_reset = 0x1, .system_soft_reset = 0x1,
.resume_boot_addr = 0xd4, .resume_boot_addr = 0xd4,
.dev_id = 0x38,
.rev_id = 0x3c,
}; };
static const struct mvebu_system_controller orion_system_controller = { static const struct mvebu_system_controller orion_system_controller = {
...@@ -101,6 +108,18 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd) ...@@ -101,6 +108,18 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd)
; ;
} }
int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
{
if (of_machine_is_compatible("marvell,armada380") &&
system_controller_base) {
*dev = readl(system_controller_base + mvebu_sc->dev_id) >> 16;
*rev = (readl(system_controller_base + mvebu_sc->rev_id) >> 8)
& 0xF;
return 0;
} else
return -ENODEV;
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr) void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
{ {
......
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