fix(ulp/lp_spi): fix driver bugs and add bus deinit API

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Sudeep Mohanty
2026-06-30 15:53:09 +02:00
co-authored by Cursor
parent cf515d20d7
commit 78d49e8747
7 changed files with 491 additions and 174 deletions
@@ -13,8 +13,10 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "soc/lp_spi_struct.h"
#include "soc/lpperi_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -51,6 +53,60 @@ static inline uint32_t lp_spi_ll_read_buffer_word(lp_spi_ll_dev_t *hw, int n)
return hw->data_buf[n].reg_buf;
}
/**
* @brief Write ``len`` bytes into the LP SPI data buffer registers from W0.
* Sub-word safe (no read past ``src``).
*
* @param hw LP SPI hardware
* @param src Source byte buffer
* @param len Number of bytes (<= ``LP_SPI_LL_MAX_BUFFER_SIZE``)
*/
static inline void lp_spi_ll_write_buffer_bytes(lp_spi_ll_dev_t *hw, const uint8_t *src, size_t len)
{
HAL_ASSERT(len <= LP_SPI_LL_MAX_BUFFER_SIZE);
size_t reg_idx = 0;
size_t remaining = len;
while (remaining >= 4) {
uint32_t word;
memcpy(&word, src, 4);
hw->data_buf[reg_idx].reg_buf = word;
reg_idx++;
src += 4;
remaining -= 4;
}
if (remaining > 0) {
uint32_t word = 0;
memcpy(&word, src, remaining);
hw->data_buf[reg_idx].reg_buf = word;
}
}
/**
* @brief Read ``len`` bytes from the LP SPI data buffer registers into ``dst``,
* starting at W0. Sub-word safe (no write past ``dst``).
*
* @param hw LP SPI hardware
* @param dst Destination byte buffer
* @param len Number of bytes (<= ``LP_SPI_LL_MAX_BUFFER_SIZE``)
*/
static inline void lp_spi_ll_read_buffer_bytes(lp_spi_ll_dev_t *hw, uint8_t *dst, size_t len)
{
HAL_ASSERT(len <= LP_SPI_LL_MAX_BUFFER_SIZE);
size_t reg_idx = 0;
size_t remaining = len;
while (remaining >= 4) {
uint32_t word = hw->data_buf[reg_idx].reg_buf;
memcpy(dst, &word, 4);
reg_idx++;
dst += 4;
remaining -= 4;
}
if (remaining > 0) {
uint32_t word = hw->data_buf[reg_idx].reg_buf;
memcpy(dst, &word, remaining);
}
}
/**
* @brief Reset RX and TX AFIFOs
*/
@@ -370,6 +426,20 @@ static inline void lp_spi_ll_reset_cs_timing(lp_spi_ll_dev_t *hw)
hw->spi_user1.reg_cs_hold_time = 0;
}
/**
* @brief This resets the LP SPI peripheral
*/
static inline void lp_spi_ll_reset(void)
{
lpperi_dev_t *lp_peri_dev = &LPPERI;
lp_peri_dev->reset_en.rst_en_lp_spi = 1;
/* Read-back fence: ensure the reset assertion propagates through the
* bus before de-asserting.
*/
(void)lp_peri_dev->reset_en.rst_en_lp_spi;
lp_peri_dev->reset_en.rst_en_lp_spi = 0;
}
#ifdef __cplusplus
}
#endif
@@ -13,8 +13,10 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "soc/lp_spi_struct.h"
#include "soc/lp_peri_clkrst_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@@ -51,6 +53,60 @@ static inline uint32_t lp_spi_ll_read_buffer_word(lp_spi_ll_dev_t *hw, int n)
return hw->data_buf[n].val;
}
/**
* @brief Write ``len`` bytes into the LP SPI data buffer registers from W0.
* Sub-word safe (no read past ``src``).
*
* @param hw LP SPI hardware
* @param src Source byte buffer
* @param len Number of bytes (<= ``LP_SPI_LL_MAX_BUFFER_SIZE``)
*/
static inline void lp_spi_ll_write_buffer_bytes(lp_spi_ll_dev_t *hw, const uint8_t *src, size_t len)
{
HAL_ASSERT(len <= LP_SPI_LL_MAX_BUFFER_SIZE);
size_t reg_idx = 0;
size_t remaining = len;
while (remaining >= 4) {
uint32_t word;
memcpy(&word, src, 4);
hw->data_buf[reg_idx].val = word;
reg_idx++;
src += 4;
remaining -= 4;
}
if (remaining > 0) {
uint32_t word = 0;
memcpy(&word, src, remaining);
hw->data_buf[reg_idx].val = word;
}
}
/**
* @brief Read ``len`` bytes from the LP SPI data buffer registers into ``dst``,
* starting at W0. Sub-word safe (no write past ``dst``).
*
* @param hw LP SPI hardware
* @param dst Destination byte buffer
* @param len Number of bytes (<= ``LP_SPI_LL_MAX_BUFFER_SIZE``)
*/
static inline void lp_spi_ll_read_buffer_bytes(lp_spi_ll_dev_t *hw, uint8_t *dst, size_t len)
{
HAL_ASSERT(len <= LP_SPI_LL_MAX_BUFFER_SIZE);
size_t reg_idx = 0;
size_t remaining = len;
while (remaining >= 4) {
uint32_t word = hw->data_buf[reg_idx].val;
memcpy(dst, &word, 4);
reg_idx++;
dst += 4;
remaining -= 4;
}
if (remaining > 0) {
uint32_t word = hw->data_buf[reg_idx].val;
memcpy(dst, &word, remaining);
}
}
/**
* @brief Reset RX and TX AFIFOs
*/
@@ -370,6 +426,16 @@ static inline void lp_spi_ll_reset_cs_timing(lp_spi_ll_dev_t *hw)
hw->spi_user1.reg_cs_hold_time = 0;
}
/**
* @brief This resets the LP SPI peripheral
*/
static inline void lp_spi_ll_reset(void)
{
LP_PERI_CLKRST.spi_ctrl.lp_spi_rst_en = 1;
(void)LP_PERI_CLKRST.spi_ctrl.lp_spi_rst_en;
LP_PERI_CLKRST.spi_ctrl.lp_spi_rst_en = 0;
}
#ifdef __cplusplus
}
#endif