spi: microchip core-qspi gpio-cs fixes + cleanup

Conor Dooley <conor@kernel.org> says:

v3 with the review comment about the core handing CS_HIGH dealt with.
I noticed that in the same function there was a "raw" BIT(1), which I
replaced with a macro that the patch was already adding for use in the
setup function...
This commit is contained in:
Mark Brown 2026-05-04 22:23:04 +09:00
commit 4b50e6cc2a
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -74,6 +74,13 @@
#define STATUS_FLAGSX4 BIT(8)
#define STATUS_MASK GENMASK(8, 0)
/*
* QSPI Direct Access register defines
*/
#define DIRECT_ACCESS_EN_SSEL BIT(0)
#define DIRECT_ACCESS_OP_SSEL BIT(1)
#define DIRECT_ACCESS_OP_SSEL_SHIFT 1
#define BYTESUPPER_MASK GENMASK(31, 16)
#define BYTESLOWER_MASK GENMASK(15, 0)
@ -158,7 +165,39 @@ static int mchp_coreqspi_set_mode(struct mchp_coreqspi *qspi, const struct spi_m
return 0;
}
static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_set_cs(struct spi_device *spi, bool enable)
{
struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
u32 val;
val = readl(qspi->regs + REG_DIRECT_ACCESS);
val &= ~DIRECT_ACCESS_OP_SSEL;
val |= !enable << DIRECT_ACCESS_OP_SSEL_SHIFT;
writel(val, qspi->regs + REG_DIRECT_ACCESS);
}
static int mchp_coreqspi_setup(struct spi_device *spi)
{
struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
u32 val;
/*
* Active low devices need to be specifically set to their inactive
* states during probe.
*/
if (spi->mode & SPI_CS_HIGH)
return 0;
val = readl(qspi->regs + REG_DIRECT_ACCESS);
val |= DIRECT_ACCESS_OP_SSEL;
writel(val, qspi->regs + REG_DIRECT_ACCESS);
return 0;
}
static void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
{
u32 control, data;
@ -194,7 +233,7 @@ static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
}
}
static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
{
u32 control, data;
@ -222,7 +261,7 @@ static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi)
}
}
static inline void mchp_coreqspi_write_read_op(struct mchp_coreqspi *qspi)
static void mchp_coreqspi_write_read_op(struct mchp_coreqspi *qspi)
{
u32 control, data;
@ -380,20 +419,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi
return 0;
}
static int mchp_coreqspi_setup_op(struct spi_device *spi_dev)
{
struct spi_controller *ctlr = spi_dev->controller;
struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
control |= (CONTROL_MASTER | CONTROL_ENABLE);
control &= ~CONTROL_CLKIDLE;
writel_relaxed(control, qspi->regs + REG_CONTROL);
return 0;
}
static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
static void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
{
u32 idle_cycles = 0;
int total_bytes, cmd_bytes, frames, ctrl;
@ -483,6 +509,7 @@ static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
reinit_completion(&qspi->data_completion);
mchp_coreqspi_config_op(qspi, op);
mchp_coreqspi_set_cs(mem->spi, true);
if (op->cmd.opcode) {
qspi->txbuf = &opcode;
qspi->rxbuf = NULL;
@ -523,6 +550,7 @@ static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
err = -ETIMEDOUT;
error:
mchp_coreqspi_set_cs(mem->spi, false);
mutex_unlock(&qspi->op_lock);
mchp_coreqspi_disable_ints(qspi);
@ -662,18 +690,28 @@ static int mchp_coreqspi_transfer_one(struct spi_controller *ctlr, struct spi_de
struct spi_transfer *t)
{
struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
bool dual_quad = false;
qspi->tx_len = t->len;
if (t->tx_nbits == SPI_NBITS_QUAD || t->rx_nbits == SPI_NBITS_QUAD ||
t->tx_nbits == SPI_NBITS_DUAL ||
t->rx_nbits == SPI_NBITS_DUAL)
dual_quad = true;
if (t->tx_buf)
qspi->txbuf = (u8 *)t->tx_buf;
if (!t->rx_buf) {
mchp_coreqspi_write_op(qspi);
} else {
} else if (!dual_quad) {
qspi->rxbuf = (u8 *)t->rx_buf;
qspi->rx_len = t->len;
mchp_coreqspi_write_read_op(qspi);
} else {
qspi->rxbuf = (u8 *)t->rx_buf;
qspi->rx_len = t->len;
mchp_coreqspi_read_op(qspi);
}
return 0;
@ -686,6 +724,7 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
u32 num_cs, val;
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*qspi));
if (!ctlr)
@ -718,10 +757,18 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
return ret;
}
/*
* The IP core only has a single CS, any more have to be provided via
* gpios
*/
if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs))
num_cs = 1;
ctlr->num_chipselect = num_cs;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->mem_ops = &mchp_coreqspi_mem_ops;
ctlr->mem_caps = &mchp_coreqspi_mem_caps;
ctlr->setup = mchp_coreqspi_setup_op;
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD;
ctlr->dev.of_node = np;
@ -729,9 +776,21 @@ static int mchp_coreqspi_probe(struct platform_device *pdev)
ctlr->prepare_message = mchp_coreqspi_prepare_message;
ctlr->unprepare_message = mchp_coreqspi_unprepare_message;
ctlr->transfer_one = mchp_coreqspi_transfer_one;
ctlr->num_chipselect = 2;
ctlr->setup = mchp_coreqspi_setup;
ctlr->set_cs = mchp_coreqspi_set_cs;
ctlr->use_gpio_descriptors = true;
val = readl_relaxed(qspi->regs + REG_CONTROL);
val |= (CONTROL_MASTER | CONTROL_ENABLE);
writel_relaxed(val, qspi->regs + REG_CONTROL);
/*
* Put cs into software controlled mode
*/
val = readl_relaxed(qspi->regs + REG_DIRECT_ACCESS);
val |= DIRECT_ACCESS_EN_SSEL;
writel(val, qspi->regs + REG_DIRECT_ACCESS);
ret = spi_register_controller(ctlr);
if (ret)
return dev_err_probe(&pdev->dev, ret,