| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * OLPC-specific OFW device tree support code. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | * |
|---|
| 10 | 11 | * Adapted for sparc by David S. Miller davem@davemloft.net |
|---|
| 11 | 12 | * Adapted for x86/OLPC by Andres Salomon <dilinger@queued.net> |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is free software; you can redistribute it and/or |
|---|
| 14 | | - * modify it under the terms of the GNU General Public License |
|---|
| 15 | | - * as published by the Free Software Foundation; either version |
|---|
| 16 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 17 | 13 | */ |
|---|
| 18 | 14 | |
|---|
| 19 | 15 | #include <linux/kernel.h> |
|---|
| 20 | | -#include <linux/bootmem.h> |
|---|
| 16 | +#include <linux/memblock.h> |
|---|
| 21 | 17 | #include <linux/of.h> |
|---|
| 22 | | -#include <linux/of_platform.h> |
|---|
| 23 | 18 | #include <linux/of_pdt.h> |
|---|
| 24 | 19 | #include <asm/olpc.h> |
|---|
| 25 | 20 | #include <asm/olpc_ofw.h> |
|---|
| .. | .. |
|---|
| 141 | 136 | * fast enough on the platforms we care about while minimizing |
|---|
| 142 | 137 | * wasted bootmem) and hand off chunks of it to callers. |
|---|
| 143 | 138 | */ |
|---|
| 144 | | - res = alloc_bootmem(chunk_size); |
|---|
| 139 | + res = memblock_alloc(chunk_size, SMP_CACHE_BYTES); |
|---|
| 140 | + if (!res) |
|---|
| 141 | + panic("%s: Failed to allocate %zu bytes\n", __func__, |
|---|
| 142 | + chunk_size); |
|---|
| 145 | 143 | BUG_ON(!res); |
|---|
| 146 | 144 | prom_early_allocated += chunk_size; |
|---|
| 147 | 145 | memset(res, 0, chunk_size); |
|---|
| .. | .. |
|---|
| 218 | 216 | return be32_to_cpu(rev); |
|---|
| 219 | 217 | } |
|---|
| 220 | 218 | |
|---|
| 219 | +static int __init olpc_dt_compatible_match(phandle node, const char *compat) |
|---|
| 220 | +{ |
|---|
| 221 | + char buf[64], *p; |
|---|
| 222 | + int plen, len; |
|---|
| 223 | + |
|---|
| 224 | + plen = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf)); |
|---|
| 225 | + if (plen <= 0) |
|---|
| 226 | + return 0; |
|---|
| 227 | + |
|---|
| 228 | + len = strlen(compat); |
|---|
| 229 | + for (p = buf; p < buf + plen; p += strlen(p) + 1) { |
|---|
| 230 | + if (strcmp(p, compat) == 0) |
|---|
| 231 | + return 1; |
|---|
| 232 | + } |
|---|
| 233 | + |
|---|
| 234 | + return 0; |
|---|
| 235 | +} |
|---|
| 236 | + |
|---|
| 221 | 237 | void __init olpc_dt_fixup(void) |
|---|
| 222 | 238 | { |
|---|
| 223 | | - int r; |
|---|
| 224 | | - char buf[64]; |
|---|
| 225 | 239 | phandle node; |
|---|
| 226 | 240 | u32 board_rev; |
|---|
| 227 | 241 | |
|---|
| .. | .. |
|---|
| 229 | 243 | if (!node) |
|---|
| 230 | 244 | return; |
|---|
| 231 | 245 | |
|---|
| 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 | 246 | board_rev = olpc_dt_get_board_revision(); |
|---|
| 248 | 247 | if (!board_rev) |
|---|
| 249 | 248 | return; |
|---|
| 250 | 249 | |
|---|
| 251 | 250 | 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"); |
|---|
| 251 | + /* XO-1.5 */ |
|---|
| 252 | + |
|---|
| 253 | + if (olpc_dt_compatible_match(node, "olpc,xo1.5-battery")) |
|---|
| 254 | + return; |
|---|
| 255 | + |
|---|
| 256 | + /* Add olpc,xo1.5-battery compatible marker to battery node */ |
|---|
| 257 | + olpc_dt_interpret("\" /battery@0\" find-device"); |
|---|
| 258 | + olpc_dt_interpret(" \" olpc,xo1.5-battery\" +compatible"); |
|---|
| 259 | + olpc_dt_interpret("device-end"); |
|---|
| 260 | + |
|---|
| 261 | + if (olpc_dt_compatible_match(node, "olpc,xo1-battery")) { |
|---|
| 262 | + /* |
|---|
| 263 | + * If we have a olpc,xo1-battery compatible, then we're |
|---|
| 264 | + * running a new enough firmware that already has |
|---|
| 265 | + * the dcon node. |
|---|
| 266 | + */ |
|---|
| 267 | + return; |
|---|
| 268 | + } |
|---|
| 269 | + |
|---|
| 270 | + /* Add dcon device */ |
|---|
| 271 | + olpc_dt_interpret("\" /pci/display@1\" find-device"); |
|---|
| 272 | + olpc_dt_interpret(" new-device"); |
|---|
| 273 | + olpc_dt_interpret(" \" dcon\" device-name"); |
|---|
| 274 | + olpc_dt_interpret(" \" olpc,xo1-dcon\" +compatible"); |
|---|
| 275 | + olpc_dt_interpret(" finish-device"); |
|---|
| 276 | + olpc_dt_interpret("device-end"); |
|---|
| 257 | 277 | } 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"); |
|---|
| 278 | + /* XO-1 */ |
|---|
| 279 | + |
|---|
| 280 | + if (olpc_dt_compatible_match(node, "olpc,xo1-battery")) { |
|---|
| 281 | + /* |
|---|
| 282 | + * If we have a olpc,xo1-battery compatible, then we're |
|---|
| 283 | + * running a new enough firmware that already has |
|---|
| 284 | + * the dcon and RTC nodes. |
|---|
| 285 | + */ |
|---|
| 286 | + return; |
|---|
| 287 | + } |
|---|
| 288 | + |
|---|
| 289 | + /* Add dcon device, mark RTC as olpc,xo1-rtc */ |
|---|
| 290 | + olpc_dt_interpret("\" /pci/display@1,1\" find-device"); |
|---|
| 291 | + olpc_dt_interpret(" new-device"); |
|---|
| 292 | + olpc_dt_interpret(" \" dcon\" device-name"); |
|---|
| 293 | + olpc_dt_interpret(" \" olpc,xo1-dcon\" +compatible"); |
|---|
| 294 | + olpc_dt_interpret(" finish-device"); |
|---|
| 295 | + olpc_dt_interpret("device-end"); |
|---|
| 296 | + |
|---|
| 297 | + olpc_dt_interpret("\" /rtc\" find-device"); |
|---|
| 298 | + olpc_dt_interpret(" \" olpc,xo1-rtc\" +compatible"); |
|---|
| 299 | + olpc_dt_interpret("device-end"); |
|---|
| 266 | 300 | } |
|---|
| 301 | + |
|---|
| 302 | + /* Add olpc,xo1-battery compatible marker to battery node */ |
|---|
| 303 | + olpc_dt_interpret("\" /battery@0\" find-device"); |
|---|
| 304 | + olpc_dt_interpret(" \" olpc,xo1-battery\" +compatible"); |
|---|
| 305 | + olpc_dt_interpret("device-end"); |
|---|
| 267 | 306 | } |
|---|
| 268 | 307 | |
|---|
| 269 | 308 | void __init olpc_dt_build_devicetree(void) |
|---|
| .. | .. |
|---|
| 285 | 324 | pr_info("PROM DT: Built device tree with %u bytes of memory.\n", |
|---|
| 286 | 325 | prom_early_allocated); |
|---|
| 287 | 326 | } |
|---|
| 288 | | - |
|---|
| 289 | | -/* A list of DT node/bus matches that we want to expose as platform devices */ |
|---|
| 290 | | -static struct of_device_id __initdata of_ids[] = { |
|---|
| 291 | | - { .compatible = "olpc,xo1-battery" }, |
|---|
| 292 | | - { .compatible = "olpc,xo1-dcon" }, |
|---|
| 293 | | - { .compatible = "olpc,xo1-rtc" }, |
|---|
| 294 | | - {}, |
|---|
| 295 | | -}; |
|---|
| 296 | | - |
|---|
| 297 | | -static int __init olpc_create_platform_devices(void) |
|---|
| 298 | | -{ |
|---|
| 299 | | - if (machine_is_olpc()) |
|---|
| 300 | | - return of_platform_bus_probe(NULL, of_ids, NULL); |
|---|
| 301 | | - else |
|---|
| 302 | | - return 0; |
|---|
| 303 | | -} |
|---|
| 304 | | -device_initcall(olpc_create_platform_devices); |
|---|