drivers: spi: Add support for Polarfire SOC SPI
Add driver for the Microchip Polarfire SOC MSS SPI controller. The interrupts of the MSS SPI are routed through PLIC(Platform level interrupt controller). Tested with generic spi-nor flash driver(spi_flash) with both Fixed flash configuration and Read flash parameters at runtime(using SFDP). Signed-off-by: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
This commit is contained in:
parent
c5818d4b3f
commit
4d6a8bc65a
|
@ -44,7 +44,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ spi_ambiq.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ mspi_ambiq.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_MCHP_MSS spi_mchp_mss.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_RTIO spi_rtio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_ASYNC spi_signal.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE spi_handlers.c)
|
||||
|
|
|
@ -139,4 +139,6 @@ source "drivers/spi/Kconfig.sedi"
|
|||
|
||||
source "drivers/spi/Kconfig.npcx"
|
||||
|
||||
source "drivers/spi/Kconfig.mchp_mss"
|
||||
|
||||
endif # SPI
|
||||
|
|
11
drivers/spi/Kconfig.mchp_mss
Normal file
11
drivers/spi/Kconfig.mchp_mss
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Microchip Polarfire SOC SPI
|
||||
|
||||
# Copyright (c) 2022 Microchip Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SPI_MCHP_MSS
|
||||
bool "Microchip Polarfire SOC SPI driver"
|
||||
default y
|
||||
depends on DT_HAS_MICROCHIP_MPFS_SPI_ENABLED
|
||||
help
|
||||
Enable support for the Polarfire SOC SPI driver.
|
480
drivers/spi/spi_mchp_mss.c
Normal file
480
drivers/spi/spi_mchp_mss.c
Normal file
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Microchip Technology Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT microchip_mpfs_spi
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/sys/sys_io.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/irq.h>
|
||||
|
||||
LOG_MODULE_REGISTER(mss_spi, CONFIG_SPI_LOG_LEVEL);
|
||||
|
||||
#include "spi_context.h"
|
||||
|
||||
/* MSS SPI Register offsets */
|
||||
#define MSS_SPI_REG_CONTROL (0x00)
|
||||
#define MSS_SPI_REG_TXRXDF_SIZE (0x04)
|
||||
#define MSS_SPI_REG_STATUS (0x08)
|
||||
#define MSS_SPI_REG_INT_CLEAR (0x0c)
|
||||
#define MSS_SPI_REG_RX_DATA (0x10)
|
||||
#define MSS_SPI_REG_TX_DATA (0x14)
|
||||
#define MSS_SPI_REG_CLK_GEN (0x18)
|
||||
#define MSS_SPI_REG_SS (0x1c)
|
||||
#define MSS_SPI_REG_MIS (0x20)
|
||||
#define MSS_SPI_REG_RIS (0x24)
|
||||
#define MSS_SPI_REG_CONTROL2 (0x28)
|
||||
#define MSS_SPI_REG_COMMAND (0x2c)
|
||||
#define MSS_SPI_REG_PKTSIZE (0x30)
|
||||
#define MSS_SPI_REG_CMD_SIZE (0x34)
|
||||
#define MSS_SPI_REG_HWSTATUS (0x38)
|
||||
#define MSS_SPI_REG_FRAMESUP (0x50)
|
||||
|
||||
/* SPICR bit definitions */
|
||||
#define MSS_SPI_CONTROL_ENABLE BIT(0)
|
||||
#define MSS_SPI_CONTROL_MASTER BIT(1)
|
||||
#define MSS_SPI_CONTROL_PROTO_MSK BIT(2)
|
||||
#define MSS_SPI_CONTROL_PROTO_MOTO (0 << 2)
|
||||
#define MSS_SPI_CONTROL_RX_DATA_INT BIT(4)
|
||||
#define MSS_SPI_CONTROL_TX_DATA_INT BIT(5)
|
||||
#define MSS_SPI_CONTROL_RX_OVER_INT BIT(6)
|
||||
#define MSS_SPI_CONTROL_TX_UNDER_INT BIT(7)
|
||||
#define MSS_SPI_CONTROL_CNT_MSK (0xffff << 8)
|
||||
#define MSS_SPI_CONTROL_CNT_SHF (8)
|
||||
#define MSS_SPI_CONTROL_SPO BIT(24)
|
||||
#define MSS_SPI_CONTROL_SPH BIT(25)
|
||||
#define MSS_SPI_CONTROL_SPS BIT(26)
|
||||
#define MSS_SPI_CONTROL_FRAMEURUN BIT(27)
|
||||
#define MSS_SPI_CONTROL_CLKMODE BIT(28)
|
||||
#define MSS_SPI_CONTROL_BIGFIFO BIT(29)
|
||||
#define MSS_SPI_CONTROL_OENOFF BIT(30)
|
||||
#define MSS_SPI_CONTROL_RESET BIT(31)
|
||||
|
||||
/* SPIFRAMESIZE bit definitions */
|
||||
#define MSS_SPI_FRAMESIZE_DEFAULT (8)
|
||||
|
||||
/* SPISS bit definitions */
|
||||
#define MSS_SPI_SSEL_MASK (0xff)
|
||||
#define MSS_SPI_DIRECT (0x100)
|
||||
#define MSS_SPI_SSELOUT (0x200)
|
||||
#define MSS_SPI_MIN_SLAVE (0)
|
||||
#define MSS_SPI_MAX_SLAVE (7)
|
||||
|
||||
/* SPIST bit definitions */
|
||||
#define MSS_SPI_STATUS_ACTIVE BIT(14)
|
||||
#define MSS_SPI_STATUS_SSEL BIT(13)
|
||||
#define MSS_SPI_STATUS_FRAMESTART BIT(12)
|
||||
#define MSS_SPI_STATUS_TXFIFO_EMPTY_NEXT_READ BIT(11)
|
||||
#define MSS_SPI_STATUS_TXFIFO_EMPTY BIT(10)
|
||||
#define MSS_SPI_STATUS_TXFIFO_FULL_NEXT_WRITE BIT(9)
|
||||
#define MSS_SPI_STATUS_TXFIFO_FULL BIT(8)
|
||||
#define MSS_SPI_STATUS_RXFIFO_EMPTY_NEXT_READ BIT(7)
|
||||
#define MSS_SPI_STATUS_RXFIFO_EMPTY BIT(6)
|
||||
#define MSS_SPI_STATUS_RXFIFO_FULL_NEXT_WRITE BIT(5)
|
||||
#define MSS_SPI_STATUS_RXFIFO_FULL BIT(4)
|
||||
#define MSS_SPI_STATUS_TX_UNDERRUN BIT(3)
|
||||
#define MSS_SPI_STATUS_RX_OVERFLOW BIT(2)
|
||||
#define MSS_SPI_STATUS_RXDAT_RCED BIT(1)
|
||||
#define MSS_SPI_STATUS_TXDAT_SENT BIT(0)
|
||||
|
||||
/* SPIINT register defines */
|
||||
#define MSS_SPI_INT_TXDONE BIT(0)
|
||||
#define MSS_SPI_INT_RXRDY BIT(1)
|
||||
#define MSS_SPI_INT_RX_CH_OVRFLW BIT(2)
|
||||
#define MSS_SPI_INT_TX_CH_UNDRUN BIT(3)
|
||||
#define MSS_SPI_INT_CMD BIT(4)
|
||||
#define MSS_SPI_INT_SSEND BIT(5)
|
||||
|
||||
/* SPICOMMAND bit definitions */
|
||||
#define MSS_SPI_COMMAND_FIFO_MASK (0xC)
|
||||
|
||||
/* SPIFRAMESUP bit definitions */
|
||||
#define MSS_SPI_FRAMESUP_UP_BYTES_MSK (0xFFFF << 16)
|
||||
#define MSS_SPI_FRAMESUP_LO_BYTES_MSK (0xFFFF << 0)
|
||||
|
||||
struct mss_spi_config {
|
||||
mm_reg_t base;
|
||||
uint8_t clk_gen;
|
||||
int clock_freq;
|
||||
};
|
||||
|
||||
struct mss_spi_transfer {
|
||||
uint32_t rx_len;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
struct mss_spi_data {
|
||||
struct spi_context ctx;
|
||||
struct mss_spi_transfer xfer;
|
||||
};
|
||||
|
||||
static inline uint32_t mss_spi_read(const struct mss_spi_config *cfg, mm_reg_t offset)
|
||||
{
|
||||
return sys_read32(cfg->base + offset);
|
||||
}
|
||||
|
||||
static inline void mss_spi_write(const struct mss_spi_config *cfg, mm_reg_t offset, uint32_t val)
|
||||
{
|
||||
sys_write32(val, cfg->base + offset);
|
||||
}
|
||||
|
||||
static inline void mss_spi_hw_tfsz_set(const struct mss_spi_config *cfg, int len)
|
||||
{
|
||||
uint32_t control;
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_FRAMESUP, (len & MSS_SPI_FRAMESUP_UP_BYTES_MSK));
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control &= ~MSS_SPI_CONTROL_CNT_MSK;
|
||||
control |= ((len & MSS_SPI_FRAMESUP_LO_BYTES_MSK) << MSS_SPI_CONTROL_CNT_SHF);
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
}
|
||||
|
||||
static inline void mss_spi_enable_controller(const struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t control;
|
||||
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control |= MSS_SPI_CONTROL_ENABLE;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
}
|
||||
|
||||
static inline void mss_spi_disable_controller(const struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t control;
|
||||
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control &= ~MSS_SPI_CONTROL_ENABLE;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
}
|
||||
|
||||
static void mss_spi_enable_ints(const struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t control;
|
||||
uint32_t mask = MSS_SPI_CONTROL_RX_DATA_INT | MSS_SPI_CONTROL_TX_DATA_INT |
|
||||
MSS_SPI_CONTROL_RX_OVER_INT | MSS_SPI_CONTROL_TX_UNDER_INT;
|
||||
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control |= mask;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
}
|
||||
|
||||
static void mss_spi_disable_ints(const struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t control;
|
||||
uint32_t mask = MSS_SPI_CONTROL_RX_DATA_INT | MSS_SPI_CONTROL_TX_DATA_INT |
|
||||
MSS_SPI_CONTROL_RX_OVER_INT | MSS_SPI_CONTROL_TX_UNDER_INT;
|
||||
|
||||
mask = ~mask;
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control &= ~mask;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
}
|
||||
|
||||
static inline void mss_spi_readwr_fifo(const struct device *dev)
|
||||
{
|
||||
const struct mss_spi_config *cfg = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
struct mss_spi_transfer *xfer = &data->xfer;
|
||||
uint32_t rx_raw = 0, rd_byte_size, tr_len;
|
||||
uint32_t data8, transfer_idx = 0;
|
||||
int count;
|
||||
|
||||
tr_len = spi_context_longest_current_buf(ctx);
|
||||
count = spi_context_total_tx_len(ctx);
|
||||
if (ctx->rx_buf) {
|
||||
rd_byte_size = count - tr_len;
|
||||
} else {
|
||||
rd_byte_size = 0;
|
||||
}
|
||||
mss_spi_hw_tfsz_set(cfg, count);
|
||||
|
||||
mss_spi_enable_ints(cfg);
|
||||
spi_context_update_rx(ctx, 1, xfer->rx_len);
|
||||
while (transfer_idx < count) {
|
||||
if (!(mss_spi_read(cfg, MSS_SPI_REG_STATUS) & MSS_SPI_STATUS_RXFIFO_EMPTY)) {
|
||||
rx_raw = mss_spi_read(cfg, MSS_SPI_REG_RX_DATA);
|
||||
if (transfer_idx >= tr_len) {
|
||||
if (spi_context_rx_buf_on(ctx)) {
|
||||
UNALIGNED_PUT(rx_raw, (uint8_t *)ctx->rx_buf);
|
||||
spi_context_update_rx(ctx, 1, 1);
|
||||
}
|
||||
}
|
||||
++transfer_idx;
|
||||
}
|
||||
|
||||
if (!(mss_spi_read(cfg, MSS_SPI_REG_STATUS) & MSS_SPI_STATUS_TXFIFO_FULL)) {
|
||||
if (spi_context_tx_buf_on(ctx)) {
|
||||
data8 = ctx->tx_buf[0];
|
||||
mss_spi_write(cfg, MSS_SPI_REG_TX_DATA, data8);
|
||||
spi_context_update_tx(ctx, 1, 1);
|
||||
} else {
|
||||
mss_spi_write(cfg, MSS_SPI_REG_TX_DATA, 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int mss_spi_select_slave(const struct mss_spi_config *cfg, int cs)
|
||||
{
|
||||
uint32_t slave;
|
||||
uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
|
||||
|
||||
slave = (cs >= MSS_SPI_MIN_SLAVE && cs <= MSS_SPI_MAX_SLAVE) ? (1 << cs) : 0;
|
||||
reg &= ~MSS_SPI_SSEL_MASK;
|
||||
reg |= slave;
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mss_spi_activate_cs(struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
|
||||
|
||||
reg |= MSS_SPI_SSELOUT;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
|
||||
}
|
||||
|
||||
static inline void mss_spi_deactivate_cs(const struct mss_spi_config *cfg)
|
||||
{
|
||||
uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
|
||||
|
||||
reg &= ~MSS_SPI_SSELOUT;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
|
||||
}
|
||||
|
||||
static inline int mss_spi_clk_gen_set(const struct mss_spi_config *cfg,
|
||||
const struct spi_config *spi_cfg)
|
||||
{
|
||||
uint32_t idx, clkrate, val = 0, speed;
|
||||
|
||||
if (spi_cfg->frequency > cfg->clock_freq) {
|
||||
speed = cfg->clock_freq / 2;
|
||||
}
|
||||
|
||||
for (idx = 1; idx < 16; idx++) {
|
||||
clkrate = cfg->clock_freq / (2 * idx);
|
||||
if (clkrate <= spi_cfg->frequency) {
|
||||
val = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CLK_GEN, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mss_spi_hw_mode_set(const struct mss_spi_config *cfg, unsigned int mode)
|
||||
{
|
||||
uint32_t control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
|
||||
/* set the mode */
|
||||
if (mode & SPI_MODE_CPHA) {
|
||||
control |= MSS_SPI_CONTROL_SPH;
|
||||
} else {
|
||||
control &= ~MSS_SPI_CONTROL_SPH;
|
||||
}
|
||||
|
||||
if (mode & SPI_MODE_CPOL) {
|
||||
control |= MSS_SPI_CONTROL_SPO;
|
||||
} else {
|
||||
control &= ~MSS_SPI_CONTROL_SPO;
|
||||
}
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mss_spi_interrupt(const struct device *dev)
|
||||
{
|
||||
const struct mss_spi_config *cfg = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
int intfield = mss_spi_read(cfg, MSS_SPI_REG_MIS) & 0xf;
|
||||
|
||||
if (intfield == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_INT_CLEAR, intfield);
|
||||
spi_context_complete(ctx, dev, 0);
|
||||
}
|
||||
|
||||
static int mss_spi_release(const struct device *dev, const struct spi_config *config)
|
||||
{
|
||||
const struct mss_spi_config *cfg = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
|
||||
mss_spi_disable_ints(cfg);
|
||||
|
||||
/* release kernel resources */
|
||||
spi_context_unlock_unconditionally(&data->ctx);
|
||||
mss_spi_disable_controller(cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mss_spi_configure(const struct device *dev, const struct spi_config *spi_cfg)
|
||||
{
|
||||
const struct mss_spi_config *cfg = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
struct mss_spi_transfer *xfer = &data->xfer;
|
||||
uint32_t control;
|
||||
|
||||
if (spi_cfg->operation & (SPI_TRANSFER_LSB | SPI_OP_MODE_SLAVE | SPI_MODE_LOOP)) {
|
||||
LOG_WRN("not supported operation\n\r");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (SPI_WORD_SIZE_GET(spi_cfg->operation) != MSS_SPI_FRAMESIZE_DEFAULT) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ctx->config = spi_cfg;
|
||||
mss_spi_select_slave(cfg, spi_cfg->slave);
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
|
||||
/*
|
||||
* Fill up the default values
|
||||
* Slave select behaviour set
|
||||
* Fifo depth greater than 4 frames
|
||||
* Methodology to calculate SPI Clock:
|
||||
* 0: SPICLK = 1 / (2 CLK_GEN + 1) , CLK_GEN is from 0 to 15
|
||||
* 1: SPICLK = 1 / (2 * (CLK_GEN + 1)) , CLK_GEN is from 0 to 255
|
||||
*/
|
||||
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, xfer->control);
|
||||
|
||||
if (mss_spi_clk_gen_set(cfg, spi_cfg)) {
|
||||
LOG_ERR("can't set clk divider\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mss_spi_hw_mode_set(cfg, spi_cfg->operation);
|
||||
mss_spi_write(cfg, MSS_SPI_REG_TXRXDF_SIZE, MSS_SPI_FRAMESIZE_DEFAULT);
|
||||
mss_spi_enable_controller(cfg);
|
||||
mss_spi_write(cfg, MSS_SPI_REG_COMMAND, MSS_SPI_COMMAND_FIFO_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mss_spi_transceive(const struct device *dev, const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs,
|
||||
bool async, spi_callback_t cb, void *userdata)
|
||||
{
|
||||
|
||||
const struct mss_spi_config *config = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
struct mss_spi_transfer *xfer = &data->xfer;
|
||||
int ret = 0;
|
||||
|
||||
spi_context_lock(ctx, async, cb, userdata, spi_cfg);
|
||||
|
||||
ret = mss_spi_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
LOG_ERR("Fail to configure\n\r");
|
||||
goto out;
|
||||
}
|
||||
|
||||
spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1);
|
||||
xfer->rx_len = ctx->rx_len;
|
||||
mss_spi_readwr_fifo(dev);
|
||||
ret = spi_context_wait_for_completion(ctx);
|
||||
out:
|
||||
spi_context_release(ctx, ret);
|
||||
mss_spi_disable_ints(config);
|
||||
mss_spi_disable_controller(config);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mss_spi_transceive_blocking(const struct device *dev, const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
|
||||
return mss_spi_transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
static int mss_spi_transceive_async(const struct device *dev, const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs, spi_callback_t cb,
|
||||
void *userdata)
|
||||
{
|
||||
return mss_spi_transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata);
|
||||
}
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
|
||||
static int mss_spi_init(const struct device *dev)
|
||||
{
|
||||
const struct mss_spi_config *cfg = dev->config;
|
||||
struct mss_spi_data *data = dev->data;
|
||||
struct mss_spi_transfer *xfer = &data->xfer;
|
||||
int ret = 0;
|
||||
uint32_t control = 0;
|
||||
|
||||
/* Remove SPI from Reset */
|
||||
control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
|
||||
control &= ~MSS_SPI_CONTROL_RESET;
|
||||
mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
|
||||
|
||||
/* Set master mode */
|
||||
mss_spi_disable_controller(cfg);
|
||||
xfer->control = (MSS_SPI_CONTROL_SPS | MSS_SPI_CONTROL_BIGFIFO | MSS_SPI_CONTROL_MASTER |
|
||||
MSS_SPI_CONTROL_CLKMODE);
|
||||
|
||||
spi_context_unlock_unconditionally(&data->ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MICROCHIP_SPI_PM_OPS (NULL)
|
||||
|
||||
static const struct spi_driver_api mss_spi_driver_api = {
|
||||
.transceive = mss_spi_transceive_blocking,
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
.transceive_async = mss_spi_transceive_async,
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
.release = mss_spi_release,
|
||||
};
|
||||
|
||||
#define MSS_SPI_INIT(n) \
|
||||
static int mss_spi_init_##n(const struct device *dev) \
|
||||
{ \
|
||||
mss_spi_init(dev); \
|
||||
\
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mss_spi_interrupt, \
|
||||
DEVICE_DT_INST_GET(n), 0); \
|
||||
\
|
||||
irq_enable(DT_INST_IRQN(n)); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static const struct mss_spi_config mss_spi_config_##n = { \
|
||||
.base = DT_INST_REG_ADDR(n), \
|
||||
.clock_freq = DT_INST_PROP(n, clock_frequency), \
|
||||
}; \
|
||||
\
|
||||
static struct mss_spi_data mss_spi_data_##n = { \
|
||||
SPI_CONTEXT_INIT_LOCK(mss_spi_data_##n, ctx), \
|
||||
SPI_CONTEXT_INIT_SYNC(mss_spi_data_##n, ctx), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, mss_spi_init_##n, NULL, &mss_spi_data_##n, &mss_spi_config_##n, \
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&mss_spi_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(MSS_SPI_INIT)
|
Loading…
Reference in a new issue