uboot/drivers/spi/zynq_spi.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2013 Inc.
   3 *
   4 * Xilinx Zynq PS SPI controller driver (master mode only)
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <config.h>
  10#include <common.h>
  11#include <malloc.h>
  12#include <spi.h>
  13#include <asm/io.h>
  14#include <asm/arch/hardware.h>
  15
  16/* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */
  17#define ZYNQ_SPI_CR_MSA_MASK            (1 << 15)       /* Manual start enb */
  18#define ZYNQ_SPI_CR_MCS_MASK            (1 << 14)       /* Manual chip select */
  19#define ZYNQ_SPI_CR_CS_MASK             (0xF << 10)     /* Chip select */
  20#define ZYNQ_SPI_CR_BRD_MASK            (0x7 << 3)      /* Baud rate div */
  21#define ZYNQ_SPI_CR_CPHA_MASK           (1 << 2)        /* Clock phase */
  22#define ZYNQ_SPI_CR_CPOL_MASK           (1 << 1)        /* Clock polarity */
  23#define ZYNQ_SPI_CR_MSTREN_MASK         (1 << 0)        /* Mode select */
  24#define ZYNQ_SPI_IXR_RXNEMPTY_MASK      (1 << 4)        /* RX_FIFO_not_empty */
  25#define ZYNQ_SPI_IXR_TXOW_MASK          (1 << 2)        /* TX_FIFO_not_full */
  26#define ZYNQ_SPI_IXR_ALL_MASK           0x7F            /* All IXR bits */
  27#define ZYNQ_SPI_ENR_SPI_EN_MASK        (1 << 0)        /* SPI Enable */
  28
  29#define ZYNQ_SPI_FIFO_DEPTH             128
  30#ifndef CONFIG_SYS_ZYNQ_SPI_WAIT
  31#define CONFIG_SYS_ZYNQ_SPI_WAIT        (CONFIG_SYS_HZ/100)     /* 10 ms */
  32#endif
  33
  34/* zynq spi register set */
  35struct zynq_spi_regs {
  36        u32 cr;         /* 0x00 */
  37        u32 isr;        /* 0x04 */
  38        u32 ier;        /* 0x08 */
  39        u32 idr;        /* 0x0C */
  40        u32 imr;        /* 0x10 */
  41        u32 enr;        /* 0x14 */
  42        u32 dr;         /* 0x18 */
  43        u32 txdr;       /* 0x1C */
  44        u32 rxdr;       /* 0x20 */
  45};
  46
  47/* zynq spi slave */
  48struct zynq_spi_slave {
  49        struct spi_slave slave;
  50        struct zynq_spi_regs *base;
  51        u8 mode;
  52        u8 fifo_depth;
  53        u32 speed_hz;
  54        u32 input_hz;
  55        u32 req_hz;
  56};
  57
  58static inline struct zynq_spi_slave *to_zynq_spi_slave(struct spi_slave *slave)
  59{
  60        return container_of(slave, struct zynq_spi_slave, slave);
  61}
  62
  63static inline struct zynq_spi_regs *get_zynq_spi_base(int dev)
  64{
  65        if (dev)
  66                return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
  67        else
  68                return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
  69}
  70
  71static void zynq_spi_init_hw(struct zynq_spi_slave *zslave)
  72{
  73        u32 confr;
  74
  75        /* Disable SPI */
  76        writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
  77
  78        /* Disable Interrupts */
  79        writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr);
  80
  81        /* Clear RX FIFO */
  82        while (readl(&zslave->base->isr) &
  83                        ZYNQ_SPI_IXR_RXNEMPTY_MASK)
  84                readl(&zslave->base->rxdr);
  85
  86        /* Clear Interrupts */
  87        writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr);
  88
  89        /* Manual slave select and Auto start */
  90        confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK |
  91                ZYNQ_SPI_CR_MSTREN_MASK;
  92        confr &= ~ZYNQ_SPI_CR_MSA_MASK;
  93        writel(confr, &zslave->base->cr);
  94
  95        /* Enable SPI */
  96        writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
  97}
  98
  99int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 100{
 101        /* 2 bus with 3 chipselect */
 102        return bus < 2 && cs < 3;
 103}
 104
 105void spi_cs_activate(struct spi_slave *slave)
 106{
 107        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 108        u32 cr;
 109
 110        debug("spi_cs_activate: 0x%08x\n", (u32)slave);
 111
 112        clrbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
 113        cr = readl(&zslave->base->cr);
 114        /*
 115         * CS cal logic: CS[13:10]
 116         * xxx0 - cs0
 117         * xx01 - cs1
 118         * x011 - cs2
 119         */
 120        cr |= (~(0x1 << slave->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
 121        writel(cr, &zslave->base->cr);
 122}
 123
 124void spi_cs_deactivate(struct spi_slave *slave)
 125{
 126        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 127
 128        debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
 129
 130        setbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
 131}
 132
 133void spi_init()
 134{
 135        /* nothing to do */
 136}
 137
 138struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 139                unsigned int max_hz, unsigned int mode)
 140{
 141        struct zynq_spi_slave *zslave;
 142
 143        if (!spi_cs_is_valid(bus, cs))
 144                return NULL;
 145
 146        zslave = spi_alloc_slave(struct zynq_spi_slave, bus, cs);
 147        if (!zslave) {
 148                printf("SPI_error: Fail to allocate zynq_spi_slave\n");
 149                return NULL;
 150        }
 151
 152        zslave->base = get_zynq_spi_base(bus);
 153        zslave->mode = mode;
 154        zslave->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
 155        zslave->input_hz = 166666700;
 156        zslave->speed_hz = zslave->input_hz / 2;
 157        zslave->req_hz = max_hz;
 158
 159        /* init the zynq spi hw */
 160        zynq_spi_init_hw(zslave);
 161
 162        return &zslave->slave;
 163}
 164
 165void spi_free_slave(struct spi_slave *slave)
 166{
 167        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 168
 169        debug("spi_free_slave: 0x%08x\n", (u32)slave);
 170        free(zslave);
 171}
 172
 173int spi_claim_bus(struct spi_slave *slave)
 174{
 175        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 176        u32 confr = 0;
 177        u8 baud_rate_val = 0;
 178
 179        writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
 180
 181        /* Set the SPI Clock phase and polarities */
 182        confr = readl(&zslave->base->cr);
 183        confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
 184        if (zslave->mode & SPI_CPHA)
 185                confr |= ZYNQ_SPI_CR_CPHA_MASK;
 186        if (zslave->mode & SPI_CPOL)
 187                confr |= ZYNQ_SPI_CR_CPOL_MASK;
 188
 189        /* Set the clock frequency */
 190        if (zslave->req_hz == 0) {
 191                /* Set baudrate x8, if the req_hz is 0 */
 192                baud_rate_val = 0x2;
 193        } else if (zslave->speed_hz != zslave->req_hz) {
 194                while ((baud_rate_val < 8) &&
 195                                ((zslave->input_hz /
 196                                (2 << baud_rate_val)) > zslave->req_hz))
 197                        baud_rate_val++;
 198                zslave->speed_hz = zslave->req_hz / (2 << baud_rate_val);
 199        }
 200        confr &= ~ZYNQ_SPI_CR_BRD_MASK;
 201        confr |= (baud_rate_val << 3);
 202        writel(confr, &zslave->base->cr);
 203
 204        writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
 205
 206        return 0;
 207}
 208
 209void spi_release_bus(struct spi_slave *slave)
 210{
 211        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 212
 213        debug("spi_release_bus: 0x%08x\n", (u32)slave);
 214        writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
 215}
 216
 217int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 218                void *din, unsigned long flags)
 219{
 220        struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
 221        u32 len = bitlen / 8;
 222        u32 tx_len = len, rx_len = len, tx_tvl;
 223        const u8 *tx_buf = dout;
 224        u8 *rx_buf = din, buf;
 225        u32 ts, status;
 226
 227        debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
 228              slave->bus, slave->cs, bitlen, len, flags);
 229
 230        if (bitlen == 0)
 231                return -1;
 232
 233        if (bitlen % 8) {
 234                debug("spi_xfer: Non byte aligned SPI transfer\n");
 235                return -1;
 236        }
 237
 238        if (flags & SPI_XFER_BEGIN)
 239                spi_cs_activate(slave);
 240
 241        while (rx_len > 0) {
 242                /* Write the data into TX FIFO - tx threshold is fifo_depth */
 243                tx_tvl = 0;
 244                while ((tx_tvl < zslave->fifo_depth) && tx_len) {
 245                        if (tx_buf)
 246                                buf = *tx_buf++;
 247                        else
 248                                buf = 0;
 249                        writel(buf, &zslave->base->txdr);
 250                        tx_len--;
 251                        tx_tvl++;
 252                }
 253
 254                /* Check TX FIFO completion */
 255                ts = get_timer(0);
 256                status = readl(&zslave->base->isr);
 257                while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
 258                        if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
 259                                printf("spi_xfer: Timeout! TX FIFO not full\n");
 260                                return -1;
 261                        }
 262                        status = readl(&zslave->base->isr);
 263                }
 264
 265                /* Read the data from RX FIFO */
 266                status = readl(&zslave->base->isr);
 267                while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
 268                        buf = readl(&zslave->base->rxdr);
 269                        if (rx_buf)
 270                                *rx_buf++ = buf;
 271                        status = readl(&zslave->base->isr);
 272                        rx_len--;
 273                }
 274        }
 275
 276        if (flags & SPI_XFER_END)
 277                spi_cs_deactivate(slave);
 278
 279        return 0;
 280}
 281