/* * Copyright (C) 2013 * Thomas Petazzoni * Sebastian Hesselbarth * * 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 #include #include #include #include #include #include #include /* * 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; }