|
@@ -65,6 +65,7 @@
|
|
|
|
|
|
/* SPIDAT1 (upper 16 bit defines) */
|
|
|
#define SPIDAT1_CSHOLD_MASK BIT(12)
|
|
|
+#define SPIDAT1_WDEL BIT(10)
|
|
|
|
|
|
/* SPIGCR1 */
|
|
|
#define SPIGCR1_CLKMOD_MASK BIT(1)
|
|
@@ -209,6 +210,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
|
|
|
{
|
|
|
struct davinci_spi *dspi;
|
|
|
struct davinci_spi_platform_data *pdata;
|
|
|
+ struct davinci_spi_config *spicfg = spi->controller_data;
|
|
|
u8 chip_sel = spi->chip_select;
|
|
|
u16 spidat1 = CS_DEFAULT;
|
|
|
bool gpio_chipsel = false;
|
|
@@ -223,6 +225,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
|
|
|
gpio = spi->cs_gpio;
|
|
|
}
|
|
|
|
|
|
+ /* program delay transfers if tx_delay is non zero */
|
|
|
+ if (spicfg->wdelay)
|
|
|
+ spidat1 |= SPIDAT1_WDEL;
|
|
|
+
|
|
|
/*
|
|
|
* Board specific chip select logic decides the polarity and cs
|
|
|
* line for the controller
|
|
@@ -237,9 +243,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
|
|
|
spidat1 |= SPIDAT1_CSHOLD_MASK;
|
|
|
spidat1 &= ~(0x1 << chip_sel);
|
|
|
}
|
|
|
-
|
|
|
- iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
|
|
|
}
|
|
|
+
|
|
|
+ iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -285,7 +291,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
|
|
|
int prescale;
|
|
|
|
|
|
dspi = spi_master_get_devdata(spi->master);
|
|
|
- spicfg = (struct davinci_spi_config *)spi->controller_data;
|
|
|
+ spicfg = spi->controller_data;
|
|
|
if (!spicfg)
|
|
|
spicfg = &davinci_spi_default_cfg;
|
|
|
|
|
@@ -332,6 +338,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
|
|
|
if (!(spi->mode & SPI_CPHA))
|
|
|
spifmt |= SPIFMT_PHASE_MASK;
|
|
|
|
|
|
+ /*
|
|
|
+ * Assume wdelay is used only on SPI peripherals that has this field
|
|
|
+ * in SPIFMTn register and when it's configured from board file or DT.
|
|
|
+ */
|
|
|
+ if (spicfg->wdelay)
|
|
|
+ spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
|
|
|
+ & SPIFMT_WDELAY_MASK);
|
|
|
+
|
|
|
/*
|
|
|
* Version 1 hardware supports two basic SPI modes:
|
|
|
* - Standard SPI mode uses 4 pins, with chipselect
|
|
@@ -349,9 +363,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
|
|
|
|
|
|
u32 delay = 0;
|
|
|
|
|
|
- spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
|
|
|
- & SPIFMT_WDELAY_MASK);
|
|
|
-
|
|
|
if (spicfg->odd_parity)
|
|
|
spifmt |= SPIFMT_ODD_PARITY_MASK;
|
|
|
|
|
@@ -383,6 +394,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int davinci_spi_of_setup(struct spi_device *spi)
|
|
|
+{
|
|
|
+ struct davinci_spi_config *spicfg = spi->controller_data;
|
|
|
+ struct device_node *np = spi->dev.of_node;
|
|
|
+ u32 prop;
|
|
|
+
|
|
|
+ if (spicfg == NULL && np) {
|
|
|
+ spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL);
|
|
|
+ if (!spicfg)
|
|
|
+ return -ENOMEM;
|
|
|
+ *spicfg = davinci_spi_default_cfg;
|
|
|
+ /* override with dt configured values */
|
|
|
+ if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
|
|
|
+ spicfg->wdelay = (u8)prop;
|
|
|
+ spi->controller_data = spicfg;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* davinci_spi_setup - This functions will set default transfer method
|
|
|
* @spi: spi device on which data transfer to be done
|
|
@@ -433,7 +464,16 @@ static int davinci_spi_setup(struct spi_device *spi)
|
|
|
else
|
|
|
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
|
|
|
|
|
|
- return retval;
|
|
|
+ return davinci_spi_of_setup(spi);
|
|
|
+}
|
|
|
+
|
|
|
+static void davinci_spi_cleanup(struct spi_device *spi)
|
|
|
+{
|
|
|
+ struct davinci_spi_config *spicfg = spi->controller_data;
|
|
|
+
|
|
|
+ spi->controller_data = NULL;
|
|
|
+ if (spi->dev.of_node)
|
|
|
+ kfree(spicfg);
|
|
|
}
|
|
|
|
|
|
static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
|
|
@@ -947,6 +987,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
|
|
master->num_chipselect = pdata->num_chipselect;
|
|
|
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
|
|
|
master->setup = davinci_spi_setup;
|
|
|
+ master->cleanup = davinci_spi_cleanup;
|
|
|
|
|
|
dspi->bitbang.chipselect = davinci_spi_chipselect;
|
|
|
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
|