xref: /rk3399_ARM-atf/drivers/nxp/clk/s32cc/mc_me.c (revision 01c80c1956a9dd25e9c8ecdf95c2bf3d157f3c59)
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 
is_interconnect_disabled(uintptr_t rdc,uint32_t part)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 
enable_interconnect(uintptr_t rdc,uint32_t part)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 
mc_me_check_partition_nb_valid(uint32_t part)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 
part_pconf_write_pce(uintptr_t mc_me,uint32_t pce_bit,uint32_t part)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 
mc_me_apply_hw_changes(uintptr_t mc_me)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 
part_pupd_update_and_wait(uintptr_t mc_me,uint32_t part,uint32_t mask)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 
part_pconf_write_osse(uintptr_t mc_me,uint32_t osse_bit,uint32_t part)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 
mc_me_enable_partition(uintptr_t mc_me,uintptr_t mc_rgm,uintptr_t rdc,uint32_t part)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 
mc_me_enable_part_cofb(uintptr_t mc_me,uint32_t partition_n,uint32_t block,bool check_status)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