1be8c67faa
To prepare PCIe device id fixups, move PCIe register defines to a common location. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
139 lines
3.3 KiB
C
139 lines
3.3 KiB
C
/*
|
|
* Copyright (C) 2013
|
|
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
|
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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 <common.h>
|
|
#include <init.h>
|
|
#include <io.h>
|
|
#include <of.h>
|
|
#include <of_address.h>
|
|
#include <linux/clk.h>
|
|
#include <mach/common.h>
|
|
#include <mach/socid.h>
|
|
|
|
/*
|
|
* Marvell MVEBU SoC id and revision can be read from any PCIe
|
|
* controller port.
|
|
*/
|
|
u16 soc_devid;
|
|
EXPORT_SYMBOL(soc_devid);
|
|
u16 soc_revid;
|
|
EXPORT_SYMBOL(soc_revid);
|
|
|
|
static const struct of_device_id mvebu_pcie_of_ids[] = {
|
|
{ .compatible = "marvell,armada-xp-pcie", },
|
|
{ .compatible = "marvell,armada-370-pcie", },
|
|
{ .compatible = "marvell,dove-pcie" },
|
|
{ .compatible = "marvell,kirkwood-pcie" },
|
|
{ },
|
|
};
|
|
|
|
static int mvebu_soc_id_init(void)
|
|
{
|
|
struct device_node *np, *cnp;
|
|
struct clk *clk;
|
|
void __iomem *base;
|
|
|
|
np = of_find_matching_node(NULL, mvebu_pcie_of_ids);
|
|
if (!np)
|
|
return -ENODEV;
|
|
|
|
for_each_child_of_node(np, cnp) {
|
|
base = of_iomap(cnp, 0);
|
|
if (!base)
|
|
continue;
|
|
|
|
clk = of_clk_get(cnp, 0);
|
|
if (IS_ERR(clk))
|
|
continue;
|
|
|
|
clk_enable(clk);
|
|
soc_devid = readl(base + PCIE_VEN_DEV_ID) >> 16;
|
|
soc_revid = readl(base + PCIE_REV_ID) & REV_ID_MASK;
|
|
clk_disable(clk);
|
|
break;
|
|
}
|
|
|
|
if (!soc_devid) {
|
|
pr_err("Unable to read SoC id from PCIe ports\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
pr_info("SoC: Marvell %04x rev %d\n", soc_devid, soc_revid);
|
|
|
|
return 0;
|
|
}
|
|
postcore_initcall(mvebu_soc_id_init);
|
|
|
|
/*
|
|
* Memory size is set up by BootROM and can be read from SoC's ram controller
|
|
* registers. Fixup provided DTs to reflect accessible amount of directly
|
|
* attached RAM. Removable RAM, e.g. SODIMM, should be added by a per-board
|
|
* fixup.
|
|
*/
|
|
int mvebu_set_memory(u64 phys_base, u64 phys_size)
|
|
{
|
|
struct device_node *np, *root;
|
|
__be32 reg[4];
|
|
int na, ns;
|
|
|
|
root = of_get_root_node();
|
|
if (!root)
|
|
return -EINVAL;
|
|
|
|
np = of_find_node_by_path("/memory");
|
|
if (!np)
|
|
np = of_create_node(root, "/memory");
|
|
if (!np)
|
|
return -EINVAL;
|
|
|
|
na = of_n_addr_cells(np);
|
|
ns = of_n_size_cells(np);
|
|
|
|
if (na == 2) {
|
|
reg[0] = cpu_to_be32(phys_base >> 32);
|
|
reg[1] = cpu_to_be32(phys_base & 0xffffffff);
|
|
} else {
|
|
reg[0] = cpu_to_be32(phys_base & 0xffffffff);
|
|
}
|
|
|
|
if (ns == 2) {
|
|
reg[2] = cpu_to_be32(phys_size >> 32);
|
|
reg[3] = cpu_to_be32(phys_size & 0xffffffff);
|
|
} else {
|
|
reg[1] = cpu_to_be32(phys_size & 0xffffffff);
|
|
}
|
|
|
|
if (of_set_property(np, "device_type", "memory", sizeof("memory"), 1) ||
|
|
of_set_property(np, "reg", reg, sizeof(u32) * (na + ns), 1))
|
|
pr_err("Unable to fixup memory node\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static __noreturn void (*mvebu_reset_cpu)(unsigned long addr);
|
|
|
|
void __noreturn reset_cpu(unsigned long addr)
|
|
{
|
|
mvebu_reset_cpu(addr);
|
|
}
|
|
EXPORT_SYMBOL(reset_cpu);
|
|
|
|
void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr))
|
|
{
|
|
mvebu_reset_cpu = reset;
|
|
}
|