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