blob: 0333b9b561651d858ee2085bd67305eab1e8c715 [file] [log] [blame]
Jit Loon Lim65b49f42025-02-10 15:15:31 +08001/*
2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <assert.h>
9#include <errno.h>
10
11#include <arch_helpers.h>
12#include <common/debug.h>
13#include <common/fdt_wrappers.h>
14#include <common/tbbr/tbbr_img_def.h>
15#include <drivers/arm/gic_common.h>
16#include <drivers/arm/gicv3.h>
17#include <drivers/delay_timer.h>
18#include <lib/mmio.h>
19#include <lib/utils.h>
20#include <libfdt.h>
21#include <platform_def.h>
22#include <tools_share/firmware_image_package.h>
23
24#include "socfpga_dt.h"
25
26static const void *fdt;
27/*******************************************************************************
28 * This function checks device tree file with its header.
29 * Returns 0 on success and a negative FDT error code on failure.
30 ******************************************************************************/
31int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str)
32{
33 int ret = 0;
34 int node = 1;
35
36 ret = fdt_check_header((void *)dt_addr);
37
38 if (ret != 0) {
39 ERROR("SOCFPGA: FDT Header invalid\n");
40 return ret;
41 }
42
43 fdt = (const void *)dt_addr;
44
45 /* As libfdt use void *, we can't avoid this cast */
46 const void *dtb = (void *)dt_addr;
47
48 /* Assert the node offset point to compatible property */
49 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
50 if (node < 0) {
51 ERROR("SOCFPGA: Can't find `%s` compatible in dtb\n",
52 compatible_str);
53 return node;
54 }
55
56 NOTICE("SOCFPGA: Successfully open and check FDT\n");
57
58 return ret;
59}
60
61int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data)
62{
63 int err;
64 int node;
65 uintptr_t addr;
66
67 /* Necessary to work with libfdt APIs */
68 const void *hw_config_dtb = (const void *)dt_addr;
69 /*
70 * Find the offset of the node containing "arm,gic-v3" compatible property.
71 * Populating fconf strucutures dynamically is not supported for legacy
72 * systems which use GICv2 IP. Simply skip extracting GIC properties.
73 */
74 node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
75 if (node < 0) {
76 ERROR("SOCFPGA: Unable to locate node with arm,gic-v3 compatible property\n");
77 return 0;
78 }
79 /* The GICv3 DT binding holds at least two address/size pairs,
80 * the first describing the distributor, the second the redistributors.
81 * See: bindings/interrupt-controller/arm,gic-v3.yaml
82 */
83 err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
84 if (err < 0) {
85 ERROR("SOCFPGA: Failed to read GICD reg property of GIC node\n");
86 } else {
87 plat_driver_data->gicd_base = addr;
88 }
89
90 err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
91 if (err < 0) {
92 ERROR("SOCFPGA: Failed to read GICR reg property of GIC node\n");
93 } else {
94 plat_driver_data->gicr_base = addr;
95 }
96 return err;
97}
98
99int socfpga_dt_populate_dram_layout(uintptr_t dt_addr)
100{
101 int node;
102 uintptr_t addr;
103 size_t size;
104
105 /* Necessary to work with libfdt APIs */
106 const void *hw_config_dtb = (const void *)dt_addr;
107
108 /* Find 'memory' node */
109 node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
110 "memory", sizeof("memory"));
111 if (node < 0) {
112 NOTICE("SOCFPGA: Unable to locate 'memory' node\n");
113 return node;
114 }
115
116 int err = fdt_get_reg_props_by_index(
117 hw_config_dtb, node, 0,
118 &addr, (size_t *)&size);
119
120 NOTICE("SOCFPGA: Mem base 0x%lx, Mem size 0x%lx\n", addr, size);
121 if (err < 0) {
122 ERROR("SOCFPGA: Failed to read 'reg' property of 'memory' node\n");
123 return err;
124 }
125
126 return 0;
127}