blob: 3bdedd7b5093ab0fefccc6131701040e16a2c538 [file] [log] [blame]
Emanuele Ghidoli73bc1882023-07-14 17:23:08 +02001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright 2023 Toradex - https://www.toradex.com/
4 */
5
6#include "common.h"
7#include <dm.h>
8#include <fdt_support.h>
9#include <linux/soc/ti/ti_sci_protocol.h>
Emanuele Ghidoli373790c2023-07-26 16:36:50 +020010#include "common_fdt.h"
Emanuele Ghidoli73bc1882023-07-14 17:23:08 +020011
12static int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name)
13{
14 u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2];
15 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
16 int ret, node, subnode, len, prev_node;
17 u32 range[4], addr, size;
18 const fdt32_t *sub_reg;
19
20 ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end);
21 msmc_size = msmc_end - msmc_start + 1;
22 debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__,
23 msmc_start, msmc_size);
24
25 /* find or create "msmc_sram node */
26 ret = fdt_path_offset(blob, parent_path);
27 if (ret < 0)
28 return ret;
29
30 node = fdt_find_or_add_subnode(blob, ret, node_name);
31 if (node < 0)
32 return node;
33
34 ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram");
35 if (ret < 0)
36 return ret;
37
38 reg[0] = cpu_to_fdt64(msmc_start);
39 reg[1] = cpu_to_fdt64(msmc_size);
40 ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg));
41 if (ret < 0)
42 return ret;
43
44 fdt_setprop_cell(blob, node, "#address-cells", 1);
45 fdt_setprop_cell(blob, node, "#size-cells", 1);
46
47 range[0] = 0;
48 range[1] = cpu_to_fdt32(msmc_start >> 32);
49 range[2] = cpu_to_fdt32(msmc_start & 0xffffffff);
50 range[3] = cpu_to_fdt32(msmc_size);
51 ret = fdt_setprop(blob, node, "ranges", range, sizeof(range));
52 if (ret < 0)
53 return ret;
54
55 subnode = fdt_first_subnode(blob, node);
56 prev_node = 0;
57
58 /* Look for invalid subnodes and delete them */
59 while (subnode >= 0) {
60 sub_reg = fdt_getprop(blob, subnode, "reg", &len);
61 addr = fdt_read_number(sub_reg, 1);
62 sub_reg++;
63 size = fdt_read_number(sub_reg, 1);
64 debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__,
65 subnode, addr, size);
66 if (addr + size > msmc_size ||
67 !strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) ||
68 !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
69 fdt_del_node(blob, subnode);
70 debug("%s: deleting subnode %d\n", __func__, subnode);
71 if (!prev_node)
72 subnode = fdt_first_subnode(blob, node);
73 else
74 subnode = fdt_next_subnode(blob, prev_node);
75 } else {
76 prev_node = subnode;
77 subnode = fdt_next_subnode(blob, prev_node);
78 }
79 }
80
81 return 0;
82}
83
84int fdt_fixup_msmc_ram_k3(void *blob)
85{
86 int ret;
87
88 ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
89 if (ret < 0)
90 ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
91 "sram@70000000");
92 if (ret)
93 printf("%s: fixing up msmc ram failed %d\n", __func__, ret);
94
95 return ret;
96}
Emanuele Ghidolid7e0b072023-07-14 17:23:10 +020097
98int fdt_del_node_path(void *blob, const char *path)
99{
100 int ret;
101 int nodeoff;
102
103 nodeoff = fdt_path_offset(blob, path);
104 if (nodeoff < 0)
105 return 0; /* Not found, skip it */
106
107 ret = fdt_del_node(blob, nodeoff);
108 if (ret < 0)
109 printf("Unable to delete node %s, err=%s\n", path, fdt_strerror(ret));
110 else
111 debug("Deleted node %s\n", path);
112
113 return ret;
114}
Andrew Davis3a7442d2024-02-14 10:30:07 -0600115
116int fdt_fixup_reserved(void *blob, const char *name,
117 unsigned int new_address, unsigned int new_size)
118{
119 int nodeoffset, subnode;
120 int ret;
121
122 /* Find reserved-memory */
123 nodeoffset = fdt_subnode_offset(blob, 0, "reserved-memory");
124 if (nodeoffset < 0) {
125 debug("Could not find reserved-memory node\n");
126 return 0;
127 }
128
129 /* Find existing matching subnode and remove it */
130 fdt_for_each_subnode(subnode, blob, nodeoffset) {
131 const char *node_name;
132 fdt_addr_t addr;
133 fdt_size_t size;
134
135 /* Name matching */
136 node_name = fdt_get_name(blob, subnode, NULL);
137 if (!name)
138 return -EINVAL;
139 if (!strncmp(node_name, name, strlen(name))) {
140 /* Read out old size first */
141 addr = fdtdec_get_addr_size(blob, subnode, "reg", &size);
142 if (addr == FDT_ADDR_T_NONE)
143 return -EINVAL;
144 new_size = size;
145
146 /* Delete node */
147 ret = fdt_del_node(blob, subnode);
148 if (ret < 0)
149 return ret;
150
151 /* Only one matching node */
152 break;
153 }
154 }
155
156 struct fdt_memory carveout = {
157 .start = new_address,
158 .end = new_address + new_size - 1,
159 };
160 ret = fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL,
161 FDTDEC_RESERVED_MEMORY_NO_MAP);
162 if (ret < 0)
163 return ret;
164
165 return 0;
166}