1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "low_level_access.h"
9 #include "pik_scp.h"
10 #include "pik_system.h"
11 #include "synquacer_mmap.h"
12 
13 #include <ppu_v0.h>
14 
15 #include <fwk_macros.h>
16 
17 #include <stdbool.h>
18 #include <stdint.h>
19 
20 void fw_clk_init(void);
21 void fw_sysoc_init(void);
22 void fw_lpcm_init(void);
23 
24 #define REG_ADDR_RSTSTA (0)
25 #define REG_ADDR_RSTSET (0x4U)
26 #define REG_ADDR_RSTCLR (0x8U)
27 
28 #define LPCM_RESET_CTRL_ADDR UINT32_C(0x400)
29 #define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8)
30 
31 #define LPCM_RESET_STA_ADDR 0x404U
32 #define LPCM_RESET_CLR 0x1U
33 
34 #define STATUS_WAIT true
35 #define STATUS_NO_WAIT false
36 
37 #define REG_ADDR_RSTSTA (0)
38 #define REG_ADDR_RSTSET (0x4U)
39 #define REG_ADDR_RSTCLR (0x8U)
40 
41 #define LPCM_RESET_CTRL_ADDR UINT32_C(0x400)
42 #define LPCM_RESET_CTRL_OFFSET UINT32_C(0x8)
43 
44 #define LPCM_RESET_STA_ADDR 0x404U
45 #define LPCM_RESET_CLR 0x1U
46 
fw_clock_pll_init(void)47 static void fw_clock_pll_init(void)
48 {
49     /* 1 bit for each cluster */
50     const uint32_t pll_mask = 0x00000FFF;
51 
52     while ((PIK_SCP->PLL_STATUS[1] & pll_mask) != pll_mask ||
53            (PIK_SCP->PLL_STATUS[9] & pll_mask) != pll_mask)
54         continue;
55 }
56 
pll_init(void)57 static void pll_init(void)
58 {
59     uint32_t pll_mask = PLL_STATUS_0_REFCLK | PLL_STATUS_0_SYSPLLLOCK;
60     /* Wait for PLL to lock */
61     while ((PIK_SCP->PLL_STATUS[0] & pll_mask) != pll_mask)
62         continue;
63 }
64 
fw_sysoc_init(void)65 void fw_sysoc_init(void)
66 {
67     uint32_t i, value;
68 
69     const uint32_t init_sysoc_addr_infos[] = {
70         CONFIG_SOC_REG_ADDR_SYSOC_DMA_TOP,
71         CONFIG_SOC_REG_ADDR_SYSOC_PCIE_TOP,
72         CONFIG_SOC_REG_ADDR_SYSOC_DDR_TOP
73     };
74 
75     const uint32_t init_sysoc_reset_infos[] = { UINT32_C(0x3), /* DMA  */
76                                                 UINT32_C(0x3), /* PCIE */
77                                                 UINT32_C(0xff),
78                                                 /* DDR  */ };
79 
80     for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) {
81         value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA);
82         if (value == 0)
83             continue; /* reset all not active */
84 
85         /* reset set only active bit */
86         writel(
87             init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR,
88             (init_sysoc_reset_infos[i] & value));
89 
90         while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) &
91                 init_sysoc_reset_infos[i]) != 0)
92             ;
93     }
94 }
95 
fw_lpcm_init(void)96 void fw_lpcm_init(void)
97 {
98     uint32_t i, j;
99 
100     const uint32_t lpcm_reset_addr_infos[] = {
101         CONFIG_SOC_LPCM_PCIE_TOP_ADDR + LPCM_RESET_CTRL_ADDR,
102         CONFIG_SOC_LPCM_DMAB_TOP_ADDR + LPCM_RESET_CTRL_ADDR
103     };
104 
105     const uint32_t lpcm_reset_flag[] = { CONFIG_SOC_LPCM_PCIE_RESET_FLAG,
106                                          CONFIG_SOC_LPCM_DMAB_RESET_FLAG };
107 
108     for (i = 0; i < FWK_ARRAY_SIZE(lpcm_reset_addr_infos); i++) {
109         for (j = 0; j < (sizeof(uint32_t) * 8); j++) {
110             if ((lpcm_reset_flag[i] & (0x1U << j)) == 0)
111                 continue; /* no reset signal */
112 
113             /* reset clr set lpcm reset_ctrl*/
114             writel(
115                 lpcm_reset_addr_infos[i] + (LPCM_RESET_CTRL_OFFSET * j),
116                 LPCM_RESET_CLR);
117         }
118     }
119 }
120 
set_clkforce_set(void)121 static void set_clkforce_set(void)
122 {
123     /* 0x0A04 : CLKFORCE_SET HW BUG WORKAROUND bit8 bit6 bit 2 */
124     /* 0 = clock gated. 1 = Clock is forced to always operate. */
125     /* bit8 : SYSPLLCLKDBGFORCE*/
126     /* bit7 : DMCCLKFORCE */
127     /* bit6 : SYSPERCLKFORCE */
128     /* bit5 : PCLKSCPFORCE */
129     /* bit2 : CCNCLKFORCE */
130     /* bit0 : PPUCLKFORCE */
131     PIK_SYSTEM->CLKFORCE_SET = 0x00000144U;
132 }
133 
fw_clear_clkforce(uint32_t value)134 void fw_clear_clkforce(uint32_t value)
135 {
136     /*
137      * Writing 1 to a bit enables dynamic hardware clock-gating.
138      * Writing 0 to a bit is ignored.
139      * bit8 : SYSPLLCLKDBGFORCE
140      * bit7 : DMCCLKFORCE
141      * bit6 : SYSPERCLKFORCE
142      * bit5 : PCLKSCPFORCE
143      * bit2 : CCNCLKFORCE
144      * bit0 : PPUCLKFORCE
145      */
146     PIK_SYSTEM->CLKFORCE_CLR = value;
147 }
148 
fw_get_clkforce_status(void)149 uint32_t fw_get_clkforce_status(void)
150 {
151     return PIK_SYSTEM->CLKFORCE_STATUS;
152 }
153 
154 static struct ppu_v0_reg *const ppu_reg_p[] = {
155     (struct ppu_v0_reg *)0x50041000, /* SYS-LOGIC-PPU0 */
156     (struct ppu_v0_reg *)0x50042000, /* SYS-L3RAM0-PPU0 */
157     (struct ppu_v0_reg *)0x50043000, /* SYS-L3RAM1-PPU0 */
158     (struct ppu_v0_reg *)0x50044000, /* SYS-SFRAM-PPU0 */
159     (struct ppu_v0_reg *)0x50045000, /* SYS-SRAM-PPU0 */
160     (struct ppu_v0_reg *)0x50021000, /* SYS-DEBUG-PPU0 */
161 };
162 
peri_ppu_on(void)163 static void peri_ppu_on(void)
164 {
165     uint32_t i;
166 
167     for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++)
168         ppu_reg_p[i]->POWER_POLICY = PPU_V0_MODE_ON;
169 }
170 
peri_ppu_wait(void)171 static void peri_ppu_wait(void)
172 {
173     uint32_t i;
174 
175     for (i = 0; i < FWK_ARRAY_SIZE(ppu_reg_p); i++) {
176         while ((ppu_reg_p[i]->POWER_STATUS & PPU_V0_PSR_POWSTAT) !=
177                PPU_V0_MODE_ON)
178             ;
179     }
180 }
181 
fw_clk_init(void)182 void fw_clk_init(void)
183 {
184     pll_init();
185     set_clkforce_set();
186 
187     peri_ppu_on();
188 
189     fw_clock_pll_init();
190 
191     peri_ppu_wait();
192 }
193 
fw_sram_sysoc_init(void)194 static void fw_sram_sysoc_init(void)
195 {
196     uint32_t i, value;
197 
198     const uint32_t init_sysoc_addr_infos[] = CONFIG_SOC_INIT_SYSOC_ADDR_INFOS;
199     const uint32_t init_sysoc_reset_infos[] = CONFIG_SOC_INIT_SYSOC_RESET_INFOS;
200 
201     for (i = 0; i < FWK_ARRAY_SIZE(init_sysoc_addr_infos); i++) {
202         value = readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA);
203         if (value == 0)
204             continue; /* reset all not active */
205 
206         /* reset set only active bit */
207         writel(
208             (init_sysoc_addr_infos[i] + REG_ADDR_RSTCLR),
209             (init_sysoc_reset_infos[i] & value));
210 
211         while ((readl(init_sysoc_addr_infos[i] + REG_ADDR_RSTSTA) &
212                 init_sysoc_reset_infos[i]) != 0)
213             ;
214     }
215 }
216 
fw_sram_lpcm_init(void)217 static void fw_sram_lpcm_init(void)
218 {
219     /* reset clr set lpcm reset_ctrl*/
220     writel(CONFIG_SOC_LPCM_SCB_TOP_ADDR + LPCM_RESET_CTRL_ADDR, LPCM_RESET_CLR);
221 }
222 
synquacer_system_init(void)223 void synquacer_system_init(void)
224 {
225     fw_sram_sysoc_init();
226 
227     fw_sram_lpcm_init();
228 
229     fw_clk_init();
230 
231     fw_sysoc_init();
232 
233     fw_lpcm_init();
234 }
235