Commit 654088cc211e021387b04a8c33420739da40ebbe
1 parent
c630e0ad3b
Exists in
smarc-imx_v2018.03_4.14.78_1.0.0_ga
MLK-20479 imx8mq: clear ocotp error bit
In case ocotp error bit is set, clear it. This is a workaround to ocotp error bit. Signed-off-by: Peng Fan <peng.fan@nxp.com> (cherry picked from commit 781f2d8febe954b2ef3e51b6a2eebcfbf24b08eb)
Showing 1 changed file with 7 additions and 0 deletions Inline Diff
arch/arm/mach-imx/imx8m/soc.c
1 | /* | 1 | /* |
2 | * Copyright 2017-2018 NXP | 2 | * Copyright 2017-2018 NXP |
3 | * | 3 | * |
4 | * Peng Fan <peng.fan@nxp.com> | 4 | * Peng Fan <peng.fan@nxp.com> |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <common.h> | 9 | #include <common.h> |
10 | #include <asm/arch/imx-regs.h> | 10 | #include <asm/arch/imx-regs.h> |
11 | #include <asm/io.h> | 11 | #include <asm/io.h> |
12 | #include <asm/arch/clock.h> | 12 | #include <asm/arch/clock.h> |
13 | #include <asm/arch/sys_proto.h> | 13 | #include <asm/arch/sys_proto.h> |
14 | #include <asm/mach-imx/hab.h> | 14 | #include <asm/mach-imx/hab.h> |
15 | #include <asm/mach-imx/boot_mode.h> | 15 | #include <asm/mach-imx/boot_mode.h> |
16 | #include <asm/mach-imx/syscounter.h> | 16 | #include <asm/mach-imx/syscounter.h> |
17 | #include <asm/armv8/mmu.h> | 17 | #include <asm/armv8/mmu.h> |
18 | #include <errno.h> | 18 | #include <errno.h> |
19 | #include <fdt_support.h> | 19 | #include <fdt_support.h> |
20 | #include <fdtdec.h> | 20 | #include <fdtdec.h> |
21 | #include <fsl_wdog.h> | 21 | #include <fsl_wdog.h> |
22 | #include <imx_sip.h> | 22 | #include <imx_sip.h> |
23 | #include <generated/version_autogenerated.h> | 23 | #include <generated/version_autogenerated.h> |
24 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
25 | #ifdef CONFIG_IMX_SEC_INIT | 25 | #ifdef CONFIG_IMX_SEC_INIT |
26 | #include <fsl_caam.h> | 26 | #include <fsl_caam.h> |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | DECLARE_GLOBAL_DATA_PTR; | 29 | DECLARE_GLOBAL_DATA_PTR; |
30 | 30 | ||
31 | #if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_AVB_ATX) | 31 | #if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_AVB_ATX) |
32 | struct imx_sec_config_fuse_t const imx_sec_config_fuse = { | 32 | struct imx_sec_config_fuse_t const imx_sec_config_fuse = { |
33 | .bank = 1, | 33 | .bank = 1, |
34 | .word = 3, | 34 | .word = 3, |
35 | }; | 35 | }; |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | int timer_init(void) | 38 | int timer_init(void) |
39 | { | 39 | { |
40 | #ifdef CONFIG_SPL_BUILD | 40 | #ifdef CONFIG_SPL_BUILD |
41 | struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR; | 41 | struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR; |
42 | unsigned long freq = readl(&sctr->cntfid0); | 42 | unsigned long freq = readl(&sctr->cntfid0); |
43 | 43 | ||
44 | /* Update with accurate clock frequency */ | 44 | /* Update with accurate clock frequency */ |
45 | asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory"); | 45 | asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory"); |
46 | 46 | ||
47 | clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1, | 47 | clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1, |
48 | SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG); | 48 | SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG); |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | gd->arch.tbl = 0; | 51 | gd->arch.tbl = 0; |
52 | gd->arch.tbu = 0; | 52 | gd->arch.tbu = 0; |
53 | 53 | ||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | void enable_tzc380(void) | 57 | void enable_tzc380(void) |
58 | { | 58 | { |
59 | struct iomuxc_gpr_base_regs *gpr = | 59 | struct iomuxc_gpr_base_regs *gpr = |
60 | (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR; | 60 | (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR; |
61 | 61 | ||
62 | /* Enable TZASC and lock setting */ | 62 | /* Enable TZASC and lock setting */ |
63 | setbits_le32(&gpr->gpr[10], GPR_TZASC_EN); | 63 | setbits_le32(&gpr->gpr[10], GPR_TZASC_EN); |
64 | setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK); | 64 | setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK); |
65 | #ifdef CONFIG_IMX8MM | 65 | #ifdef CONFIG_IMX8MM |
66 | setbits_le32(&gpr->gpr[10], GPR_TZASC_SWAP_ID); | 66 | setbits_le32(&gpr->gpr[10], GPR_TZASC_SWAP_ID); |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * set Region 0 attribute to allow secure and non-secure read/write permission | 70 | * set Region 0 attribute to allow secure and non-secure read/write permission |
71 | * Found some masters like usb dwc3 controllers can't work with secure memory. | 71 | * Found some masters like usb dwc3 controllers can't work with secure memory. |
72 | */ | 72 | */ |
73 | writel(0xf0000000, TZASC_BASE_ADDR + 0x108); | 73 | writel(0xf0000000, TZASC_BASE_ADDR + 0x108); |
74 | } | 74 | } |
75 | 75 | ||
76 | void set_wdog_reset(struct wdog_regs *wdog) | 76 | void set_wdog_reset(struct wdog_regs *wdog) |
77 | { | 77 | { |
78 | /* | 78 | /* |
79 | * Output WDOG_B signal to reset external pmic or POR_B decided by | 79 | * Output WDOG_B signal to reset external pmic or POR_B decided by |
80 | * the board design. Without external reset, the peripherals/DDR/ | 80 | * the board design. Without external reset, the peripherals/DDR/ |
81 | * PMIC are not reset, that may cause system working abnormal. | 81 | * PMIC are not reset, that may cause system working abnormal. |
82 | * WDZST bit is write-once only bit. Align this bit in kernel, | 82 | * WDZST bit is write-once only bit. Align this bit in kernel, |
83 | * otherwise kernel code will have no chance to set this bit. | 83 | * otherwise kernel code will have no chance to set this bit. |
84 | */ | 84 | */ |
85 | setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK); | 85 | setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK); |
86 | } | 86 | } |
87 | 87 | ||
88 | static struct mm_region imx8m_mem_map[] = { | 88 | static struct mm_region imx8m_mem_map[] = { |
89 | { | 89 | { |
90 | /* ROM */ | 90 | /* ROM */ |
91 | .virt = 0x0UL, | 91 | .virt = 0x0UL, |
92 | .phys = 0x0UL, | 92 | .phys = 0x0UL, |
93 | .size = 0x100000UL, | 93 | .size = 0x100000UL, |
94 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | 94 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
95 | PTE_BLOCK_OUTER_SHARE | 95 | PTE_BLOCK_OUTER_SHARE |
96 | }, { | 96 | }, { |
97 | .virt = 0x100000UL, | 97 | .virt = 0x100000UL, |
98 | .phys = 0x100000UL, | 98 | .phys = 0x100000UL, |
99 | .size = 0x8000UL, | 99 | .size = 0x8000UL, |
100 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | 100 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
101 | PTE_BLOCK_NON_SHARE | | 101 | PTE_BLOCK_NON_SHARE | |
102 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | 102 | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
103 | }, { | 103 | }, { |
104 | .virt = 0x7C0000UL, | 104 | .virt = 0x7C0000UL, |
105 | .phys = 0x7C0000UL, | 105 | .phys = 0x7C0000UL, |
106 | .size = 0x80000UL, | 106 | .size = 0x80000UL, |
107 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | 107 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
108 | PTE_BLOCK_NON_SHARE | | 108 | PTE_BLOCK_NON_SHARE | |
109 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | 109 | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
110 | }, { | 110 | }, { |
111 | /* OCRAM */ | 111 | /* OCRAM */ |
112 | .virt = 0x900000UL, | 112 | .virt = 0x900000UL, |
113 | .phys = 0x900000UL, | 113 | .phys = 0x900000UL, |
114 | .size = 0x200000UL, | 114 | .size = 0x200000UL, |
115 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | 115 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
116 | PTE_BLOCK_OUTER_SHARE | 116 | PTE_BLOCK_OUTER_SHARE |
117 | }, { | 117 | }, { |
118 | /* AIPS */ | 118 | /* AIPS */ |
119 | .virt = 0xB00000UL, | 119 | .virt = 0xB00000UL, |
120 | .phys = 0xB00000UL, | 120 | .phys = 0xB00000UL, |
121 | .size = 0x3f500000UL, | 121 | .size = 0x3f500000UL, |
122 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | 122 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
123 | PTE_BLOCK_NON_SHARE | | 123 | PTE_BLOCK_NON_SHARE | |
124 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | 124 | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
125 | }, { | 125 | }, { |
126 | /* DRAM1 */ | 126 | /* DRAM1 */ |
127 | .virt = 0x40000000UL, | 127 | .virt = 0x40000000UL, |
128 | .phys = 0x40000000UL, | 128 | .phys = 0x40000000UL, |
129 | .size = PHYS_SDRAM_SIZE, | 129 | .size = PHYS_SDRAM_SIZE, |
130 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | 130 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
131 | PTE_BLOCK_OUTER_SHARE | 131 | PTE_BLOCK_OUTER_SHARE |
132 | #if CONFIG_NR_DRAM_BANKS > 1 | 132 | #if CONFIG_NR_DRAM_BANKS > 1 |
133 | }, { | 133 | }, { |
134 | /* DRAM2 */ | 134 | /* DRAM2 */ |
135 | .virt = 0x100000000UL, | 135 | .virt = 0x100000000UL, |
136 | .phys = 0x100000000UL, | 136 | .phys = 0x100000000UL, |
137 | .size = PHYS_SDRAM_2_SIZE, | 137 | .size = PHYS_SDRAM_2_SIZE, |
138 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | 138 | .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
139 | PTE_BLOCK_OUTER_SHARE | 139 | PTE_BLOCK_OUTER_SHARE |
140 | #endif | 140 | #endif |
141 | }, { | 141 | }, { |
142 | /* List terminator */ | 142 | /* List terminator */ |
143 | 0, | 143 | 0, |
144 | } | 144 | } |
145 | }; | 145 | }; |
146 | 146 | ||
147 | struct mm_region *mem_map = imx8m_mem_map; | 147 | struct mm_region *mem_map = imx8m_mem_map; |
148 | 148 | ||
149 | void enable_caches(void) | 149 | void enable_caches(void) |
150 | { | 150 | { |
151 | /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */ | 151 | /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */ |
152 | if (rom_pointer[1]) { | 152 | if (rom_pointer[1]) { |
153 | imx8m_mem_map[5].size -= rom_pointer[1]; | 153 | imx8m_mem_map[5].size -= rom_pointer[1]; |
154 | } | 154 | } |
155 | 155 | ||
156 | icache_enable(); | 156 | icache_enable(); |
157 | dcache_enable(); | 157 | dcache_enable(); |
158 | } | 158 | } |
159 | 159 | ||
160 | static u32 get_cpu_variant_type(u32 type) | 160 | static u32 get_cpu_variant_type(u32 type) |
161 | { | 161 | { |
162 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 162 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
163 | struct fuse_bank *bank = &ocotp->bank[1]; | 163 | struct fuse_bank *bank = &ocotp->bank[1]; |
164 | struct fuse_bank1_regs *fuse = | 164 | struct fuse_bank1_regs *fuse = |
165 | (struct fuse_bank1_regs *)bank->fuse_regs; | 165 | (struct fuse_bank1_regs *)bank->fuse_regs; |
166 | 166 | ||
167 | u32 value = readl(&fuse->tester4); | 167 | u32 value = readl(&fuse->tester4); |
168 | 168 | ||
169 | if (type == MXC_CPU_IMX8MQ) { | 169 | if (type == MXC_CPU_IMX8MQ) { |
170 | if ((value & 0x3) == 0x2) | 170 | if ((value & 0x3) == 0x2) |
171 | return MXC_CPU_IMX8MD; | 171 | return MXC_CPU_IMX8MD; |
172 | else if (value & 0x200000) | 172 | else if (value & 0x200000) |
173 | return MXC_CPU_IMX8MQL; | 173 | return MXC_CPU_IMX8MQL; |
174 | 174 | ||
175 | } else if (type == MXC_CPU_IMX8MM) { | 175 | } else if (type == MXC_CPU_IMX8MM) { |
176 | switch (value & 0x3) { | 176 | switch (value & 0x3) { |
177 | case 2: | 177 | case 2: |
178 | if (value & 0x1c0000) | 178 | if (value & 0x1c0000) |
179 | return MXC_CPU_IMX8MMDL; | 179 | return MXC_CPU_IMX8MMDL; |
180 | else | 180 | else |
181 | return MXC_CPU_IMX8MMD; | 181 | return MXC_CPU_IMX8MMD; |
182 | case 3: | 182 | case 3: |
183 | if (value & 0x1c0000) | 183 | if (value & 0x1c0000) |
184 | return MXC_CPU_IMX8MMSL; | 184 | return MXC_CPU_IMX8MMSL; |
185 | else | 185 | else |
186 | return MXC_CPU_IMX8MMS; | 186 | return MXC_CPU_IMX8MMS; |
187 | default: | 187 | default: |
188 | if (value & 0x1c0000) | 188 | if (value & 0x1c0000) |
189 | return MXC_CPU_IMX8MML; | 189 | return MXC_CPU_IMX8MML; |
190 | break; | 190 | break; |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
194 | return type; | 194 | return type; |
195 | } | 195 | } |
196 | 196 | ||
197 | u32 get_cpu_rev(void) | 197 | u32 get_cpu_rev(void) |
198 | { | 198 | { |
199 | struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; | 199 | struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; |
200 | u32 reg = readl(&ana_pll->digprog); | 200 | u32 reg = readl(&ana_pll->digprog); |
201 | u32 type = (reg >> 16) & 0xff; | 201 | u32 type = (reg >> 16) & 0xff; |
202 | u32 major_low = (reg >> 8) & 0xff; | 202 | u32 major_low = (reg >> 8) & 0xff; |
203 | u32 rom_version; | 203 | u32 rom_version; |
204 | 204 | ||
205 | reg &= 0xff; | 205 | reg &= 0xff; |
206 | 206 | ||
207 | /* iMX8MM */ | 207 | /* iMX8MM */ |
208 | if (major_low == 0x41) { | 208 | if (major_low == 0x41) { |
209 | type = get_cpu_variant_type(MXC_CPU_IMX8MM); | 209 | type = get_cpu_variant_type(MXC_CPU_IMX8MM); |
210 | return (type << 12) | reg; | 210 | return (type << 12) | reg; |
211 | } else { | 211 | } else { |
212 | /* iMX8MQ */ | 212 | /* iMX8MQ */ |
213 | if (reg == CHIP_REV_1_0) { | 213 | if (reg == CHIP_REV_1_0) { |
214 | /* | 214 | /* |
215 | * For B0 chip, the DIGPROG is not updated, still TO1.0. | 215 | * For B0 chip, the DIGPROG is not updated, still TO1.0. |
216 | * we have to check ROM version or OCOTP_READ_FUSE_DATA | 216 | * we have to check ROM version or OCOTP_READ_FUSE_DATA |
217 | */ | 217 | */ |
218 | if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) | 218 | if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) |
219 | == 0xff0055aa) { | 219 | == 0xff0055aa) { |
220 | /* 0xff0055aa is magic number for B1 */ | 220 | /* 0xff0055aa is magic number for B1 */ |
221 | reg = CHIP_REV_2_1; | 221 | reg = CHIP_REV_2_1; |
222 | } else { | 222 | } else { |
223 | rom_version = readb((void __iomem *)ROM_VERSION_A0); | 223 | rom_version = readb((void __iomem *)ROM_VERSION_A0); |
224 | if (rom_version != CHIP_REV_1_0) { | 224 | if (rom_version != CHIP_REV_1_0) { |
225 | rom_version = readb((void __iomem *)ROM_VERSION_B0); | 225 | rom_version = readb((void __iomem *)ROM_VERSION_B0); |
226 | if (rom_version == CHIP_REV_2_0) | 226 | if (rom_version == CHIP_REV_2_0) |
227 | reg = CHIP_REV_2_0; | 227 | reg = CHIP_REV_2_0; |
228 | } | 228 | } |
229 | } | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
232 | type = get_cpu_variant_type(type); | 232 | type = get_cpu_variant_type(type); |
233 | 233 | ||
234 | return (type << 12) | reg; | 234 | return (type << 12) | reg; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | static void imx_set_wdog_powerdown(bool enable) | 238 | static void imx_set_wdog_powerdown(bool enable) |
239 | { | 239 | { |
240 | struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; | 240 | struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; |
241 | struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; | 241 | struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; |
242 | struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR; | 242 | struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR; |
243 | 243 | ||
244 | /* Write to the PDE (Power Down Enable) bit */ | 244 | /* Write to the PDE (Power Down Enable) bit */ |
245 | writew(enable, &wdog1->wmcr); | 245 | writew(enable, &wdog1->wmcr); |
246 | writew(enable, &wdog2->wmcr); | 246 | writew(enable, &wdog2->wmcr); |
247 | writew(enable, &wdog3->wmcr); | 247 | writew(enable, &wdog3->wmcr); |
248 | } | 248 | } |
249 | 249 | ||
250 | int arch_cpu_init(void) | 250 | int arch_cpu_init(void) |
251 | { | 251 | { |
252 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | ||
252 | /* | 253 | /* |
253 | * Init timer at very early state, because pll setting will use it, | 254 | * Init timer at very early state, because pll setting will use it, |
254 | * Rom Turnned off SCTR, enable it before timer_init | 255 | * Rom Turnned off SCTR, enable it before timer_init |
255 | */ | 256 | */ |
256 | 257 | ||
257 | clock_enable(CCGR_SCTR, 1); | 258 | clock_enable(CCGR_SCTR, 1); |
258 | timer_init(); | 259 | timer_init(); |
259 | 260 | ||
260 | if (IS_ENABLED(CONFIG_SPL_BUILD)) { | 261 | if (IS_ENABLED(CONFIG_SPL_BUILD)) { |
261 | clock_init(); | 262 | clock_init(); |
262 | imx_set_wdog_powerdown(false); | 263 | imx_set_wdog_powerdown(false); |
263 | 264 | ||
264 | if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() || is_imx8mmsl()) { | 265 | if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() || is_imx8mmsl()) { |
265 | /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */ | 266 | /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */ |
266 | struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840); | 267 | struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840); |
267 | struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880); | 268 | struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880); |
268 | struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0); | 269 | struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0); |
269 | struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR; | 270 | struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR; |
270 | 271 | ||
271 | writel(0x1, &pgc_core2->pgcr); | 272 | writel(0x1, &pgc_core2->pgcr); |
272 | writel(0x1, &pgc_core3->pgcr); | 273 | writel(0x1, &pgc_core3->pgcr); |
273 | if (is_imx8mms() || is_imx8mmsl()) { | 274 | if (is_imx8mms() || is_imx8mmsl()) { |
274 | writel(0x1, &pgc_core1->pgcr); | 275 | writel(0x1, &pgc_core1->pgcr); |
275 | writel(0xE, &gpc->cpu_pgc_dn_trg); | 276 | writel(0xE, &gpc->cpu_pgc_dn_trg); |
276 | } else { | 277 | } else { |
277 | writel(0xC, &gpc->cpu_pgc_dn_trg); | 278 | writel(0xC, &gpc->cpu_pgc_dn_trg); |
278 | } | 279 | } |
279 | } | 280 | } |
280 | } | 281 | } |
281 | 282 | ||
282 | #ifdef CONFIG_IMX_SEC_INIT | 283 | #ifdef CONFIG_IMX_SEC_INIT |
283 | /* Secure init function such RNG */ | 284 | /* Secure init function such RNG */ |
284 | imx_sec_init(); | 285 | imx_sec_init(); |
285 | #endif | 286 | #endif |
286 | #if defined(CONFIG_ANDROID_SUPPORT) | 287 | #if defined(CONFIG_ANDROID_SUPPORT) |
287 | /* Enable RTC */ | 288 | /* Enable RTC */ |
288 | writel(0x21, 0x30370038); | 289 | writel(0x21, 0x30370038); |
289 | #endif | 290 | #endif |
291 | |||
292 | if (is_imx8mq()) { | ||
293 | clock_enable(CCGR_OCOTP, 1); | ||
294 | if (readl(&ocotp->ctrl) & 0x200) | ||
295 | writel(0x200, &ocotp->ctrl_clr); | ||
296 | } | ||
290 | 297 | ||
291 | return 0; | 298 | return 0; |
292 | } | 299 | } |
293 | 300 | ||
294 | bool is_usb_boot(void) | 301 | bool is_usb_boot(void) |
295 | { | 302 | { |
296 | return get_boot_device() == USB_BOOT; | 303 | return get_boot_device() == USB_BOOT; |
297 | } | 304 | } |
298 | #ifdef CONFIG_SERIAL_TAG | 305 | #ifdef CONFIG_SERIAL_TAG |
299 | void get_board_serial(struct tag_serialnr *serialnr) | 306 | void get_board_serial(struct tag_serialnr *serialnr) |
300 | { | 307 | { |
301 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 308 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
302 | struct fuse_bank *bank = &ocotp->bank[0]; | 309 | struct fuse_bank *bank = &ocotp->bank[0]; |
303 | struct fuse_bank0_regs *fuse = | 310 | struct fuse_bank0_regs *fuse = |
304 | (struct fuse_bank0_regs *)bank->fuse_regs; | 311 | (struct fuse_bank0_regs *)bank->fuse_regs; |
305 | 312 | ||
306 | serialnr->low = fuse->uid_low; | 313 | serialnr->low = fuse->uid_low; |
307 | serialnr->high = fuse->uid_high; | 314 | serialnr->high = fuse->uid_high; |
308 | } | 315 | } |
309 | #endif | 316 | #endif |
310 | 317 | ||
311 | #ifdef CONFIG_OF_SYSTEM_SETUP | 318 | #ifdef CONFIG_OF_SYSTEM_SETUP |
312 | static int ft_add_optee_node(void *fdt, bd_t *bd) | 319 | static int ft_add_optee_node(void *fdt, bd_t *bd) |
313 | { | 320 | { |
314 | const char *path, *subpath; | 321 | const char *path, *subpath; |
315 | int offs; | 322 | int offs; |
316 | 323 | ||
317 | /* | 324 | /* |
318 | * No TEE space allocated indicating no TEE running, so no | 325 | * No TEE space allocated indicating no TEE running, so no |
319 | * need to add optee node in dts | 326 | * need to add optee node in dts |
320 | */ | 327 | */ |
321 | if (!rom_pointer[1]) | 328 | if (!rom_pointer[1]) |
322 | return 0; | 329 | return 0; |
323 | 330 | ||
324 | offs = fdt_increase_size(fdt, 512); | 331 | offs = fdt_increase_size(fdt, 512); |
325 | if (offs) { | 332 | if (offs) { |
326 | printf("No Space for dtb\n"); | 333 | printf("No Space for dtb\n"); |
327 | return 1; | 334 | return 1; |
328 | } | 335 | } |
329 | 336 | ||
330 | path = "/firmware"; | 337 | path = "/firmware"; |
331 | offs = fdt_path_offset(fdt, path); | 338 | offs = fdt_path_offset(fdt, path); |
332 | if (offs < 0) { | 339 | if (offs < 0) { |
333 | path = "/"; | 340 | path = "/"; |
334 | offs = fdt_path_offset(fdt, path); | 341 | offs = fdt_path_offset(fdt, path); |
335 | 342 | ||
336 | if (offs < 0) { | 343 | if (offs < 0) { |
337 | printf("Could not find root node.\n"); | 344 | printf("Could not find root node.\n"); |
338 | return 1; | 345 | return 1; |
339 | } | 346 | } |
340 | 347 | ||
341 | subpath = "firmware"; | 348 | subpath = "firmware"; |
342 | offs = fdt_add_subnode(fdt, offs, subpath); | 349 | offs = fdt_add_subnode(fdt, offs, subpath); |
343 | if (offs < 0) { | 350 | if (offs < 0) { |
344 | printf("Could not create %s node.\n", subpath); | 351 | printf("Could not create %s node.\n", subpath); |
345 | } | 352 | } |
346 | } | 353 | } |
347 | 354 | ||
348 | subpath = "optee"; | 355 | subpath = "optee"; |
349 | offs = fdt_add_subnode(fdt, offs, subpath); | 356 | offs = fdt_add_subnode(fdt, offs, subpath); |
350 | if (offs < 0) { | 357 | if (offs < 0) { |
351 | printf("Could not create %s node.\n", subpath); | 358 | printf("Could not create %s node.\n", subpath); |
352 | } | 359 | } |
353 | 360 | ||
354 | fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz"); | 361 | fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz"); |
355 | fdt_setprop_string(fdt, offs, "method", "smc"); | 362 | fdt_setprop_string(fdt, offs, "method", "smc"); |
356 | 363 | ||
357 | return 0; | 364 | return 0; |
358 | } | 365 | } |
359 | 366 | ||
360 | static int disable_fdt_nodes(void *blob, const char *nodes_path[], int size_array) | 367 | static int disable_fdt_nodes(void *blob, const char *nodes_path[], int size_array) |
361 | { | 368 | { |
362 | int i = 0; | 369 | int i = 0; |
363 | int rc; | 370 | int rc; |
364 | int nodeoff; | 371 | int nodeoff; |
365 | const char *status = "disabled"; | 372 | const char *status = "disabled"; |
366 | 373 | ||
367 | for (i = 0; i < size_array; i++) { | 374 | for (i = 0; i < size_array; i++) { |
368 | nodeoff = fdt_path_offset(blob, nodes_path[i]); | 375 | nodeoff = fdt_path_offset(blob, nodes_path[i]); |
369 | if (nodeoff < 0) | 376 | if (nodeoff < 0) |
370 | continue; /* Not found, skip it */ | 377 | continue; /* Not found, skip it */ |
371 | 378 | ||
372 | printf("Found %s node\n", nodes_path[i]); | 379 | printf("Found %s node\n", nodes_path[i]); |
373 | 380 | ||
374 | add_status: | 381 | add_status: |
375 | rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1); | 382 | rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1); |
376 | if (rc) { | 383 | if (rc) { |
377 | if (rc == -FDT_ERR_NOSPACE) { | 384 | if (rc == -FDT_ERR_NOSPACE) { |
378 | rc = fdt_increase_size(blob, 512); | 385 | rc = fdt_increase_size(blob, 512); |
379 | if (!rc) | 386 | if (!rc) |
380 | goto add_status; | 387 | goto add_status; |
381 | } | 388 | } |
382 | printf("Unable to update property %s:%s, err=%s\n", | 389 | printf("Unable to update property %s:%s, err=%s\n", |
383 | nodes_path[i], "status", fdt_strerror(rc)); | 390 | nodes_path[i], "status", fdt_strerror(rc)); |
384 | } else { | 391 | } else { |
385 | printf("Modify %s:%s disabled\n", | 392 | printf("Modify %s:%s disabled\n", |
386 | nodes_path[i], "status"); | 393 | nodes_path[i], "status"); |
387 | } | 394 | } |
388 | } | 395 | } |
389 | 396 | ||
390 | return 0; | 397 | return 0; |
391 | } | 398 | } |
392 | 399 | ||
393 | #ifdef CONFIG_IMX8MQ | 400 | #ifdef CONFIG_IMX8MQ |
394 | static int disable_mipi_dsi_nodes(void *blob) | 401 | static int disable_mipi_dsi_nodes(void *blob) |
395 | { | 402 | { |
396 | const char *nodes_path[] = { | 403 | const char *nodes_path[] = { |
397 | "/mipi_dsi@30A00000", | 404 | "/mipi_dsi@30A00000", |
398 | "/mipi_dsi_bridge@30A00000", | 405 | "/mipi_dsi_bridge@30A00000", |
399 | "/dsi_phy@30A00300" | 406 | "/dsi_phy@30A00300" |
400 | }; | 407 | }; |
401 | 408 | ||
402 | return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path)); | 409 | return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path)); |
403 | } | 410 | } |
404 | 411 | ||
405 | static int disable_dcss_nodes(void *blob) | 412 | static int disable_dcss_nodes(void *blob) |
406 | { | 413 | { |
407 | const char *nodes_path[] = { | 414 | const char *nodes_path[] = { |
408 | "/dcss@0x32e00000", | 415 | "/dcss@0x32e00000", |
409 | "/dcss@32e00000", | 416 | "/dcss@32e00000", |
410 | "/hdmi@32c00000", | 417 | "/hdmi@32c00000", |
411 | "/hdmi_cec@32c33800", | 418 | "/hdmi_cec@32c33800", |
412 | "/hdmi_drm@32c00000", | 419 | "/hdmi_drm@32c00000", |
413 | "/display-subsystem", | 420 | "/display-subsystem", |
414 | "/sound-hdmi" | 421 | "/sound-hdmi" |
415 | }; | 422 | }; |
416 | 423 | ||
417 | return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path)); | 424 | return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path)); |
418 | } | 425 | } |
419 | 426 | ||
420 | static int check_mipi_dsi_nodes(void *blob) | 427 | static int check_mipi_dsi_nodes(void *blob) |
421 | { | 428 | { |
422 | const char *lcdif_path = "/lcdif@30320000"; | 429 | const char *lcdif_path = "/lcdif@30320000"; |
423 | const char *mipi_dsi_path = "/mipi_dsi@30A00000"; | 430 | const char *mipi_dsi_path = "/mipi_dsi@30A00000"; |
424 | 431 | ||
425 | const char *lcdif_ep_path = "/lcdif@30320000/port@0/mipi-dsi-endpoint"; | 432 | const char *lcdif_ep_path = "/lcdif@30320000/port@0/mipi-dsi-endpoint"; |
426 | const char *mipi_dsi_ep_path = "/mipi_dsi@30A00000/port@1/endpoint"; | 433 | const char *mipi_dsi_ep_path = "/mipi_dsi@30A00000/port@1/endpoint"; |
427 | 434 | ||
428 | int nodeoff; | 435 | int nodeoff; |
429 | nodeoff = fdt_path_offset(blob, lcdif_path); | 436 | nodeoff = fdt_path_offset(blob, lcdif_path); |
430 | if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) { | 437 | if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) { |
431 | /* If can't find lcdif node or lcdif node is disabled, then disable all mipi dsi, | 438 | /* If can't find lcdif node or lcdif node is disabled, then disable all mipi dsi, |
432 | since they only can input from DCSS */ | 439 | since they only can input from DCSS */ |
433 | return disable_mipi_dsi_nodes(blob); | 440 | return disable_mipi_dsi_nodes(blob); |
434 | } | 441 | } |
435 | 442 | ||
436 | nodeoff = fdt_path_offset(blob, mipi_dsi_path); | 443 | nodeoff = fdt_path_offset(blob, mipi_dsi_path); |
437 | if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) | 444 | if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) |
438 | return 0; | 445 | return 0; |
439 | 446 | ||
440 | nodeoff = fdt_path_offset(blob, lcdif_ep_path); | 447 | nodeoff = fdt_path_offset(blob, lcdif_ep_path); |
441 | if (nodeoff < 0) { | 448 | if (nodeoff < 0) { |
442 | /* If can't find lcdif endpoint, then disable all mipi dsi, | 449 | /* If can't find lcdif endpoint, then disable all mipi dsi, |
443 | since they only can input from DCSS */ | 450 | since they only can input from DCSS */ |
444 | return disable_mipi_dsi_nodes(blob); | 451 | return disable_mipi_dsi_nodes(blob); |
445 | } else { | 452 | } else { |
446 | int lookup_node; | 453 | int lookup_node; |
447 | lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint"); | 454 | lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint"); |
448 | nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path); | 455 | nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path); |
449 | 456 | ||
450 | if (nodeoff >0 && nodeoff == lookup_node) | 457 | if (nodeoff >0 && nodeoff == lookup_node) |
451 | return 0; | 458 | return 0; |
452 | 459 | ||
453 | return disable_mipi_dsi_nodes(blob); | 460 | return disable_mipi_dsi_nodes(blob); |
454 | } | 461 | } |
455 | 462 | ||
456 | } | 463 | } |
457 | 464 | ||
458 | void board_quiesce_devices(void) | 465 | void board_quiesce_devices(void) |
459 | { | 466 | { |
460 | #ifdef CONFIG_USB_DWC3 | 467 | #ifdef CONFIG_USB_DWC3 |
461 | if (is_usb_boot()) | 468 | if (is_usb_boot()) |
462 | disconnect_from_pc(); | 469 | disconnect_from_pc(); |
463 | #endif | 470 | #endif |
464 | } | 471 | } |
465 | #endif | 472 | #endif |
466 | 473 | ||
467 | static int disable_vpu_nodes(void *blob) | 474 | static int disable_vpu_nodes(void *blob) |
468 | { | 475 | { |
469 | const char *nodes_path_8mq[] = { | 476 | const char *nodes_path_8mq[] = { |
470 | "/vpu@38300000" | 477 | "/vpu@38300000" |
471 | }; | 478 | }; |
472 | 479 | ||
473 | const char *nodes_path_8mm[] = { | 480 | const char *nodes_path_8mm[] = { |
474 | "/vpu_g1@38300000", | 481 | "/vpu_g1@38300000", |
475 | "/vpu_g2@38310000", | 482 | "/vpu_g2@38310000", |
476 | "/vpu_h1@38320000" | 483 | "/vpu_h1@38320000" |
477 | }; | 484 | }; |
478 | 485 | ||
479 | if (is_imx8mq()) | 486 | if (is_imx8mq()) |
480 | return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq)); | 487 | return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq)); |
481 | else if (is_imx8mm()) | 488 | else if (is_imx8mm()) |
482 | return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm)); | 489 | return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm)); |
483 | else | 490 | else |
484 | return -EPERM; | 491 | return -EPERM; |
485 | 492 | ||
486 | } | 493 | } |
487 | 494 | ||
488 | static int disable_cpu_nodes(void *blob, u32 disabled_cores) | 495 | static int disable_cpu_nodes(void *blob, u32 disabled_cores) |
489 | { | 496 | { |
490 | const char *nodes_path[] = { | 497 | const char *nodes_path[] = { |
491 | "/cpus/cpu@1", | 498 | "/cpus/cpu@1", |
492 | "/cpus/cpu@2", | 499 | "/cpus/cpu@2", |
493 | "/cpus/cpu@3", | 500 | "/cpus/cpu@3", |
494 | }; | 501 | }; |
495 | 502 | ||
496 | u32 i = 0; | 503 | u32 i = 0; |
497 | int rc; | 504 | int rc; |
498 | int nodeoff; | 505 | int nodeoff; |
499 | 506 | ||
500 | if (disabled_cores > 3) | 507 | if (disabled_cores > 3) |
501 | return -EINVAL; | 508 | return -EINVAL; |
502 | 509 | ||
503 | i = 3 - disabled_cores; | 510 | i = 3 - disabled_cores; |
504 | 511 | ||
505 | for (; i < 3; i++) { | 512 | for (; i < 3; i++) { |
506 | nodeoff = fdt_path_offset(blob, nodes_path[i]); | 513 | nodeoff = fdt_path_offset(blob, nodes_path[i]); |
507 | if (nodeoff < 0) | 514 | if (nodeoff < 0) |
508 | continue; /* Not found, skip it */ | 515 | continue; /* Not found, skip it */ |
509 | 516 | ||
510 | printf("Found %s node\n", nodes_path[i]); | 517 | printf("Found %s node\n", nodes_path[i]); |
511 | 518 | ||
512 | rc = fdt_del_node(blob, nodeoff); | 519 | rc = fdt_del_node(blob, nodeoff); |
513 | if (rc < 0) { | 520 | if (rc < 0) { |
514 | printf("Unable to delete node %s, err=%s\n", | 521 | printf("Unable to delete node %s, err=%s\n", |
515 | nodes_path[i], fdt_strerror(rc)); | 522 | nodes_path[i], fdt_strerror(rc)); |
516 | } else { | 523 | } else { |
517 | printf("Delete node %s\n", nodes_path[i]); | 524 | printf("Delete node %s\n", nodes_path[i]); |
518 | } | 525 | } |
519 | } | 526 | } |
520 | 527 | ||
521 | return 0; | 528 | return 0; |
522 | } | 529 | } |
523 | 530 | ||
524 | int ft_system_setup(void *blob, bd_t *bd) | 531 | int ft_system_setup(void *blob, bd_t *bd) |
525 | { | 532 | { |
526 | #ifdef CONFIG_IMX8MQ | 533 | #ifdef CONFIG_IMX8MQ |
527 | int i = 0; | 534 | int i = 0; |
528 | int rc; | 535 | int rc; |
529 | int nodeoff; | 536 | int nodeoff; |
530 | 537 | ||
531 | if (get_boot_device() == USB_BOOT) { | 538 | if (get_boot_device() == USB_BOOT) { |
532 | 539 | ||
533 | disable_dcss_nodes(blob); | 540 | disable_dcss_nodes(blob); |
534 | 541 | ||
535 | const char *usb_dwc3_path = "/usb@38100000/dwc3"; | 542 | const char *usb_dwc3_path = "/usb@38100000/dwc3"; |
536 | nodeoff = fdt_path_offset(blob, usb_dwc3_path); | 543 | nodeoff = fdt_path_offset(blob, usb_dwc3_path); |
537 | if (nodeoff >= 0) { | 544 | if (nodeoff >= 0) { |
538 | const char *speed = "high-speed"; | 545 | const char *speed = "high-speed"; |
539 | printf("Found %s node\n", usb_dwc3_path); | 546 | printf("Found %s node\n", usb_dwc3_path); |
540 | 547 | ||
541 | usb_modify_speed: | 548 | usb_modify_speed: |
542 | 549 | ||
543 | rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1); | 550 | rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1); |
544 | if (rc) { | 551 | if (rc) { |
545 | if (rc == -FDT_ERR_NOSPACE) { | 552 | if (rc == -FDT_ERR_NOSPACE) { |
546 | rc = fdt_increase_size(blob, 512); | 553 | rc = fdt_increase_size(blob, 512); |
547 | if (!rc) | 554 | if (!rc) |
548 | goto usb_modify_speed; | 555 | goto usb_modify_speed; |
549 | } | 556 | } |
550 | printf("Unable to set property %s:%s, err=%s\n", | 557 | printf("Unable to set property %s:%s, err=%s\n", |
551 | usb_dwc3_path, "maximum-speed", fdt_strerror(rc)); | 558 | usb_dwc3_path, "maximum-speed", fdt_strerror(rc)); |
552 | } else { | 559 | } else { |
553 | printf("Modify %s:%s = %s\n", | 560 | printf("Modify %s:%s = %s\n", |
554 | usb_dwc3_path, "maximum-speed", speed); | 561 | usb_dwc3_path, "maximum-speed", speed); |
555 | } | 562 | } |
556 | }else { | 563 | }else { |
557 | printf("Can't found %s node\n", usb_dwc3_path); | 564 | printf("Can't found %s node\n", usb_dwc3_path); |
558 | } | 565 | } |
559 | } | 566 | } |
560 | 567 | ||
561 | /* Disable the CPU idle for A0 chip since the HW does not support it */ | 568 | /* Disable the CPU idle for A0 chip since the HW does not support it */ |
562 | if (is_soc_rev(CHIP_REV_1_0)) { | 569 | if (is_soc_rev(CHIP_REV_1_0)) { |
563 | static const char * const nodes_path[] = { | 570 | static const char * const nodes_path[] = { |
564 | "/cpus/cpu@0", | 571 | "/cpus/cpu@0", |
565 | "/cpus/cpu@1", | 572 | "/cpus/cpu@1", |
566 | "/cpus/cpu@2", | 573 | "/cpus/cpu@2", |
567 | "/cpus/cpu@3", | 574 | "/cpus/cpu@3", |
568 | }; | 575 | }; |
569 | 576 | ||
570 | for (i = 0; i < ARRAY_SIZE(nodes_path); i++) { | 577 | for (i = 0; i < ARRAY_SIZE(nodes_path); i++) { |
571 | nodeoff = fdt_path_offset(blob, nodes_path[i]); | 578 | nodeoff = fdt_path_offset(blob, nodes_path[i]); |
572 | if (nodeoff < 0) | 579 | if (nodeoff < 0) |
573 | continue; /* Not found, skip it */ | 580 | continue; /* Not found, skip it */ |
574 | 581 | ||
575 | printf("Found %s node\n", nodes_path[i]); | 582 | printf("Found %s node\n", nodes_path[i]); |
576 | 583 | ||
577 | rc = fdt_delprop(blob, nodeoff, "cpu-idle-states"); | 584 | rc = fdt_delprop(blob, nodeoff, "cpu-idle-states"); |
578 | if (rc) { | 585 | if (rc) { |
579 | printf("Unable to update property %s:%s, err=%s\n", | 586 | printf("Unable to update property %s:%s, err=%s\n", |
580 | nodes_path[i], "status", fdt_strerror(rc)); | 587 | nodes_path[i], "status", fdt_strerror(rc)); |
581 | return rc; | 588 | return rc; |
582 | } | 589 | } |
583 | 590 | ||
584 | printf("Remove %s:%s\n", nodes_path[i], | 591 | printf("Remove %s:%s\n", nodes_path[i], |
585 | "cpu-idle-states"); | 592 | "cpu-idle-states"); |
586 | } | 593 | } |
587 | } | 594 | } |
588 | 595 | ||
589 | if (is_imx8mql()) { | 596 | if (is_imx8mql()) { |
590 | disable_vpu_nodes(blob); | 597 | disable_vpu_nodes(blob); |
591 | disable_dcss_nodes(blob); | 598 | disable_dcss_nodes(blob); |
592 | check_mipi_dsi_nodes(blob); | 599 | check_mipi_dsi_nodes(blob); |
593 | } | 600 | } |
594 | 601 | ||
595 | if (is_imx8md()) | 602 | if (is_imx8md()) |
596 | disable_cpu_nodes(blob, 2); | 603 | disable_cpu_nodes(blob, 2); |
597 | 604 | ||
598 | #elif defined(CONFIG_IMX8MM) | 605 | #elif defined(CONFIG_IMX8MM) |
599 | if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl()) | 606 | if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl()) |
600 | disable_vpu_nodes(blob); | 607 | disable_vpu_nodes(blob); |
601 | 608 | ||
602 | if (is_imx8mmd() || is_imx8mmdl()) | 609 | if (is_imx8mmd() || is_imx8mmdl()) |
603 | disable_cpu_nodes(blob, 2); | 610 | disable_cpu_nodes(blob, 2); |
604 | else if (is_imx8mms() || is_imx8mmsl()) | 611 | else if (is_imx8mms() || is_imx8mmsl()) |
605 | disable_cpu_nodes(blob, 3); | 612 | disable_cpu_nodes(blob, 3); |
606 | #endif | 613 | #endif |
607 | 614 | ||
608 | return ft_add_optee_node(blob, bd); | 615 | return ft_add_optee_node(blob, bd); |
609 | } | 616 | } |
610 | #endif | 617 | #endif |
611 | 618 | ||
612 | void reset_cpu(ulong addr) | 619 | void reset_cpu(ulong addr) |
613 | { | 620 | { |
614 | struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; | 621 | struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; |
615 | 622 | ||
616 | /* Clear WDA to trigger WDOG_B immediately */ | 623 | /* Clear WDA to trigger WDOG_B immediately */ |
617 | writew((WCR_WDE | WCR_SRS), &wdog->wcr); | 624 | writew((WCR_WDE | WCR_SRS), &wdog->wcr); |
618 | 625 | ||
619 | while (1) { | 626 | while (1) { |
620 | /* | 627 | /* |
621 | * spin for .5 seconds before reset | 628 | * spin for .5 seconds before reset |
622 | */ | 629 | */ |
623 | } | 630 | } |
624 | } | 631 | } |
625 | 632 | ||
626 | #if defined(CONFIG_ARCH_MISC_INIT) | 633 | #if defined(CONFIG_ARCH_MISC_INIT) |
627 | #define FSL_SIP_BUILDINFO 0xC2000003 | 634 | #define FSL_SIP_BUILDINFO 0xC2000003 |
628 | #define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 | 635 | #define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 |
629 | static void acquire_buildinfo(void) | 636 | static void acquire_buildinfo(void) |
630 | { | 637 | { |
631 | uint64_t atf_commit = 0; | 638 | uint64_t atf_commit = 0; |
632 | 639 | ||
633 | /* Get ARM Trusted Firmware commit id */ | 640 | /* Get ARM Trusted Firmware commit id */ |
634 | atf_commit = call_imx_sip(FSL_SIP_BUILDINFO, | 641 | atf_commit = call_imx_sip(FSL_SIP_BUILDINFO, |
635 | FSL_SIP_BUILDINFO_GET_COMMITHASH, 0, 0, 0); | 642 | FSL_SIP_BUILDINFO_GET_COMMITHASH, 0, 0, 0); |
636 | if (atf_commit == 0xffffffff) { | 643 | if (atf_commit == 0xffffffff) { |
637 | debug("ATF does not support build info\n"); | 644 | debug("ATF does not support build info\n"); |
638 | atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */ | 645 | atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */ |
639 | } | 646 | } |
640 | 647 | ||
641 | printf("\n BuildInfo:\n - ATF %s\n - %s\n\n", (char *)&atf_commit, | 648 | printf("\n BuildInfo:\n - ATF %s\n - %s\n\n", (char *)&atf_commit, |
642 | U_BOOT_VERSION); | 649 | U_BOOT_VERSION); |
643 | } | 650 | } |
644 | 651 | ||
645 | int arch_misc_init(void) | 652 | int arch_misc_init(void) |
646 | { | 653 | { |
647 | acquire_buildinfo(); | 654 | acquire_buildinfo(); |
648 | 655 | ||
649 | return 0; | 656 | return 0; |
650 | } | 657 | } |
651 | #endif | 658 | #endif |
652 | 659 | ||
653 | #define FSL_SIP_GPC 0xC2000000 | 660 | #define FSL_SIP_GPC 0xC2000000 |
654 | #define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03 | 661 | #define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03 |
655 | 662 | ||
656 | #ifdef CONFIG_SPL_BUILD | 663 | #ifdef CONFIG_SPL_BUILD |
657 | static uint32_t gpc_pu_m_core_offset[11] = { | 664 | static uint32_t gpc_pu_m_core_offset[11] = { |
658 | 0xc00, 0xc40, 0xc80, 0xcc0, | 665 | 0xc00, 0xc40, 0xc80, 0xcc0, |
659 | 0xdc0, 0xe00, 0xe40, 0xe80, | 666 | 0xdc0, 0xe00, 0xe40, 0xe80, |
660 | 0xec0, 0xf00, 0xf40, | 667 | 0xec0, 0xf00, 0xf40, |
661 | }; | 668 | }; |
662 | 669 | ||
663 | #define PGC_PCR 0 | 670 | #define PGC_PCR 0 |
664 | 671 | ||
665 | void imx_gpc_set_m_core_pgc(unsigned int offset, bool pdn) | 672 | void imx_gpc_set_m_core_pgc(unsigned int offset, bool pdn) |
666 | { | 673 | { |
667 | uint32_t val; | 674 | uint32_t val; |
668 | uintptr_t reg = GPC_BASE_ADDR + offset; | 675 | uintptr_t reg = GPC_BASE_ADDR + offset; |
669 | 676 | ||
670 | val = readl(reg); | 677 | val = readl(reg); |
671 | val &= ~(0x1 << PGC_PCR); | 678 | val &= ~(0x1 << PGC_PCR); |
672 | 679 | ||
673 | if(pdn) | 680 | if(pdn) |
674 | val |= 0x1 << PGC_PCR; | 681 | val |= 0x1 << PGC_PCR; |
675 | writel(val, reg); | 682 | writel(val, reg); |
676 | } | 683 | } |
677 | 684 | ||
678 | void imx8m_usb_power_domain(uint32_t domain_id, bool on) | 685 | void imx8m_usb_power_domain(uint32_t domain_id, bool on) |
679 | { | 686 | { |
680 | uint32_t val; | 687 | uint32_t val; |
681 | uintptr_t reg; | 688 | uintptr_t reg; |
682 | 689 | ||
683 | imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], true); | 690 | imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], true); |
684 | 691 | ||
685 | reg = GPC_BASE_ADDR + (on ? 0xf8 : 0x104); | 692 | reg = GPC_BASE_ADDR + (on ? 0xf8 : 0x104); |
686 | val = 1 << (domain_id > 3 ? (domain_id + 3) : domain_id); | 693 | val = 1 << (domain_id > 3 ? (domain_id + 3) : domain_id); |
687 | writel(val, reg); | 694 | writel(val, reg); |
688 | while (readl(reg) & val) | 695 | while (readl(reg) & val) |
689 | ; | 696 | ; |
690 | imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], false); | 697 | imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], false); |
691 | } | 698 | } |
692 | #endif | 699 | #endif |
693 | 700 | ||
694 | int imx8m_usb_power(int usb_id, bool on) | 701 | int imx8m_usb_power(int usb_id, bool on) |
695 | { | 702 | { |
696 | if (usb_id > 1) | 703 | if (usb_id > 1) |
697 | return -EINVAL; | 704 | return -EINVAL; |
698 | #ifdef CONFIG_SPL_BUILD | 705 | #ifdef CONFIG_SPL_BUILD |
699 | imx8m_usb_power_domain(2 + usb_id, on); | 706 | imx8m_usb_power_domain(2 + usb_id, on); |
700 | #else | 707 | #else |
701 | if (call_imx_sip(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, | 708 | if (call_imx_sip(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, |
702 | 2 + usb_id, on, 0)) | 709 | 2 + usb_id, on, 0)) |
703 | return -EPERM; | 710 | return -EPERM; |
704 | #endif | 711 | #endif |
705 | return 0; | 712 | return 0; |
706 | } | 713 | } |
707 | 714 |