uboot/drivers/spi/ath79_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
   4 */
   5
   6#include <common.h>
   7#include <spi.h>
   8#include <dm.h>
   9#include <div64.h>
  10#include <errno.h>
  11#include <asm/io.h>
  12#include <asm/addrspace.h>
  13#include <asm/types.h>
  14#include <dm/pinctrl.h>
  15#include <mach/ar71xx_regs.h>
  16
  17/* CLOCK_DIVIDER = 3 (SPI clock = 200 / 8 ~ 25 MHz) */
  18#define ATH79_SPI_CLK_DIV(x)           (((x) >> 1) - 1)
  19#define ATH79_SPI_RRW_DELAY_FACTOR     12000
  20#define ATH79_SPI_MHZ                  (1000 * 1000)
  21
  22struct ath79_spi_priv {
  23        void __iomem *regs;
  24        u32 rrw_delay;
  25};
  26
  27static void spi_cs_activate(struct udevice *dev)
  28{
  29        struct udevice *bus = dev_get_parent(dev);
  30        struct ath79_spi_priv *priv = dev_get_priv(bus);
  31
  32        writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS);
  33        writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC);
  34}
  35
  36static void spi_cs_deactivate(struct udevice *dev)
  37{
  38        struct udevice *bus = dev_get_parent(dev);
  39        struct ath79_spi_priv *priv = dev_get_priv(bus);
  40
  41        writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC);
  42        writel(0, priv->regs + AR71XX_SPI_REG_FS);
  43}
  44
  45static int ath79_spi_claim_bus(struct udevice *dev)
  46{
  47        return 0;
  48}
  49
  50static int ath79_spi_release_bus(struct udevice *dev)
  51{
  52        return 0;
  53}
  54
  55static int ath79_spi_xfer(struct udevice *dev, unsigned int bitlen,
  56                const void *dout, void *din, unsigned long flags)
  57{
  58        struct udevice *bus = dev_get_parent(dev);
  59        struct ath79_spi_priv *priv = dev_get_priv(bus);
  60        struct dm_spi_slave_platdata *slave = dev_get_parent_platdata(dev);
  61        u8 *rx = din;
  62        const u8 *tx = dout;
  63        u8 curbyte, curbitlen, restbits;
  64        u32 bytes = bitlen / 8;
  65        u32 out, in;
  66        u64 tick;
  67
  68        if (flags & SPI_XFER_BEGIN)
  69                spi_cs_activate(dev);
  70
  71        restbits = (bitlen % 8);
  72        if (restbits)
  73                bytes++;
  74
  75        out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs));
  76        while (bytes > 0) {
  77                bytes--;
  78                curbyte = 0;
  79                if (tx)
  80                        curbyte = *tx++;
  81
  82                if (restbits && !bytes) {
  83                        curbitlen = restbits;
  84                        curbyte <<= 8 - restbits;
  85                } else {
  86                        curbitlen = 8;
  87                }
  88
  89                for (curbyte <<= (8 - curbitlen); curbitlen; curbitlen--) {
  90                        if (curbyte & 0x80)
  91                                out |= AR71XX_SPI_IOC_DO;
  92                        else
  93                                out &= ~(AR71XX_SPI_IOC_DO);
  94
  95                        writel(out, priv->regs + AR71XX_SPI_REG_IOC);
  96
  97                        /* delay for low level */
  98                        if (priv->rrw_delay) {
  99                                tick = get_ticks() + priv->rrw_delay;
 100                                while (get_ticks() < tick)
 101                                        /*NOP*/;
 102                        }
 103
 104                        writel(out | AR71XX_SPI_IOC_CLK,
 105                               priv->regs + AR71XX_SPI_REG_IOC);
 106
 107                        /* delay for high level */
 108                        if (priv->rrw_delay) {
 109                                tick = get_ticks() + priv->rrw_delay;
 110                                while (get_ticks() < tick)
 111                                        /*NOP*/;
 112                        }
 113
 114                        curbyte <<= 1;
 115                }
 116
 117                if (!bytes)
 118                        writel(out, priv->regs + AR71XX_SPI_REG_IOC);
 119
 120                in = readl(priv->regs + AR71XX_SPI_REG_RDS);
 121                if (rx) {
 122                        if (restbits && !bytes)
 123                                *rx++ = (in << (8 - restbits));
 124                        else
 125                                *rx++ = in;
 126                }
 127        }
 128
 129        if (flags & SPI_XFER_END)
 130                spi_cs_deactivate(dev);
 131
 132        return 0;
 133}
 134
 135
 136static int ath79_spi_set_speed(struct udevice *bus, uint speed)
 137{
 138        struct ath79_spi_priv *priv = dev_get_priv(bus);
 139        u32 val, div = 0;
 140        u64 time;
 141
 142        if (speed)
 143                div = get_bus_freq(0) / speed;
 144
 145        if (div > 63)
 146                div = 63;
 147
 148        if (div < 5)
 149                div = 5;
 150
 151        /* calculate delay */
 152        time = get_tbclk();
 153        do_div(time, speed / 2);
 154        val = get_bus_freq(0) / ATH79_SPI_MHZ;
 155        val = ATH79_SPI_RRW_DELAY_FACTOR / val;
 156        if (time > val)
 157                priv->rrw_delay = time - val + 1;
 158        else
 159                priv->rrw_delay = 0;
 160
 161        writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS);
 162        clrsetbits_be32(priv->regs + AR71XX_SPI_REG_CTRL,
 163                        AR71XX_SPI_CTRL_DIV_MASK,
 164                        ATH79_SPI_CLK_DIV(div));
 165        writel(0, priv->regs + AR71XX_SPI_REG_FS);
 166        return 0;
 167}
 168
 169static int ath79_spi_set_mode(struct udevice *bus, uint mode)
 170{
 171        return 0;
 172}
 173
 174static int ath79_spi_probe(struct udevice *bus)
 175{
 176        struct ath79_spi_priv *priv = dev_get_priv(bus);
 177        fdt_addr_t addr;
 178
 179        addr = devfdt_get_addr(bus);
 180        if (addr == FDT_ADDR_T_NONE)
 181                return -EINVAL;
 182
 183        priv->regs = map_physmem(addr,
 184                                 AR71XX_SPI_SIZE,
 185                                 MAP_NOCACHE);
 186
 187        /* Init SPI Hardware, disable remap, set clock */
 188        writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS);
 189        writel(AR71XX_SPI_CTRL_RD | ATH79_SPI_CLK_DIV(8),
 190               priv->regs + AR71XX_SPI_REG_CTRL);
 191        writel(0, priv->regs + AR71XX_SPI_REG_FS);
 192
 193        return 0;
 194}
 195
 196static int ath79_cs_info(struct udevice *bus, uint cs,
 197                           struct spi_cs_info *info)
 198{
 199        /* Always allow activity on CS 0/1/2 */
 200        if (cs >= 3)
 201                return -ENODEV;
 202
 203        return 0;
 204}
 205
 206static const struct dm_spi_ops ath79_spi_ops = {
 207        .claim_bus  = ath79_spi_claim_bus,
 208        .release_bus    = ath79_spi_release_bus,
 209        .xfer       = ath79_spi_xfer,
 210        .set_speed  = ath79_spi_set_speed,
 211        .set_mode   = ath79_spi_set_mode,
 212        .cs_info    = ath79_cs_info,
 213};
 214
 215static const struct udevice_id ath79_spi_ids[] = {
 216        { .compatible = "qca,ar7100-spi" },
 217        {}
 218};
 219
 220U_BOOT_DRIVER(ath79_spi) = {
 221        .name   = "ath79_spi",
 222        .id = UCLASS_SPI,
 223        .of_match = ath79_spi_ids,
 224        .ops    = &ath79_spi_ops,
 225        .priv_auto_alloc_size = sizeof(struct ath79_spi_priv),
 226        .probe  = ath79_spi_probe,
 227};
 228