This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
++ ++config SPI_AU1550
++ ++ tristate "Au1550/Au1200/Au1300 SPI Controller"
++ ++ depends on MIPS_ALCHEMY
++ ++ select SPI_BITBANG
++ ++ help
++ ++ If you say yes to this option, support will be included for the
++ ++ PSC SPI controller found on Au1550, Au1200 and Au1300 series.
++ ++
++ ++config SPI_AXI_SPI_ENGINE
++ ++ tristate "Analog Devices AXI SPI Engine controller"
++ ++ depends on HAS_IOMEM
++ ++ help
++ ++ This enables support for the Analog Devices AXI SPI Engine SPI controller.
++ ++ It is part of the SPI Engine framework that is used in some Analog Devices
++ ++ reference designs for FPGAs.
++ ++
config SPI_BCM2835
tristate "BCM2835 SPI controller"
depends on GPIOLIB
depends on ARCH_BCM2835 || COMPILE_TEST
--- - depends on GPIOLIB
help
This selects a driver for the Broadcom BCM2835 SPI master.
config SPI_BCM2835AUX
tristate "BCM2835 SPI auxiliary controller"
---- depends on ARCH_BCM2835 || COMPILE_TEST
---- depends on GPIOLIB
++++ depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST
help
This selects a driver for the Broadcom BCM2835 SPI aux master.
help
Enable support for a SPI bus via the Blackfin SPORT peripheral.
-- --config SPI_AU1550
-- -- tristate "Au1550/Au1200/Au1300 SPI Controller"
-- -- depends on MIPS_ALCHEMY
-- -- select SPI_BITBANG
-- -- help
-- -- If you say yes to this option, support will be included for the
-- -- PSC SPI controller found on Au1550, Au1200 and Au1300 series.
-- --
config SPI_BCM53XX
tristate "Broadcom BCM53xx SPI controller"
depends on ARCH_BCM_5301X
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
++ ++config SPI_DESIGNWARE
++ ++ tristate "DesignWare SPI controller core support"
++ ++ help
++ ++ general driver for SPI controller core from DesignWare
++ ++
++ ++config SPI_DW_PCI
++ ++ tristate "PCI interface driver for DW SPI core"
++ ++ depends on SPI_DESIGNWARE && PCI
++ ++
++ ++config SPI_DW_MID_DMA
++ ++ bool "DMA support for DW SPI controller on Intel MID platform"
++ ++ depends on SPI_DW_PCI && DW_DMAC_PCI
++ ++
++ ++config SPI_DW_MMIO
++ ++ tristate "Memory-mapped io interface driver for DW SPI core"
++ ++ depends on SPI_DESIGNWARE
++ ++
config SPI_DLN2
tristate "Diolan DLN-2 USB SPI adapter"
depends on MFD_DLN2
say Y or M here.If you are not sure, say N.
SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
++ ++config SPI_NUC900
++ ++ tristate "Nuvoton NUC900 series SPI"
++ ++ depends on ARCH_W90X900
++ ++ select SPI_BITBANG
++ ++ help
++ ++ SPI driver for Nuvoton NUC900 series ARM SoCs
++ ++
config SPI_OC_TINY
tristate "OpenCores tiny SPI"
depends on GPIOLIB || COMPILE_TEST
help
Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
-- --config SPI_NUC900
-- -- tristate "Nuvoton NUC900 series SPI"
-- -- depends on ARCH_W90X900
-- -- select SPI_BITBANG
-- -- help
-- -- SPI driver for Nuvoton NUC900 series ARM SoCs
-- --
#
# Add new SPI master controllers in alphabetical order above this line
#
-- --config SPI_DESIGNWARE
-- -- tristate "DesignWare SPI controller core support"
-- -- help
-- -- general driver for SPI controller core from DesignWare
-- --
-- --config SPI_DW_PCI
-- -- tristate "PCI interface driver for DW SPI core"
-- -- depends on SPI_DESIGNWARE && PCI
-- --
-- --config SPI_DW_MID_DMA
-- -- bool "DMA support for DW SPI controller on Intel MID platform"
-- -- depends on SPI_DW_PCI && DW_DMAC_PCI
-- --
-- --config SPI_DW_MMIO
-- -- tristate "Memory-mapped io interface driver for DW SPI core"
-- -- depends on SPI_DESIGNWARE
-- --
#
# There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones.
#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
---- #define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400
++++ #define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400
#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
---- #define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100
++++ #define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100
#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
/* Bitfields in CNTL1 */
#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700
----#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080
----#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040
++++#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080
++++#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040
#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002
#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001
#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30
#define BCM2835_AUX_SPI_POLLING_JIFFIES 2
---- #define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
---- | SPI_NO_CS)
----
struct bcm2835aux_spi {
void __iomem *regs;
struct clk *clk;
ret = IRQ_HANDLED;
}
---- /* and if rx_len is 0 then wake up completion and disable spi */
++++ if (!bs->tx_len) {
++++ /* disable tx fifo empty interrupt */
++++ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
++++ BCM2835_AUX_SPI_CNTL1_IDLE);
++++ }
++++
++++ /* and if rx_len is 0 then disable interrupts and wake up completion */
if (!bs->rx_len) {
---- bcm2835aux_spi_reset_hw(bs);
++++ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
complete(&master->xfer_completion);
}
}
}
---- /* Transfer complete - reset SPI HW */
---- bcm2835aux_spi_reset_hw(bs);
----
/* and return without waiting for completion */
return 0;
}
* resulting (potentially) in more interrupts when transferring
* more than 12 bytes
*/
---- bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
---- BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
---- BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
---- bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
/* set clock */
spi_hz = tfr->speed_hz;
} else { /* the slowest we can go */
speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
}
++++ /* mask out old speed from previous spi_transfer */
++++ bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED);
++++ /* set the new speed */
bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
spi_used_hz = clk_hz / (2 * (speed + 1));
---- /* handle all the modes */
---- if (spi->mode & SPI_CPOL)
---- bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
---- if (spi->mode & SPI_CPHA)
---- bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
---- BCM2835_AUX_SPI_CNTL0_CPHA_IN;
----
/* set transmit buffers and length */
bs->tx_buf = tfr->tx_buf;
bs->rx_buf = tfr->rx_buf;
return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
}
++++ static int bcm2835aux_spi_prepare_message(struct spi_master *master,
++++ struct spi_message *msg)
++++ {
++++ struct spi_device *spi = msg->spi;
++++ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
++++
++++ bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
++++ BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
++++ BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
++++ bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
++++
++++ /* handle all the modes */
++++ if (spi->mode & SPI_CPOL) {
++++ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
++++ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
++++ } else {
++++ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
++++ }
++++ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
++++ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
++++
++++ return 0;
++++ }
++++
++++ static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
++++ struct spi_message *msg)
++++ {
++++ struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
++++
++++ bcm2835aux_spi_reset_hw(bs);
++++
++++ return 0;
++++ }
++++
static void bcm2835aux_spi_handle_err(struct spi_master *master,
struct spi_message *msg)
{
}
platform_set_drvdata(pdev, master);
---- master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
++++ master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->num_chipselect = -1;
master->transfer_one = bcm2835aux_spi_transfer_one;
master->handle_err = bcm2835aux_spi_handle_err;
++++ master->prepare_message = bcm2835aux_spi_prepare_message;
++++ master->unprepare_message = bcm2835aux_spi_unprepare_message;
master->dev.of_node = pdev->dev.of_node;
bs = spi_master_get_devdata(master);
enum dma_data_direction dir)
{
const bool vmalloced_buf = is_vmalloc_addr(buf);
++++ unsigned int max_seg_size = dma_get_max_seg_size(dev);
int desc_len;
int sgs;
struct page *vm_page;
int i, ret;
if (vmalloced_buf) {
---- desc_len = PAGE_SIZE;
++++ desc_len = min_t(int, max_seg_size, PAGE_SIZE);
sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
} else {
---- desc_len = master->max_dma_len;
++++ desc_len = min_t(int, max_seg_size, master->max_dma_len);
sgs = DIV_ROUND_UP(len, desc_len);
}
sg_set_buf(&sgt->sgl[i], sg_buf, min);
}
----
buf += min;
len -= min;
}
}
}
++++ mutex_lock(&master->bus_lock_mutex);
trace_spi_message_start(master->cur_msg);
if (master->prepare_message) {
"failed to prepare message: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
++++ mutex_unlock(&master->bus_lock_mutex);
return;
}
master->cur_msg_prepared = true;
if (ret) {
master->cur_msg->status = ret;
spi_finalize_current_message(master);
++++ mutex_unlock(&master->bus_lock_mutex);
return;
}
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
++++ mutex_unlock(&master->bus_lock_mutex);
return;
}
++++ mutex_unlock(&master->bus_lock_mutex);
++++
++++ /* Prod the scheduler in case transfer_one() was busy waiting */
++++ cond_resched();
}
/**
static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
{
struct spi_device *spi = data;
+ +++ struct spi_master *master = spi->master;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
struct acpi_resource_spi_serialbus *sb;
sb = &ares->data.spi_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
- --- spi->chip_select = sb->device_selection;
+ +++ /*
+ +++ * ACPI DeviceSelection numbering is handled by the
+ +++ * host controller driver in Windows and can vary
+ +++ * from driver to driver. In Linux we always expect
+ +++ * 0 .. max - 1 so we need to ask the driver to
+ +++ * translate between the two schemes.
+ +++ */
+ +++ if (master->fw_translate_cs) {
+ +++ int cs = master->fw_translate_cs(master,
+ +++ sb->device_selection);
+ +++ if (cs < 0)
+ +++ return cs;
+ +++ spi->chip_select = cs;
+ +++ } else {
+ +++ spi->chip_select = sb->device_selection;
+ +++ }
+ +++
spi->max_speed_hz = sb->connection_speed;
if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
EXPORT_SYMBOL_GPL(spi_async_locked);
++++int spi_flash_read(struct spi_device *spi,
++++ struct spi_flash_read_message *msg)
++++
++++{
++++ struct spi_master *master = spi->master;
++++ int ret;
++++
++++ if ((msg->opcode_nbits == SPI_NBITS_DUAL ||
++++ msg->addr_nbits == SPI_NBITS_DUAL) &&
++++ !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD)))
++++ return -EINVAL;
++++ if ((msg->opcode_nbits == SPI_NBITS_QUAD ||
++++ msg->addr_nbits == SPI_NBITS_QUAD) &&
++++ !(spi->mode & SPI_TX_QUAD))
++++ return -EINVAL;
++++ if (msg->data_nbits == SPI_NBITS_DUAL &&
++++ !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD)))
++++ return -EINVAL;
++++ if (msg->data_nbits == SPI_NBITS_QUAD &&
++++ !(spi->mode & SPI_RX_QUAD))
++++ return -EINVAL;
++++
++++ if (master->auto_runtime_pm) {
++++ ret = pm_runtime_get_sync(master->dev.parent);
++++ if (ret < 0) {
++++ dev_err(&master->dev, "Failed to power device: %d\n",
++++ ret);
++++ return ret;
++++ }
++++ }
++++ mutex_lock(&master->bus_lock_mutex);
++++ ret = master->spi_flash_read(spi, msg);
++++ mutex_unlock(&master->bus_lock_mutex);
++++ if (master->auto_runtime_pm)
++++ pm_runtime_put(master->dev.parent);
++++
++++ return ret;
++++}
++++EXPORT_SYMBOL_GPL(spi_flash_read);
++++
/*-------------------------------------------------------------------------*/
/* Utility methods for SPI master protocol drivers, layered on
struct dma_chan;
struct spi_master;
struct spi_transfer;
++++struct spi_flash_read_message;
/*
* INTERFACES between SPI master-side drivers and SPI infrastructure.
* @handle_err: the subsystem calls the driver to handle an error that occurs
* in the generic implementation of transfer_one_message().
* @unprepare_message: undo any work done by prepare_message().
++++ * @spi_flash_read: to support spi-controller hardwares that provide
++++ * accelerated interface to read from flash devices.
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
* number. Any individual value may be -ENOENT for CS lines that
* are not GPIOs (driven by the SPI controller itself).
* @dma_rx: DMA receive channel
* @dummy_rx: dummy receive buffer for full-duplex devices
* @dummy_tx: dummy transmit buffer for full-duplex devices
+ +++ * @fw_translate_cs: If the boot firmware uses different numbering scheme
+ +++ * what Linux expects, this optional hook can be used to translate
+ +++ * between the two.
*
* Each SPI master controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals
struct spi_message *message);
int (*unprepare_message)(struct spi_master *master,
struct spi_message *message);
++++ int (*spi_flash_read)(struct spi_device *spi,
++++ struct spi_flash_read_message *msg);
/*
* These hooks are for drivers that use a generic implementation
/* dummy data for full duplex devices */
void *dummy_rx;
void *dummy_tx;
+ +++
+ +++ int (*fw_translate_cs)(struct spi_master *master, unsigned cs);
};
static inline void *spi_master_get_devdata(struct spi_master *master)
return be16_to_cpu(result);
}
++++/**
++++ * struct spi_flash_read_message - flash specific information for
++++ * spi-masters that provide accelerated flash read interfaces
++++ * @buf: buffer to read data
++++ * @from: offset within the flash from where data is to be read
++++ * @len: length of data to be read
++++ * @retlen: actual length of data read
++++ * @read_opcode: read_opcode to be used to communicate with flash
++++ * @addr_width: number of address bytes
++++ * @dummy_bytes: number of dummy bytes
++++ * @opcode_nbits: number of lines to send opcode
++++ * @addr_nbits: number of lines to send address
++++ * @data_nbits: number of lines for data
++++ */
++++struct spi_flash_read_message {
++++ void *buf;
++++ loff_t from;
++++ size_t len;
++++ size_t retlen;
++++ u8 read_opcode;
++++ u8 addr_width;
++++ u8 dummy_bytes;
++++ u8 opcode_nbits;
++++ u8 addr_nbits;
++++ u8 data_nbits;
++++};
++++
++++/* SPI core interface for flash read support */
++++static inline bool spi_flash_read_supported(struct spi_device *spi)
++++{
++++ return spi->master->spi_flash_read ? true : false;
++++}
++++
++++int spi_flash_read(struct spi_device *spi,
++++ struct spi_flash_read_message *msg);
++++
/*---------------------------------------------------------------------------*/
/*