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