blob: 2fd06f38a32fd13711b5100bd603a7a46fcf1fdb [file] [log] [blame]
Yann Gautier3edc7c32019-05-20 19:17:08 +02001/*
2 * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <platform_def.h>
8
9#include <common/debug.h>
10#include <drivers/st/bsec.h>
11#include <drivers/st/stpmic1.h>
12#include <lib/mmio.h>
13
14#include <stm32mp_dt.h>
15#include <stm32mp1_private.h>
16
17/*
18 * SYSCFG REGISTER OFFSET (base relative)
19 */
20#define SYSCFG_BOOTR 0x00U
21#define SYSCFG_IOCTRLSETR 0x18U
22#define SYSCFG_ICNR 0x1CU
23#define SYSCFG_CMPCR 0x20U
24#define SYSCFG_CMPENSETR 0x24U
25
26/*
27 * SYSCFG_BOOTR Register
28 */
29#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
30#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
31#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
32/*
33 * SYSCFG_IOCTRLSETR Register
34 */
35#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
36#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
37#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
38#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
39#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
40
41/*
42 * SYSCFG_ICNR Register
43 */
44#define SYSCFG_ICNR_AXI_M9 BIT(9)
45
46/*
47 * SYSCFG_CMPCR Register
48 */
49#define SYSCFG_CMPCR_SW_CTRL BIT(1)
50#define SYSCFG_CMPCR_READY BIT(8)
51#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
52#define SYSCFG_CMPCR_RANSRC_SHIFT 16
53#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
54#define SYSCFG_CMPCR_ANSRC_SHIFT 24
55
56/*
57 * SYSCFG_CMPENSETR Register
58 */
59#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
60
61void stm32mp1_syscfg_init(void)
62{
63 uint32_t bootr;
64 uint32_t otp = 0;
65 uint32_t vdd_voltage;
66 uintptr_t syscfg_base = dt_get_syscfg_base();
67
68 /*
69 * Interconnect update : select master using the port 1.
70 * LTDC = AXI_M9.
71 */
72 mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
73
74 /* Disable Pull-Down for boot pin connected to VDD */
75 bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR) &
76 SYSCFG_BOOTR_BOOT_MASK;
77 mmio_clrsetbits_32(syscfg_base + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
78 bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
79
80 /*
81 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
82 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
83 * It could be disabled for low frequencies or if AFMUX is selected
84 * but the function is not used, typically for TRACE.
85 * If high speed low voltage pad mode is node enable, platform will
86 * over consume.
87 *
88 * WARNING:
89 * Enabling High Speed mode while VDD > 2.7V
90 * with the OTP product_below_2v5 (OTP 18, BIT 13)
91 * erroneously set to 1 can damage the SoC!
92 * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
93 * but this value needs to be consistent with board design.
94 */
95 if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) {
96 panic();
97 }
98
99 otp = otp & HW2_OTP_PRODUCT_BELOW_2V5;
100
101 /* Get VDD supply */
102 vdd_voltage = dt_get_pwr_vdd_voltage();
103
104 /* Check if VDD is Low Voltage */
105 if (vdd_voltage == 0U) {
106 WARN("VDD unknown");
107 } else if (vdd_voltage < 2700000U) {
108 mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR,
109 SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
110 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
111 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
112 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
113 SYSCFG_IOCTRLSETR_HSLVEN_SPI);
114
115 if (otp == 0U) {
116 INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
117 }
118 } else {
119 if (otp != 0U) {
120 ERROR("Product_below_2v5=1:\n");
121 ERROR("\tHSLVEN update is destructive,\n");
122 ERROR("\tno update as VDD > 2.7V\n");
123 panic();
124 }
125 }
126
127 stm32mp1_syscfg_enable_io_compensation();
128}
129
130void stm32mp1_syscfg_enable_io_compensation(void)
131{
132 uintptr_t syscfg_base = dt_get_syscfg_base();
133
134 /*
135 * Activate automatic I/O compensation.
136 * Warning: need to ensure CSI enabled and ready in clock driver.
137 * Enable non-secure clock, we assume non-secure is suspended.
138 */
139 stm32mp1_clk_enable_non_secure(SYSCFG);
140
141 mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR,
142 SYSCFG_CMPENSETR_MPU_EN);
143
144 while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) &
145 SYSCFG_CMPCR_READY) == 0U) {
146 ;
147 }
148
149 mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
150}
151
152void stm32mp1_syscfg_disable_io_compensation(void)
153{
154 uintptr_t syscfg_base = dt_get_syscfg_base();
155 uint32_t value;
156
157 /*
158 * Deactivate automatic I/O compensation.
159 * Warning: CSI is disabled automatically in STOP if not
160 * requested for other usages and always OFF in STANDBY.
161 * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
162 */
163 value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >>
164 SYSCFG_CMPCR_ANSRC_SHIFT;
165
166 mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR,
167 SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
168
169 value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) |
170 (value << SYSCFG_CMPCR_RANSRC_SHIFT);
171
172 mmio_write_32(syscfg_base + SYSCFG_CMPCR, value);
173
174 mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
175
176 mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR,
177 SYSCFG_CMPENSETR_MPU_EN);
178
179 stm32mp1_clk_disable_non_secure(SYSCFG);
180}