2012-08-02 16:17:51 +08:00
|
|
|
/*
|
|
|
|
* Power Management Service Unit(PMSU) support for Armada 370/XP platforms.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Marvell
|
|
|
|
*
|
|
|
|
* Yehuda Yitschak <yehuday@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.
|
|
|
|
*
|
|
|
|
* The Armada 370 and Armada XP SOCs have a power management service
|
|
|
|
* unit which is responsible for powering down and waking up CPUs and
|
|
|
|
* other SOC units
|
|
|
|
*/
|
|
|
|
|
2014-04-14 21:50:30 +08:00
|
|
|
#define pr_fmt(fmt) "mvebu-pmsu: " fmt
|
|
|
|
|
2012-08-02 16:17:51 +08:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/smp.h>
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
#include <linux/resource.h>
|
2012-08-02 16:17:51 +08:00
|
|
|
#include <asm/smp_plat.h>
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
#include "common.h"
|
2013-11-07 17:02:38 +08:00
|
|
|
#include "pmsu.h"
|
2012-08-02 16:17:51 +08:00
|
|
|
|
|
|
|
static void __iomem *pmsu_mp_base;
|
|
|
|
|
2014-04-14 21:50:31 +08:00
|
|
|
#define PMSU_BASE_OFFSET 0x100
|
|
|
|
#define PMSU_REG_SIZE 0x1000
|
|
|
|
|
|
|
|
#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124)
|
2012-08-02 16:17:51 +08:00
|
|
|
|
|
|
|
static struct of_device_id of_pmsu_table[] = {
|
2014-04-14 21:50:31 +08:00
|
|
|
{ .compatible = "marvell,armada-370-pmsu", },
|
|
|
|
{ .compatible = "marvell,armada-370-xp-pmsu", },
|
2012-08-02 16:17:51 +08:00
|
|
|
{ /* end of list */ },
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr)
|
|
|
|
{
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
int hw_cpu, ret;
|
2012-08-02 16:17:51 +08:00
|
|
|
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
if (!pmsu_mp_base) {
|
2012-08-02 16:17:51 +08:00
|
|
|
pr_warn("Can't boot CPU. PMSU is uninitialized\n");
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
return -ENODEV;
|
2012-08-02 16:17:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
hw_cpu = cpu_logical_map(cpu_id);
|
|
|
|
|
|
|
|
writel(virt_to_phys(boot_addr), pmsu_mp_base +
|
|
|
|
PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
|
|
|
|
|
ARM: mvebu: start using the CPU reset driver
This commit changes the PMSU driver to no longer map itself the CPU
reset registers, and instead call into the CPU reset driver to
deassert the secondary CPUs for SMP booting.
In order to provide Device Tree backward compatibility, the CPU reset
driver is extended to not only support its official compatible string
"marvell,armada-370-cpu-reset", but to also look at the PMSU
compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset
registers address. This allows old Device Tree to work correctly with
newer kernel versions. Therefore, the CPU reset driver implements the
following logic:
* If one of the normal compatible strings
"marvell,armada-370-cpu-reset" is found, then we map its first
memory resource as the CPU reset registers.
* Otherwise, if none of the normal compatible strings have been
found, we look for the "marvell,armada-370-xp-pmsu" compatible
string, and we map the second memory as the CPU reset registers.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
2014-04-14 21:50:29 +08:00
|
|
|
ret = mvebu_cpu_reset_deassert(hw_cpu);
|
|
|
|
if (ret) {
|
|
|
|
pr_warn("unable to boot CPU: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2012-08-02 16:17:51 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-07 17:02:38 +08:00
|
|
|
static int __init armada_370_xp_pmsu_init(void)
|
2012-08-02 16:17:51 +08:00
|
|
|
{
|
|
|
|
struct device_node *np;
|
2014-04-14 21:50:30 +08:00
|
|
|
struct resource res;
|
|
|
|
int ret = 0;
|
2012-08-02 16:17:51 +08:00
|
|
|
|
|
|
|
np = of_find_matching_node(NULL, of_pmsu_table);
|
2014-04-14 21:50:30 +08:00
|
|
|
if (!np)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pr_info("Initializing Power Management Service Unit\n");
|
|
|
|
|
|
|
|
if (of_address_to_resource(np, 0, &res)) {
|
|
|
|
pr_err("unable to get resource\n");
|
|
|
|
ret = -ENOENT;
|
|
|
|
goto out;
|
2012-08-02 16:17:51 +08:00
|
|
|
}
|
|
|
|
|
2014-04-14 21:50:31 +08:00
|
|
|
if (of_device_is_compatible(np, "marvell,armada-370-xp-pmsu")) {
|
|
|
|
pr_warn(FW_WARN "deprecated pmsu binding\n");
|
|
|
|
res.start = res.start - PMSU_BASE_OFFSET;
|
|
|
|
res.end = res.start + PMSU_REG_SIZE - 1;
|
|
|
|
}
|
|
|
|
|
2014-04-14 21:50:30 +08:00
|
|
|
if (!request_mem_region(res.start, resource_size(&res),
|
|
|
|
np->full_name)) {
|
|
|
|
pr_err("unable to request region\n");
|
|
|
|
ret = -EBUSY;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
pmsu_mp_base = ioremap(res.start, resource_size(&res));
|
|
|
|
if (!pmsu_mp_base) {
|
|
|
|
pr_err("unable to map registers\n");
|
|
|
|
release_mem_region(res.start, resource_size(&res));
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
of_node_put(np);
|
|
|
|
return ret;
|
2012-08-02 16:17:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
early_initcall(armada_370_xp_pmsu_init);
|