• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
is_interconnect_disabled(uintptr_t rdc,uint32_t part)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 
enable_interconnect(uintptr_t rdc,uint32_t part)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 
mc_me_check_partition_nb_valid(uint32_t part)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 
part_pconf_write_pce(uintptr_t mc_me,uint32_t pce_bit,uint32_t part)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 
mc_me_apply_hw_changes(uintptr_t mc_me)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 
part_pupd_update_and_wait(uintptr_t mc_me,uint32_t part,uint32_t mask)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 
part_pconf_write_osse(uintptr_t mc_me,uint32_t osse_bit,uint32_t part)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 
mc_me_enable_partition(uintptr_t mc_me,uintptr_t mc_rgm,uintptr_t rdc,uint32_t part)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 
mc_me_enable_part_cofb(uintptr_t mc_me,uint32_t partition_n,uint32_t block,bool check_status)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