blob: 8baef728b5cbdeea2fb1a4e58981394dca9eddb0 [file] [log] [blame]
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _HARDWARE_RESETS_H
#define _HARDWARE_RESETS_H
#include "pico.h"
#include "hardware/structs/resets.h"
/** \file hardware/resets.h
* \defgroup hardware_resets hardware_resets
*
* \brief Hardware Reset API
*
* The reset controller allows software control of the resets to all of the peripherals that are not
* critical to boot the processor in the RP-series microcontroller.
*
* \subsubsection reset_bitmask
* \addtogroup hardware_resets
*
* Multiple blocks are referred to using a bitmask as follows:
*
* Block to reset | Bit
* ---------------|----
* USB | 24
* UART 1 | 23
* UART 0 | 22
* Timer | 21
* TB Manager | 20
* SysInfo | 19
* System Config | 18
* SPI 1 | 17
* SPI 0 | 16
* RTC | 15
* PWM | 14
* PLL USB | 13
* PLL System | 12
* PIO 1 | 11
* PIO 0 | 10
* Pads - QSPI | 9
* Pads - bank 0 | 8
* JTAG | 7
* IO Bank 1 | 6
* IO Bank 0 | 5
* I2C 1 | 4
* I2C 0 | 3
* DMA | 2
* Bus Control | 1
* ADC 0 | 0
*
* \subsection reset_example Example
* \addtogroup hardware_resets
* \include hello_reset.c
*/
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS, Enable/disable assertions in the hardware_resets module, type=bool, default=0, group=hardware_adc
#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS
#ifdef PARAM_ASSERTIONS_ENABLED_RESET // backwards compatibility with SDK < 2.0.0
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS PARAM_ASSERTIONS_ENABLED_RESET
#else
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_RESETS 0
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
static __force_inline void reset_block_reg_mask(io_rw_32 *reset, uint32_t mask) {
hw_set_bits(reset, mask);
}
static __force_inline void unreset_block_reg_mask(io_rw_32 *reset, uint32_t mask) {
hw_clear_bits(reset, mask);
}
static __force_inline void unreset_block_reg_mask_wait_blocking(io_rw_32 *reset, io_ro_32 *reset_done, uint32_t mask) {
hw_clear_bits(reset, mask);
while (~*reset_done & mask)
tight_loop_contents();
}
/// \tag::reset_funcs[]
/*! \brief Reset the specified HW blocks
* \ingroup hardware_resets
*
* \param bits Bit pattern indicating blocks to reset. See \ref reset_bitmask
*/
static __force_inline void reset_block_mask(uint32_t bits) {
reset_block_reg_mask(&resets_hw->reset, bits);
}
/*! \brief bring specified HW blocks out of reset
* \ingroup hardware_resets
*
* \param bits Bit pattern indicating blocks to unreset. See \ref reset_bitmask
*/
static __force_inline void unreset_block_mask(uint32_t bits) {
unreset_block_reg_mask(&resets_hw->reset, bits);
}
/*! \brief Bring specified HW blocks out of reset and wait for completion
* \ingroup hardware_resets
*
* \param bits Bit pattern indicating blocks to unreset. See \ref reset_bitmask
*/
static __force_inline void unreset_block_mask_wait_blocking(uint32_t bits) {
unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, bits);
}
/// \end::reset_funcs[]
#ifndef HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY
#define HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY 1
#endif
#if HARDWARE_RESETS_ENABLE_SDK1XX_COMPATIBILITY
static __force_inline void reset_block(uint32_t bits) {
reset_block_mask(bits);
}
static __force_inline void unreset_block(uint32_t bits) {
unreset_block_mask(bits);
}
static __force_inline void unreset_block_wait(uint32_t bits) {
return unreset_block_mask_wait_blocking(bits);
}
#endif
/*! \brief Reset the specified HW block
* \ingroup hardware_resets
*
* \param block_num the block number
*/
static inline void reset_block_num(uint32_t block_num) {
reset_block_reg_mask(&resets_hw->reset, 1u << block_num);
}
/*! \brief bring specified HW block out of reset
* \ingroup hardware_resets
*
* \param block_num the block number
*/
static inline void unreset_block_num(uint block_num) {
invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
unreset_block_reg_mask(&resets_hw->reset, 1u << block_num);
}
/*! \brief Bring specified HW block out of reset and wait for completion
* \ingroup hardware_resets
*
* \param block_num the block number
*/
static inline void unreset_block_num_wait_blocking(uint block_num) {
invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, 1u << block_num);
}
/*! \brief Reset the specified HW block, and then bring at back out of reset and wait for completion
* \ingroup hardware_resets
*
* \param block_num the block number
*/
static inline void reset_unreset_block_num_wait_blocking(uint block_num) {
invalid_params_if(HARDWARE_RESETS, block_num > NUM_RESETS);
reset_block_reg_mask(&resets_hw->reset, 1u << block_num);
unreset_block_reg_mask_wait_blocking(&resets_hw->reset, &resets_hw->reset_done, 1u << block_num);
}
#ifdef __cplusplus
}
#endif
#endif