linux/drivers/spi/spi-jcore.c
<<
>>
Prefs
   1/*
   2 * J-Core SPI controller driver
   3 *
   4 * Copyright (C) 2012-2016 Smart Energy Instruments, Inc.
   5 *
   6 * Current version by Rich Felker
   7 * Based loosely on initial version by Oleksandr G Zhadan
   8 *
   9 */
  10#include <linux/init.h>
  11#include <linux/interrupt.h>
  12#include <linux/errno.h>
  13#include <linux/module.h>
  14#include <linux/platform_device.h>
  15#include <linux/spi/spi.h>
  16#include <linux/clk.h>
  17#include <linux/err.h>
  18#include <linux/io.h>
  19#include <linux/of.h>
  20#include <linux/delay.h>
  21
  22#define DRV_NAME        "jcore_spi"
  23
  24#define CTRL_REG        0x0
  25#define DATA_REG        0x4
  26
  27#define JCORE_SPI_CTRL_XMIT             0x02
  28#define JCORE_SPI_STAT_BUSY             0x02
  29#define JCORE_SPI_CTRL_LOOP             0x08
  30#define JCORE_SPI_CTRL_CS_BITS          0x15
  31
  32#define JCORE_SPI_WAIT_RDY_MAX_LOOP     2000000
  33
  34struct jcore_spi {
  35        struct spi_master *master;
  36        void __iomem *base;
  37        unsigned int cs_reg;
  38        unsigned int speed_reg;
  39        unsigned int speed_hz;
  40        unsigned int clock_freq;
  41};
  42
  43static int jcore_spi_wait(void __iomem *ctrl_reg)
  44{
  45        unsigned timeout = JCORE_SPI_WAIT_RDY_MAX_LOOP;
  46
  47        do {
  48                if (!(readl(ctrl_reg) & JCORE_SPI_STAT_BUSY))
  49                        return 0;
  50                cpu_relax();
  51        } while (--timeout);
  52
  53        return -EBUSY;
  54}
  55
  56static void jcore_spi_program(struct jcore_spi *hw)
  57{
  58        void __iomem *ctrl_reg = hw->base + CTRL_REG;
  59
  60        if (jcore_spi_wait(ctrl_reg))
  61                dev_err(hw->master->dev.parent,
  62                        "timeout waiting to program ctrl reg.\n");
  63
  64        writel(hw->cs_reg | hw->speed_reg, ctrl_reg);
  65}
  66
  67static void jcore_spi_chipsel(struct spi_device *spi, bool value)
  68{
  69        struct jcore_spi *hw = spi_master_get_devdata(spi->master);
  70        u32 csbit = 1U << (2 * spi->chip_select);
  71
  72        dev_dbg(hw->master->dev.parent, "chipselect %d\n", spi->chip_select);
  73
  74        if (value)
  75                hw->cs_reg |= csbit;
  76        else
  77                hw->cs_reg &= ~csbit;
  78
  79        jcore_spi_program(hw);
  80}
  81
  82static void jcore_spi_baudrate(struct jcore_spi *hw, int speed)
  83{
  84        if (speed == hw->speed_hz) return;
  85        hw->speed_hz = speed;
  86        if (speed >= hw->clock_freq / 2)
  87                hw->speed_reg = 0;
  88        else
  89                hw->speed_reg = ((hw->clock_freq / 2 / speed) - 1) << 27;
  90        jcore_spi_program(hw);
  91        dev_dbg(hw->master->dev.parent, "speed=%d reg=0x%x\n",
  92                speed, hw->speed_reg);
  93}
  94
  95static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi,
  96                          struct spi_transfer *t)
  97{
  98        struct jcore_spi *hw = spi_master_get_devdata(master);
  99
 100        void __iomem *ctrl_reg = hw->base + CTRL_REG;
 101        void __iomem *data_reg = hw->base + DATA_REG;
 102        u32 xmit;
 103
 104        /* data buffers */
 105        const unsigned char *tx;
 106        unsigned char *rx;
 107        unsigned int len;
 108        unsigned int count;
 109
 110        jcore_spi_baudrate(hw, t->speed_hz);
 111
 112        xmit = hw->cs_reg | hw->speed_reg | JCORE_SPI_CTRL_XMIT;
 113        tx = t->tx_buf;
 114        rx = t->rx_buf;
 115        len = t->len;
 116
 117        for (count = 0; count < len; count++) {
 118                if (jcore_spi_wait(ctrl_reg))
 119                        break;
 120
 121                writel(tx ? *tx++ : 0, data_reg);
 122                writel(xmit, ctrl_reg);
 123
 124                if (jcore_spi_wait(ctrl_reg))
 125                        break;
 126
 127                if (rx)
 128                        *rx++ = readl(data_reg);
 129        }
 130
 131        spi_finalize_current_transfer(master);
 132
 133        if (count < len)
 134                return -EREMOTEIO;
 135
 136        return 0;
 137}
 138
 139static int jcore_spi_probe(struct platform_device *pdev)
 140{
 141        struct device_node *node = pdev->dev.of_node;
 142        struct jcore_spi *hw;
 143        struct spi_master *master;
 144        struct resource *res;
 145        u32 clock_freq;
 146        struct clk *clk;
 147        int err = -ENODEV;
 148
 149        master = spi_alloc_master(&pdev->dev, sizeof(struct jcore_spi));
 150        if (!master)
 151                return err;
 152
 153        /* Setup the master state. */
 154        master->num_chipselect = 3;
 155        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 156        master->transfer_one = jcore_spi_txrx;
 157        master->set_cs = jcore_spi_chipsel;
 158        master->dev.of_node = node;
 159        master->bus_num = pdev->id;
 160
 161        hw = spi_master_get_devdata(master);
 162        hw->master = master;
 163        platform_set_drvdata(pdev, hw);
 164
 165        /* Find and map our resources */
 166        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 167        if (!res)
 168                goto exit_busy;
 169        if (!devm_request_mem_region(&pdev->dev, res->start,
 170                                     resource_size(res), pdev->name))
 171                goto exit_busy;
 172        hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
 173                                        resource_size(res));
 174        if (!hw->base)
 175                goto exit_busy;
 176
 177        /*
 178         * The SPI clock rate controlled via a configurable clock divider
 179         * which is applied to the reference clock. A 50 MHz reference is
 180         * most suitable for obtaining standard SPI clock rates, but some
 181         * designs may have a different reference clock, and the DT must
 182         * make the driver aware so that it can properly program the
 183         * requested rate. If the clock is omitted, 50 MHz is assumed.
 184         */
 185        clock_freq = 50000000;
 186        clk = devm_clk_get(&pdev->dev, "ref_clk");
 187        if (!IS_ERR_OR_NULL(clk)) {
 188                if (clk_enable(clk) == 0)
 189                        clock_freq = clk_get_rate(clk);
 190                else
 191                        dev_warn(&pdev->dev, "could not enable ref_clk\n");
 192        }
 193        hw->clock_freq = clock_freq;
 194
 195        /* Initialize all CS bits to high. */
 196        hw->cs_reg = JCORE_SPI_CTRL_CS_BITS;
 197        jcore_spi_baudrate(hw, 400000);
 198
 199        /* Register our spi controller */
 200        err = devm_spi_register_master(&pdev->dev, master);
 201        if (err)
 202                goto exit;
 203
 204        return 0;
 205
 206exit_busy:
 207        err = -EBUSY;
 208exit:
 209        spi_master_put(master);
 210        return err;
 211}
 212
 213static const struct of_device_id jcore_spi_of_match[] = {
 214        { .compatible = "jcore,spi2" },
 215        {},
 216};
 217MODULE_DEVICE_TABLE(of, jcore_spi_of_match);
 218
 219static struct platform_driver jcore_spi_driver = {
 220        .probe = jcore_spi_probe,
 221        .driver = {
 222                .name = DRV_NAME,
 223                .of_match_table = jcore_spi_of_match,
 224        },
 225};
 226
 227module_platform_driver(jcore_spi_driver);
 228
 229MODULE_DESCRIPTION("J-Core SPI driver");
 230MODULE_AUTHOR("Rich Felker <dalias@libc.org>");
 231MODULE_LICENSE("GPL");
 232MODULE_ALIAS("platform:" DRV_NAME);
 233