ODROID-C5: spi: Add support cs-gpios using gpiod
Signed-off-by: YoungSoo Shin <shinys000114@gmail.com>
Change-Id: Id2729ed05a0ebc696aef413a0517150846cbdff5
diff --git a/drivers/spi/spi-meson-spicc-v2.c b/drivers/spi/spi-meson-spicc-v2.c
index 4391057..781c86d 100644
--- a/drivers/spi/spi-meson-spicc-v2.c
+++ b/drivers/spi/spi-meson-spicc-v2.c
@@ -626,6 +626,59 @@
return IRQ_HANDLED;
}
+static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
+{
+ bool activate = enable;
+
+ /*
+ * Avoid calling into the driver (or doing delays) if the chip select
+ * isn't actually changing from the last time this was called.
+ */
+ if (!force && (spi->controller->last_cs_enable == enable) &&
+ (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH)))
+ return;
+
+ spi->controller->last_cs_enable = enable;
+ spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
+
+ if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
+ !spi->controller->set_cs_timing) && !activate) {
+ spi_delay_exec(&spi->cs_hold, NULL);
+ }
+
+ if (spi->mode & SPI_CS_HIGH)
+ enable = !enable;
+
+ if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
+ if (!(spi->mode & SPI_NO_CS)) {
+ if (spi->cs_gpiod) {
+ /* Polarity handled by GPIO library */
+ gpiod_set_value_cansleep(spi->cs_gpiod, activate);
+ } else {
+ /*
+ * invert the enable line, as active low is
+ * default for SPI.
+ */
+ gpio_set_value_cansleep(spi->cs_gpio, !enable);
+ }
+ }
+ /* Some SPI masters need both GPIO CS & slave_select */
+ if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
+ spi->controller->set_cs)
+ spi->controller->set_cs(spi, !enable);
+ } else if (spi->controller->set_cs) {
+ spi->controller->set_cs(spi, !enable);
+ }
+
+ if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
+ !spi->controller->set_cs_timing) {
+ if (activate)
+ spi_delay_exec(&spi->cs_setup, NULL);
+ else
+ spi_delay_exec(&spi->cs_inactive, NULL);
+ }
+}
+
/*
* spi_transfer_one_message - Default implementation of transfer_one_message()
*
@@ -647,6 +700,7 @@
int desc_num = 0, descs_len;
int ret = -EIO;
+ spi_set_cs(msg->spi, true, false);
if (!spicc_sem_down_read(spicc)) {
spi_finalize_current_message(ctlr);
dev_err(dev, "controller busy\n");
@@ -703,6 +757,7 @@
dma_unmap_single(dev, descs_paddr, descs_len, DMA_TO_DEVICE);
end:
+ spi_set_cs(msg->spi, false, false);
desc = descs;
exdesc = exdescs;
list_for_each_entry(xfer, &msg->transfers, transfer_list)
@@ -1245,6 +1300,7 @@
ctlr->slave_abort = meson_spicc_slave_abort;
ctlr->can_dma = meson_spicc_can_dma;
ctlr->max_dma_len = SPICC_BLOCK_MAX;
+ ctlr->use_gpio_descriptors = true;
dma_set_max_seg_size(&pdev->dev, SPICC_BLOCK_MAX);
ret = devm_spi_register_master(&pdev->dev, ctlr);
if (ret) {