1 /*
2 * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <common/debug.h>
8 #include <drivers/arm/css/css_mhu_doorbell.h>
9 #include <drivers/arm/css/scmi.h>
10 #include <drivers/arm/css/sds.h>
11 #include <drivers/arm/gic600_multichip.h>
12 #include <lib/mmio.h>
13 #include <lib/utils.h>
14 #include <plat/arm/common/plat_arm.h>
15
16 #include "n1sdp_def.h"
17 #include <platform_def.h>
18
19 /*
20 * Platform information structure stored in SDS.
21 * This structure holds information about platform's DDR
22 * size which will be used to zero out the memory before
23 * enabling the ECC capability as well as information
24 * about multichip setup
25 * - multichip mode
26 * - secondary_count
27 * - Local DDR size in GB, DDR memory in master board
28 * - Remote DDR size in GB, DDR memory in secondary board
29 */
30 struct n1sdp_plat_info {
31 bool multichip_mode;
32 uint8_t secondary_count;
33 uint8_t local_ddr_size;
34 uint8_t remote_ddr_size;
35 } __packed;
36
37 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
38 .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE,
39 .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
40 .db_preserve_mask = 0xfffffffe,
41 .db_modify_mask = 0x1,
42 .ring_doorbell = &mhu_ring_doorbell
43 };
44
45 static struct gic600_multichip_data n1sdp_multichip_data __init = {
46 .rt_owner_base = PLAT_ARM_GICD_BASE,
47 .rt_owner = 0,
48 .chip_count = 1,
49 .chip_addrs = {
50 PLAT_ARM_GICD_BASE >> 16,
51 PLAT_ARM_GICD_BASE >> 16
52 },
53 .spi_ids = {
54 {32, 479},
55 {512, 959}
56 }
57 };
58
59 static uintptr_t n1sdp_multichip_gicr_frames[3] = {
60 PLAT_ARM_GICR_BASE,
61 PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET,
62 0
63 };
64
plat_css_get_scmi_info(int channel_id)65 scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
66 {
67 return &n1sdp_scmi_plat_info;
68 }
69
plat_arm_psci_override_pm_ops(plat_psci_ops_t * ops)70 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
71 {
72 return css_scmi_override_pm_ops(ops);
73 }
74
75 /*
76 * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
77 * capability, the entire DDR memory space has to be zeroed out before
78 * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
79 * memory from SCP is quite time consuming so the following function
80 * is added to zero out the DDR memory from application processor which is
81 * much faster compared to SCP. Local DDR memory is zeroed out during BL2
82 * stage. If remote chip is connected, it's DDR memory is zeroed out here.
83 */
84
remote_dmc_ecc_setup(uint8_t remote_ddr_size)85 void remote_dmc_ecc_setup(uint8_t remote_ddr_size)
86 {
87 uint64_t remote_dram2_size;
88
89 remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) -
90 N1SDP_REMOTE_DRAM1_SIZE;
91 /* multichip setup */
92 INFO("Zeroing remote DDR memories\n");
93 zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE,
94 N1SDP_REMOTE_DRAM1_SIZE);
95 flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE);
96 zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
97 flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
98
99 INFO("Enabling ECC on remote DMCs\n");
100 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
101 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG,
102 N1SDP_DMC_MEMC_CMD_CONFIG);
103 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG,
104 N1SDP_DMC_MEMC_CMD_CONFIG);
105
106 /* Enable ECC in DMCs */
107 mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG,
108 N1SDP_DMC_ERR0CTLR0_ECC_EN);
109 mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG,
110 N1SDP_DMC_ERR0CTLR0_ECC_EN);
111
112 /* Set DMCs to READY state */
113 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
114 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
115 }
116
n1sdp_bl31_multichip_setup(void)117 void n1sdp_bl31_multichip_setup(void)
118 {
119 plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames);
120 gic600_multichip_init(&n1sdp_multichip_data);
121 }
122
bl31_platform_setup(void)123 void bl31_platform_setup(void)
124 {
125 int ret;
126 struct n1sdp_plat_info plat_info;
127
128 ret = sds_init();
129 if (ret != SDS_OK) {
130 ERROR("SDS initialization failed\n");
131 panic();
132 }
133
134 ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
135 N1SDP_SDS_PLATFORM_INFO_OFFSET,
136 &plat_info,
137 N1SDP_SDS_PLATFORM_INFO_SIZE,
138 SDS_ACCESS_MODE_NON_CACHED);
139 if (ret != SDS_OK) {
140 ERROR("Error getting platform info from SDS\n");
141 panic();
142 }
143 /* Validate plat_info SDS */
144 if ((plat_info.local_ddr_size == 0)
145 || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
146 || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
147 || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) {
148 ERROR("platform info SDS is corrupted\n");
149 panic();
150 }
151
152 if (plat_info.multichip_mode) {
153 n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1;
154 n1sdp_bl31_multichip_setup();
155 }
156 arm_bl31_platform_setup();
157
158 /* Check if remote memory is present */
159 if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0))
160 remote_dmc_ecc_setup(plat_info.remote_ddr_size);
161 }
162