1 /*
2  * Copyright (c) 2022 Renesas Electronics Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/init.h>
8 #include <zephyr/linker/linker-defs.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/sys/reboot.h>
11 #include <string.h>
12 #include <DA1469xAB.h>
13 #include <da1469x_clock.h>
14 #include <da1469x_otp.h>
15 #include <da1469x_pd.h>
16 #include <da1469x_pdc.h>
17 #include <da1469x_trimv.h>
18 #include <da1469x_sleep.h>
19 
20 LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
21 
22 #define REMAP_ADR0_QSPI           0x2
23 
24 #define FLASH_REGION_SIZE_32M     0
25 #define FLASH_REGION_SIZE_16M     1
26 #define FLASH_REGION_SIZE_8M      2
27 #define FLASH_REGION_SIZE_4M      3
28 #define FLASH_REGION_SIZE_2M      4
29 #define FLASH_REGION_SIZE_1M      5
30 #define FLASH_REGION_SIZE_05M     6
31 #define FLASH_REGION_SIZE_025M    7
32 
33 #if defined(CONFIG_BOOTLOADER_MCUBOOT)
34 #define MAGIC 0xaabbccdd
35 static uint32_t z_renesas_cache_configured;
36 #endif
37 
sys_arch_reboot(int type)38 void sys_arch_reboot(int type)
39 {
40 	if (type == SYS_REBOOT_WARM) {
41 		NVIC_SystemReset();
42 	} else if (type == SYS_REBOOT_COLD) {
43 		if ((SYS_WDOG->WATCHDOG_REG & SYS_WDOG_WATCHDOG_REG_WDOG_VAL_NEG_Msk) == 0) {
44 			/* Cannot write WATCHDOG_REG while WRITE_BUSY */
45 			while ((SYS_WDOG->WATCHDOG_REG &
46 				SYS_WDOG_WATCHDOG_CTRL_REG_WRITE_BUSY_Msk) != 0) {
47 			}
48 			/* Write WATCHDOG_REG */
49 			SYS_WDOG->WATCHDOG_REG = BIT(SYS_WDOG_WATCHDOG_REG_WDOG_VAL_Pos);
50 
51 			GPREG->RESET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk;
52 			SYS_WDOG->WATCHDOG_CTRL_REG &=
53 				~SYS_WDOG_WATCHDOG_CTRL_REG_WDOG_FREEZE_EN_Msk;
54 		}
55 		/* Wait */
56 		for (;;) {
57 			__NOP();
58 		}
59 	}
60 }
61 
62 #if defined(CONFIG_BOOTLOADER_MCUBOOT)
z_renesas_configure_cache(void)63 static void z_renesas_configure_cache(void)
64 {
65 	uint32_t cache_start;
66 	uint32_t region_size;
67 	uint32_t reg_region_size;
68 	uint32_t reg_cache_len;
69 
70 	if (z_renesas_cache_configured == MAGIC) {
71 		return;
72 	}
73 
74 	cache_start = (uint32_t)&_vector_start;
75 	region_size = (uint32_t)&__rom_region_end - cache_start;
76 
77 	/* Disable cache before configuring it */
78 	CACHE->CACHE_CTRL2_REG = 0;
79 	CRG_TOP->SYS_CTRL_REG &= ~CRG_TOP_SYS_CTRL_REG_CACHERAM_MUX_Msk;
80 
81 	/* Disable MRM unit */
82 	CACHE->CACHE_MRM_CTRL_REG = 0;
83 	CACHE->CACHE_MRM_TINT_REG = 0;
84 	CACHE->CACHE_MRM_MISSES_THRES_REG = 0;
85 
86 	if (region_size > MB(16)) {
87 		reg_region_size = FLASH_REGION_SIZE_32M;
88 	} else if (region_size > MB(8)) {
89 		reg_region_size = FLASH_REGION_SIZE_16M;
90 	} else if (region_size > MB(4)) {
91 		reg_region_size = FLASH_REGION_SIZE_8M;
92 	} else if (region_size > MB(2)) {
93 		reg_region_size = FLASH_REGION_SIZE_4M;
94 	} else if (region_size > MB(1)) {
95 		reg_region_size = FLASH_REGION_SIZE_2M;
96 	} else if (region_size > KB(512)) {
97 		reg_region_size = FLASH_REGION_SIZE_1M;
98 	} else if (region_size > KB(256)) {
99 		reg_region_size = FLASH_REGION_SIZE_05M;
100 	} else {
101 		reg_region_size = FLASH_REGION_SIZE_025M;
102 	}
103 	CACHE->CACHE_FLASH_REG =
104 		(cache_start >> 16) << CACHE_CACHE_FLASH_REG_FLASH_REGION_BASE_Pos |
105 		((cache_start & 0xffff) >> 2) << CACHE_CACHE_FLASH_REG_FLASH_REGION_OFFSET_Pos |
106 		reg_region_size << CACHE_CACHE_FLASH_REG_FLASH_REGION_SIZE_Pos;
107 
108 	reg_cache_len = CLAMP(reg_region_size / KB(64), 0, 0x1ff);
109 	CACHE->CACHE_CTRL2_REG = (CACHE->CACHE_FLASH_REG & ~CACHE_CACHE_CTRL2_REG_CACHE_LEN_Msk) |
110 				 reg_cache_len;
111 
112 	/* Copy IVT from flash to start of RAM.
113 	 * It will be remapped at 0x0 so it can be used after SW Reset
114 	 */
115 	memcpy(&_image_ram_start, &_vector_start, 0x200);
116 
117 	/* Configure remapping */
118 	CRG_TOP->SYS_CTRL_REG = (CRG_TOP->SYS_CTRL_REG & ~CRG_TOP_SYS_CTRL_REG_REMAP_ADR0_Msk) |
119 				CRG_TOP_SYS_CTRL_REG_CACHERAM_MUX_Msk |
120 				CRG_TOP_SYS_CTRL_REG_REMAP_INTVECT_Msk |
121 				REMAP_ADR0_QSPI;
122 
123 	z_renesas_cache_configured = MAGIC;
124 
125 	/* Trigger SW Reset to apply cache configuration */
126 	CRG_TOP->SYS_CTRL_REG |= CRG_TOP_SYS_CTRL_REG_SW_RESET_Msk;
127 }
128 #endif /* CONFIG_HAS_FLASH_LOAD_OFFSET */
129 
soc_reset_hook(void)130 void soc_reset_hook(void)
131 {
132 #if defined(CONFIG_PM)
133 	uint32_t *ivt;
134 #endif
135 
136 #if defined(CONFIG_BOOTLOADER_MCUBOOT)
137 	z_renesas_configure_cache();
138 #endif
139 
140 #if defined(CONFIG_PM)
141 	/* IVT is always placed in reserved space at the start of RAM which
142 	 * is then remapped to 0x0 and retained. Generic reset handler is
143 	 * changed to custom routine since next time ARM core is reset we
144 	 * need to determine whether it was a regular reset or a wakeup from
145 	 * extended sleep and ARM core state needs to be restored.
146 	 */
147 	ivt = (uint32_t *)_image_ram_start;
148 	ivt[1] = (uint32_t)da1469x_wakeup_handler;
149 #endif
150 }
151 
152 /* defined in power.c */
153 extern int renesas_da1469x_pm_init(void);
154 
soc_early_init_hook(void)155 void soc_early_init_hook(void)
156 {
157 	/* Freeze watchdog until configured */
158 	GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk;
159 	SYS_WDOG->WATCHDOG_REG = SYS_WDOG_WATCHDOG_REG_WDOG_VAL_Msk;
160 
161 	/* Reset clock dividers to 0 */
162 	CRG_TOP->CLK_AMBA_REG &= ~(CRG_TOP_CLK_AMBA_REG_HCLK_DIV_Msk |
163 				CRG_TOP_CLK_AMBA_REG_PCLK_DIV_Msk);
164 
165 	CRG_TOP->PMU_CTRL_REG |= (CRG_TOP_PMU_CTRL_REG_TIM_SLEEP_Msk   |
166 				CRG_TOP_PMU_CTRL_REG_PERIPH_SLEEP_Msk  |
167 				CRG_TOP_PMU_CTRL_REG_COM_SLEEP_Msk     |
168 				CRG_TOP_PMU_CTRL_REG_RADIO_SLEEP_Msk);
169 
170 #if defined(CONFIG_PM)
171 	/* Enable cache retainability */
172 	CRG_TOP->PMU_CTRL_REG |= CRG_TOP_PMU_CTRL_REG_RETAIN_CACHE_Msk;
173 #endif
174 
175 	/*
176 	 *	Due to crosstalk issues any power rail can potentially
177 	 *	issue a fake event. This is typically observed upon
178 	 *	switching power sources, that is DCDC <--> LDOs <--> Retention LDOs.
179 	 */
180 	CRG_TOP->BOD_CTRL_REG &= ~(CRG_TOP_BOD_CTRL_REG_BOD_V14_EN_Msk |
181 				CRG_TOP_BOD_CTRL_REG_BOD_V18F_EN_Msk   |
182 				CRG_TOP_BOD_CTRL_REG_BOD_VDD_EN_Msk    |
183 				CRG_TOP_BOD_CTRL_REG_BOD_V18P_EN_Msk   |
184 				CRG_TOP_BOD_CTRL_REG_BOD_V18_EN_Msk    |
185 				CRG_TOP_BOD_CTRL_REG_BOD_V30_EN_Msk    |
186 				CRG_TOP_BOD_CTRL_REG_BOD_VBAT_EN_Msk);
187 
188 	da1469x_otp_init();
189 	da1469x_trimv_init_from_otp();
190 
191 	da1469x_pd_init();
192 
193 	/*
194 	 * Take PD_SYS control.
195 	 */
196 	da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
197 	da1469x_pd_acquire(MCU_PD_DOMAIN_TIM);
198 
199 	da1469x_pdc_reset();
200 #if CONFIG_PM
201 	renesas_da1469x_pm_init();
202 #endif
203 }
204