Merge "spi: spi-geni-qcom: Allow clients to specify SPI slave parameters"
This commit is contained in:
commit
c9d621a420
2 changed files with 72 additions and 5 deletions
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/qcom-geni-se.h>
|
||||
#include <linux/msm_gpi.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-geni-qcom.h>
|
||||
|
||||
#define SPI_NUM_CHIPSELECT (4)
|
||||
#define SPI_XFER_TIMEOUT_MS (250)
|
||||
|
|
@ -67,6 +68,11 @@
|
|||
/* SPI_TX/SPI_RX_TRANS_LEN fields */
|
||||
#define TRANS_LEN_MSK (GENMASK(23, 0))
|
||||
|
||||
/* SE_SPI_DELAY_COUNTERS */
|
||||
#define SPI_INTER_WORDS_DELAY_MSK (GENMASK(9, 0))
|
||||
#define SPI_CS_CLK_DELAY_MSK (GENMASK(19, 10))
|
||||
#define SPI_CS_CLK_DELAY_SHFT (10)
|
||||
|
||||
/* M_CMD OP codes for SPI */
|
||||
#define SPI_TX_ONLY (1)
|
||||
#define SPI_RX_ONLY (2)
|
||||
|
|
@ -229,6 +235,8 @@ static int setup_fifo_params(struct spi_device *spi_slv,
|
|||
int ret = 0;
|
||||
int idx;
|
||||
int div;
|
||||
struct spi_geni_qcom_ctrl_data *delay_params = NULL;
|
||||
u32 spi_delay_params = 0;
|
||||
|
||||
loopback_cfg &= ~LOOPBACK_MSK;
|
||||
cpol &= ~CPOL;
|
||||
|
|
@ -246,6 +254,22 @@ static int setup_fifo_params(struct spi_device *spi_slv,
|
|||
if (spi_slv->mode & SPI_CS_HIGH)
|
||||
demux_output_inv |= BIT(spi_slv->chip_select);
|
||||
|
||||
if (spi_slv->controller_data) {
|
||||
u32 cs_clk_delay = 0;
|
||||
u32 inter_words_delay = 0;
|
||||
|
||||
delay_params =
|
||||
(struct spi_geni_qcom_ctrl_data *) spi_slv->controller_data;
|
||||
cs_clk_delay =
|
||||
(delay_params->spi_cs_clk_delay << SPI_CS_CLK_DELAY_SHFT)
|
||||
& SPI_CS_CLK_DELAY_MSK;
|
||||
inter_words_delay =
|
||||
delay_params->spi_inter_words_delay &
|
||||
SPI_INTER_WORDS_DELAY_MSK;
|
||||
spi_delay_params =
|
||||
(inter_words_delay | cs_clk_delay);
|
||||
}
|
||||
|
||||
demux_sel = spi_slv->chip_select;
|
||||
mas->cur_speed_hz = spi_slv->max_speed_hz;
|
||||
mas->cur_word_len = spi_slv->bits_per_word;
|
||||
|
|
@ -267,12 +291,13 @@ static int setup_fifo_params(struct spi_device *spi_slv,
|
|||
geni_write_reg(demux_output_inv, mas->base, SE_SPI_DEMUX_OUTPUT_INV);
|
||||
geni_write_reg(clk_sel, mas->base, SE_GENI_CLK_SEL);
|
||||
geni_write_reg(m_clk_cfg, mas->base, GENI_SER_M_CLK_CFG);
|
||||
geni_write_reg(spi_delay_params, mas->base, SE_SPI_DELAY_COUNTERS);
|
||||
GENI_SE_DBG(mas->ipc, false, mas->dev,
|
||||
"%s:Loopback%d demux_sel0x%x demux_op_inv 0x%x clk_cfg 0x%x\n",
|
||||
__func__, loopback_cfg, demux_sel, demux_output_inv, m_clk_cfg);
|
||||
GENI_SE_DBG(mas->ipc, false, mas->dev,
|
||||
"%s:clk_sel 0x%x cpol %d cpha %d\n", __func__,
|
||||
clk_sel, cpol, cpha);
|
||||
"%s:clk_sel 0x%x cpol %d cpha %d delay 0x%x\n", __func__,
|
||||
clk_sel, cpol, cpha, spi_delay_params);
|
||||
/* Ensure message level attributes are written before returning */
|
||||
mb();
|
||||
setup_fifo_params_exit:
|
||||
|
|
@ -306,7 +331,8 @@ static int select_xfer_mode(struct spi_master *spi,
|
|||
}
|
||||
|
||||
static struct msm_gpi_tre *setup_config0_tre(struct spi_transfer *xfer,
|
||||
struct spi_geni_master *mas, u16 mode)
|
||||
struct spi_geni_master *mas, u16 mode,
|
||||
u32 cs_clk_delay, u32 inter_words_delay)
|
||||
{
|
||||
struct msm_gpi_tre *c0_tre = &mas->gsi[mas->num_xfers].config0_tre;
|
||||
u8 flags = 0;
|
||||
|
|
@ -340,12 +366,16 @@ static struct msm_gpi_tre *setup_config0_tre(struct spi_transfer *xfer,
|
|||
}
|
||||
c0_tre->dword[0] = MSM_GPI_SPI_CONFIG0_TRE_DWORD0(pack, flags,
|
||||
word_len);
|
||||
c0_tre->dword[1] = MSM_GPI_SPI_CONFIG0_TRE_DWORD1(0, 0, 0);
|
||||
c0_tre->dword[1] = MSM_GPI_SPI_CONFIG0_TRE_DWORD1(0, cs_clk_delay,
|
||||
inter_words_delay);
|
||||
c0_tre->dword[2] = MSM_GPI_SPI_CONFIG0_TRE_DWORD2(idx, div);
|
||||
c0_tre->dword[3] = MSM_GPI_SPI_CONFIG0_TRE_DWORD3(0, 0, 0, 1);
|
||||
GENI_SE_DBG(mas->ipc, false, mas->dev,
|
||||
"%s: flags 0x%x word %d pack %d idx %d div %d\n",
|
||||
__func__, flags, word_len, pack, idx, div);
|
||||
GENI_SE_DBG(mas->ipc, false, mas->dev,
|
||||
"%s: cs_clk_delay %d inter_words_delay %d\n", __func__,
|
||||
cs_clk_delay, inter_words_delay);
|
||||
return c0_tre;
|
||||
}
|
||||
|
||||
|
|
@ -503,13 +533,27 @@ static int setup_gsi_xfer(struct spi_transfer *xfer,
|
|||
u32 rx_len = 0;
|
||||
int go_flags = 0;
|
||||
unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
|
||||
struct spi_geni_qcom_ctrl_data *delay_params = NULL;
|
||||
u32 cs_clk_delay = 0;
|
||||
u32 inter_words_delay = 0;
|
||||
|
||||
if (spi_slv->controller_data) {
|
||||
delay_params =
|
||||
(struct spi_geni_qcom_ctrl_data *) spi_slv->controller_data;
|
||||
|
||||
cs_clk_delay =
|
||||
delay_params->spi_cs_clk_delay;
|
||||
inter_words_delay =
|
||||
delay_params->spi_inter_words_delay;
|
||||
}
|
||||
|
||||
if ((xfer->bits_per_word != mas->cur_word_len) ||
|
||||
(xfer->speed_hz != mas->cur_speed_hz)) {
|
||||
mas->cur_word_len = xfer->bits_per_word;
|
||||
mas->cur_speed_hz = xfer->speed_hz;
|
||||
tx_nent++;
|
||||
c0_tre = setup_config0_tre(xfer, mas, spi_slv->mode);
|
||||
c0_tre = setup_config0_tre(xfer, mas, spi_slv->mode,
|
||||
cs_clk_delay, inter_words_delay);
|
||||
if (IS_ERR_OR_NULL(c0_tre)) {
|
||||
dev_err(mas->dev, "%s:Err setting c0tre:%d\n",
|
||||
__func__, ret);
|
||||
|
|
|
|||
23
include/linux/spi/spi-geni-qcom.h
Normal file
23
include/linux/spi/spi-geni-qcom.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPI_GENI_QCOM_HEADER___
|
||||
#define __SPI_GENI_QCOM_HEADER___
|
||||
|
||||
struct spi_geni_qcom_ctrl_data {
|
||||
u32 spi_cs_clk_delay;
|
||||
u32 spi_inter_words_delay;
|
||||
};
|
||||
|
||||
#endif /*__SPI_GENI_QCOM_HEADER___*/
|
||||
Loading…
Reference in a new issue