blob: 4a016711566871e5147d63e9a695a7e80aeceaab [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) ||
Udit Kumar7f8bd5d2025-01-13 09:55:24 +053068 !strncmp(fdt_get_name(blob, subnode, &len), "tifs", 4) ||
Emanuele Ghidoli73bc1882023-07-14 17:23:08 +020069 !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
70 fdt_del_node(blob, subnode);
71 debug("%s: deleting subnode %d\n", __func__, subnode);
72 if (!prev_node)
73 subnode = fdt_first_subnode(blob, node);
74 else
75 subnode = fdt_next_subnode(blob, prev_node);
76 } else {
77 prev_node = subnode;
78 subnode = fdt_next_subnode(blob, prev_node);
79 }
80 }
81
82 return 0;
83}
84
85int fdt_fixup_msmc_ram_k3(void *blob)
86{
87 int ret;
88
89 ret = fdt_fixup_msmc_ram(blob, "/bus@100000", "sram@70000000");
90 if (ret < 0)
91 ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000",
92 "sram@70000000");
93 if (ret)
94 printf("%s: fixing up msmc ram failed %d\n", __func__, ret);
95
96 return ret;
97}
Emanuele Ghidolid7e0b072023-07-14 17:23:10 +020098
99int fdt_del_node_path(void *blob, const char *path)
100{
101 int ret;
102 int nodeoff;
103
104 nodeoff = fdt_path_offset(blob, path);
105 if (nodeoff < 0)
106 return 0; /* Not found, skip it */
107
108 ret = fdt_del_node(blob, nodeoff);
109 if (ret < 0)
110 printf("Unable to delete node %s, err=%s\n", path, fdt_strerror(ret));
111 else
112 debug("Deleted node %s\n", path);
113
114 return ret;
115}
Andrew Davis3a7442d2024-02-14 10:30:07 -0600116
117int fdt_fixup_reserved(void *blob, const char *name,
118 unsigned int new_address, unsigned int new_size)
119{
120 int nodeoffset, subnode;
121 int ret;
122
123 /* Find reserved-memory */
124 nodeoffset = fdt_subnode_offset(blob, 0, "reserved-memory");
125 if (nodeoffset < 0) {
126 debug("Could not find reserved-memory node\n");
127 return 0;
128 }
129
130 /* Find existing matching subnode and remove it */
131 fdt_for_each_subnode(subnode, blob, nodeoffset) {
132 const char *node_name;
133 fdt_addr_t addr;
134 fdt_size_t size;
135
136 /* Name matching */
137 node_name = fdt_get_name(blob, subnode, NULL);
138 if (!name)
139 return -EINVAL;
140 if (!strncmp(node_name, name, strlen(name))) {
141 /* Read out old size first */
142 addr = fdtdec_get_addr_size(blob, subnode, "reg", &size);
143 if (addr == FDT_ADDR_T_NONE)
144 return -EINVAL;
145 new_size = size;
146
147 /* Delete node */
148 ret = fdt_del_node(blob, subnode);
149 if (ret < 0)
150 return ret;
151
152 /* Only one matching node */
153 break;
154 }
155 }
156
157 struct fdt_memory carveout = {
158 .start = new_address,
159 .end = new_address + new_size - 1,
160 };
161 ret = fdtdec_add_reserved_memory(blob, name, &carveout, NULL, 0, NULL,
162 FDTDEC_RESERVED_MEMORY_NO_MAP);
163 if (ret < 0)
164 return ret;
165
166 return 0;
167}