stm32mp1_syscfg.c 4.59 KB
Newer Older
1
/*
2
 * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <platform_def.h>

#include <common/debug.h>
#include <drivers/st/bsec.h>
#include <drivers/st/stpmic1.h>
#include <lib/mmio.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
25
#define SYSCFG_CMPENCLRR			0x28U
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

/*
 * 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

/*
 * SYSCFG_CMPENSETR Register
 */
#define SYSCFG_CMPENSETR_MPU_EN			BIT(0)

void stm32mp1_syscfg_init(void)
{
	uint32_t bootr;
	uint32_t otp = 0;
	uint32_t vdd_voltage;

	/*
	 * Interconnect update : select master using the port 1.
	 * LTDC = AXI_M9.
	 */
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
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
			   bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);

	/*
	 * 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) {
108
		mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
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
			      SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
			      SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
			      SYSCFG_IOCTRLSETR_HSLVEN_ETH |
			      SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
			      SYSCFG_IOCTRLSETR_HSLVEN_SPI);

		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();
		}
	}

	stm32mp1_syscfg_enable_io_compensation();
}

void stm32mp1_syscfg_enable_io_compensation(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.
	 */
	stm32mp1_clk_enable_non_secure(SYSCFG);

139
	mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENSETR,
140
141
			SYSCFG_CMPENSETR_MPU_EN);

142
	while ((mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) &
143
144
145
146
		SYSCFG_CMPCR_READY) == 0U) {
		;
	}

147
	mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
148
149
150
151
152
153
154
155
156
157
158
159
}

void stm32mp1_syscfg_disable_io_compensation(void)
{
	uint32_t value;

	/*
	 * 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.
	 */
160
	value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) >>
161
162
	      SYSCFG_CMPCR_ANSRC_SHIFT;

163
	mmio_clrbits_32(SYSCFG_BASE + SYSCFG_CMPCR,
164
165
			SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);

166
	value = mmio_read_32(SYSCFG_BASE + SYSCFG_CMPCR) |
167
168
		(value << SYSCFG_CMPCR_RANSRC_SHIFT);

169
	mmio_write_32(SYSCFG_BASE + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL);
170

171
	mmio_setbits_32(SYSCFG_BASE + SYSCFG_CMPENCLRR, SYSCFG_CMPENSETR_MPU_EN);
172
173
174

	stm32mp1_clk_disable_non_secure(SYSCFG);
}