Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: axi-spi-engine: Add SPI_CS_HIGH support

The AXI SPI Engine IP core v1.2 added support for SPI_CS_HIGH. This
provides the driver implementation to make use of this feature when
supported hardware is detected.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://msgid.link/r/20240508-spi-axi-spi-engine-add-spi_cs_high-support-v1-1-695dd8e45f00@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

David Lechner and committed by
Mark Brown
6ecdb0aa f44b3730

+34
+34
drivers/spi/spi-axi-spi-engine.c
··· 46 46 #define SPI_ENGINE_INST_ASSERT 0x1 47 47 #define SPI_ENGINE_INST_WRITE 0x2 48 48 #define SPI_ENGINE_INST_MISC 0x3 49 + #define SPI_ENGINE_INST_CS_INV 0x4 49 50 50 51 #define SPI_ENGINE_CMD_REG_CLK_DIV 0x0 51 52 #define SPI_ENGINE_CMD_REG_CONFIG 0x1 ··· 74 73 SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay)) 75 74 #define SPI_ENGINE_CMD_SYNC(id) \ 76 75 SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id)) 76 + #define SPI_ENGINE_CMD_CS_INV(flags) \ 77 + SPI_ENGINE_CMD(SPI_ENGINE_INST_CS_INV, 0, (flags)) 77 78 78 79 struct spi_engine_program { 79 80 unsigned int length; ··· 114 111 struct spi_engine_message_state msg_state; 115 112 struct completion msg_complete; 116 113 unsigned int int_enable; 114 + /* shadows hardware CS inversion flag state */ 115 + u8 cs_inv; 117 116 }; 118 117 119 118 static void spi_engine_program_add_cmd(struct spi_engine_program *p, ··· 535 530 return 0; 536 531 } 537 532 533 + static int spi_engine_setup(struct spi_device *device) 534 + { 535 + struct spi_controller *host = device->controller; 536 + struct spi_engine *spi_engine = spi_controller_get_devdata(host); 537 + 538 + if (device->mode & SPI_CS_HIGH) 539 + spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0)); 540 + else 541 + spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0)); 542 + 543 + writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv), 544 + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); 545 + 546 + /* 547 + * In addition to setting the flags, we have to do a CS assert command 548 + * to make the new setting actually take effect. 549 + */ 550 + writel_relaxed(SPI_ENGINE_CMD_ASSERT(0, 0xff), 551 + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); 552 + 553 + return 0; 554 + } 555 + 538 556 static int spi_engine_transfer_one_message(struct spi_controller *host, 539 557 struct spi_message *msg) 540 558 { ··· 680 652 host->optimize_message = spi_engine_optimize_message; 681 653 host->unoptimize_message = spi_engine_unoptimize_message; 682 654 host->num_chipselect = 8; 655 + 656 + /* Some features depend of the IP core version. */ 657 + if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) { 658 + host->mode_bits |= SPI_CS_HIGH; 659 + host->setup = spi_engine_setup; 660 + } 683 661 684 662 if (host->max_speed_hz == 0) 685 663 return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0");