1 /* 2 * Copyright 2024 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <errno.h> 8 #include <inttypes.h> 9 #include <stdbool.h> 10 11 #include <common/debug.h> 12 #include <lib/mmio.h> 13 #include <lib/utils_def.h> 14 #include <s32cc-mc-me.h> 15 #include <s32cc-mc-rgm.h> 16 17 #define MC_ME_MAX_PARTITIONS (4U) 18 19 #define MC_ME_CTL_KEY(MC_ME) ((MC_ME) + 0x0UL) 20 #define MC_ME_CTL_KEY_KEY (0x5AF0U) 21 #define MC_ME_CTL_KEY_INVERTEDKEY (0xA50FU) 22 23 #define MC_ME_PRTN_N(MC_ME, PART) ((MC_ME) + 0x100UL + ((PART) * 0x200UL)) 24 #define MC_ME_PRTN_N_PCONF(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART)) 25 #define MC_ME_PRTN_N_PCE BIT_32(0) 26 #define MC_ME_PRTN_N_OSSE BIT_32(2) 27 #define MC_ME_PRTN_N_PUPD(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART) + 0x4UL) 28 #define MC_ME_PRTN_N_PCUD BIT_32(0) 29 #define MC_ME_PRTN_N_OSSUD BIT_32(2) 30 #define MC_ME_PRTN_N_STAT(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART) + 0x8UL) 31 #define MC_ME_PRTN_N_PCS BIT_32(0) 32 #define MC_ME_PRTN_N_COFB0_STAT(MC_ME, PART) \ 33 (MC_ME_PRTN_N(MC_ME, PART) + 0x10UL) 34 #define MC_ME_PRTN_N_COFB0_CLKEN(MC_ME, PART) \ 35 (MC_ME_PRTN_N(MC_ME, PART) + 0x30UL) 36 #define MC_ME_PRTN_N_REQ(PART) BIT_32(PART) 37 38 #define RDC_RD_CTRL(RDC, PART) ((RDC) + ((PART) * 0x4UL)) 39 #define RDC_CTRL_UNLOCK BIT_32(31) 40 #define RDC_RD_INTERCONNECT_DISABLE BIT_32(3) 41 42 #define RDC_RD_N_STATUS(RDC, PART) ((RDC) + ((PART) * 0x4UL) + 0x80UL) 43 #define RDC_RD_INTERCONNECT_DISABLE_STAT \ 44 BIT_32(4) 45 46 static bool is_interconnect_disabled(uintptr_t rdc, uint32_t part) 47 { 48 return ((mmio_read_32(RDC_RD_N_STATUS(rdc, part)) & 49 RDC_RD_INTERCONNECT_DISABLE_STAT) != 0U); 50 } 51 52 static void enable_interconnect(uintptr_t rdc, uint32_t part) 53 { 54 /* Unlock RDC register write */ 55 mmio_setbits_32(RDC_RD_CTRL(rdc, part), RDC_CTRL_UNLOCK); 56 57 /* Clear corresponding RDC_RD_INTERCONNECT bit */ 58 mmio_clrbits_32(RDC_RD_CTRL(rdc, part), RDC_RD_INTERCONNECT_DISABLE); 59 60 /* Wait until the interface gets enabled */ 61 while (is_interconnect_disabled(rdc, part)) { 62 } 63 64 /* Lock RDC register write */ 65 mmio_clrbits_32(RDC_RD_CTRL(rdc, part), RDC_CTRL_UNLOCK); 66 } 67 68 static int mc_me_check_partition_nb_valid(uint32_t part) 69 { 70 if (part >= MC_ME_MAX_PARTITIONS) { 71 ERROR("Invalid partition %" PRIu32 "\n", part); 72 return -EINVAL; 73 } 74 75 return 0; 76 } 77 78 static void part_pconf_write_pce(uintptr_t mc_me, uint32_t pce_bit, 79 uint32_t part) 80 { 81 mmio_clrsetbits_32(MC_ME_PRTN_N_PCONF(mc_me, part), MC_ME_PRTN_N_PCE, 82 pce_bit & MC_ME_PRTN_N_PCE); 83 } 84 85 static void mc_me_apply_hw_changes(uintptr_t mc_me) 86 { 87 mmio_write_32(MC_ME_CTL_KEY(mc_me), MC_ME_CTL_KEY_KEY); 88 mmio_write_32(MC_ME_CTL_KEY(mc_me), MC_ME_CTL_KEY_INVERTEDKEY); 89 } 90 91 static void part_pupd_update_and_wait(uintptr_t mc_me, uint32_t part, 92 uint32_t mask) 93 { 94 uint32_t pconf, stat; 95 96 mmio_setbits_32(MC_ME_PRTN_N_PUPD(mc_me, part), mask); 97 98 mc_me_apply_hw_changes(mc_me); 99 100 /* wait for the updates to apply */ 101 pconf = mmio_read_32(MC_ME_PRTN_N_PCONF(mc_me, part)); 102 do { 103 stat = mmio_read_32(MC_ME_PRTN_N_STAT(mc_me, part)); 104 } while ((stat & mask) != (pconf & mask)); 105 } 106 107 static void part_pconf_write_osse(uintptr_t mc_me, uint32_t osse_bit, 108 uint32_t part) 109 { 110 mmio_clrsetbits_32(MC_ME_PRTN_N_PCONF(mc_me, part), MC_ME_PRTN_N_OSSE, 111 (osse_bit & MC_ME_PRTN_N_OSSE)); 112 } 113 114 int mc_me_enable_partition(uintptr_t mc_me, uintptr_t mc_rgm, uintptr_t rdc, 115 uint32_t part) 116 { 117 uint32_t part_stat; 118 int ret; 119 120 /* Partition 0 is already enabled by BootROM */ 121 if (part == 0U) { 122 return 0; 123 } 124 125 ret = mc_me_check_partition_nb_valid(part); 126 if (ret != 0) { 127 return ret; 128 } 129 130 /* Enable a partition only if it's disabled */ 131 part_stat = mmio_read_32(MC_ME_PRTN_N_STAT(mc_me, part)); 132 if ((MC_ME_PRTN_N_PCS & part_stat) != 0U) { 133 return 0; 134 } 135 136 part_pconf_write_pce(mc_me, MC_ME_PRTN_N_PCE, part); 137 part_pupd_update_and_wait(mc_me, part, MC_ME_PRTN_N_PCUD); 138 139 enable_interconnect(rdc, part); 140 141 /* Release partition reset */ 142 mc_rgm_release_part(mc_rgm, part); 143 144 /* Clear OSSE bit */ 145 part_pconf_write_osse(mc_me, 0, part); 146 147 part_pupd_update_and_wait(mc_me, part, MC_ME_PRTN_N_OSSUD); 148 149 mc_rgm_wait_part_deassert(mc_rgm, part); 150 151 return 0; 152 } 153 154 void mc_me_enable_part_cofb(uintptr_t mc_me, uint32_t partition_n, uint32_t block, 155 bool check_status) 156 { 157 uint32_t block_mask = MC_ME_PRTN_N_REQ(block); 158 uintptr_t cofb_stat_addr; 159 160 mmio_setbits_32(MC_ME_PRTN_N_COFB0_CLKEN(mc_me, partition_n), 161 block_mask); 162 163 mmio_setbits_32(MC_ME_PRTN_N_PCONF(mc_me, partition_n), 164 MC_ME_PRTN_N_PCE); 165 166 part_pupd_update_and_wait(mc_me, partition_n, MC_ME_PRTN_N_PCUD); 167 168 cofb_stat_addr = MC_ME_PRTN_N_COFB0_STAT(mc_me, partition_n); 169 if (check_status) { 170 while ((mmio_read_32(cofb_stat_addr) & block_mask) == 0U) { 171 } 172 } 173 } 174