libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
pwr.c
Go to the documentation of this file.
1/**
2 * @brief <b>libopencm3 STM32H7xx Power Control</b>
3 *
4 * @version 1.0.0
5 *
6 * @date 16 December, 2019
7 *
8 * This library supports the power control system for the
9 * STM32H7 series of ARM Cortex Microcontrollers by ST Microelectronics.
10 *
11 * LGPL License Terms @ref lgpl_license
12 */
13/*
14 * This file is part of the libopencm3 project.
15 *
16 * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
17 * Copyright (C) 2017 Matthew Lai <m@matthewlai.ca>
18 * Copyright (C) 2019 Brian Viele <vielster@allocor.tech>
19 *
20 * This library is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU Lesser General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public License
31 * along with this library. If not, see <http://www.gnu.org/licenses/>.
32 */
38
39/* DBGMCU_IDC DEV ID values needed to account for variations between part types. */
40#define DBGMCU_IDCODE_DEV_ID_STM32H74X_5X 0x450
41#define DBGMCU_IDCODE_DEV_ID_STM32H7A3_B3_B0 0x480
42
43void pwr_set_mode_ldo(void) {
44 /* Per table in manual for SMPS, mask and set SMPSEN=0 : LDOEN=1 : BYPASS=0. */
45 const uint32_t cr3_mask = (PWR_CR3_SMPSEN | PWR_CR3_LDOEN | PWR_CR3_BYPASS);
46 PWR_CR3 = (PWR_CR3 & ~cr3_mask) | (PWR_CR3_LDOEN);
47}
48
50 const uint32_t cr3_mask = (PWR_CR3_SCUEN | PWR_CR3_LDOEN | PWR_CR3_BYPASS);
51 PWR_CR3 = (PWR_CR3 & ~cr3_mask) | (PWR_CR3_SCUEN | PWR_CR3_LDOEN);
52}
53
54void pwr_set_mode_smps_ldo(bool supply_external, uint32_t smps_level, bool use_ldo) {
55 uint32_t cr3_mask, cr3_set;
58
59 /* Default, take in unconditional settings, will OR in the rest. */
60 cr3_set = PWR_CR3_SMPSEN | (smps_level << PWR_CR3_SMPSLEVEL_SHIFT);
61 if (supply_external) {
62 cm3_assert(smps_level != PWR_CR3_SMPSLEVEL_VOS); /* Unsupported setting! */
63 cr3_set |= PWR_CR3_SMPSEXTHP;
64 }
65
66 if (use_ldo) {
67 cr3_set |= PWR_CR3_LDOEN;
68 }
69 PWR_CR3 = (PWR_CR3 & ~cr3_mask) | cr3_set;
70}
71
73 const uint32_t cr3_mask = (PWR_CR3_SMPSEN | PWR_CR3_LDOEN | PWR_CR3_BYPASS);
74 PWR_CR3 = (PWR_CR3 & ~cr3_mask) | PWR_CR3_BYPASS;
75}
76
78 const uint32_t cr3_mask = (PWR_CR3_SCUEN | PWR_CR3_LDOEN | PWR_CR3_BYPASS);
79 PWR_CR3 = (PWR_CR3 & ~cr3_mask) | (PWR_CR3_SCUEN | PWR_CR3_BYPASS);
80}
81
82
83void pwr_set_mode(enum pwr_sys_mode mode, uint8_t smps_level) {
84 switch (mode) {
85 case PWR_SYS_SCU_LDO:
87 break;
90 break;
91 case PWR_SYS_LDO:
93 break;
97 break;
100 pwr_set_mode_smps_ldo(false, smps_level, mode == PWR_SYS_EXT_SMPS_LDO);
101 break;
102 case PWR_SYS_BYPASS:
104 break;
105 }
106 /* Wait for power supply status to state ready. */
107 while (!(PWR_CSR1 & PWR_CSR1_ACTVOSRDY));
108}
109
111{
112 uint32_t pwr_cr1_reg = PWR_CR1;
113 pwr_cr1_reg = (pwr_cr1_reg & ~(PWR_CR1_SVOS_MASK << PWR_CR1_SVOS_SHIFT));
114 PWR_CR1 = pwr_cr1_reg | scale;
115}
116
118 static const uint8_t srdcr_vos_values[] = {
123 };
124 static const uint8_t d3cr_vos_values[] = {
129 };
130 cm3_assert(scale != PWR_VOS_SCALE_UNDEFINED); /* Make sure this has been set. */
131
132 /* "SmartRun Domain" devices (presently only know of A3/B3/B0) have different mapping.
133 * Note: DBGMCU_IDCODE_DEV_ID_STM32H7A3 covers all three of these models.
134 */
135 uint32_t devid = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK;
137 const uint32_t srdcr_vos_mask = (PWR_SRDCR_VOS_MASK << PWR_SRDCR_VOS_SHIFT);
138 const uint32_t vos_value = srdcr_vos_values[scale - 1] << PWR_SRDCR_VOS_SHIFT;
139 PWR_SRDCR = (PWR_SRDCR & ~srdcr_vos_mask) | vos_value;
140 } else {
141 /* Get the VOS value for the non-smart domain types. */
142 uint32_t d3cr_vos = (uint32_t)d3cr_vos_values[scale - 1] << PWR_D3CR_VOS_SHIFT;
143 uint32_t d3cr_masked = PWR_D3CR & ~(PWR_D3CR_VOS_MASK << PWR_D3CR_VOS_SHIFT);
144 /* STM32H742/43/45/47/50/53/55/57 have special handling of VOS0, which is to set
145 * VOS1, and also enable the ODEN in the SYSCFG_PWRCR.
146 * Note: Conveniently, all devices with this setup share a devid, so pick one.
147 */
149 rcc_periph_clock_enable(RCC_SYSCFG); /* Ensure we can access ODEN. */
150 /* Per the manual, VOS0 is implemented as VOS1 + ODEN. Handle this case. */
151 if (scale == PWR_VOS_SCALE_0) {
154 } else {
155 SYSCFG_PWRCR &= ~SYSCFG_PWRCR_ODEN;
156 PWR_D3CR = d3cr_masked | d3cr_vos;
157 }
158 } else {
159 PWR_D3CR = d3cr_masked | d3cr_vos;
160 }
161 }
162 while (!(PWR_D3CR & PWR_D3CR_VOSRDY)); /* VOSRDY bit is same between D3CR and SRDCR. */
163}
#define DBGMCU_IDCODE_DEV_ID_MASK
Definition: dbgmcu.h:37
#define DBGMCU_IDCODE
Definition: dbgmcu.h:29
#define cm3_assert(expr)
Check if assertion is true.
Definition: assert.h:86
#define PWR_CR3_SMPSLEVEL_VOS
Definition: h7/pwr.h:149
#define PWR_SRDCR_VOS_SHIFT
Definition: h7/pwr.h:176
#define PWR_CR3_BYPASS
Definition: h7/pwr.h:162
#define PWR_D3CR_VOS_SCALE_0
VOS0 is implemented on STM32H72x/3x with simple VOS setting.
Definition: h7/pwr.h:170
#define PWR_CR3_SMPSEXTHP
SMPS step-down converter external power delivery selection.
Definition: h7/pwr.h:157
#define PWR_CR3_LDOEN
Definition: h7/pwr.h:161
#define PWR_SRDCR_VOS_MASK
Definition: h7/pwr.h:177
#define PWR_D3CR_VOSRDY
D3CR Register Bits.
Definition: h7/pwr.h:165
#define PWR_CR1_SVOS_SHIFT
VOS[15:14]: Regulator voltage scaling output selection.
Definition: h7/pwr.h:63
#define PWR_CR3_SMPSLEVEL_SHIFT
Definition: h7/pwr.h:153
pwr_svos_scale
Definition: h7/pwr.h:194
#define PWR_D3CR_VOS_MASK
Definition: h7/pwr.h:167
#define PWR_D3CR_VOS_SHIFT
Definition: h7/pwr.h:166
#define PWR_CSR1_ACTVOSRDY
Definition: h7/pwr.h:117
pwr_vos_scale
Definition: h7/pwr.h:200
#define PWR_D3CR_VOS_SCALE_1
Definition: h7/pwr.h:173
#define PWR_CR1_SVOS_MASK
Definition: h7/pwr.h:64
#define PWR_SRDCR_VOS_SCALE_3
Definition: h7/pwr.h:178
#define PWR_SRDCR_VOS_SCALE_2
Definition: h7/pwr.h:179
#define PWR_SRDCR_VOS_SCALE_1
Definition: h7/pwr.h:180
#define PWR_CR3_SMPSLEVEL_MASK
Definition: h7/pwr.h:154
#define PWR_D3CR_VOS_SCALE_3
Definition: h7/pwr.h:171
#define PWR_D3CR_VOS_SCALE_2
Definition: h7/pwr.h:172
#define PWR_CR3_SMPSEN
Definition: h7/pwr.h:160
#define PWR_CR3_SCUEN
Definition: h7/pwr.h:158
#define PWR_SRDCR_VOS_SCALE_0
Definition: h7/pwr.h:181
pwr_sys_mode
Definition: h7/pwr.h:183
@ PWR_VOS_SCALE_0
Definition: h7/pwr.h:202
@ PWR_VOS_SCALE_UNDEFINED
Definition: h7/pwr.h:201
@ PWR_SYS_SMPS_DIRECT
Disable LDO, apply SMPS direct to CPU using VOS.
Definition: h7/pwr.h:187
@ PWR_SYS_EXT_SMPS_LDO
SMPS supplies external power, and CPU through LDO.
Definition: h7/pwr.h:189
@ PWR_SYS_SMPS_LDO
SMPS supplies internal LDO.
Definition: h7/pwr.h:188
@ PWR_SYS_SCU_LDO
STM32H742/43/50/53 has special SCUEN handling, use for LDO.
Definition: h7/pwr.h:184
@ PWR_SYS_LDO
Devices with SMPS use this to run from LDO only.
Definition: h7/pwr.h:186
@ PWR_SYS_EXT_SMPS_LDO_BYP
SMPS supplies external power, bypasses LDO (e.g.
Definition: h7/pwr.h:190
@ PWR_SYS_BYPASS
Disable all internal power supplies.
Definition: h7/pwr.h:191
@ PWR_SYS_SCU_BYPASS
STM32H742/43/50/53 has special SCUEN handling, use for bypass.
Definition: h7/pwr.h:185
void pwr_set_svos_scale(enum pwr_svos_scale scale)
Set the voltage scaling/strength for the internal SMPS/LDO when in Stop mode.
Definition: pwr.c:110
void pwr_set_mode_ldo(void)
Set power subsystem to utilize the LDO for CPU.
Definition: pwr.c:43
void pwr_set_vos_scale(enum pwr_vos_scale scale)
Set the voltage scaling/strength for the internal SMPS/LDO while running.
Definition: pwr.c:117
void pwr_set_mode_bypass(void)
Set power subsystem to bypass all internal supplies.
Definition: pwr.c:72
void pwr_set_mode_scu_bypass(void)
Specific STM32H742/43/50/53 Bypsass mode setting.
Definition: pwr.c:77
void pwr_set_mode_smps_ldo(bool supply_external, uint32_t smps_level, bool use_ldo)
Set power subsystem to utilize the SMPS run through the LDO for CPU.
Definition: pwr.c:54
void pwr_set_mode_scu_ldo(void)
Specific STM32H742/43/50/53 LDO mode setting.
Definition: pwr.c:49
void pwr_set_mode(enum pwr_sys_mode mode, uint8_t smps_level)
Set power system based on "System Supply Configurations" table in reference manual.
Definition: pwr.c:83
#define PWR_D3CR
D3 Domain Power Control register.
Definition: h7/pwr.h:54
#define PWR_SRDCR
Definition: h7/pwr.h:55
#define PWR_CR1
Power control register.
Definition: h7/pwr.h:36
#define PWR_CSR1
Power control/status register.
Definition: h7/pwr.h:39
#define PWR_CR3
Power control register 3.
Definition: h7/pwr.h:45
void rcc_periph_clock_enable(enum rcc_periph_clken clken)
Enable Peripheral Clock in running mode.
@ RCC_SYSCFG
Definition: h7/rcc.h:576
#define SYSCFG_PWRCR_ODEN
Definition: h7/syscfg.h:61
#define SYSCFG_PWRCR
Definition: h7/syscfg.h:49
#define DBGMCU_IDCODE_DEV_ID_STM32H74X_5X
libopencm3 STM32H7xx Power Control
Definition: pwr.c:40
#define DBGMCU_IDCODE_DEV_ID_STM32H7A3_B3_B0
Definition: pwr.c:41