Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, olpc: Add missing elements to device tree

In response to new device tree code in the kernel, OLPC will start
using it for probing of certain devices. However, some firmware fixes
are needed to put the devicetree into a usable state.

Retain compatibility with old firmware by fixing up the device tree
at boot-time if it does not contain the new nodes/properties that
we need for probing. This is the same approach taken on PPC platforms.

Signed-off-by: Daniel Drake <dsd@laptop.org>
Link: http://lkml.kernel.org/r/1309019658-1712-2-git-send-email-dsd@laptop.org
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Andres Salomon <dilinger@queued.net>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

authored by

Daniel Drake and committed by
H. Peter Anvin
f70d8ef4 fe0d4220

+103
+103
arch/x86/platform/olpc/olpc_dt.c
··· 165 165 .pkg2path = olpc_dt_pkg2path, 166 166 }; 167 167 168 + static phandle __init olpc_dt_finddevice(const char *path) 169 + { 170 + phandle node; 171 + const void *args[] = { path }; 172 + void *res[] = { &node }; 173 + 174 + if (olpc_ofw("finddevice", args, res)) { 175 + pr_err("olpc_dt: finddevice failed!\n"); 176 + return 0; 177 + } 178 + 179 + if ((s32) node == -1) 180 + return 0; 181 + 182 + return node; 183 + } 184 + 185 + static int __init olpc_dt_interpret(const char *words) 186 + { 187 + int result; 188 + const void *args[] = { words }; 189 + void *res[] = { &result }; 190 + 191 + if (olpc_ofw("interpret", args, res)) { 192 + pr_err("olpc_dt: interpret failed!\n"); 193 + return -1; 194 + } 195 + 196 + return result; 197 + } 198 + 199 + /* 200 + * Extract board revision directly from OFW device tree. 201 + * We can't use olpc_platform_info because that hasn't been set up yet. 202 + */ 203 + static u32 __init olpc_dt_get_board_revision(void) 204 + { 205 + phandle node; 206 + __be32 rev; 207 + int r; 208 + 209 + node = olpc_dt_finddevice("/"); 210 + if (!node) 211 + return 0; 212 + 213 + r = olpc_dt_getproperty(node, "board-revision-int", 214 + (char *) &rev, sizeof(rev)); 215 + if (r < 0) 216 + return 0; 217 + 218 + return be32_to_cpu(rev); 219 + } 220 + 221 + void __init olpc_dt_fixup(void) 222 + { 223 + int r; 224 + char buf[64]; 225 + phandle node; 226 + u32 board_rev; 227 + 228 + node = olpc_dt_finddevice("/battery@0"); 229 + if (!node) 230 + return; 231 + 232 + /* 233 + * If the battery node has a compatible property, we are running a new 234 + * enough firmware and don't have fixups to make. 235 + */ 236 + r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf)); 237 + if (r > 0) 238 + return; 239 + 240 + pr_info("PROM DT: Old firmware detected, applying fixes\n"); 241 + 242 + /* Add olpc,xo1-battery compatible marker to battery node */ 243 + olpc_dt_interpret("\" /battery@0\" find-device" 244 + " \" olpc,xo1-battery\" +compatible" 245 + " device-end"); 246 + 247 + board_rev = olpc_dt_get_board_revision(); 248 + if (!board_rev) 249 + return; 250 + 251 + if (board_rev >= olpc_board_pre(0xd0)) { 252 + /* XO-1.5: add dcon device */ 253 + olpc_dt_interpret("\" /pci/display@1\" find-device" 254 + " new-device" 255 + " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible" 256 + " finish-device device-end"); 257 + } else { 258 + /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */ 259 + olpc_dt_interpret("\" /pci/display@1,1\" find-device" 260 + " new-device" 261 + " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible" 262 + " finish-device device-end" 263 + " \" /rtc\" find-device" 264 + " \" olpc,xo1-rtc\" +compatible" 265 + " device-end"); 266 + } 267 + } 268 + 168 269 void __init olpc_dt_build_devicetree(void) 169 270 { 170 271 phandle root; 171 272 172 273 if (!olpc_ofw_is_installed()) 173 274 return; 275 + 276 + olpc_dt_fixup(); 174 277 175 278 root = olpc_dt_getsibling(0); 176 279 if (!root) {