The fsl-dspi is found on Freescale Vybrid, Coldfire and Layerscape SoCs.
This adds the driver based on the Linux driver as of v5.5. Coldfire
support has been dropped as it's rather obsolete. Vybrid support has
been dropped because it needs the DMA engine support we do not have in
barebox. What's left is support for Layerscape where this driver has
been tested on.

Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de>
---
 drivers/spi/Kconfig        |   7 +
 drivers/spi/Makefile       |   1 +
 drivers/spi/spi-fsl-dspi.c | 655 +++++++++++++++++++++++++++++++++++++
 3 files changed, 663 insertions(+)
 create mode 100644 drivers/spi/spi-fsl-dspi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3758a0fad9..96235a1be2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -44,6 +44,13 @@ config DRIVER_SPI_FSL_QUADSPI
           This controller does not support generic SPI messages. It only
           supports the high-level SPI memory interface.
 
+config SPI_FSL_DSPI
+       bool "Freescale DSPI controller"
+       depends on ARCH_LAYERSCAPE
+       help
+         This enables support for the Freescale DSPI controller in master
+         mode. VF610, LS1021A and ColdFire platforms uses the controller.
+
 config DRIVER_SPI_GPIO
        bool "GPIO SPI Master driver"
        depends on GPIOLIB
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 75a89ef38e..908d514a01 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o
 obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o
 obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
 obj-$(CONFIG_DRIVER_SPI_ATMEL) += atmel_spi.o
+obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
 obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
 obj-$(CONFIG_DRIVER_SPI_OMAP3) += omap3_spi.o
 obj-$(CONFIG_DRIVER_SPI_DSPI) += dspi_spi.o
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
new file mode 100644
index 0000000000..a7ceb854e9
--- /dev/null
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
+//
+// Freescale DSPI driver
+// This file contains a driver for the Freescale DSPI
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <regmap.h>
+#include <spi/spi.h>
+#include <linux/clk.h>
+#include <linux/math64.h>
+
+#define DRIVER_NAME                    "fsl-dspi"
+
+#define DSPI_FIFO_SIZE                 4
+#define DSPI_DMA_BUFSIZE               (DSPI_FIFO_SIZE * 1024)
+
+#define SPI_MCR                                0x00
+#define SPI_MCR_MASTER                 BIT(31)
+#define SPI_MCR_PCSIS                  (0x3F << 16)
+#define SPI_MCR_CLR_TXF                        BIT(11)
+#define SPI_MCR_CLR_RXF                        BIT(10)
+#define SPI_MCR_XSPI                   BIT(3)
+
+#define SPI_TCR                                0x08
+#define SPI_TCR_GET_TCNT(x)            (((x) & GENMASK(31, 16)) >> 16)
+
+#define SPI_CTAR(x)                    (0x0c + (((x) & GENMASK(1, 0)) * 4))
+#define SPI_CTAR_FMSZ(x)               (((x) << 27) & GENMASK(30, 27))
+#define SPI_CTAR_CPOL                  BIT(26)
+#define SPI_CTAR_CPHA                  BIT(25)
+#define SPI_CTAR_LSBFE                 BIT(24)
+#define SPI_CTAR_PCSSCK(x)             (((x) << 22) & GENMASK(23, 22))
+#define SPI_CTAR_PASC(x)               (((x) << 20) & GENMASK(21, 20))
+#define SPI_CTAR_PDT(x)                        (((x) << 18) & GENMASK(19, 18))
+#define SPI_CTAR_PBR(x)                        (((x) << 16) & GENMASK(17, 16))
+#define SPI_CTAR_CSSCK(x)              (((x) << 12) & GENMASK(15, 12))
+#define SPI_CTAR_ASC(x)                        (((x) << 8) & GENMASK(11, 8))
+#define SPI_CTAR_DT(x)                 (((x) << 4) & GENMASK(7, 4))
+#define SPI_CTAR_BR(x)                 ((x) & GENMASK(3, 0))
+#define SPI_CTAR_SCALE_BITS            0xf
+
+#define SPI_CTAR0_SLAVE                        0x0c
+
+#define SPI_SR                         0x2c
+#define SPI_SR_TCFQF                   BIT(31)
+#define SPI_SR_EOQF                    BIT(28)
+#define SPI_SR_TFUF                    BIT(27)
+#define SPI_SR_TFFF                    BIT(25)
+#define SPI_SR_CMDTCF                  BIT(23)
+#define SPI_SR_SPEF                    BIT(21)
+#define SPI_SR_RFOF                    BIT(19)
+#define SPI_SR_TFIWF                   BIT(18)
+#define SPI_SR_RFDF                    BIT(17)
+#define SPI_SR_CMDFFF                  BIT(16)
+#define SPI_SR_CLEAR                   (SPI_SR_TCFQF | SPI_SR_EOQF | \
+                                       SPI_SR_TFUF | SPI_SR_TFFF | \
+                                       SPI_SR_CMDTCF | SPI_SR_SPEF | \
+                                       SPI_SR_RFOF | SPI_SR_TFIWF | \
+                                       SPI_SR_RFDF | SPI_SR_CMDFFF)
+
+#define SPI_RSER_TFFFE                 BIT(25)
+#define SPI_RSER_TFFFD                 BIT(24)
+#define SPI_RSER_RFDFE                 BIT(17)
+#define SPI_RSER_RFDFD                 BIT(16)
+
+#define SPI_RSER                       0x30
+#define SPI_RSER_TCFQE                 BIT(31)
+#define SPI_RSER_EOQFE                 BIT(28)
+
+#define SPI_PUSHR                      0x34
+#define SPI_PUSHR_CMD_CONT             BIT(15)
+#define SPI_PUSHR_CMD_CTAS(x)          (((x) << 12 & GENMASK(14, 12)))
+#define SPI_PUSHR_CMD_EOQ              BIT(11)
+#define SPI_PUSHR_CMD_CTCNT            BIT(10)
+#define SPI_PUSHR_CMD_PCS(x)           (BIT(x) & GENMASK(5, 0))
+
+#define SPI_PUSHR_SLAVE                        0x34
+
+#define SPI_POPR                       0x38
+
+#define SPI_TXFR0                      0x3c
+#define SPI_TXFR1                      0x40
+#define SPI_TXFR2                      0x44
+#define SPI_TXFR3                      0x48
+#define SPI_RXFR0                      0x7c
+#define SPI_RXFR1                      0x80
+#define SPI_RXFR2                      0x84
+#define SPI_RXFR3                      0x88
+
+#define SPI_CTARE(x)                   (0x11c + (((x) & GENMASK(1, 0)) * 4))
+#define SPI_CTARE_FMSZE(x)             (((x) & 0x1) << 16)
+#define SPI_CTARE_DTCP(x)              ((x) & 0x7ff)
+
+#define SPI_SREX                       0x13c
+
+#define SPI_FRAME_BITS(bits)           SPI_CTAR_FMSZ((bits) - 1)
+#define SPI_FRAME_EBITS(bits)          SPI_CTARE_FMSZE(((bits) - 1) >> 4)
+
+/* Register offsets for regmap_pushr */
+#define PUSHR_CMD                      0x0
+#define PUSHR_TX                       0x2
+
+#define DMA_COMPLETION_TIMEOUT         msecs_to_jiffies(3000)
+
+struct chip_data {
+       u32                     ctar_val;
+       u16                     void_write_data;
+};
+
+struct fsl_dspi_devtype_data {
+       u8                      max_clock_factor;
+       bool                    ptp_sts_supported;
+       bool                    xspi_mode;
+};
+
+static const struct fsl_dspi_devtype_data ls1021a_v1_data = {
+       .max_clock_factor       = 8,
+       .ptp_sts_supported      = true,
+       .xspi_mode              = true,
+};
+
+static const struct fsl_dspi_devtype_data ls2085a_data = {
+       .max_clock_factor       = 8,
+       .ptp_sts_supported      = true,
+};
+
+struct fsl_dspi {
+       struct spi_controller                   ctlr;
+       struct device_d                         *dev;
+
+       struct regmap                           *regmap;
+       struct regmap                           *regmap_pushr;
+       int                                     irq;
+       struct clk                              *clk;
+
+       struct spi_transfer                     *cur_transfer;
+       struct spi_message                      *cur_msg;
+       struct chip_data                        *cur_chip;
+       size_t                                  progress;
+       size_t                                  len;
+       const void                              *tx;
+       void                                    *rx;
+       void                                    *rx_end;
+       u16                                     void_write_data;
+       u16                                     tx_cmd;
+       u8                                      bits_per_word;
+       u8                                      bytes_per_word;
+       const struct fsl_dspi_devtype_data      *devtype_data;
+};
+
+static u32 dspi_pop_tx(struct fsl_dspi *dspi)
+{
+       u32 txdata = 0;
+
+       if (dspi->tx) {
+               if (dspi->bytes_per_word == 1)
+                       txdata = *(u8 *)dspi->tx;
+               else if (dspi->bytes_per_word == 2)
+                       txdata = *(u16 *)dspi->tx;
+               else  /* dspi->bytes_per_word == 4 */
+                       txdata = *(u32 *)dspi->tx;
+               dspi->tx += dspi->bytes_per_word;
+       }
+       dspi->len -= dspi->bytes_per_word;
+       return txdata;
+}
+
+static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
+{
+       u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
+
+       if (dspi->len > 0)
+               cmd |= SPI_PUSHR_CMD_CONT;
+       return cmd << 16 | data;
+}
+
+static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata)
+{
+       if (!dspi->rx)
+               return;
+
+       /* Mask off undefined bits */
+       rxdata &= (1 << dspi->bits_per_word) - 1;
+
+       if (dspi->bytes_per_word == 1)
+               *(u8 *)dspi->rx = rxdata;
+       else if (dspi->bytes_per_word == 2)
+               *(u16 *)dspi->rx = rxdata;
+       else /* dspi->bytes_per_word == 4 */
+               *(u32 *)dspi->rx = rxdata;
+       dspi->rx += dspi->bytes_per_word;
+}
+
+static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
+                          unsigned long clkrate)
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = { 2,      4,      6,      8,
+                       16,     32,     64,     128,
+                       256,    512,    1024,   2048,
+                       4096,   8192,   16384,  32768 };
+       int scale_needed, scale, minscale = INT_MAX;
+       int i, j;
+
+       scale_needed = clkrate / speed_hz;
+       if (clkrate % speed_hz)
+               scale_needed++;
+
+       for (i = 0; i < ARRAY_SIZE(brs); i++)
+               for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
+                       scale = brs[i] * pbr_tbl[j];
+                       if (scale >= scale_needed) {
+                               if (scale < minscale) {
+                                       minscale = scale;
+                                       *br = i;
+                                       *pbr = j;
+                               }
+                               break;
+                       }
+               }
+
+       if (minscale == INT_MAX) {
+               pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is 
%ld, we use the max prescaler value.\n",
+                       speed_hz, clkrate);
+               *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+               *br =  ARRAY_SIZE(brs) - 1;
+       }
+}
+
+static void ns_delay_scale(char *psc, char *sc, int delay_ns,
+                          unsigned long clkrate)
+{
+       int scale_needed, scale, minscale = INT_MAX;
+       int pscale_tbl[4] = {1, 3, 5, 7};
+       u32 remainder;
+       int i, j;
+
+       scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
+                                  &remainder);
+       if (remainder)
+               scale_needed++;
+
+       for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
+               for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
+                       scale = pscale_tbl[i] * (2 << j);
+                       if (scale >= scale_needed) {
+                               if (scale < minscale) {
+                                       minscale = scale;
+                                       *psc = i;
+                                       *sc = j;
+                               }
+                               break;
+                       }
+               }
+
+       if (minscale == INT_MAX) {
+               pr_warn("Cannot find correct scale values for %dns delay at 
clkrate %ld, using max prescaler value",
+                       delay_ns, clkrate);
+               *psc = ARRAY_SIZE(pscale_tbl) - 1;
+               *sc = SPI_CTAR_SCALE_BITS;
+       }
+}
+
+static void fifo_write(struct fsl_dspi *dspi)
+{
+       regmap_write(dspi->regmap, SPI_PUSHR, dspi_pop_tx_pushr(dspi));
+}
+
+static void cmd_fifo_write(struct fsl_dspi *dspi)
+{
+       u16 cmd = dspi->tx_cmd;
+
+       if (dspi->len > 0)
+               cmd |= SPI_PUSHR_CMD_CONT;
+       regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd);
+}
+
+static void tx_fifo_write(struct fsl_dspi *dspi, u16 txdata)
+{
+       regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata);
+}
+
+static void dspi_tcfq_write(struct fsl_dspi *dspi)
+{
+       /* Clear transfer count */
+       dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT;
+
+       if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) {
+               /* Write the CMD FIFO entry first, and then the two
+                * corresponding TX FIFO entries.
+                */
+               u32 data = dspi_pop_tx(dspi);
+
+               cmd_fifo_write(dspi);
+               tx_fifo_write(dspi, data & 0xFFFF);
+               tx_fifo_write(dspi, data >> 16);
+       } else {
+               /* Write one entry to both TX FIFO and CMD FIFO
+                * simultaneously.
+                */
+               fifo_write(dspi);
+       }
+}
+
+static u32 fifo_read(struct fsl_dspi *dspi)
+{
+       u32 rxdata = 0;
+
+       regmap_read(dspi->regmap, SPI_POPR, &rxdata);
+       return rxdata;
+}
+
+static void dspi_tcfq_read(struct fsl_dspi *dspi)
+{
+       dspi_push_rx(dspi, fifo_read(dspi));
+}
+
+static int dspi_rxtx(struct fsl_dspi *dspi)
+{
+       struct spi_message *msg = dspi->cur_msg;
+       u16 spi_tcnt;
+       u32 spi_tcr;
+
+       /* Get transfer counter (in number of SPI transfers). It was
+        * reset to 0 when transfer(s) were started.
+        */
+       regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
+       spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
+       /* Update total number of bytes that were transferred */
+       msg->actual_length += spi_tcnt * dspi->bytes_per_word;
+       dspi->progress += spi_tcnt;
+
+       dspi_tcfq_read(dspi);
+       if (!dspi->len)
+               /* Success! */
+               return 0;
+
+       dspi_tcfq_write(dspi);
+
+       return -EINPROGRESS;
+}
+
+static int dspi_poll(struct fsl_dspi *dspi)
+{
+       int tries = 1000;
+       u32 spi_sr;
+
+       do {
+               regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+               regmap_write(dspi->regmap, SPI_SR, spi_sr);
+
+               if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF))
+                       break;
+               udelay(1);
+       } while (--tries);
+
+       if (!tries)
+               return -ETIMEDOUT;
+
+       return dspi_rxtx(dspi);
+}
+
+static int dspi_transfer_one_message(struct spi_device *spi,
+                                    struct spi_message *message)
+{
+       struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, 
ctlr);
+       struct spi_transfer *transfer;
+       int status = 0;
+
+       message->actual_length = 0;
+
+       list_for_each_entry(transfer, &message->transfers, transfer_list) {
+               dspi->cur_transfer = transfer;
+               dspi->cur_msg = message;
+               dspi->cur_chip = spi->controller_data;
+               /* Prepare command word for CMD FIFO */
+               dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) |
+                              SPI_PUSHR_CMD_PCS(spi->chip_select);
+               if (list_is_last(&dspi->cur_transfer->transfer_list,
+                                &dspi->cur_msg->transfers)) {
+                       /* Leave PCS activated after last transfer when
+                        * cs_change is set.
+                        */
+                       if (transfer->cs_change)
+                               dspi->tx_cmd |= SPI_PUSHR_CMD_CONT;
+               } else {
+                       /* Keep PCS active between transfers in same message
+                        * when cs_change is not set, and de-activate PCS
+                        * between transfers in the same message when
+                        * cs_change is set.
+                        */
+                       if (!transfer->cs_change)
+                               dspi->tx_cmd |= SPI_PUSHR_CMD_CONT;
+               }
+
+               dspi->void_write_data = dspi->cur_chip->void_write_data;
+
+               dspi->tx = transfer->tx_buf;
+               dspi->rx = transfer->rx_buf;
+               dspi->rx_end = dspi->rx + transfer->len;
+               dspi->len = transfer->len;
+               dspi->progress = 0;
+               /* Validated transfer specific frame size (defaults applied) */
+               dspi->bits_per_word = transfer->bits_per_word;
+
+               if (transfer->bits_per_word <= 8)
+                       dspi->bytes_per_word = 1;
+               else if (transfer->bits_per_word <= 16)
+                       dspi->bytes_per_word = 2;
+               else
+                       dspi->bytes_per_word = 4;
+
+               regmap_update_bits(dspi->regmap, SPI_MCR,
+                                  SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
+                                  SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
+               regmap_write(dspi->regmap, SPI_CTAR(0),
+                            dspi->cur_chip->ctar_val |
+                            SPI_FRAME_BITS(transfer->bits_per_word));
+               if (dspi->devtype_data->xspi_mode)
+                       regmap_write(dspi->regmap, SPI_CTARE(0),
+                                    SPI_FRAME_EBITS(transfer->bits_per_word) |
+                                    SPI_CTARE_DTCP(1));
+
+               regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
+               dspi_tcfq_write(dspi);
+
+               do {
+                       status = dspi_poll(dspi);
+               } while (status == -EINPROGRESS);
+
+               if (status)
+                       dev_err(dspi->dev,
+                               "Waiting for transfer to complete failed!\n");
+       }
+
+       message->status = status;
+
+       return status;
+}
+
+static int dspi_setup(struct spi_device *spi)
+{
+       struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, 
ctlr);
+       unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
+       u32 cs_sck_delay = 0, sck_cs_delay = 0;
+       unsigned char pasc = 0, asc = 0;
+       struct chip_data *chip;
+       unsigned long clkrate;
+
+       /* Only alloc on first setup */
+       chip = spi->controller_data;
+       if (chip == NULL) {
+               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+               if (!chip)
+                       return -ENOMEM;
+       }
+
+       of_property_read_u32(spi->dev.device_node, "fsl,spi-cs-sck-delay",
+                            &cs_sck_delay);
+
+       of_property_read_u32(spi->dev.device_node, "fsl,spi-sck-cs-delay",
+                            &sck_cs_delay);
+
+       chip->void_write_data = 0;
+
+       clkrate = clk_get_rate(dspi->clk);
+       hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
+
+       /* Set PCS to SCK delay scale values */
+       ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
+
+       /* Set After SCK delay scale values */
+       ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
+
+       chip->ctar_val = 0;
+       if (spi->mode & SPI_CPOL)
+               chip->ctar_val |= SPI_CTAR_CPOL;
+       if (spi->mode & SPI_CPHA)
+               chip->ctar_val |= SPI_CTAR_CPHA;
+
+       chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) |
+                         SPI_CTAR_CSSCK(cssck) |
+                         SPI_CTAR_PASC(pasc) |
+                         SPI_CTAR_ASC(asc) |
+                         SPI_CTAR_PBR(pbr) |
+                         SPI_CTAR_BR(br);
+
+       if (spi->mode & SPI_LSB_FIRST)
+               chip->ctar_val |= SPI_CTAR_LSBFE;
+
+       spi->controller_data = chip;
+
+       return 0;
+}
+
+static void dspi_cleanup(struct spi_device *spi)
+{
+       struct chip_data *chip = spi->controller_data;
+
+       dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n",
+               spi->controller->bus_num, spi->chip_select);
+
+       kfree(chip);
+}
+
+static const struct of_device_id fsl_dspi_dt_ids[] = {
+       { .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, },
+       { .compatible = "fsl,ls2085a-dspi", .data = &ls2085a_data, },
+       { /* sentinel */ }
+};
+
+static const struct regmap_config dspi_regmap_config = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+       .max_register   = 0x88,
+};
+
+static const struct regmap_config dspi_xspi_regmap_config[] = {
+       {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .max_register   = 0x13c,
+       }, {
+               .name           = "pushr",
+               .reg_bits       = 16,
+               .val_bits       = 16,
+               .reg_stride     = 2,
+               .max_register   = 0x2,
+       },
+};
+
+static void dspi_init(struct fsl_dspi *dspi)
+{
+       unsigned int mcr = SPI_MCR_PCSIS;
+
+       if (dspi->devtype_data->xspi_mode)
+               mcr |= SPI_MCR_XSPI;
+       mcr |= SPI_MCR_MASTER;
+
+       regmap_write(dspi->regmap, SPI_MCR, mcr);
+       regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
+       if (dspi->devtype_data->xspi_mode)
+               regmap_write(dspi->regmap, SPI_CTARE(0),
+                            SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1));
+}
+
+static int dspi_probe(struct device_d *dev)
+{
+       struct device_node *np = dev->device_node;
+       const struct regmap_config *regmap_config;
+       struct spi_master *master;
+       int ret, cs_num, bus_num = -1;
+       struct fsl_dspi *dspi;
+       struct resource *res;
+       void __iomem *base;
+
+       dspi = xzalloc(sizeof(*dspi));
+
+       dspi->dev = dev;
+       master = &dspi->ctlr;
+
+       master->dev = dev;
+       master->setup = dspi_setup;
+       master->transfer = dspi_transfer_one_message;
+
+       master->cleanup = dspi_cleanup;
+
+       ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num);
+       if (ret < 0) {
+               dev_err(dev, "can't get spi-num-chipselects\n");
+               goto out_ctlr_put;
+       }
+       master->num_chipselect = cs_num;
+
+       of_property_read_u32(np, "bus-num", &bus_num);
+       master->bus_num = bus_num;
+
+       ret = dev_get_drvdata(dev, (const void **)&dspi->devtype_data);
+       if (ret)
+               return -ENODEV;
+
+       res = dev_request_mem_resource(dev, 0);
+       if (IS_ERR(res))
+               return PTR_ERR(res);
+
+       base = IOMEM(res->start);
+
+       if (dspi->devtype_data->xspi_mode)
+               regmap_config = &dspi_xspi_regmap_config[0];
+       else
+               regmap_config = &dspi_regmap_config;
+
+       dspi->regmap = regmap_init_mmio(dev, base, regmap_config);
+       if (IS_ERR(dspi->regmap)) {
+               dev_err(dev, "failed to init regmap: %ld\n",
+                               PTR_ERR(dspi->regmap));
+               ret = PTR_ERR(dspi->regmap);
+               goto out_ctlr_put;
+       }
+
+       if (dspi->devtype_data->xspi_mode) {
+               dspi->regmap_pushr = regmap_init_mmio(
+                       dev, base + SPI_PUSHR,
+                       &dspi_xspi_regmap_config[1]);
+               if (IS_ERR(dspi->regmap_pushr)) {
+                       dev_err(dev,
+                               "failed to init pushr regmap: %ld\n",
+                               PTR_ERR(dspi->regmap_pushr));
+                       ret = PTR_ERR(dspi->regmap_pushr);
+                       goto out_ctlr_put;
+               }
+       }
+
+       dspi->clk = clk_get(dev, "dspi");
+       if (IS_ERR(dspi->clk)) {
+               ret = PTR_ERR(dspi->clk);
+               dev_err(dev, "unable to get clock\n");
+               goto out_ctlr_put;
+       }
+       ret = clk_enable(dspi->clk);
+       if (ret)
+               goto out_ctlr_put;
+
+       dspi_init(dspi);
+
+       ret = spi_register_master(master);
+       if (ret != 0) {
+               dev_err(dev, "Problem registering DSPI ctlr\n");
+               goto out_clk_put;
+       }
+
+       return ret;
+
+out_clk_put:
+       clk_disable(dspi->clk);
+out_ctlr_put:
+
+       return ret;
+}
+
+static struct driver_d fsl_dspi_driver = {
+       .name  = "fsl-dspi",
+       .probe = dspi_probe,
+       .of_compatible = DRV_OF_COMPAT(fsl_dspi_dt_ids),
+};
+coredevice_platform_driver(fsl_dspi_driver);
-- 
2.26.0.rc2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to