mirror of https://gitee.com/openkylin/linux.git
mvebu SoC changes for v3.17
- 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTsqSHAAoJEP45WPkGe8Zn/6QP/2cTEIpMUDVMHCIPqyu32xNX 3uprZuay6hL5vyLOM/p2iUHLGyMVKvEVVWJuB2bGZX9Nf47Uq92PQ4MEGxS7xJYU EKh8qjX3rQBFpsX1mOyP4XStlYxI5QxM3Jie2n2lquo5mxMMNNU8FcNWWMw02W0g EfyKwtxNRBkZi8KhgvDDGvE+Oe6qB394p/erFDaP8s9vLbGisoX/prnqBEYOWbAA e8qy338lSVu/if/Q4U4ffjBRXFShw1uJK+AHS9xEH2veuBisR3FaHcIqvgYpeMqx sIJWVyNaqWFs3kEAp4TlEkoEGUIc1Z/pL76WK69mgpnCO3X0OtnNFlrwMqb8rAwg 9ziHN9uxSmxcjSLeYlroCxHzt8XKZ0UPmPASZq78Sl/q9Gr0V6bPTPusUYPKDln4 uR7Px49Vvuc1ijn2mWRAQMW9wvDGCgUw8u3nhOHLktH2osWfD41SjAmbLEnysP// 7j3Rw+auxtbyFrKGQDfVon+l/yUrUT9jXW6yq7/ON/YpT4OSJTHWz19nvokyCmW1 aH8qlKS2oMy1ZfncWgHjgVCREmQP9lSfxfpqsHLxPVRPDuyhwp10EN3JeO+9MS85 Vf9YveGiYWuGhkZtYrTy8qFMLoHOaTum5HVONNor0KIlUpeC5Epc7G2jO0P/Nmfx roK5zlcKzTGFyVZKDuur =Uq4l -----END PGP SIGNATURE----- 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: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
b3c20e9832
|
@ -83,7 +83,9 @@ EBU Armada family
|
|||
88F6710
|
||||
88F6707
|
||||
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:
|
||||
88F6720
|
||||
|
|
|
@ -96,4 +96,11 @@ config MACH_KIRKWOOD
|
|||
Say 'Y' here if you want your kernel to support boards based
|
||||
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
|
||||
|
|
|
@ -9,8 +9,8 @@ obj-y += system-controller.o mvebu-soc-id.o
|
|||
ifeq ($(CONFIG_MACH_MVEBU_V7),y)
|
||||
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_HOTPLUG_CPU) += hotplug.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_MACH_DOVE) += dove.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);
|
|||
extern struct smp_operations armada_xp_smp_ops;
|
||||
#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 */
|
||||
|
|
|
@ -118,8 +118,16 @@ static void __init thermal_quirk(void)
|
|||
{
|
||||
struct device_node *np;
|
||||
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;
|
||||
|
||||
for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
|
||||
|
@ -153,7 +161,8 @@ static void __init thermal_quirk(void)
|
|||
|
||||
/*
|
||||
* 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->name = kstrdup("compatible", GFP_KERNEL);
|
||||
|
|
|
@ -13,4 +13,9 @@
|
|||
#ifndef __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
|
||||
|
|
|
@ -21,7 +21,6 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd);
|
|||
int mvebu_cpu_reset_deassert(int cpu);
|
||||
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 armada_xp_cpu_die(unsigned int cpu);
|
||||
int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,7 +67,7 @@ static int mvebu_cpu_reset_map(struct device_node *np, int res_idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int __init mvebu_cpu_reset_init(void)
|
||||
static int __init mvebu_cpu_reset_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int res_idx;
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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)
|
|||
kirkwood_pm_init();
|
||||
kirkwood_dt_eth_fixup();
|
||||
|
||||
if (of_machine_is_compatible("lacie,netxbig"))
|
||||
netxbig_init();
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include "common.h"
|
||||
#include "mvebu-soc-id.h"
|
||||
|
||||
#define PCIE_DEV_ID_OFF 0x0
|
||||
|
@ -51,10 +52,10 @@ int mvebu_get_soc_id(u32 *dev, u32 *rev)
|
|||
*rev = soc_rev;
|
||||
return 0;
|
||||
} 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;
|
||||
int ret = 0;
|
||||
|
@ -129,6 +130,22 @@ static int __init mvebu_soc_id_init(void)
|
|||
|
||||
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);
|
||||
|
||||
static int __init mvebu_soc_device(void)
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* 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 @@
|
|||
extern unsigned char armada_375_smp_cpu1_enable_code_end;
|
||||
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;
|
||||
|
||||
|
@ -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 = {
|
||||
.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",
|
||||
|
|
|
@ -78,6 +78,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
|
||||
hw_cpu = cpu_logical_map(cpu);
|
||||
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);
|
||||
if (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)
|
|||
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)
|
||||
{
|
||||
unsigned int ncores = num_possible_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");
|
||||
}
|
||||
|
||||
#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 = {
|
||||
.smp_init_cpus = armada_xp_smp_init_cpus,
|
||||
.smp_prepare_cpus = armada_xp_smp_prepare_cpus,
|
||||
.smp_boot_secondary = armada_xp_boot_secondary,
|
||||
.smp_secondary_init = armada_xp_secondary_init,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = armada_xp_cpu_die,
|
||||
.cpu_kill = armada_xp_cpu_kill,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -148,13 +148,13 @@ static void armada_370_xp_cpu_resume(void)
|
|||
}
|
||||
|
||||
/* 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());
|
||||
u32 reg;
|
||||
|
||||
if (pmsu_mp_base == NULL)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Adjust the PMSU configuration to wait for WFI signal, enable
|
||||
|
@ -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 |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
|
||||
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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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 */
|
||||
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());
|
||||
u32 reg;
|
||||
|
@ -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());
|
||||
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume);
|
||||
} else if (action == CPU_PM_EXIT) {
|
||||
armada_370_xp_pmsu_idle_restore();
|
||||
armada_370_xp_pmsu_idle_exit();
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
@ -263,7 +258,7 @@ static struct notifier_block armada_370_xp_cpu_pm_notifier = {
|
|||
.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;
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ struct mvebu_system_controller {
|
|||
u32 system_soft_reset;
|
||||
|
||||
u32 resume_boot_addr;
|
||||
|
||||
u32 dev_id;
|
||||
u32 rev_id;
|
||||
};
|
||||
static struct mvebu_system_controller *mvebu_sc;
|
||||
|
||||
|
@ -47,6 +50,8 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = {
|
|||
.system_soft_reset_offset = 0x64,
|
||||
.rstoutn_mask_reset_out_en = 0x1,
|
||||
.system_soft_reset = 0x1,
|
||||
.dev_id = 0x38,
|
||||
.rev_id = 0x3c,
|
||||
};
|
||||
|
||||
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,
|
||||
.system_soft_reset = 0x1,
|
||||
.resume_boot_addr = 0xd4,
|
||||
.dev_id = 0x38,
|
||||
.rev_id = 0x3c,
|
||||
};
|
||||
|
||||
static const struct mvebu_system_controller orion_system_controller = {
|
||||
|
@ -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
|
||||
void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue