drivers: spi: Add LiteX SPI driver
This commit adds LiteX SPI drivers and its bindings. Signed-off-by: Daniel Craviee <dcraviee@internships.antmicro.com> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
This commit is contained in:
parent
0f4e21cae8
commit
256c5c4e17
6 changed files with 263 additions and 0 deletions
|
@ -13,5 +13,6 @@ zephyr_library_sources_ifdef(CONFIG_SPI_SIFIVE spi_sifive.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPI spi_nrfx_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPIM spi_nrfx_spim.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPIS spi_nrfx_spis.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_LITESPI spi_litespi.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE spi_handlers.c)
|
||||
|
|
|
@ -197,4 +197,6 @@ source "drivers/spi/Kconfig.nrfx"
|
|||
|
||||
source "drivers/spi/Kconfig.cc13xx_cc26xx"
|
||||
|
||||
source "drivers/spi/Kconfig.litex"
|
||||
|
||||
endif # SPI
|
||||
|
|
12
drivers/spi/Kconfig.litex
Normal file
12
drivers/spi/Kconfig.litex
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Kconfig.litex - LiteX SPI (LiteSPI) configuration option
|
||||
#
|
||||
# Copyright (c) 2019 Antmicro <www.antmicro.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig SPI_LITESPI
|
||||
bool "LiteX SPI controller driver"
|
||||
depends on SOC_RISCV32_LITEX_VEXRISCV
|
||||
help
|
||||
Enable the SPI peripherals on LiteX
|
187
drivers/spi/spi_litespi.c
Normal file
187
drivers/spi/spi_litespi.c
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro <www.antmicro.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(spi_litespi);
|
||||
#include "spi_litespi.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Helper Functions */
|
||||
static int spi_config(const struct spi_config *config, u16_t *control)
|
||||
{
|
||||
u8_t cs = 0x00;
|
||||
|
||||
if (config->slave != 0) {
|
||||
if (config->slave >= SPI_MAX_CS_SIZE) {
|
||||
LOG_ERR("More slaves than supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
cs = (u8_t)(config->slave);
|
||||
}
|
||||
|
||||
if (SPI_WORD_SIZE_GET(config->operation) != 8) {
|
||||
LOG_ERR("Word size must be %d", SPI_WORD_SIZE);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->operation & SPI_CS_ACTIVE_HIGH) {
|
||||
LOG_ERR("CS active high not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->operation & SPI_LOCK_ON) {
|
||||
LOG_ERR("Lock On not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
|
||||
LOG_ERR("Only supports single mode");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->operation & SPI_TRANSFER_LSB) {
|
||||
LOG_ERR("LSB first not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->operation & (SPI_MODE_CPOL | SPI_MODE_CPHA)) {
|
||||
LOG_ERR("Only supports CPOL=CPHA=0");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->operation & SPI_OP_MODE_SLAVE) {
|
||||
LOG_ERR("Slave mode not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Set Loopback */
|
||||
if (config->operation & SPI_MODE_LOOP) {
|
||||
litex_write8(SPI_ENABLE, SPI_LOOPBACK_REG);
|
||||
}
|
||||
/* Set word size */
|
||||
*control = (u16_t) (SPI_WORD_SIZE_GET(config->operation)
|
||||
<< POSITION_WORD_SIZE);
|
||||
/* Write configurations */
|
||||
litex_write8(cs, SPI_CS_REG);
|
||||
litex_write16(*control, SPI_CONTROL_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spi_litespi_send(struct device *dev, u8_t frame, u16_t control)
|
||||
{
|
||||
/* Write frame to register */
|
||||
litex_write8(frame, SPI_MOSI_DATA_REG);
|
||||
/* Start the transfer */
|
||||
litex_write16(control | SPI_ENABLE, SPI_CONTROL_REG);
|
||||
/* Wait until the transfer ends */
|
||||
while (!(litex_read8(SPI_STATUS_REG)))
|
||||
;
|
||||
}
|
||||
|
||||
static u8_t spi_litespi_recv(void)
|
||||
{
|
||||
/* Return data inside MISO register */
|
||||
return litex_read8(SPI_MISO_DATA_REG);
|
||||
}
|
||||
|
||||
static void spi_litespi_xfer(struct device *dev,
|
||||
const struct spi_config *config, u16_t control)
|
||||
{
|
||||
struct spi_context *ctx = &SPI_DATA(dev)->ctx;
|
||||
u32_t send_len = spi_context_longest_current_buf(ctx);
|
||||
u8_t read_data;
|
||||
|
||||
for (u32_t i = 0; i < send_len; i++) {
|
||||
/* Send a frame */
|
||||
if (i < ctx->tx_len) {
|
||||
spi_litespi_send(dev, (u8_t) (ctx->tx_buf)[i],
|
||||
control);
|
||||
} else {
|
||||
/* Send dummy bytes */
|
||||
spi_litespi_send(dev, 0, control);
|
||||
}
|
||||
/* Receive a frame */
|
||||
read_data = spi_litespi_recv();
|
||||
if (i < ctx->rx_len) {
|
||||
ctx->rx_buf[i] = read_data;
|
||||
}
|
||||
}
|
||||
spi_context_complete(ctx, 0);
|
||||
}
|
||||
|
||||
/* API Functions */
|
||||
|
||||
static int spi_litespi_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_litespi_transceive(struct device *dev,
|
||||
const struct spi_config *config,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
u16_t control = 0;
|
||||
|
||||
spi_config(config, &control);
|
||||
spi_context_buffers_setup(&SPI_DATA(dev)->ctx, tx_bufs, rx_bufs, 1);
|
||||
spi_litespi_xfer(dev, config, control);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
static int spi_litespi_transceive_async(struct device *dev,
|
||||
const struct spi_config *config,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs,
|
||||
struct k_poll_signal *async)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
|
||||
static int spi_litespi_release(struct device *dev,
|
||||
const struct spi_config *config)
|
||||
{
|
||||
if (!(litex_read8(SPI_STATUS_REG))) {
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Device Instantiation */
|
||||
static struct spi_driver_api spi_litespi_api = {
|
||||
.transceive = spi_litespi_transceive,
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
.transceive_async = spi_litespi_transceive_async,
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
.release = spi_litespi_release,
|
||||
};
|
||||
|
||||
#define SPI_INIT(n) \
|
||||
static struct spi_litespi_data spi_litespi_data_##n = { \
|
||||
SPI_CONTEXT_INIT_LOCK(spi_litespi_data_##n, ctx), \
|
||||
SPI_CONTEXT_INIT_SYNC(spi_litespi_data_##n, ctx), \
|
||||
}; \
|
||||
static struct spi_litespi_cfg spi_litespi_cfg_##n = { \
|
||||
.base = DT_INST_##n##_LITEX_SPI_CONTROL_BASE_ADDRESS, \
|
||||
}; \
|
||||
DEVICE_AND_API_INIT(spi_##n, \
|
||||
DT_INST_##n##_LITEX_SPI_LABEL, \
|
||||
spi_litespi_init, \
|
||||
&spi_litespi_data_##n, \
|
||||
&spi_litespi_cfg_##n, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SPI_INIT_PRIORITY, \
|
||||
&spi_litespi_api)
|
||||
|
||||
#ifdef DT_INST_0_LITEX_SPI_LABEL
|
||||
|
||||
SPI_INIT(0);
|
||||
|
||||
#endif /* DT_INST_0_LITEX_SPI_LABEL */
|
43
drivers/spi/spi_litespi.h
Normal file
43
drivers/spi/spi_litespi.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Antmicro <www.antmicro.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SPI_LITESPI__H
|
||||
#define _SPI_LITESPI__H
|
||||
|
||||
#include "spi_context.h"
|
||||
|
||||
#include <sys/sys_io.h>
|
||||
#include <device.h>
|
||||
#include <drivers/spi.h>
|
||||
|
||||
#define SPI_BASE_ADDR DT_INST_0_LITEX_SPI_BASE_ADDRESS
|
||||
#define SPI_CONTROL_REG SPI_BASE_ADDR
|
||||
#define SPI_STATUS_REG (SPI_BASE_ADDR + 0x08)
|
||||
#define SPI_MOSI_DATA_REG (SPI_BASE_ADDR + 0x0c)
|
||||
#define SPI_MISO_DATA_REG (SPI_BASE_ADDR + 0x10)
|
||||
#define SPI_CS_REG (SPI_BASE_ADDR + 0x14)
|
||||
#define SPI_LOOPBACK_REG (SPI_BASE_ADDR + 0x18)
|
||||
|
||||
#define POSITION_WORD_SIZE 8
|
||||
#define SPI_MAX_CS_SIZE 0x100
|
||||
#define SPI_WORD_SIZE 8
|
||||
|
||||
#define SPI_ENABLE 0x1
|
||||
|
||||
#define SPI_DATA(dev) ((struct spi_litespi_data *) ((dev)->driver_data))
|
||||
|
||||
/* Structure Declarations */
|
||||
|
||||
struct spi_litespi_data {
|
||||
struct spi_context ctx;
|
||||
};
|
||||
|
||||
struct spi_litespi_cfg {
|
||||
u32_t base;
|
||||
u32_t f_sys;
|
||||
};
|
||||
|
||||
#endif /* _SPI_LITESPI__H */
|
18
dts/bindings/spi/litex,spi.yaml
Normal file
18
dts/bindings/spi/litex,spi.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Copyright (c) 2019 Antmicro <www.antmicro.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
title: LiteX SPI
|
||||
|
||||
description: >
|
||||
This binding gives a base representation of the LiteX SPI
|
||||
|
||||
compatible: "litex,spi"
|
||||
|
||||
include: spi-controller.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
Loading…
Add table
Add a link
Reference in a new issue