+ };
+ };
+
spi_ss0_pins: spi-ss0 {
mux {
groups = "spi_ss0";
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index 0bc7daa7afc8..d42171ee1d61 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/reset.h>
+#include <linux/pinctrl/consumer.h>
/*
* The Meson SPICC controller could support DMA based transfers, but is not
@@ -166,14 +167,31 @@ struct meson_spicc_device {
unsigned long tx_remain;
unsigned long rx_remain;
unsigned long xfer_remain;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_idle_high;
+ struct pinctrl_state *pins_idle_low;
};
static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
{
u32 conf;
- if (!spicc->data->has_oen)
+ if (!spicc->data->has_oen) {
+ /* Try to get pinctrl states for idle high/low */
+ spicc->pins_idle_high = pinctrl_lookup_state(spicc->pinctrl,
+ "idle-high");
+ if (IS_ERR(spicc->pins_idle_high)) {
+ dev_warn(&spicc->pdev->dev, "can't get idle-high pinctrl\n");
+ spicc->pins_idle_high = NULL;
+ }
+ spicc->pins_idle_low = pinctrl_lookup_state(spicc->pinctrl,
+ "idle-low");
+ if (IS_ERR(spicc->pins_idle_low)) {
+ dev_warn(&spicc->pdev->dev, "can't get idle-low pinctrl\n");
+ spicc->pins_idle_low = NULL;
+ }
return;
+ }
conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) |
SPICC_ENH_MOSI_OEN | SPICC_ENH_CLK_OEN | SPICC_ENH_CS_OEN;
@@ -438,6 +456,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
else
conf &= ~SPICC_POL;
+ if (!spicc->data->has_oen) {
+ if (spi->mode & SPI_CPOL) {
+ if (spicc->pins_idle_high)
+ pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_high);
+ } else {
+ if (spicc->pins_idle_low)
+ pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_low);
+ }
+ }
+
if (spi->mode & SPI_CPHA)
conf |= SPICC_PHA;
else
@@ -482,6 +510,9 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master)
device_reset_optional(&spicc->pdev->dev);
+ if (!spicc->data->has_oen)
+ pinctrl_select_default_state(&spicc->pdev->dev);
+
return 0;
}
@@ -733,6 +764,12 @@ static int meson_spicc_probe(struct platform_device *pdev)
goto out_core_clk;
}
+ spicc->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(spicc->pinctrl)) {
+ ret = PTR_ERR(spicc->pinctrl);
+ goto out_clk;
+ }
+
device_reset_optional(&pdev->dev);
master->num_chipselect = 4;