1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef _HARDWARE_RESETS_H
8 #define _HARDWARE_RESETS_H
9
10 #include "pico.h"
11 #include "hardware/structs/resets.h"
12
13 /** \file hardware/resets.h
14 * \defgroup hardware_resets hardware_resets
15 *
16 * \brief Hardware Reset API
17 *
18 * The reset controller allows software control of the resets to all of the peripherals that are not
19 * critical to boot the processor in the RP-series microcontroller.
20 *
21 * \subsubsection reset_bitmask
22 * \addtogroup hardware_resets
23 *
24 * Multiple blocks are referred to using a bitmask as follows:
25 *
26 * Block to reset | Bit
27 * ---------------|----
28 * USB | 24
29 * UART 1 | 23
30 * UART 0 | 22
31 * Timer | 21
32 * TB Manager | 20
33 * SysInfo | 19
34 * System Config | 18
35 * SPI 1 | 17
36 * SPI 0 | 16
37 * RTC | 15
38 * PWM | 14
39 * PLL USB | 13
40 * PLL System | 12
41 * PIO 1 | 11
42 * PIO 0 | 10
43 * Pads - QSPI | 9
44 * Pads - bank 0 | 8
45 * JTAG | 7
46 * IO Bank 1 | 6
47 * IO Bank 0 | 5
48 * I2C 1 | 4
49 * I2C 0 | 3
50 * DMA | 2
51 * Bus Control | 1
52 * ADC 0 | 0
53 *
54 * \subsection reset_example Example
55 * \addtogroup hardware_resets
56 * \include hello_reset.c
57 */
58
59 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS, Enable/disable assertions in the hardware_resets module, type=bool, default=0, group=hardware_adc
60 #ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS
61 #ifdef PARAM_ASSERTIONS_ENABLED_RESET // backwards compatibility with SDK < 2.0.0
62 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS PARAM_ASSERTIONS_ENABLED_RESET
63 #else
64 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS 0
65 #endif
66 #endif
67 #ifdef __cplusplus
68 extern "C" {
69 #endif
70
reset_block_reg_mask(io_rw_32 * reset,uint32_t mask)71 static __force_inline void reset_block_reg_mask(io_rw_32 *reset, uint32_t mask) {
72 hw_set_bits(reset, mask);
73 }
74
unreset_block_reg_mask(io_rw_32 * reset,uint32_t mask)75 static __force_inline void unreset_block_reg_mask(io_rw_32 *reset, uint32_t mask) {
76 hw_clear_bits(reset, mask);
77 }
78
unreset_block_reg_mask_wait_blocking(io_rw_32 * reset,io_ro_32 * reset_done,uint32_t mask)79 static __force_inline void unreset_block_reg_mask_wait_blocking(io_rw_32 *reset, io_ro_32 *reset_done, uint32_t mask) {
80 hw_clear_bits(reset, mask);
81 while (~*reset_done & mask)
82 tight_loop_contents();
83 }
84
85 /// \tag::reset_funcs[]
86
87 /*! \brief Reset the specified HW blocks
88 * \ingroup hardware_resets
89 *
90 * \param bits Bit pattern indicating blocks to reset. See \ref reset_bitmask
91 */
reset_block_mask(uint32_t bits)92 static __force_inline void reset_block_mask(uint32_t bits) {
93 reset_block_reg_mask(&resets_hw->reset, bits);
94 }
95
96 /*! \brief bring specified HW blocks out of reset
97 * \ingroup hardware_resets
98 *
99 * \param bits Bit pattern indicating blocks to unreset. See \ref reset_bitmask
100 */
unreset_block_mask(uint32_t bits)101 static __force_inline void unreset_block_mask(uint32_t bits) {
102 unreset_block_reg_mask(&resets_hw->reset, bits);
103 }
104
105 /*! \brief Bring specified HW blocks out of reset and wait for completion
106 * \ingroup hardware_resets
107 *
108 * \param bits Bit pattern indicating blocks to unreset. See \ref reset_bitmask
109 */
unreset_block_mask_wait_blocking(uint32_t bits)110 static __force_inline void unreset_block_mask_wait_blocking(uint32_t bits) {
111 unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, bits);
112 }
113
114 /// \end::reset_funcs[]
115
116 #ifndef HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY
117 #define HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY 1
118 #endif
119
120 #if HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY
reset_block(uint32_t bits)121 static __force_inline void reset_block(uint32_t bits) {
122 reset_block_mask(bits);
123 }
124
unreset_block(uint32_t bits)125 static __force_inline void unreset_block(uint32_t bits) {
126 unreset_block_mask(bits);
127 }
128
unreset_block_wait(uint32_t bits)129 static __force_inline void unreset_block_wait(uint32_t bits) {
130 return unreset_block_mask_wait_blocking(bits);
131 }
132 #endif
133
134 /*! \brief Reset the specified HW block
135 * \ingroup hardware_resets
136 *
137 * \param block_num the block number
138 */
reset_block_num(uint32_t block_num)139 static inline void reset_block_num(uint32_t block_num) {
140 reset_block_reg_mask(&resets_hw->reset, 1u << block_num);
141 }
142
143 /*! \brief bring specified HW block out of reset
144 * \ingroup hardware_resets
145 *
146 * \param block_num the block number
147 */
unreset_block_num(uint block_num)148 static inline void unreset_block_num(uint block_num) {
149 invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
150 unreset_block_reg_mask(&resets_hw->reset, 1u << block_num);
151 }
152
153 /*! \brief Bring specified HW block out of reset and wait for completion
154 * \ingroup hardware_resets
155 *
156 * \param block_num the block number
157 */
unreset_block_num_wait_blocking(uint block_num)158 static inline void unreset_block_num_wait_blocking(uint block_num) {
159 invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
160 unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, 1u << block_num);
161 }
162
163 /*! \brief Reset the specified HW block, and then bring at back out of reset and wait for completion
164 * \ingroup hardware_resets
165 *
166 * \param block_num the block number
167 */
reset_unreset_block_num_wait_blocking(uint block_num)168 static inline void reset_unreset_block_num_wait_blocking(uint block_num) {
169 invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
170 reset_block_reg_mask(&resets_hw->reset, 1u << block_num);
171 unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, 1u << block_num);
172 }
173
174 #ifdef __cplusplus
175 }
176 #endif
177
178 #endif
179