|
@@ -165,6 +165,107 @@ static struct of_pdt_ops prom_olpc_ops __initdata = {
|
|
|
.pkg2path = olpc_dt_pkg2path,
|
|
|
};
|
|
|
|
|
|
+static phandle __init olpc_dt_finddevice(const char *path)
|
|
|
+{
|
|
|
+ phandle node;
|
|
|
+ const void *args[] = { path };
|
|
|
+ void *res[] = { &node };
|
|
|
+
|
|
|
+ if (olpc_ofw("finddevice", args, res)) {
|
|
|
+ pr_err("olpc_dt: finddevice failed!\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((s32) node == -1)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return node;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init olpc_dt_interpret(const char *words)
|
|
|
+{
|
|
|
+ int result;
|
|
|
+ const void *args[] = { words };
|
|
|
+ void *res[] = { &result };
|
|
|
+
|
|
|
+ if (olpc_ofw("interpret", args, res)) {
|
|
|
+ pr_err("olpc_dt: interpret failed!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Extract board revision directly from OFW device tree.
|
|
|
+ * We can't use olpc_platform_info because that hasn't been set up yet.
|
|
|
+ */
|
|
|
+static u32 __init olpc_dt_get_board_revision(void)
|
|
|
+{
|
|
|
+ phandle node;
|
|
|
+ __be32 rev;
|
|
|
+ int r;
|
|
|
+
|
|
|
+ node = olpc_dt_finddevice("/");
|
|
|
+ if (!node)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ r = olpc_dt_getproperty(node, "board-revision-int",
|
|
|
+ (char *) &rev, sizeof(rev));
|
|
|
+ if (r < 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return be32_to_cpu(rev);
|
|
|
+}
|
|
|
+
|
|
|
+void __init olpc_dt_fixup(void)
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ char buf[64];
|
|
|
+ phandle node;
|
|
|
+ u32 board_rev;
|
|
|
+
|
|
|
+ node = olpc_dt_finddevice("/battery@0");
|
|
|
+ if (!node)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the battery node has a compatible property, we are running a new
|
|
|
+ * enough firmware and don't have fixups to make.
|
|
|
+ */
|
|
|
+ r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
|
|
|
+ if (r > 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ pr_info("PROM DT: Old firmware detected, applying fixes\n");
|
|
|
+
|
|
|
+ /* Add olpc,xo1-battery compatible marker to battery node */
|
|
|
+ olpc_dt_interpret("\" /battery@0\" find-device"
|
|
|
+ " \" olpc,xo1-battery\" +compatible"
|
|
|
+ " device-end");
|
|
|
+
|
|
|
+ board_rev = olpc_dt_get_board_revision();
|
|
|
+ if (!board_rev)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (board_rev >= olpc_board_pre(0xd0)) {
|
|
|
+ /* XO-1.5: add dcon device */
|
|
|
+ olpc_dt_interpret("\" /pci/display@1\" find-device"
|
|
|
+ " new-device"
|
|
|
+ " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
|
|
|
+ " finish-device device-end");
|
|
|
+ } else {
|
|
|
+ /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
|
|
|
+ olpc_dt_interpret("\" /pci/display@1,1\" find-device"
|
|
|
+ " new-device"
|
|
|
+ " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
|
|
|
+ " finish-device device-end"
|
|
|
+ " \" /rtc\" find-device"
|
|
|
+ " \" olpc,xo1-rtc\" +compatible"
|
|
|
+ " device-end");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void __init olpc_dt_build_devicetree(void)
|
|
|
{
|
|
|
phandle root;
|
|
@@ -172,6 +273,8 @@ void __init olpc_dt_build_devicetree(void)
|
|
|
if (!olpc_ofw_is_installed())
|
|
|
return;
|
|
|
|
|
|
+ olpc_dt_fixup();
|
|
|
+
|
|
|
root = olpc_dt_getsibling(0);
|
|
|
if (!root) {
|
|
|
pr_err("PROM: unable to get root node from OFW!\n");
|