Skip to content

Commit

Permalink
spi: bcm63xx-hsspi: Handle cs_change correctly
Browse files Browse the repository at this point in the history
The kernel SPI interface includes the cs_change flag that alters how
the CS behaves.

If we're in the middle of transfers, it tells us to unselect the
CS momentarily since the target device requires that.

If we're at the end of a transfer, it tells us to keep the CS
selected, perhaps because the next transfer is likely targeted
to the same device.

We implement this scheme in the HSSPI driver in this change.

Prior to this change, the CS would toggle momentarily if cs_change
was set for the last transfer. This can be ignored by some or
most devices, but the Microchip TPM2 device does not ignore it.

With the change, the behavior is corrected and the 'glitch' is
eliminated.

Signed-off-by: Kursad Oney <kursad.oney@broadcom.com>
Signed-off-by: William Zhang <william.zhang@broadcom.com>
Link: https://lore.kernel.org/r/20230209200246.141520-10-william.zhang@broadcom.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
William Zhang authored and Mark Brown committed Feb 10, 2023
1 parent 6e80133 commit c00d5e9
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions drivers/spi/spi-bcm63xx-hsspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
unsigned long limit;

bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
if (!t->cs_off)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);

if (tx && rx)
opcode = HSSPI_OP_READ_WRITE;
Expand Down Expand Up @@ -338,7 +339,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
struct spi_device *spi = msg->spi;
int status = -EINVAL;
int dummy_cs;
u32 reg;
bool keep_cs = false;

mutex_lock(&bs->msg_mutex);
/* This controller does not support keeping CS active during idle.
Expand Down Expand Up @@ -367,16 +368,28 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master,

spi_transfer_delay_exec(t);

if (t->cs_change)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
/* use existing cs change logic from spi_transfer_one_message */
if (t->cs_change) {
if (list_is_last(&t->transfer_list, &msg->transfers)) {
keep_cs = true;
} else {
if (!t->cs_off)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);

spi_transfer_cs_change_delay_exec(msg, t);

if (!list_next_entry(t, transfer_list)->cs_off)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
}
} else if (!list_is_last(&t->transfer_list, &msg->transfers) &&
t->cs_off != list_next_entry(t, transfer_list)->cs_off) {
bcm63xx_hsspi_set_cs(bs, spi->chip_select, t->cs_off);
}
}

mutex_lock(&bs->bus_mutex);
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK;
reg |= bs->cs_polarity;
__raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
mutex_unlock(&bs->bus_mutex);
bcm63xx_hsspi_set_cs(bs, dummy_cs, false);
if (status || !keep_cs)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);

mutex_unlock(&bs->msg_mutex);
msg->status = status;
Expand Down

0 comments on commit c00d5e9

Please sign in to comment.