Merge series "Support ROCKCHIP SPI new feature" from Jon Lin <jon.lin@rock-chips.com>:
Changes in v10: - The internal CS inactive function is only supported after VER 0x00110002 Changes in v9: - Conver to use CS GPIO description Changes in v8: - There is a problem with the version 7 mail format. resend it Changes in v7: - Fall back "rockchip,rv1126-spi" to "rockchip,rk3066-spi" Changes in v6: - Consider to compatibility, the "rockchip,rk3568-spi" is removed in Series-changes v5, so the commit massage should also remove the corresponding information Changes in v5: - Change to leave one compatible id rv1126, and rk3568 is compatible with rv1126 Changes in v4: - Adjust the order patches - Simply commit massage like redundancy "application" content Changes in v3: - Fix compile error which is find by Sascha in [v2,2/8] Jon Lin (6): dt-bindings: spi: spi-rockchip: add description for rv1126 spi: rockchip: add compatible string for rv1126 spi: rockchip: Set rx_fifo interrupt waterline base on transfer item spi: rockchip: Wait for STB status in slave mode tx_xfer spi: rockchip: Support cs-gpio spi: rockchip: Support SPI_CS_HIGH .../devicetree/bindings/spi/spi-rockchip.yaml | 1 + drivers/spi/spi-rockchip.c | 55 ++++++++++++++----- 2 files changed, 41 insertions(+), 15 deletions(-) -- 2.17.1
This commit is contained in:
commit
d74d99229f
|
@ -33,6 +33,7 @@ properties:
|
|||
- rockchip,rk3328-spi
|
||||
- rockchip,rk3368-spi
|
||||
- rockchip,rk3399-spi
|
||||
- rockchip,rv1126-spi
|
||||
- const: rockchip,rk3066-spi
|
||||
|
||||
reg:
|
||||
|
|
|
@ -107,6 +107,8 @@
|
|||
#define CR0_OPM_MASTER 0x0
|
||||
#define CR0_OPM_SLAVE 0x1
|
||||
|
||||
#define CR0_SOI_OFFSET 23
|
||||
|
||||
#define CR0_MTM_OFFSET 0x21
|
||||
|
||||
/* Bit fields in SER, 2bit */
|
||||
|
@ -116,13 +118,14 @@
|
|||
#define BAUDR_SCKDV_MIN 2
|
||||
#define BAUDR_SCKDV_MAX 65534
|
||||
|
||||
/* Bit fields in SR, 5bit */
|
||||
#define SR_MASK 0x1f
|
||||
/* Bit fields in SR, 6bit */
|
||||
#define SR_MASK 0x3f
|
||||
#define SR_BUSY (1 << 0)
|
||||
#define SR_TF_FULL (1 << 1)
|
||||
#define SR_TF_EMPTY (1 << 2)
|
||||
#define SR_RF_EMPTY (1 << 3)
|
||||
#define SR_RF_FULL (1 << 4)
|
||||
#define SR_SLAVE_TX_BUSY (1 << 5)
|
||||
|
||||
/* Bit fields in ISR, IMR, ISR, RISR, 5bit */
|
||||
#define INT_MASK 0x1f
|
||||
|
@ -156,7 +159,8 @@
|
|||
*/
|
||||
#define ROCKCHIP_SPI_MAX_TRANLEN 0xffff
|
||||
|
||||
#define ROCKCHIP_SPI_MAX_CS_NUM 2
|
||||
/* 2 for native cs, 2 for cs-gpio */
|
||||
#define ROCKCHIP_SPI_MAX_CS_NUM 4
|
||||
#define ROCKCHIP_SPI_VER2_TYPE1 0x05EC0002
|
||||
#define ROCKCHIP_SPI_VER2_TYPE2 0x00110002
|
||||
|
||||
|
@ -197,13 +201,19 @@ static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
|
|||
writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR);
|
||||
}
|
||||
|
||||
static inline void wait_for_idle(struct rockchip_spi *rs)
|
||||
static inline void wait_for_tx_idle(struct rockchip_spi *rs, bool slave_mode)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(5);
|
||||
|
||||
do {
|
||||
if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))
|
||||
return;
|
||||
if (slave_mode) {
|
||||
if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_SLAVE_TX_BUSY) &&
|
||||
!((readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY)))
|
||||
return;
|
||||
} else {
|
||||
if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))
|
||||
return;
|
||||
}
|
||||
} while (!time_after(jiffies, timeout));
|
||||
|
||||
dev_warn(rs->dev, "spi controller is in busy state!\n");
|
||||
|
@ -228,7 +238,7 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
|
|||
{
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
|
||||
bool cs_asserted = !enable;
|
||||
bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable;
|
||||
|
||||
/* Return immediately for no-op */
|
||||
if (cs_asserted == rs->cs_asserted[spi->chip_select])
|
||||
|
@ -238,11 +248,15 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
|
|||
/* Keep things powered as long as CS is asserted */
|
||||
pm_runtime_get_sync(rs->dev);
|
||||
|
||||
ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER,
|
||||
BIT(spi->chip_select));
|
||||
if (spi->cs_gpiod)
|
||||
ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, 1);
|
||||
else
|
||||
ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select));
|
||||
} else {
|
||||
ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER,
|
||||
BIT(spi->chip_select));
|
||||
if (spi->cs_gpiod)
|
||||
ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, 1);
|
||||
else
|
||||
ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select));
|
||||
|
||||
/* Drop reference from when we first asserted CS */
|
||||
pm_runtime_put(rs->dev);
|
||||
|
@ -383,7 +397,7 @@ static void rockchip_spi_dma_txcb(void *data)
|
|||
return;
|
||||
|
||||
/* Wait until the FIFO data completely. */
|
||||
wait_for_idle(rs);
|
||||
wait_for_tx_idle(rs, ctlr->slave);
|
||||
|
||||
spi_enable_chip(rs, false);
|
||||
spi_finalize_current_transfer(ctlr);
|
||||
|
@ -495,6 +509,8 @@ static int rockchip_spi_config(struct rockchip_spi *rs,
|
|||
cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
|
||||
if (spi->mode & SPI_LSB_FIRST)
|
||||
cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
|
||||
if (spi->mode & SPI_CS_HIGH)
|
||||
cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;
|
||||
|
||||
if (xfer->rx_buf && xfer->tx_buf)
|
||||
cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
|
||||
|
@ -540,12 +556,12 @@ static int rockchip_spi_config(struct rockchip_spi *rs,
|
|||
* interrupt exactly when the fifo is full doesn't seem to work,
|
||||
* so we need the strict inequality here
|
||||
*/
|
||||
if (xfer->len < rs->fifo_len)
|
||||
writel_relaxed(xfer->len - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
|
||||
if ((xfer->len / rs->n_bytes) < rs->fifo_len)
|
||||
writel_relaxed(xfer->len / rs->n_bytes - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
|
||||
else
|
||||
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
|
||||
|
||||
writel_relaxed(rs->fifo_len / 2, rs->regs + ROCKCHIP_SPI_DMATDLR);
|
||||
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);
|
||||
writel_relaxed(rockchip_spi_calc_burst_size(xfer->len / rs->n_bytes) - 1,
|
||||
rs->regs + ROCKCHIP_SPI_DMARDLR);
|
||||
writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
|
||||
|
@ -783,6 +799,14 @@ static int rockchip_spi_probe(struct platform_device *pdev)
|
|||
ctlr->can_dma = rockchip_spi_can_dma;
|
||||
}
|
||||
|
||||
switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) {
|
||||
case ROCKCHIP_SPI_VER2_TYPE2:
|
||||
ctlr->mode_bits |= SPI_CS_HIGH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, ctlr);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register controller\n");
|
||||
|
@ -922,6 +946,7 @@ static const struct of_device_id rockchip_spi_dt_match[] = {
|
|||
{ .compatible = "rockchip,rk3368-spi", },
|
||||
{ .compatible = "rockchip,rk3399-spi", },
|
||||
{ .compatible = "rockchip,rv1108-spi", },
|
||||
{ .compatible = "rockchip,rv1126-spi", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
|
||||
|
|
Loading…
Reference in New Issue