SyterKit 0.4.0.x
SyterKit is a bare-metal framework
Loading...
Searching...
No Matches
Functions
sys-spi.c File Reference

Allwinner Platform SPI Controller Driver. More...

#include <io.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <types.h>
#include <timer.h>
#include <log.h>
#include <sys-spi.h>
Include dependency graph for sys-spi.c:

Functions

static __attribute__ ((section(".data")))
 DMA configuration structure for SPI RX (Receive)
 
static void sunxi_spi_enable_bus (sunxi_spi_t *spi)
 Enable the SPI bus.
 
static void sunxi_spi_disable_bus (sunxi_spi_t *spi)
 Disable the SPI bus.
 
static void sunxi_spi_set_cs (sunxi_spi_t *spi, uint8_t cs)
 Set the chip select (CS) for the SPI transfer.
 
static void sunxi_spi_set_master (sunxi_spi_t *spi)
 Set the SPI controller to master mode.
 
static void sunxi_spi_start_xfer (sunxi_spi_t *spi)
 Start the SPI data transfer.
 
static void sunxi_spi_enable_transmit_pause (sunxi_spi_t *spi)
 Enable the SPI transmit pause feature.
 
static void sunxi_spi_set_ss_owner (sunxi_spi_t *spi, uint32_t on_off)
 Set the SPI chip select (SS) ownership.
 
static uint32_t sunxi_spi_query_txfifo (sunxi_spi_t *spi)
 Query the number of bytes in the SPI transmit FIFO.
 
static uint32_t sunxi_spi_query_rxfifo (sunxi_spi_t *spi)
 Query the number of bytes in the SPI receive FIFO.
 
static void sunxi_spi_disable_irq (sunxi_spi_t *spi, uint32_t bitmap)
 Disable SPI interrupts.
 
static void sunxi_spi_clr_irq_pending (sunxi_spi_t *spi, uint32_t pending_bit)
 Clear SPI interrupt pending flags.
 
static uint32_t sunxi_spi_query_irq_pending (sunxi_spi_t *spi)
 Query the status of pending SPI interrupts.
 
static void sunxi_spi_set_ss_level (sunxi_spi_t *spi, uint32_t high_low)
 Set the SPI chip select (SS) level.
 
static void sunxi_spi_dma_disable (sunxi_spi_t *spi)
 Disable DMA for SPI data transmission and reception.
 
static void sunxi_spi_reset_fifo (sunxi_spi_t *spi)
 Reset the SPI FIFO buffers.
 
static uint32_t sunxi_spi_read_rx_fifo (sunxi_spi_t *spi, uint8_t *buf, uint32_t len)
 Read data from the SPI receive FIFO.
 
static void sunxi_spi_write_tx_fifo (sunxi_spi_t *spi, uint8_t *buf, uint32_t len)
 Write data to the SPI transmit FIFO.
 
static void sunxi_spi_read_by_dma (sunxi_spi_t *spi, uint8_t *buf, uint32_t len)
 Perform SPI data reception using DMA.
 
static uint32_t sunxi_spi_set_clk (sunxi_spi_t *spi, uint32_t spi_clk, uint32_t mclk, uint32_t cdr_mode)
 Set the SPI clock frequency.
 
static int sunxi_spi_dma_init (sunxi_spi_t *spi)
 Initialize the SPI DMA for data transfer.
 
static int sunxi_spi_dma_deinit (sunxi_spi_t *spi)
 Deinitialize the SPI DMA.
 
static int sunxi_spi_get_clk (sunxi_spi_t *spi)
 Get the current SPI clock frequency.
 
void __attribute__ ((weak))
 Initializes the SPI clock.
 
static void sunxi_spi_clk_deinit (sunxi_spi_t *spi)
 Deinitializes the SPI clock.
 
static void sunxi_spi_config_transer_control (sunxi_spi_t *spi)
 Configures the SPI transfer control settings.
 
static void sunxi_spi_set_io_mode (sunxi_spi_t *spi, spi_io_mode_t mode)
 Sets the SPI I/O mode.
 
static void sunxi_spi_set_counters (sunxi_spi_t *spi, int txlen, int rxlen, int stxlen, int dummylen)
 Sets the counters for SPI transmission.
 
static void sunxi_spi_bus_init (sunxi_spi_t *spi)
 Initializes the SPI bus.
 
static void sunxi_spi_gpio_init (sunxi_spi_t *spi)
 Configures the GPIO pins for SPI communication.
 
int sunxi_spi_init (sunxi_spi_t *spi)
 Initializes the SPI interface.
 
void sunxi_spi_disable (sunxi_spi_t *spi)
 Disables the SPI interface.
 
int sunxi_spi_update_clk (sunxi_spi_t *spi, uint32_t clk)
 Updates the SPI clock rate.
 
int sunxi_spi_transfer (sunxi_spi_t *spi, spi_io_mode_t mode, void *txbuf, uint32_t txlen, void *rxbuf, uint32_t rxlen)
 Performs SPI data transfer.
 

Detailed Description

Allwinner Platform SPI Controller Driver.

This file implements the SPI (Serial Peripheral Interface) controller driver for Allwinner platforms. The SPI driver provides functionality for initializing and controlling the SPI interface, including clock configuration, data transfer, GPIO setup, and DMA operations. It supports various SPI modes, data widths, and transfer methods (polling and DMA).

The driver supports different I/O modes including single, dual, and quad SPI, making it suitable for interfacing with various SPI devices such as flash memory, sensors, and other peripheral devices.

SPDX-License-Identifier: GPL-2.0-or-later

Copyright (c) 2023, Allwinner Technology Co., Ltd.

Function Documentation

◆ __attribute__() [1/2]

static __attribute__ ( (section(".data"))  )
static

DMA configuration structure for SPI RX (Receive)

This structure is used for configuring the Direct Memory Access (DMA) controller for SPI data reception. It is placed in the section ".data" of the memory.

Perform a software reset on the SPI controller

This function triggers a software reset on the SPI controller by setting the appropriate bit in the control register.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
This function is typically used to reset the SPI controller to its initial state.

◆ __attribute__() [2/2]

void __attribute__ ( (weak)  )

Initializes the SPI clock.

This function configures the SPI clock by setting the appropriate divisor and clock source, enabling the SPI clock, performing a reset on the SPI, and setting up the clock gating.

Parameters
spiPointer to the SPI structure containing configuration and register information.

◆ sunxi_spi_bus_init()

static void sunxi_spi_bus_init ( sunxi_spi_t spi)
static

Initializes the SPI bus.

This function performs the necessary initialization steps for the SPI bus, including performing a soft reset, enabling the bus, configuring the chip select (CS), setting the SPI mode to master, configuring the clock, transfer control, and setting other SPI bus settings like slave select level and transmit pause.

Parameters
spiPointer to the SPI structure containing configuration and register information.

◆ sunxi_spi_clk_deinit()

static void sunxi_spi_clk_deinit ( sunxi_spi_t spi)
static

Deinitializes the SPI clock.

This function disables the SPI clock, clears the clock gating, and asserts the SPI reset.

Parameters
spiPointer to the SPI structure containing configuration and register information.

◆ sunxi_spi_clr_irq_pending()

static void sunxi_spi_clr_irq_pending ( sunxi_spi_t spi,
uint32_t  pending_bit 
)
inlinestatic

Clear SPI interrupt pending flags.

This function clears the interrupt pending flags for the SPI controller by writing the relevant bits to the interrupt status register.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]pending_bitA mask representing the pending interrupt to be cleared.
Note
Clearing interrupt flags is necessary after interrupt handling to prevent repeated interrupts for the same event.

◆ sunxi_spi_config_transer_control()

static void sunxi_spi_config_transer_control ( sunxi_spi_t spi)
static

Configures the SPI transfer control settings.

This function configures the transfer control register (tc) based on the SPI clock frequency. The transfer control settings such as data width, polarity, and phase are set accordingly.

Parameters
spiPointer to the SPI structure containing configuration and register information.

◆ sunxi_spi_disable()

void sunxi_spi_disable ( sunxi_spi_t spi)

Disables the SPI interface.

This function disables the SPI bus, deinitializes DMA (if used), and deinitializes the SPI clock. It is called when the SPI interface is no longer needed or when performing cleanup operations.

Parameters
spiPointer to the SPI structure containing configuration and register information.

◆ sunxi_spi_disable_bus()

static void sunxi_spi_disable_bus ( sunxi_spi_t spi)
inlinestatic

Disable the SPI bus.

This function disables the SPI bus by clearing the enable bit in the control register.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
Disabling the bus stops SPI communication and can be used for power saving or for configuring the controller before restarting it.

◆ sunxi_spi_disable_irq()

static void sunxi_spi_disable_irq ( sunxi_spi_t spi,
uint32_t  bitmap 
)
inlinestatic

Disable SPI interrupts.

This function disables specific interrupts for the SPI controller based on the provided interrupt bitmap. The interrupt mask is applied to the interrupt control register.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]bitmapA mask representing the interrupts to be disabled. Each bit corresponds to a specific interrupt.
Note
This function can be used to disable unwanted interrupts to avoid unnecessary interrupt handling.

◆ sunxi_spi_dma_deinit()

static int sunxi_spi_dma_deinit ( sunxi_spi_t spi)
static

Deinitialize the SPI DMA.

This function disables the DMA interrupt for the SPI DMA channel, effectively deinitializing the DMA setup and preparing for cleanup.

Parameters
[in]spiA pointer to the SPI structure.
Returns
0 on success.
Note
This function is typically called when SPI DMA operations are no longer required.

◆ sunxi_spi_dma_disable()

static void sunxi_spi_dma_disable ( sunxi_spi_t spi)
inlinestatic

Disable DMA for SPI data transmission and reception.

This function disables the Direct Memory Access (DMA) for both transmitting and receiving data through the SPI interface. Disabling DMA may be useful when switching to interrupt or polling modes of data transfer.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
This function disables both the TX and RX DMA requests by clearing the corresponding bits in the FIFO control register.

◆ sunxi_spi_dma_init()

static int sunxi_spi_dma_init ( sunxi_spi_t spi)
static

Initialize the SPI DMA for data transfer.

This function initializes the DMA controller for SPI data reception. It requests a DMA channel, configures the DMA settings for the SPI receive path, and installs the DMA interrupt handler. The DMA is then enabled and the necessary settings are applied to start data transfer via DMA.

Parameters
[in]spiA pointer to the SPI structure, containing the necessary information about the SPI controller and DMA settings.
Returns
0 on success, -1 on failure if DMA channel request fails.
Note
The DMA handler must be available and correctly initialized before calling this function.
Warning
If the DMA channel cannot be requested, an error message is printed using printk_error.

◆ sunxi_spi_enable_bus()

static void sunxi_spi_enable_bus ( sunxi_spi_t spi)
inlinestatic

Enable the SPI bus.

This function enables the SPI bus by setting the enable bit in the control register.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
Enabling the bus allows SPI communication to begin.

◆ sunxi_spi_enable_transmit_pause()

static void sunxi_spi_enable_transmit_pause ( sunxi_spi_t spi)
inlinestatic

Enable the SPI transmit pause feature.

This function enables the transmit pause feature for the SPI controller. When enabled, it allows the SPI transmission to be paused, providing control over when to send data.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
The transmit pause feature can be used to temporarily halt data transmission.

◆ sunxi_spi_get_clk()

static int sunxi_spi_get_clk ( sunxi_spi_t spi)
static

Get the current SPI clock frequency.

This function calculates and returns the current SPI clock frequency based on the SPI clock configuration registers. It reads the configuration, extracts the relevant clock parameters, and computes the actual SPI clock frequency in Hz.

Parameters
[in]spiA pointer to the SPI structure.
Returns
The actual SPI clock frequency in Hz.
Note
The SPI clock frequency is calculated based on the clock source, clock divider (n and m), and the configured clock source.
The function prints a trace message with the computed SPI clock frequency, the register value, and the clock divider values (n and m).

◆ sunxi_spi_gpio_init()

static void sunxi_spi_gpio_init ( sunxi_spi_t spi)
static

Configures the GPIO pins for SPI communication.

This function configures the SPI-related GPIO pins, including chip select (CS), clock (SCK), master-out slave-in (MOSI), master-in slave-out (MISO), write protect (WP), and hold pins. It sets the appropriate multiplexing functions and default pull-up resistors for the WP and hold pins.

Parameters
spiPointer to the SPI structure containing the GPIO configuration.

◆ sunxi_spi_init()

int sunxi_spi_init ( sunxi_spi_t spi)

Initializes the SPI interface.

This function initializes the SPI interface by configuring the GPIO pins, clock, bus, and counters. If a DMA handle is set, DMA mode is used for data transfers. The function calls several other SPI initialization functions to set up the SPI hardware.

Parameters
spiPointer to the SPI structure containing configuration and register information.
Returns
0 on success.

◆ sunxi_spi_query_irq_pending()

static uint32_t sunxi_spi_query_irq_pending ( sunxi_spi_t spi)
inlinestatic

Query the status of pending SPI interrupts.

This function queries the interrupt status register to determine which SPI interrupts are pending. The function returns a mask of the pending interrupts.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Returns
A mask representing the pending interrupts. Each bit corresponds to a specific interrupt status.
Note
This function is useful for checking which interrupts need to be handled.

◆ sunxi_spi_query_rxfifo()

static uint32_t sunxi_spi_query_rxfifo ( sunxi_spi_t spi)
inlinestatic

Query the number of bytes in the SPI receive FIFO.

This function queries the SPI receive FIFO to determine how many bytes are currently available to be read.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Returns
The number of bytes currently in the receive FIFO.
Note
This function is useful for checking if data is available in the receive FIFO.

◆ sunxi_spi_query_txfifo()

static uint32_t sunxi_spi_query_txfifo ( sunxi_spi_t spi)
inlinestatic

Query the number of bytes in the SPI transmit FIFO.

This function queries the SPI transmit FIFO to determine how many bytes are currently waiting to be transmitted.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Returns
The number of bytes currently in the transmit FIFO.
Note
This function is useful for monitoring the status of the transmit FIFO and managing data flow.

◆ sunxi_spi_read_by_dma()

static void sunxi_spi_read_by_dma ( sunxi_spi_t spi,
uint8_t buf,
uint32_t  len 
)
static

Perform SPI data reception using DMA.

This function initiates a DMA transfer to read data from the SPI receive FIFO into a provided buffer. It enables the DMA receive request and starts the DMA transfer. The function waits until the DMA transfer is complete before returning.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[out]bufA pointer to the buffer where received data will be stored.
[in]lenThe number of bytes to read from the SPI receive FIFO.
Note
This function uses DMA for data transfer, so it requires the DMA controller to be set up and ready to handle the transfer. The DMA handler spi_dma_handler must be initialized properly before calling this function.
Warning
If the DMA transfer fails, a warning message will be printed using printk_warning.

◆ sunxi_spi_read_rx_fifo()

static uint32_t sunxi_spi_read_rx_fifo ( sunxi_spi_t spi,
uint8_t buf,
uint32_t  len 
)
static

Read data from the SPI receive FIFO.

This function reads data from the SPI receive FIFO into a buffer. It waits until there is sufficient data available in the FIFO and transfers it into the provided buffer.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[out]bufA pointer to the buffer where the received data will be stored.
[in]lenThe number of bytes to read from the receive FIFO.
Returns
The number of bytes remaining to be read. This can be used to determine if the entire requested data has been transferred.
Note
This function reads data from the SPI FIFO in blocks, based on the FIFO shift size. It ensures that enough data is available in the FIFO before proceeding with the read.

◆ sunxi_spi_reset_fifo()

static void sunxi_spi_reset_fifo ( sunxi_spi_t spi)
static

Reset the SPI FIFO buffers.

This function resets the SPI transmit and receive FIFO buffers. The FIFO reset is done by writing specific bits to the FIFO control register. It also configures the trigger levels for both receive and transmit FIFOs.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
The reset process clears the FIFO contents and sets the FIFO trigger levels to 0x20 for both TX and RX FIFO.

◆ sunxi_spi_set_clk()

static uint32_t sunxi_spi_set_clk ( sunxi_spi_t spi,
uint32_t  spi_clk,
uint32_t  mclk,
uint32_t  cdr_mode 
)
static

Set the SPI clock frequency.

This function calculates and sets the SPI clock frequency based on the desired SPI clock (spi_clk), the system's master clock (mclk), and the clock divider mode (cdr2). It configures the clock control register to achieve the requested clock frequency for the SPI interface.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]spi_clkThe desired SPI clock frequency in Hz.
[in]mclkThe master clock frequency in Hz.
[in]cdr2If set to 1, the clock divider mode will be set to CDR2 (double the frequency).
Returns
The actual frequency of the SPI clock set by the function, in Hz.
Note
If the requested SPI clock is different from the current parent clock, the function will attempt to adjust the clock divider to achieve the desired SPI clock frequency.
The function prints debug messages regarding the clock divider settings and the resulting actual SPI clock frequency using printk_debug.

◆ sunxi_spi_set_counters()

static void sunxi_spi_set_counters ( sunxi_spi_t spi,
int  txlen,
int  rxlen,
int  stxlen,
int  dummylen 
)
static

Sets the counters for SPI transmission.

This function sets the burst, transmit, and dummy counters for SPI data transmission. The counters are configured based on the transmission length, reception length, start transmission length, and dummy data length.

Parameters
spiPointer to the SPI structure containing configuration and register information.
txlenThe length of the transmission data in bytes.
rxlenThe length of the reception data in bytes.
stxlenThe length of the start transmission data in bytes.
dummylenThe length of the dummy data in bytes.

◆ sunxi_spi_set_cs()

static void sunxi_spi_set_cs ( sunxi_spi_t spi,
uint8_t  cs 
)
inlinestatic

Set the chip select (CS) for the SPI transfer.

This function sets the chip select (CS) line by writing the value of the cs parameter to the relevant bits in the SPI control register. The CS line is used to select which peripheral is active for communication.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]csThe chip select value to be set. This is typically a 0 or 1, corresponding to a specific peripheral on the SPI bus.
Note
The CS line is used to enable or disable communication with specific SPI peripherals.

◆ sunxi_spi_set_io_mode()

static void sunxi_spi_set_io_mode ( sunxi_spi_t spi,
spi_io_mode_t  mode 
)
static

Sets the SPI I/O mode.

This function configures the I/O mode for SPI data transfer, including single, dual, or quad mode.

Parameters
spiPointer to the SPI structure containing configuration and register information.
modeThe desired SPI I/O mode (e.g., SPI_IO_SINGLE, SPI_IO_DUAL_RX, SPI_IO_QUAD_RX, etc.).

◆ sunxi_spi_set_master()

static void sunxi_spi_set_master ( sunxi_spi_t spi)
inlinestatic

Set the SPI controller to master mode.

This function sets the SPI controller to master mode by modifying the relevant control bit. In master mode, the SPI controller generates clock signals for communication with slaves.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
In master mode, the SPI controller will control the clock line and initiate data transfers.

◆ sunxi_spi_set_ss_level()

static void sunxi_spi_set_ss_level ( sunxi_spi_t spi,
uint32_t  high_low 
)
inlinestatic

Set the SPI chip select (SS) level.

This function controls the logic level of the chip select (SS) line. It sets the SS line to either high or low level, depending on the high_low parameter.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]high_lowA value indicating the level of the SS line:
  • 1: Set SS line to high
  • 0: Set SS line to low
Note
The SS line is used to select the SPI slave device for communication. The level of the SS line controls when the SPI communication starts.

◆ sunxi_spi_set_ss_owner()

static void sunxi_spi_set_ss_owner ( sunxi_spi_t spi,
uint32_t  on_off 
)
inlinestatic

Set the SPI chip select (SS) ownership.

This function controls the ownership of the chip select (SS) line. When the SS ownership is set to "on", the SPI controller has control over the SS line; when set to "off", the external controller or logic can take control.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]on_offA value indicating whether to enable or disable SS ownership:
  • 1: Enable SS ownership
  • 0: Disable SS ownership
Note
The SS line is critical in determining which device on the SPI bus is selected for communication.

◆ sunxi_spi_start_xfer()

static void sunxi_spi_start_xfer ( sunxi_spi_t spi)
inlinestatic

Start the SPI data transfer.

This function triggers the start of a data transfer by setting the relevant bit in the transfer control register. It begins the exchange of data on the SPI bus.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
Note
This function should be called after configuring the SPI bus and chip select.

◆ sunxi_spi_transfer()

int sunxi_spi_transfer ( sunxi_spi_t spi,
spi_io_mode_t  mode,
void *  txbuf,
uint32_t  txlen,
void *  rxbuf,
uint32_t  rxlen 
)

Performs SPI data transfer.

This function initiates a data transfer on the SPI bus. The transfer can be either full-duplex (both transmission and reception) or half-duplex (only transmission or reception). The transfer is done based on the specified SPI I/O mode. The function handles both transmit and receive operations, including the use of DMA if required for large transfers.

Parameters
spiPointer to the SPI structure containing configuration and register information.
modeThe I/O mode to use for the transfer (e.g., single, dual, quad).
txbufPointer to the transmission buffer.
txlenLength of the transmission data in bytes.
rxbufPointer to the reception buffer.
rxlenLength of the reception data in bytes.
Returns
The total number of bytes transferred (txlen + rxlen).

◆ sunxi_spi_update_clk()

int sunxi_spi_update_clk ( sunxi_spi_t spi,
uint32_t  clk 
)

Updates the SPI clock rate.

This function updates the SPI clock rate and reinitializes the clock, bus, and transfer control settings to apply the new clock rate.

Parameters
spiPointer to the SPI structure containing configuration and register information.
clkThe new clock rate to be set.
Returns
0 on success.

◆ sunxi_spi_write_tx_fifo()

static void sunxi_spi_write_tx_fifo ( sunxi_spi_t spi,
uint8_t buf,
uint32_t  len 
)
static

Write data to the SPI transmit FIFO.

This function writes data from a buffer to the SPI transmit FIFO. It waits until there is space available in the FIFO before writing more data.

Parameters
[in]spiA pointer to the SPI structure, which contains the base address of the SPI controller's registers.
[in]bufA pointer to the buffer containing the data to be transmitted.
[in]lenThe number of bytes to write to the transmit FIFO.
Note
This function writes data to the TX FIFO in blocks, based on the FIFO shift size. It ensures that there is space in the FIFO before writing more data.