.. | .. |
---|
| 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); |
---|