Commit d74d9922 authored by Mark Brown's avatar Mark Brown

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
parents a26dee29 c58c7e9b
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment