mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
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:
commit
4b50e6cc2a
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user