S: Odd Fixes
-F: Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
+F: Documentation/devicetree/bindings/spi/brcm,bcm63xx-spi.yaml
F: drivers/spi/spi-bcm63xx.c
BROADCOM ETHERNET PHY DRIVERS
S: Maintained
F: Documentation/devicetree/bindings/sound/cirrus,cs*
+F: drivers/mfd/cs42l43*
+F: drivers/pinctrl/cirrus/pinctrl-cs42l43*
+F: drivers/spi/spi-cs42l43*
F: include/dt-bindings/sound/cs*
+F: include/linux/mfd/cs42l43*
F: include/sound/cs*
F: sound/pci/hda/cs*
F: sound/pci/hda/hda_cs_dsp_ctl.*
S: Maintained
F: drivers/gpio/gpio-regmap.c
F: include/linux/gpio/regmap.h
+ K: (devm_)?gpio_regmap_(un)?register
GPIO SUBSYSTEM
F: drivers/clk/clk-loongson2.c
F: include/dt-bindings/clock/loongson,ls2k-clk.h
+LOONGSON SPI DRIVER
+S: Maintained
+F: Documentation/devicetree/bindings/spi/loongson,ls2k-spi.yaml
+F: drivers/spi/spi-loongson-core.c
+F: drivers/spi/spi-loongson-pci.c
+F: drivers/spi/spi-loongson-plat.c
+F: drivers/spi/spi-loongson.h
+
LOONGSON-2 SOC SERIES GUTS DRIVER
F: net/netfilter/xt_SECMARK.c
F: net/netlabel/
+ NETWORKING [MACSEC]
+ S: Maintained
+ F: drivers/net/macsec.c
+ F: include/net/macsec.h
+ F: include/uapi/linux/if_macsec.h
+ K: macsec
+ K: \bmdo_
+
NETWORKING [MPTCP]
F: drivers/tty/serdev/
F: include/linux/serdev.h
- SERIAL DRIVERS
- S: Maintained
- F: Documentation/devicetree/bindings/serial/
- F: drivers/tty/serial/
-
SERIAL IR RECEIVER
F: Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
F: sound/soc/ti/
+ TEXAS INSTRUMENTS AUDIO (ASoC/HDA) DRIVERS
+ S: Maintained
+ F: Documentation/devicetree/bindings/sound/tas2552.txt
+ F: Documentation/devicetree/bindings/sound/tas2562.yaml
+ F: Documentation/devicetree/bindings/sound/tas2770.yaml
+ F: Documentation/devicetree/bindings/sound/tas27xx.yaml
+ F: Documentation/devicetree/bindings/sound/ti,pcm1681.txt
+ F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
+ F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml
+ F: Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
+ F: Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
+ F: Documentation/devicetree/bindings/sound/tpa6130a2.txt
+ F: include/sound/tas2*.h
+ F: include/sound/tlv320*.h
+ F: include/sound/tpa6130a2-plat.h
+ F: sound/pci/hda/tas2781_hda_i2c.c
+ F: sound/soc/codecs/pcm1681.c
+ F: sound/soc/codecs/pcm1789*.*
+ F: sound/soc/codecs/pcm179x*.*
+ F: sound/soc/codecs/pcm186x*.*
+ F: sound/soc/codecs/pcm3008.*
+ F: sound/soc/codecs/pcm3060*.*
+ F: sound/soc/codecs/pcm3168a*.*
+ F: sound/soc/codecs/pcm5102a.c
+ F: sound/soc/codecs/pcm512x*.*
+ F: sound/soc/codecs/tas2*.*
+ F: sound/soc/codecs/tlv320*.*
+ F: sound/soc/codecs/tpa6130a2.*
+
TEXAS INSTRUMENTS DMA DRIVERS
T: git git://github.com/srcres258/linux-doc.git doc-zh-tw
F: Documentation/translations/zh_TW/
- TTY LAYER
+ TTY LAYER AND SERIAL DRIVERS
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
+ F: Documentation/devicetree/bindings/serial/
F: Documentation/driver-api/serial/
F: drivers/tty/
- F: drivers/tty/serial/serial_base.h
- F: drivers/tty/serial/serial_base_bus.c
- F: drivers/tty/serial/serial_core.c
- F: drivers/tty/serial/serial_ctrl.c
- F: drivers/tty/serial/serial_port.c
F: include/linux/selection.h
F: include/linux/serial.h
F: include/linux/serial_core.h
S: Maintained
F: drivers/block/virtio_blk.c
F: drivers/scsi/virtio_scsi.c
- F: drivers/vhost/scsi.c
F: include/uapi/linux/virtio_blk.h
F: include/uapi/linux/virtio_scsi.h
F: include/uapi/linux/vhost.h
F: kernel/vhost_task.c
+ VIRTIO HOST (VHOST-SCSI)
+ S: Maintained
+ F: drivers/vhost/scsi.c
+
VIRTIO I2C DRIVER
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Cadence SPI controller driver (master and slave mode)
+ * Cadence SPI controller driver (host and target mode)
*
* Copyright (C) 2008 - 2014 Xilinx, Inc.
*
CDNS_SPI_CR_BAUD_DIV_4)
/*
- * SPI Configuration Register - Baud rate and slave select
+ * SPI Configuration Register - Baud rate and target select
*
* These are the values used in the calculation of baud rate divisor and
- * setting the slave select.
+ * setting the target select.
*/
#define CDNS_SPI_BAUD_DIV_MAX 7 /* Baud rate divisor maximum */
/**
* cdns_spi_init_hw - Initialize the hardware and configure the SPI controller
* @xspi: Pointer to the cdns_spi structure
- * @is_slave: Flag to indicate slave or master mode
- * * On reset the SPI controller is configured to slave or master mode.
- * In master mode baud rate divisor is set to 4, threshold value for TX FIFO
+ * @is_target: Flag to indicate target or host mode
+ * * On reset the SPI controller is configured to target or host mode.
+ * In host mode baud rate divisor is set to 4, threshold value for TX FIFO
* not full interrupt is set to 1 and size of the word to be transferred as 8 bit.
*
* This function initializes the SPI controller to disable and clear all the
- * interrupts, enable manual slave select and manual start, deselect all the
+ * interrupts, enable manual target select and manual start, deselect all the
* chip select lines, and enable the SPI controller.
*/
-static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_slave)
+static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_target)
{
u32 ctrl_reg = 0;
- if (!is_slave)
+ if (!is_target)
ctrl_reg |= CDNS_SPI_CR_DEFAULT;
if (xspi->is_decoded_cs)
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
if (is_high) {
- /* Deselect the slave */
+ /* Deselect the target */
ctrl_reg |= CDNS_SPI_CR_SSCTRL;
} else {
- /* Select the slave */
+ /* Select the target */
ctrl_reg &= ~CDNS_SPI_CR_SSCTRL;
if (!(xspi->is_decoded_cs))
ctrl_reg |= ((~(CDNS_SPI_SS0 << spi_get_chipselect(spi, 0))) <<
/*
* Just writing the CR register does not seem to apply the clock
* setting changes. This is problematic when changing the clock
- * polarity as it will cause the SPI slave to see spurious clock
+ * polarity as it will cause the SPI target to see spurious clock
* transitions. To workaround the issue toggle the ER register.
*/
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
xspi->rx_bytes -= nrx;
while (ntx || nrx) {
- /* When xspi in busy condition, bytes may send failed,
- * then spi control did't work thoroughly, add one byte delay
- */
- if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
- udelay(10);
-
if (ntx) {
if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
if (xspi->tx_bytes) {
cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
} else {
+ /* Fixed delay due to controller limitation with
+ * RX_NEMPTY incorrect status
+ * Xilinx AR:65885 contains more details
+ */
+ udelay(10);
cdns_spi_process_fifo(xspi, 0, trans_cnt);
cdns_spi_write(xspi, CDNS_SPI_IDR,
CDNS_SPI_IXR_DEFAULT);
static int cdns_prepare_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
- if (!spi_controller_is_slave(ctlr))
+ if (!spi_controller_is_target(ctlr))
cdns_spi_config_clock_mode(msg->spi);
return 0;
}
* @transfer: Pointer to the spi_transfer structure which provides
* information about next transfer parameters
*
- * This function in master mode fills the TX FIFO, starts the SPI transfer and
+ * This function in host mode fills the TX FIFO, starts the SPI transfer and
* returns a positive transfer count so that core will wait for completion.
- * This function in slave mode fills the TX FIFO and wait for transfer trigger.
+ * This function in target mode fills the TX FIFO and wait for transfer trigger.
*
* Return: Number of bytes transferred in the last transfer
*/
xspi->tx_bytes = transfer->len;
xspi->rx_bytes = transfer->len;
- if (!spi_controller_is_slave(ctlr)) {
+ if (!spi_controller_is_target(ctlr)) {
cdns_spi_setup_transfer(spi, transfer);
} else {
/* Set TX empty threshold to half of FIFO depth
- * only if TX bytes are more than half FIFO depth.
+ * only if TX bytes are more than FIFO depth.
*/
if (xspi->tx_bytes > xspi->tx_fifo_depth)
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}
+ /* When xspi in busy condition, bytes may send failed,
+ * then spi control didn't work thoroughly, add one byte delay
+ */
+ if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
+ udelay(10);
+
cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
spi_transfer_delay_exec(transfer);
* @ctlr: Pointer to the spi_controller structure which provides
* information about the controller.
*
- * This function enables SPI master controller.
+ * This function enables SPI host controller.
*
* Return: 0 always
*/
* @ctlr: Pointer to the spi_controller structure which provides
* information about the controller.
*
- * This function disables the SPI master controller when no slave selected.
+ * This function disables the SPI host controller when no target selected.
* This function flush out if any pending data in FIFO.
*
* Return: 0 always
u32 ctrl_reg;
unsigned int cnt = xspi->tx_fifo_depth;
- if (spi_controller_is_slave(ctlr)) {
+ if (spi_controller_is_target(ctlr)) {
while (cnt--)
cdns_spi_read(xspi, CDNS_SPI_RXD);
}
- /* Disable the SPI if slave is deselected */
+ /* Disable the SPI if target is deselected */
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
ctrl_reg = (ctrl_reg & CDNS_SPI_CR_SSCTRL) >> CDNS_SPI_SS_SHIFT;
- if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_slave(ctlr))
+ if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_target(ctlr))
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
/* Reset to default */
}
/**
- * cdns_slave_abort - Abort slave transfer
+ * cdns_target_abort - Abort target transfer
* @ctlr: Pointer to the spi_controller structure
*
- * This function abort slave transfer if there any transfer timeout.
+ * This function abort target transfer if there any transfer timeout.
*
* Return: 0 always
*/
-static int cdns_slave_abort(struct spi_controller *ctlr)
+static int cdns_target_abort(struct spi_controller *ctlr)
{
struct cdns_spi *xspi = spi_controller_get_devdata(ctlr);
u32 intr_status;
struct spi_controller *ctlr;
struct cdns_spi *xspi;
u32 num_cs;
- bool slave;
+ bool target;
- slave = of_property_read_bool(pdev->dev.of_node, "spi-slave");
- if (slave)
- ctlr = spi_alloc_slave(&pdev->dev, sizeof(*xspi));
+ target = of_property_read_bool(pdev->dev.of_node, "spi-slave");
+ if (target)
+ ctlr = spi_alloc_target(&pdev->dev, sizeof(*xspi));
else
- ctlr = spi_alloc_master(&pdev->dev, sizeof(*xspi));
+ ctlr = spi_alloc_host(&pdev->dev, sizeof(*xspi));
if (!ctlr)
return -ENOMEM;
goto remove_ctlr;
}
- if (!spi_controller_is_slave(ctlr)) {
+ if (!spi_controller_is_target(ctlr)) {
xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
if (IS_ERR(xspi->ref_clk)) {
dev_err(&pdev->dev, "ref_clk clock not found.\n");
cdns_spi_detect_fifo_depth(xspi);
/* SPI controller initializations */
- cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr));
+ cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr));
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- ret = -ENXIO;
+ if (irq < 0) {
+ ret = irq;
goto clk_dis_all;
}
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
- if (!spi_controller_is_slave(ctlr)) {
+ if (!spi_controller_is_target(ctlr)) {
ctlr->mode_bits |= SPI_CS_HIGH;
ctlr->set_cs = cdns_spi_chipselect;
ctlr->auto_runtime_pm = true;
pm_runtime_put_autosuspend(&pdev->dev);
} else {
ctlr->mode_bits |= SPI_NO_CS;
- ctlr->slave_abort = cdns_slave_abort;
+ ctlr->target_abort = cdns_target_abort;
}
ret = spi_register_controller(ctlr);
if (ret) {
return ret;
clk_dis_all:
- if (!spi_controller_is_slave(ctlr)) {
+ if (!spi_controller_is_target(ctlr)) {
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(xspi->ref_clk);
* This function is called if a device is physically removed from the system or
* if the driver module is being unloaded. It frees all resources allocated to
* the device.
- *
- * Return: 0 on success and error value on error
*/
static void cdns_spi_remove(struct platform_device *pdev)
{
struct spi_controller *ctlr = dev_get_drvdata(dev);
struct cdns_spi *xspi = spi_controller_get_devdata(ctlr);
- cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr));
+ cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr));
return spi_controller_resume(ctlr);
}
* @baud_rate_div_min: minimum baud rate divisor
* @baud_rate_div_max: maximum baud rate divisor
* @has_fifo: boolean to know if fifo is used for driver
+ * @has_device_mode: is this compatible capable to switch on device mode
* @flags: compatible specific SPI controller flags used at registration time
*/
struct stm32_spi_cfg {
unsigned int baud_rate_div_min;
unsigned int baud_rate_div_max;
bool has_fifo;
+ bool has_device_mode;
u16 flags;
};
if (spi->cfg->set_number_of_data) {
int ret;
- ret = spi_split_transfers_maxsize(ctrl, msg,
- STM32H7_SPI_TSIZE_MAX,
- GFP_KERNEL | GFP_DMA);
+ ret = spi_split_transfers_maxwords(ctrl, msg,
+ STM32H7_SPI_TSIZE_MAX,
+ GFP_KERNEL | GFP_DMA);
if (ret)
return ret;
}
.baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN,
.baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX,
.has_fifo = false,
- .flags = SPI_MASTER_MUST_TX,
+ .has_device_mode = false,
+ .flags = SPI_CONTROLLER_MUST_TX,
};
static const struct stm32_spi_cfg stm32h7_spi_cfg = {
.baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN,
.baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX,
.has_fifo = true,
+ .has_device_mode = true,
};
static const struct of_device_id stm32_spi_of_match[] = {
struct device_node *np = pdev->dev.of_node;
bool device_mode;
int ret;
+ const struct stm32_spi_cfg *cfg = of_device_get_match_data(&pdev->dev);
device_mode = of_property_read_bool(np, "spi-slave");
+ if (!cfg->has_device_mode && device_mode) {
+ dev_err(&pdev->dev, "spi-slave not supported\n");
+ return -EPERM;
+ }
if (device_mode)
ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi));
spi->device_mode = device_mode;
spin_lock_init(&spi->lock);
- spi->cfg = (const struct stm32_spi_cfg *)
- of_match_device(pdev->dev.driver->of_match_table,
- &pdev->dev)->data;
+ spi->cfg = cfg;
spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(spi->base))
spi->irq = platform_get_irq(pdev, 0);
if (spi->irq <= 0)
- return dev_err_probe(&pdev->dev, spi->irq,
- "failed to get irq\n");
+ return spi->irq;
ret = devm_request_threaded_irq(&pdev->dev, spi->irq,
spi->cfg->irq_handler_event,
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#define SUN6I_XMIT_CNT_REG 0x34
#define SUN6I_BURST_CTL_CNT_REG 0x38
+#define SUN6I_BURST_CTL_CNT_STC_MASK GENMASK(23, 0)
+#define SUN6I_BURST_CTL_CNT_DRM BIT(28)
+#define SUN6I_BURST_CTL_CNT_QUAD_EN BIT(29)
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
struct sun6i_spi_cfg {
unsigned long fifo_depth;
bool has_clk_ctl;
+ u32 mode_bits;
};
struct sun6i_spi {
struct reset_control *rstc;
struct completion done;
+ struct completion dma_rx_done;
const u8 *tx_buf;
u8 *rx_buf;
return SUN6I_MAX_XFER_SIZE - 1;
}
+ static void sun6i_spi_dma_rx_cb(void *param)
+ {
+ struct sun6i_spi *sspi = param;
+
+ complete(&sspi->dma_rx_done);
+ }
+
static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
struct spi_transfer *tfr)
{
struct dma_slave_config rxconf = {
.direction = DMA_DEV_TO_MEM,
.src_addr = sspi->dma_addr_rx,
- .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.src_maxburst = 8,
};
DMA_PREP_INTERRUPT);
if (!rxdesc)
return -EINVAL;
+ rxdesc->callback_param = sspi;
+ rxdesc->callback = sun6i_spi_dma_rx_cb;
}
txdesc = NULL;
unsigned int div, div_cdr1, div_cdr2, timeout;
unsigned int start, end, tx_time;
unsigned int trig_level;
- unsigned int tx_len = 0, rx_len = 0;
+ unsigned int tx_len = 0, rx_len = 0, nbits = 0;
bool use_dma;
int ret = 0;
u32 reg;
return -EINVAL;
reinit_completion(&sspi->done);
+ reinit_completion(&sspi->dma_rx_done);
sspi->tx_buf = tfr->tx_buf;
sspi->rx_buf = tfr->rx_buf;
sspi->len = tfr->len;
sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
/* Setup the transfer now... */
- if (sspi->tx_buf)
+ if (sspi->tx_buf) {
tx_len = tfr->len;
+ nbits = tfr->tx_nbits;
+ } else if (tfr->rx_buf) {
+ nbits = tfr->rx_nbits;
+ }
+
+ switch (nbits) {
+ case SPI_NBITS_DUAL:
+ reg = SUN6I_BURST_CTL_CNT_DRM;
+ break;
+ case SPI_NBITS_QUAD:
+ reg = SUN6I_BURST_CTL_CNT_QUAD_EN;
+ break;
+ case SPI_NBITS_SINGLE:
+ default:
+ reg = FIELD_PREP(SUN6I_BURST_CTL_CNT_STC_MASK, tx_len);
+ }
/* Setup the counters */
+ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg);
sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len);
sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
- sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len);
if (!use_dma) {
/* Fill the TX FIFO */
start = jiffies;
timeout = wait_for_completion_timeout(&sspi->done,
msecs_to_jiffies(tx_time));
+
+ if (!use_dma) {
+ sun6i_spi_drain_fifo(sspi);
+ } else {
+ if (timeout && rx_len) {
+ /*
+ * Even though RX on the peripheral side has finished
+ * RX DMA might still be in flight
+ */
+ timeout = wait_for_completion_timeout(&sspi->dma_rx_done,
+ timeout);
+ if (!timeout)
+ dev_warn(&master->dev, "RX DMA timeout\n");
+ }
+ }
+
end = jiffies;
if (!timeout) {
dev_warn(&master->dev,
/* Transfer complete */
if (status & SUN6I_INT_CTL_TC) {
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
- sun6i_spi_drain_fifo(sspi);
complete(&sspi->done);
return IRQ_HANDLED;
}
master->set_cs = sun6i_spi_set_cs;
master->transfer_one = sun6i_spi_transfer_one;
master->num_chipselect = 4;
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
+ sspi->cfg->mode_bits;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
}
init_completion(&sspi->done);
+ init_completion(&sspi->dma_rx_done);
sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(sspi->rstc)) {
static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
.fifo_depth = SUN8I_FIFO_DEPTH,
+ .mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD,
};
static const struct of_device_id sun6i_spi_match[] = {