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