summaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2014-07-23 11:28:07 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-07-25 08:59:00 +0200
commit315e1a41385dd8a226117f974f4573da625882e6 (patch)
tree057b7c0b4b61fd5561964f694f741eeb4f9b6289 /drivers/bus
parent5f1c61079665fa4d647fa72f06534dd39eaf8040 (diff)
downloadbarebox-315e1a41385dd8a226117f974f4573da625882e6.tar.gz
barebox-315e1a41385dd8a226117f974f4573da625882e6.tar.xz
ARM: mvebu: allow to fixup mbus ranges
On Marvell MVEBU SoCs internal registers are usually remapped from reset default. While Dove and Kirkwood always had their registers remapped, some Armada 370 and XP where shipped with bootloaders that did not remap them. On Barebox these registers are remapped early and on all MVEBU SoCs, so provided DTs should always reflect that in their mbus ranges property. This patch registers a fixup for DTBs and allows individual SoCs to add specific remap ranges to the fixup list. The fixup is registered on pure_initcall to even allow to fixup pbl or appended DTBs. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/mvebu-mbus.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 11e3777a60..2fefa63edd 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -53,6 +53,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <malloc.h>
#include <of.h>
#include <of_address.h>
#include <linux/mbus.h>
@@ -546,7 +547,7 @@ void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
* - bits 16 to 23: window attribute ID
* - bits 0 to 15: unused
*/
-#define CUSTOM(id) (((id) & 0xF0000000) >> 24)
+#define CUSTOM(id) (((id) & 0xF0000000) >> 28)
#define TARGET(id) (((id) & 0x0F000000) >> 24)
#define ATTR(id) (((id) & 0x00FF0000) >> 16)
@@ -741,3 +742,74 @@ static int mvebu_mbus_init(void)
return platform_driver_register(&mvebu_mbus_driver);
}
postcore_initcall(mvebu_mbus_init);
+
+struct mbus_range {
+ u32 mbusid;
+ u32 remap;
+ struct list_head list;
+};
+
+#define MBUS_ID(t,a) (((t) << 24) | ((attr) << 16))
+static LIST_HEAD(mbus_ranges);
+
+void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap)
+{
+ struct mbus_range *r = xzalloc(sizeof(*r));
+
+ r->mbusid = MBUS_ID(target, attr);
+ r->remap = remap;
+ list_add_tail(&r->list, &mbus_ranges);
+}
+
+/*
+ * Barebox always remaps internal registers to 0xf1000000 on every SoC.
+ * As we (and Linux) need a working DT and there is no way to tell the current
+ * remap address, fixup any provided DT to ensure custom MBUS_IDs are correct.
+ */
+static int mvebu_mbus_of_fixup(struct device_node *root, void *context)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, mvebu_mbus_dt_ids) {
+ struct property *p;
+ int n, pa, na, ns, lenp, size;
+ u32 *ranges;
+
+ p = of_find_property(np, "ranges", &lenp);
+ if (!p)
+ return -EINVAL;
+
+ pa = of_n_addr_cells(np);
+ if (of_property_read_u32(np, "#address-cells", &na) ||
+ of_property_read_u32(np, "#size-cells", &ns))
+ return -EINVAL;
+
+ size = pa + na + ns;
+ ranges = xzalloc(lenp);
+ of_property_read_u32_array(np, "ranges", ranges, lenp/4);
+
+ for (n = 0; n < lenp/4; n += size) {
+ struct mbus_range *r;
+ u32 mbusid = ranges[n];
+
+ if (!CUSTOM(mbusid))
+ continue;
+
+ list_for_each_entry(r, &mbus_ranges, list) {
+ if (r->mbusid == mbusid)
+ ranges[n + na] = r->remap;
+ }
+ }
+
+ if (of_property_write_u32_array(np, "ranges", ranges, lenp/4))
+ pr_err("Unable to fixup mbus ranges\n");
+ free(ranges);
+ }
+
+ return 0;
+}
+
+static int mvebu_mbus_fixup_register(void) {
+ return of_register_fixup(mvebu_mbus_of_fixup, NULL);
+}
+pure_initcall(mvebu_mbus_fixup_register);