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