blob: 485294b88d0ac5516f58fb616ca59eebe30ef022 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Masahiro Yamada2663cd62016-06-27 19:31:05 +09002/*
3 * Copyright (C) 2016 Socionext Inc.
4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
Masahiro Yamada2663cd62016-06-27 19:31:05 +09005 */
6
Masahiro Yamada75f82d02018-03-05 01:20:11 +09007#include <linux/libfdt.h>
Masahiro Yamada2663cd62016-06-27 19:31:05 +09008#include <asm/spin_table.h>
9
10int spin_table_update_dt(void *fdt)
11{
12 int cpus_offset, offset;
13 const char *prop;
14 int ret;
15 unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin;
16 unsigned long rsv_size = &spin_table_reserve_end -
17 &spin_table_reserve_begin;
18
19 cpus_offset = fdt_path_offset(fdt, "/cpus");
20 if (cpus_offset < 0)
21 return -ENODEV;
22
23 for (offset = fdt_first_subnode(fdt, cpus_offset);
24 offset >= 0;
25 offset = fdt_next_subnode(fdt, offset)) {
26 prop = fdt_getprop(fdt, offset, "device_type", NULL);
27 if (!prop || strcmp(prop, "cpu"))
28 continue;
29
30 /*
31 * In the first loop, we check if every CPU node specifies
32 * spin-table. Otherwise, just return successfully to not
33 * disturb other methods, like psci.
34 */
35 prop = fdt_getprop(fdt, offset, "enable-method", NULL);
36 if (!prop || strcmp(prop, "spin-table"))
37 return 0;
38 }
39
40 for (offset = fdt_first_subnode(fdt, cpus_offset);
41 offset >= 0;
42 offset = fdt_next_subnode(fdt, offset)) {
43 prop = fdt_getprop(fdt, offset, "device_type", NULL);
44 if (!prop || strcmp(prop, "cpu"))
45 continue;
46
47 ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr",
48 (unsigned long)&spin_table_cpu_release_addr);
49 if (ret)
50 return -ENOSPC;
51 }
52
53 ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size);
54 if (ret)
55 return -ENOSPC;
56
57 printf(" Reserved memory region for spin-table: addr=%lx size=%lx\n",
58 rsv_addr, rsv_size);
59
60 return 0;
61}