spi: spi-msm-geni: Add spi slave mode support to QUPv3

Propagate SPI slave change from 4.14 to 5.4.
'commit db7d4f6203927b ("spi: spi-geni-qcom: Add spi
slave mode support to QUPv3")'.

Change-Id: I353198be51525572d8916ebbaab66db8e797c245
Signed-off-by: Rama Krishna Phani A <rphani@codeaurora.org>
Signed-off-by: Ashish Kori <akori@codeaurora.org>
This commit is contained in:
Rama Krishna Phani A 2018-10-30 10:02:26 +05:30 • committed by Gerrit - the friendly Code Review server
commit 10386109e9
2 changed files with 109 additions and 11 deletions

View file

@ -35,6 +35,8 @@
#define SE_SPI_RX_TRANS_LEN (0x270)
#define SE_SPI_PRE_POST_CMD_DLY (0x274)
#define SE_SPI_DELAY_COUNTERS (0x278)
#define SE_SPI_SLAVE_EN (0x2BC)
#define SPI_SLAVE_EN BIT(0)
/* SE_SPI_CPHA register fields */
#define CPHA (BIT(0))
@ -169,8 +171,59 @@ struct spi_geni_master {
u32 miso_sampling_ctrl_val;
bool gpi_reset; /* GPI channel reset*/
bool disable_dma;
bool slave_setup;
bool slave_state;
};
static void spi_slv_setup(struct spi_geni_master *mas);
static ssize_t spi_slave_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
struct platform_device *pdev = container_of(dev, struct
platform_device, dev);
struct spi_master *spi = platform_get_drvdata(pdev);
struct spi_geni_master *geni_mas;
geni_mas = spi_master_get_devdata(spi);
if (geni_mas)
ret = scnprintf(buf, sizeof(int), "%d\n",
geni_mas->slave_state);
return ret;
}
static ssize_t spi_slave_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return 1;
}
static DEVICE_ATTR_RW(spi_slave_state);
static void spi_slv_setup(struct spi_geni_master *mas)
{
geni_write_reg(SPI_SLAVE_EN, mas->base, SE_SPI_SLAVE_EN);
geni_write_reg(1, mas->base, GENI_OUTPUT_CTRL);
geni_write_reg(START_TRIGGER, mas->base, SE_GENI_CFG_SEQ_START);
/* ensure data is written to hardware register */
wmb();
dev_info(mas->dev, "spi slave setup done\n");
}
static int spi_slv_abort(struct spi_master *spi)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
complete_all(&mas->tx_cb);
complete_all(&mas->rx_cb);
return 0;
}
static struct spi_master *get_spi_master(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@ -271,8 +324,10 @@ static int setup_fifo_params(struct spi_device *spi_slv,
if (mode & SPI_CPOL)
cpol |= CPOL;
if (mode & SPI_CPHA)
cpha |= CPHA;
if (!spi->slave) {
if (mode & SPI_CPHA)
cpha |= CPHA;
}
if (spi_slv->mode & SPI_CS_HIGH)
demux_output_inv |= BIT(spi_slv->chip_select);
@ -1059,10 +1114,28 @@ static int spi_geni_mas_setup(struct spi_master *spi)
int hw_ver;
int ret = 0;
if (unlikely(proto != SPI)) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
return -ENXIO;
if (spi->slave) {
if (mas->slave_setup)
goto setup_ipc;
proto = get_se_proto(mas->base);
if (unlikely(proto != SPI_SLAVE)) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
return -ENXIO;
}
}
if (unlikely(!mas->setup)) {
proto = get_se_proto(mas->base);
if ((unlikely(proto != SPI)) && (!spi->slave)) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
return -ENXIO;
}
if (spi->slave)
spi_slv_setup(mas);
}
geni_se_init(mas->base, 0x0, (mas->tx_fifo_depth - 2));
mas->tx_fifo_depth = get_tx_fifo_depth(mas->base);
mas->rx_fifo_depth = get_rx_fifo_depth(mas->base);
@ -1186,6 +1259,7 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
u32 max_speed = spi->cur_msg->spi->max_speed_hz;
struct se_geni_rsc *rsc = &mas->spi_rsc;
/* Adjust the IB based on the max speed of the slave in kHz.*/
rsc->ib = (max_speed * DEFAULT_BUS_WIDTH) / 1000;
@ -1316,7 +1390,9 @@ static int setup_fifo_xfer(struct spi_transfer *xfer,
else if (xfer->rx_buf)
m_cmd = SPI_RX_ONLY;
spi_tx_cfg &= ~CS_TOGGLE;
if (!spi->slave)
spi_tx_cfg &= ~CS_TOGGLE;
if (!(mas->cur_word_len % MIN_WORD_LEN)) {
trans_len =
((xfer->len << 3) / mas->cur_word_len) & TRANS_LEN_MSK;
@ -1356,7 +1432,8 @@ static int setup_fifo_xfer(struct spi_transfer *xfer,
mas->cur_xfer_mode = FIFO_MODE;
geni_se_select_mode(mas->base, mas->cur_xfer_mode);
geni_write_reg(spi_tx_cfg, mas->base, SE_SPI_TRANS_CFG);
if (!spi->slave)
geni_write_reg(spi_tx_cfg, mas->base, SE_SPI_TRANS_CFG);
geni_setup_m_cmd(mas->base, m_cmd, m_param);
GENI_SE_DBG(mas->ipc, false, mas->dev,
"%s: trans_len %d xferlen%d tx_cfg 0x%x cmd 0x%x cs%d mode%d\n",
@ -1488,8 +1565,13 @@ static int spi_geni_transfer_one(struct spi_master *spi,
goto err_fifo_geni_transfer_one;
}
if (spi->slave)
mas->slave_state = true;
timeout = wait_for_completion_timeout(&mas->xfer_done,
msecs_to_jiffies(SPI_XFER_TIMEOUT_MS));
if (spi->slave)
mas->slave_state = false;
if (!timeout) {
GENI_SE_ERR(mas->ipc, true, mas->dev,
"Xfer[len %d tx %pK rx %pK n %d] timed out.\n",
@ -1575,7 +1657,8 @@ err_gsi_geni_transfer_one:
}
return ret;
err_fifo_geni_transfer_one:
handle_fifo_timeout(mas, xfer);
if (!spi->slave)
handle_fifo_timeout(mas, xfer);
return ret;
}
@ -1763,7 +1846,7 @@ static int spi_geni_probe(struct platform_device *pdev)
struct resource *res;
struct platform_device *wrapper_pdev;
struct device_node *wrapper_ph_node;
bool rt_pri;
bool rt_pri, slave_en;
spi = spi_alloc_master(&pdev->dev, sizeof(struct spi_geni_master));
if (!spi) {
@ -1952,6 +2035,13 @@ static int spi_geni_probe(struct platform_device *pdev)
geni_mas->disable_dma = of_property_read_bool(pdev->dev.of_node,
"qcom,disable-dma");
slave_en = of_property_read_bool(pdev->dev.of_node,
"qcom,slv-ctrl");
if (slave_en) {
spi->slave = true;
spi->slave_abort = spi_slv_abort;
}
spi->mode_bits = (SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH);
spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
@ -1979,6 +2069,8 @@ static int spi_geni_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register SPI master\n");
goto spi_geni_probe_unmap;
}
ret = sysfs_create_file(&(geni_mas->dev->kobj),
&dev_attr_spi_slave_state.attr);
return ret;
spi_geni_probe_unmap:
devm_iounmap(&pdev->dev, geni_mas->base);
@ -1992,6 +2084,7 @@ static int spi_geni_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct spi_geni_master *geni_mas = spi_master_get_devdata(master);
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_spi_slave_state.attr);
se_geni_resources_off(&geni_mas->spi_rsc);
spi_unregister_master(master);
pm_runtime_put_noidle(&pdev->dev);

View file

@ -24,7 +24,8 @@ enum se_protocol_types {
SPI,
UART,
I2C,
I3C
I3C,
SPI_SLAVE
};
/**
@ -93,6 +94,8 @@ struct se_geni_rsc {
#define GENI_FW_REVISION_RO (0x68)
#define GENI_FW_S_REVISION_RO (0x6C)
#define SE_GENI_CLK_SEL (0x7C)
#define SE_GENI_CFG_SEQ_START (0x84)
#define SE_GENI_CFG_REG (0x200)
#define SE_GENI_BYTE_GRAN (0x254)
#define SE_GENI_DMA_MODE_EN (0x258)
#define SE_GENI_TX_PACKING_CFG0 (0x260)
@ -125,10 +128,12 @@ struct se_geni_rsc {
#define SE_HW_PARAM_1 (0xE28)
#define SE_DMA_GENERAL_CFG (0xE30)
#define SE_DMA_DEBUG_REG0 (0xE40)
#define SLAVE_MODE_EN (BIT(3))
#define START_TRIGGER (BIT(0))
#define QUPV3_HW_VER (0x4)
/* GENI_OUTPUT_CTRL fields */
#define DEFAULT_IO_OUTPUT_CTRL_MSK (GENMASK(6, 0))
#define DEFAULT_IO_OUTPUT_CTRL_MSK (GENMASK(6, 0))
/* GENI_FORCE_DEFAULT_REG fields */
#define FORCE_DEFAULT (BIT(0))