blob: 04d04253dd4e9b1faa0be32ccbbe81d86285a260 [file] [log] [blame]
Ghennadi Procopciucf7dd84a2024-09-16 16:22:55 +03001/*
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
46static 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
52static 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
68static 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
78static 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
85static 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
91static 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
107static 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
114int 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
154void 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}