uboot/drivers/spi/bcm63xx_hsspi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
   4 *
   5 * Derived from linux/drivers/spi/spi-bcm63xx-hsspi.c:
   6 *      Copyright (C) 2000-2010 Broadcom Corporation
   7 *      Copyright (C) 2012-2013 Jonas Gorski <jogo@openwrt.org>
   8 */
   9
  10#include <common.h>
  11#include <clk.h>
  12#include <dm.h>
  13#include <log.h>
  14#include <malloc.h>
  15#include <spi.h>
  16#include <reset.h>
  17#include <wait_bit.h>
  18#include <asm/io.h>
  19#include <linux/bitops.h>
  20
  21#define HSSPI_PP                        0
  22
  23#define SPI_MAX_SYNC_CLOCK              30000000
  24
  25/* SPI Control register */
  26#define SPI_CTL_REG                     0x000
  27#define SPI_CTL_CS_POL_SHIFT            0
  28#define SPI_CTL_CS_POL_MASK             (0xff << SPI_CTL_CS_POL_SHIFT)
  29#define SPI_CTL_CLK_GATE_SHIFT          16
  30#define SPI_CTL_CLK_GATE_MASK           (1 << SPI_CTL_CLK_GATE_SHIFT)
  31#define SPI_CTL_CLK_POL_SHIFT           17
  32#define SPI_CTL_CLK_POL_MASK            (1 << SPI_CTL_CLK_POL_SHIFT)
  33
  34/* SPI Interrupts registers */
  35#define SPI_IR_STAT_REG                 0x008
  36#define SPI_IR_ST_MASK_REG              0x00c
  37#define SPI_IR_MASK_REG                 0x010
  38
  39#define SPI_IR_CLEAR_ALL                0xff001f1f
  40
  41/* SPI Ping-Pong Command registers */
  42#define SPI_CMD_REG                     (0x080 + (0x40 * (HSSPI_PP)) + 0x00)
  43#define SPI_CMD_OP_SHIFT                0
  44#define SPI_CMD_OP_START                (0x1 << SPI_CMD_OP_SHIFT)
  45#define SPI_CMD_PFL_SHIFT               8
  46#define SPI_CMD_PFL_MASK                (0x7 << SPI_CMD_PFL_SHIFT)
  47#define SPI_CMD_SLAVE_SHIFT             12
  48#define SPI_CMD_SLAVE_MASK              (0x7 << SPI_CMD_SLAVE_SHIFT)
  49
  50/* SPI Ping-Pong Status registers */
  51#define SPI_STAT_REG                    (0x080 + (0x40 * (HSSPI_PP)) + 0x04)
  52#define SPI_STAT_SRCBUSY_SHIFT          1
  53#define SPI_STAT_SRCBUSY_MASK           (1 << SPI_STAT_SRCBUSY_SHIFT)
  54
  55/* SPI Profile Clock registers */
  56#define SPI_PFL_CLK_REG(x)              (0x100 + (0x20 * (x)) + 0x00)
  57#define SPI_PFL_CLK_FREQ_SHIFT          0
  58#define SPI_PFL_CLK_FREQ_MASK           (0x3fff << SPI_PFL_CLK_FREQ_SHIFT)
  59#define SPI_PFL_CLK_RSTLOOP_SHIFT       15
  60#define SPI_PFL_CLK_RSTLOOP_MASK        (1 << SPI_PFL_CLK_RSTLOOP_SHIFT)
  61
  62/* SPI Profile Signal registers */
  63#define SPI_PFL_SIG_REG(x)              (0x100 + (0x20 * (x)) + 0x04)
  64#define SPI_PFL_SIG_LATCHRIS_SHIFT      12
  65#define SPI_PFL_SIG_LATCHRIS_MASK       (1 << SPI_PFL_SIG_LATCHRIS_SHIFT)
  66#define SPI_PFL_SIG_LAUNCHRIS_SHIFT     13
  67#define SPI_PFL_SIG_LAUNCHRIS_MASK      (1 << SPI_PFL_SIG_LAUNCHRIS_SHIFT)
  68#define SPI_PFL_SIG_ASYNCIN_SHIFT       16
  69#define SPI_PFL_SIG_ASYNCIN_MASK        (1 << SPI_PFL_SIG_ASYNCIN_SHIFT)
  70
  71/* SPI Profile Mode registers */
  72#define SPI_PFL_MODE_REG(x)             (0x100 + (0x20 * (x)) + 0x08)
  73#define SPI_PFL_MODE_FILL_SHIFT         0
  74#define SPI_PFL_MODE_FILL_MASK          (0xff << SPI_PFL_MODE_FILL_SHIFT)
  75#define SPI_PFL_MODE_MDRDSZ_SHIFT       16
  76#define SPI_PFL_MODE_MDRDSZ_MASK        (1 << SPI_PFL_MODE_MDRDSZ_SHIFT)
  77#define SPI_PFL_MODE_MDWRSZ_SHIFT       18
  78#define SPI_PFL_MODE_MDWRSZ_MASK        (1 << SPI_PFL_MODE_MDWRSZ_SHIFT)
  79#define SPI_PFL_MODE_3WIRE_SHIFT        20
  80#define SPI_PFL_MODE_3WIRE_MASK         (1 << SPI_PFL_MODE_3WIRE_SHIFT)
  81
  82/* SPI Ping-Pong FIFO registers */
  83#define HSSPI_FIFO_SIZE                 0x200
  84#define HSSPI_FIFO_BASE                 (0x200 + \
  85                                         (HSSPI_FIFO_SIZE * HSSPI_PP))
  86
  87/* SPI Ping-Pong FIFO OP register */
  88#define HSSPI_FIFO_OP_SIZE              0x2
  89#define HSSPI_FIFO_OP_REG               (HSSPI_FIFO_BASE + 0x00)
  90#define HSSPI_FIFO_OP_BYTES_SHIFT       0
  91#define HSSPI_FIFO_OP_BYTES_MASK        (0x3ff << HSSPI_FIFO_OP_BYTES_SHIFT)
  92#define HSSPI_FIFO_OP_MBIT_SHIFT        11
  93#define HSSPI_FIFO_OP_MBIT_MASK         (1 << HSSPI_FIFO_OP_MBIT_SHIFT)
  94#define HSSPI_FIFO_OP_CODE_SHIFT        13
  95#define HSSPI_FIFO_OP_READ_WRITE        (1 << HSSPI_FIFO_OP_CODE_SHIFT)
  96#define HSSPI_FIFO_OP_CODE_W            (2 << HSSPI_FIFO_OP_CODE_SHIFT)
  97#define HSSPI_FIFO_OP_CODE_R            (3 << HSSPI_FIFO_OP_CODE_SHIFT)
  98
  99struct bcm63xx_hsspi_priv {
 100        void __iomem *regs;
 101        ulong clk_rate;
 102        uint8_t num_cs;
 103        uint8_t cs_pols;
 104        uint speed;
 105};
 106
 107static int bcm63xx_hsspi_cs_info(struct udevice *bus, uint cs,
 108                           struct spi_cs_info *info)
 109{
 110        struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus);
 111
 112        if (cs >= priv->num_cs) {
 113                printf("no cs %u\n", cs);
 114                return -EINVAL;
 115        }
 116
 117        return 0;
 118}
 119
 120static int bcm63xx_hsspi_set_mode(struct udevice *bus, uint mode)
 121{
 122        struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus);
 123
 124        /* clock polarity */
 125        if (mode & SPI_CPOL)
 126                setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
 127        else
 128                clrbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
 129
 130        return 0;
 131}
 132
 133static int bcm63xx_hsspi_set_speed(struct udevice *bus, uint speed)
 134{
 135        struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus);
 136
 137        priv->speed = speed;
 138
 139        return 0;
 140}
 141
 142static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv,
 143                                   struct dm_spi_slave_plat *plat)
 144{
 145        uint32_t clr, set;
 146
 147        /* profile clock */
 148        set = DIV_ROUND_UP(priv->clk_rate, priv->speed);
 149        set = DIV_ROUND_UP(2048, set);
 150        set &= SPI_PFL_CLK_FREQ_MASK;
 151        set |= SPI_PFL_CLK_RSTLOOP_MASK;
 152        writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs));
 153
 154        /* profile signal */
 155        set = 0;
 156        clr = SPI_PFL_SIG_LAUNCHRIS_MASK |
 157              SPI_PFL_SIG_LATCHRIS_MASK |
 158              SPI_PFL_SIG_ASYNCIN_MASK;
 159
 160        /* latch/launch config */
 161        if (plat->mode & SPI_CPHA)
 162                set |= SPI_PFL_SIG_LAUNCHRIS_MASK;
 163        else
 164                set |= SPI_PFL_SIG_LATCHRIS_MASK;
 165
 166        /* async clk */
 167        if (priv->speed > SPI_MAX_SYNC_CLOCK)
 168                set |= SPI_PFL_SIG_ASYNCIN_MASK;
 169
 170        clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set);
 171
 172        /* global control */
 173        set = 0;
 174        clr = 0;
 175
 176        /* invert cs polarity */
 177        if (priv->cs_pols & BIT(plat->cs))
 178                clr |= BIT(plat->cs);
 179        else
 180                set |= BIT(plat->cs);
 181
 182        /* invert dummy cs polarity */
 183        if (priv->cs_pols & BIT(!plat->cs))
 184                clr |= BIT(!plat->cs);
 185        else
 186                set |= BIT(!plat->cs);
 187
 188        clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set);
 189}
 190
 191static void bcm63xx_hsspi_deactivate_cs(struct bcm63xx_hsspi_priv *priv)
 192{
 193        /* restore cs polarities */
 194        clrsetbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CS_POL_MASK,
 195                        priv->cs_pols);
 196}
 197
 198/*
 199 * BCM63xx HSSPI driver doesn't allow keeping CS active between transfers
 200 * because they are controlled by HW.
 201 * However, it provides a mechanism to prepend write transfers prior to read
 202 * transfers (with a maximum prepend of 15 bytes), which is usually enough for
 203 * SPI-connected flashes since reading requires prepending a write transfer of
 204 * 5 bytes. On the other hand it also provides a way to invert each CS
 205 * polarity, not only between transfers like the older BCM63xx SPI driver, but
 206 * also the rest of the time.
 207 *
 208 * Instead of using the prepend mechanism, this implementation inverts the
 209 * polarity of both the desired CS and another dummy CS when the bus is
 210 * claimed. This way, the dummy CS is restored to its inactive value when
 211 * transfers are issued and the desired CS is preserved in its active value
 212 * all the time. This hack is also used in the upstream linux driver and
 213 * allows keeping CS active between trasnfers even if the HW doesn't give
 214 * this possibility.
 215 */
 216static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen,
 217                const void *dout, void *din, unsigned long flags)
 218{
 219        struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent);
 220        struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev);
 221        size_t data_bytes = bitlen / 8;
 222        size_t step_size = HSSPI_FIFO_SIZE;
 223        uint16_t opcode = 0;
 224        uint32_t val;
 225        const uint8_t *tx = dout;
 226        uint8_t *rx = din;
 227
 228        if (flags & SPI_XFER_BEGIN)
 229                bcm63xx_hsspi_activate_cs(priv, plat);
 230
 231        /* fifo operation */
 232        if (tx && rx)
 233                opcode = HSSPI_FIFO_OP_READ_WRITE;
 234        else if (rx)
 235                opcode = HSSPI_FIFO_OP_CODE_R;
 236        else if (tx)
 237                opcode = HSSPI_FIFO_OP_CODE_W;
 238
 239        if (opcode != HSSPI_FIFO_OP_CODE_R)
 240                step_size -= HSSPI_FIFO_OP_SIZE;
 241
 242        /* dual mode */
 243        if ((opcode == HSSPI_FIFO_OP_CODE_R && plat->mode == SPI_RX_DUAL) ||
 244            (opcode == HSSPI_FIFO_OP_CODE_W && plat->mode == SPI_TX_DUAL))
 245                opcode |= HSSPI_FIFO_OP_MBIT_MASK;
 246
 247        /* profile mode */
 248        val = SPI_PFL_MODE_FILL_MASK |
 249              SPI_PFL_MODE_MDRDSZ_MASK |
 250              SPI_PFL_MODE_MDWRSZ_MASK;
 251        if (plat->mode & SPI_3WIRE)
 252                val |= SPI_PFL_MODE_3WIRE_MASK;
 253        writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs));
 254
 255        /* transfer loop */
 256        while (data_bytes > 0) {
 257                size_t curr_step = min(step_size, data_bytes);
 258                int ret;
 259
 260                /* copy tx data */
 261                if (tx) {
 262                        memcpy_toio(priv->regs + HSSPI_FIFO_BASE +
 263                                    HSSPI_FIFO_OP_SIZE, tx, curr_step);
 264                        tx += curr_step;
 265                }
 266
 267                /* set fifo operation */
 268                writew(cpu_to_be16(opcode | (curr_step & HSSPI_FIFO_OP_BYTES_MASK)),
 269                          priv->regs + HSSPI_FIFO_OP_REG);
 270
 271                /* issue the transfer */
 272                val = SPI_CMD_OP_START;
 273                val |= (plat->cs << SPI_CMD_PFL_SHIFT) &
 274                       SPI_CMD_PFL_MASK;
 275                val |= (!plat->cs << SPI_CMD_SLAVE_SHIFT) &
 276                       SPI_CMD_SLAVE_MASK;
 277                writel(val, priv->regs + SPI_CMD_REG);
 278
 279                /* wait for completion */
 280                ret = wait_for_bit_32(priv->regs + SPI_STAT_REG,
 281                                        SPI_STAT_SRCBUSY_MASK, false,
 282                                        1000, false);
 283                if (ret) {
 284                        printf("interrupt timeout\n");
 285                        return ret;
 286                }
 287
 288                /* copy rx data */
 289                if (rx) {
 290                        memcpy_fromio(rx, priv->regs + HSSPI_FIFO_BASE,
 291                                      curr_step);
 292                        rx += curr_step;
 293                }
 294
 295                data_bytes -= curr_step;
 296        }
 297
 298        if (flags & SPI_XFER_END)
 299                bcm63xx_hsspi_deactivate_cs(priv);
 300
 301        return 0;
 302}
 303
 304static const struct dm_spi_ops bcm63xx_hsspi_ops = {
 305        .cs_info = bcm63xx_hsspi_cs_info,
 306        .set_mode = bcm63xx_hsspi_set_mode,
 307        .set_speed = bcm63xx_hsspi_set_speed,
 308        .xfer = bcm63xx_hsspi_xfer,
 309};
 310
 311static const struct udevice_id bcm63xx_hsspi_ids[] = {
 312        { .compatible = "brcm,bcm6328-hsspi", },
 313        { /* sentinel */ }
 314};
 315
 316static int bcm63xx_hsspi_child_pre_probe(struct udevice *dev)
 317{
 318        struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent);
 319        struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev);
 320
 321        /* check cs */
 322        if (plat->cs >= priv->num_cs) {
 323                printf("no cs %u\n", plat->cs);
 324                return -ENODEV;
 325        }
 326
 327        /* cs polarity */
 328        if (plat->mode & SPI_CS_HIGH)
 329                priv->cs_pols |= BIT(plat->cs);
 330        else
 331                priv->cs_pols &= ~BIT(plat->cs);
 332
 333        return 0;
 334}
 335
 336static int bcm63xx_hsspi_probe(struct udevice *dev)
 337{
 338        struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev);
 339        struct reset_ctl rst_ctl;
 340        struct clk clk;
 341        int ret;
 342
 343        priv->regs = dev_remap_addr(dev);
 344        if (!priv->regs)
 345                return -EINVAL;
 346
 347        priv->num_cs = dev_read_u32_default(dev, "num-cs", 8);
 348
 349        /* enable clock */
 350        ret = clk_get_by_name(dev, "hsspi", &clk);
 351        if (ret < 0)
 352                return ret;
 353
 354        ret = clk_enable(&clk);
 355        if (ret < 0 && ret != -ENOSYS)
 356                return ret;
 357
 358        ret = clk_free(&clk);
 359        if (ret < 0 && ret != -ENOSYS)
 360                return ret;
 361
 362        /* get clock rate */
 363        ret = clk_get_by_name(dev, "pll", &clk);
 364        if (ret < 0 && ret != -ENOSYS)
 365                return ret;
 366
 367        priv->clk_rate = clk_get_rate(&clk);
 368
 369        ret = clk_free(&clk);
 370        if (ret < 0 && ret != -ENOSYS)
 371                return ret;
 372
 373        /* perform reset */
 374        ret = reset_get_by_index(dev, 0, &rst_ctl);
 375        if (ret >= 0) {
 376                ret = reset_deassert(&rst_ctl);
 377                if (ret < 0)
 378                        return ret;
 379        }
 380
 381        ret = reset_free(&rst_ctl);
 382        if (ret < 0)
 383                return ret;
 384
 385        /* initialize hardware */
 386        writel(0, priv->regs + SPI_IR_MASK_REG);
 387
 388        /* clear pending interrupts */
 389        writel(SPI_IR_CLEAR_ALL, priv->regs + SPI_IR_STAT_REG);
 390
 391        /* enable clk gate */
 392        setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_GATE_MASK);
 393
 394        /* read default cs polarities */
 395        priv->cs_pols = readl(priv->regs + SPI_CTL_REG) &
 396                        SPI_CTL_CS_POL_MASK;
 397
 398        return 0;
 399}
 400
 401U_BOOT_DRIVER(bcm63xx_hsspi) = {
 402        .name = "bcm63xx_hsspi",
 403        .id = UCLASS_SPI,
 404        .of_match = bcm63xx_hsspi_ids,
 405        .ops = &bcm63xx_hsspi_ops,
 406        .priv_auto      = sizeof(struct bcm63xx_hsspi_priv),
 407        .child_pre_probe = bcm63xx_hsspi_child_pre_probe,
 408        .probe = bcm63xx_hsspi_probe,
 409};
 410