diff --git a/Documentation/devicetree/bindings/spi/spi-davinci.txt b/Documentation/devicetree/bindings/spi/spi-davinci.txt index 12ecfe9e3599..d1e914adcf6e 100644 --- a/Documentation/devicetree/bindings/spi/spi-davinci.txt +++ b/Documentation/devicetree/bindings/spi/spi-davinci.txt @@ -12,6 +12,8 @@ Required properties: - compatible: - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family + - "ti,keystone-spi" for SPI used similar to that on Keystone2 SoC + family - reg: Offset and length of SPI controller register space - num-cs: Number of chip selects. This includes internal as well as GPIO chip selects. diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index ddfdd820e6f2..29e08aac8294 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -1010,11 +1010,13 @@ static struct davinci_spi_platform_data da8xx_spi_pdata[] = { .version = SPI_VERSION_2, .intr_line = 1, .dma_event_q = EVENTQ_0, + .prescaler_limit = 2, }, [1] = { .version = SPI_VERSION_2, .intr_line = 1, .dma_event_q = EVENTQ_0, + .prescaler_limit = 2, }, }; diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 9cbeda798584..567dc56fe8cd 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -411,6 +411,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = { .num_chipselect = 2, .cshold_bug = true, .dma_event_q = EVENTQ_1, + .prescaler_limit = 1, }; static struct platform_device dm355_spi0_device = { .name = "spi_davinci", diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e3a3c54b6832..6a890a8486d0 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -646,6 +646,7 @@ static struct davinci_spi_platform_data dm365_spi0_pdata = { .version = SPI_VERSION_1, .num_chipselect = 2, .dma_event_q = EVENTQ_3, + .prescaler_limit = 1, }; static struct resource dm365_spi0_resources[] = { diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index c9eca347787d..bf9ed380bb1c 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index f5ca6dc3a157..55789f7cda92 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -76,6 +76,7 @@ #define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200) +#define HSSPI_OP_MULTIBIT BIT(11) #define HSSPI_OP_CODE_SHIFT 13 #define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT) #define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT) @@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) if (opcode != HSSPI_OP_READ) step_size -= HSSPI_OPCODE_LEN; - __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT | - 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT | - 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff, + if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) || + (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) + opcode |= HSSPI_OP_MULTIBIT; + + __raw_writel(1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT | + 1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT | 0xff, bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); while (pending > 0) { @@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) master->num_chipselect = 8; master->setup = bcm63xx_hsspi_setup; master->transfer_one_message = bcm63xx_hsspi_transfer_one; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | + SPI_RX_DUAL | SPI_TX_DUAL; master->bits_per_word_mask = SPI_BPW_MASK(8); master->auto_runtime_pm = true; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 987afebea093..3cf9faa6cc3f 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -139,6 +139,8 @@ struct davinci_spi { u32 (*get_tx)(struct davinci_spi *); u8 *bytes_per_word; + + u8 prescaler_limit; }; static struct davinci_spi_config davinci_spi_default_cfg; @@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * This function calculates the prescale value that generates a clock rate * less than or equal to the specified maximum. * - * Returns: calculated prescale - 1 for easy programming into SPI registers + * Returns: calculated prescale value for easy programming into SPI registers * or negative error number if valid prescalar cannot be updated. */ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, @@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, { int ret; - ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz); + /* Subtract 1 to match what will be programmed into SPI register. */ + ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1; - if (ret < 1 || ret > 256) + if (ret < dspi->prescaler_limit || ret > 255) return -EINVAL; - return ret - 1; + return ret; } /** @@ -832,13 +835,40 @@ rx_dma_failed: } #if defined(CONFIG_OF) + +/* OF SPI data structure */ +struct davinci_spi_of_data { + u8 version; + u8 prescaler_limit; +}; + +static const struct davinci_spi_of_data dm6441_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data da830_spi_data = { + .version = SPI_VERSION_2, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data keystone_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 0, +}; + static const struct of_device_id davinci_spi_of_match[] = { { .compatible = "ti,dm6441-spi", + .data = &dm6441_spi_data, }, { .compatible = "ti,da830-spi", - .data = (void *)SPI_VERSION_2, + .data = &da830_spi_data, + }, + { + .compatible = "ti,keystone-spi", + .data = &keystone_spi_data, }, { }, }; @@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, struct davinci_spi *dspi) { struct device_node *node = pdev->dev.of_node; + struct davinci_spi_of_data *spi_data; struct davinci_spi_platform_data *pdata; unsigned int num_cs, intr_line = 0; const struct of_device_id *match; pdata = &dspi->pdata; - pdata->version = SPI_VERSION_1; match = of_match_device(davinci_spi_of_match, &pdev->dev); if (!match) return -ENODEV; - /* match data has the SPI version number for SPI_VERSION_2 */ - if (match->data == (void *)SPI_VERSION_2) - pdata->version = SPI_VERSION_2; + spi_data = (struct davinci_spi_of_data *)match->data; + pdata->version = spi_data->version; + pdata->prescaler_limit = spi_data->prescaler_limit; /* * default num_cs is 1 and all chipsel are internal to the chip * indicated by chip_sel being NULL or cs_gpios being NULL or @@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; - + dspi->prescaler_limit = pdata->prescaler_limit; dspi->version = pdata->version; dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; diff --git a/include/linux/platform_data/spi-davinci.h b/include/linux/platform_data/spi-davinci.h index 8dc2fa47a2aa..f4edcb03c40c 100644 --- a/include/linux/platform_data/spi-davinci.h +++ b/include/linux/platform_data/spi-davinci.h @@ -49,6 +49,7 @@ struct davinci_spi_platform_data { u8 num_chipselect; u8 intr_line; u8 *chip_sel; + u8 prescaler_limit; bool cshold_bug; enum dma_event_q dma_event_q; };