linux/drivers/spi/spi-xtensa-xtfpga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Xtensa xtfpga SPI controller driver
   4 *
   5 * Copyright (c) 2014 Cadence Design Systems Inc.
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/io.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/platform_device.h>
  13#include <linux/spi/spi.h>
  14#include <linux/spi/spi_bitbang.h>
  15
  16#define XTFPGA_SPI_NAME "xtfpga_spi"
  17
  18#define XTFPGA_SPI_START        0x0
  19#define XTFPGA_SPI_BUSY         0x4
  20#define XTFPGA_SPI_DATA         0x8
  21
  22#define BUSY_WAIT_US            100
  23
  24struct xtfpga_spi {
  25        struct spi_bitbang bitbang;
  26        void __iomem *regs;
  27        u32 data;
  28        unsigned data_sz;
  29};
  30
  31static inline void xtfpga_spi_write32(const struct xtfpga_spi *spi,
  32                                      unsigned addr, u32 val)
  33{
  34        __raw_writel(val, spi->regs + addr);
  35}
  36
  37static inline unsigned int xtfpga_spi_read32(const struct xtfpga_spi *spi,
  38                                             unsigned addr)
  39{
  40        return __raw_readl(spi->regs + addr);
  41}
  42
  43static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi)
  44{
  45        unsigned i;
  46
  47        for (i = 0; xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY) &&
  48             i < BUSY_WAIT_US; ++i)
  49                udelay(1);
  50        WARN_ON_ONCE(i == BUSY_WAIT_US);
  51}
  52
  53static u32 xtfpga_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
  54                                u32 v, u8 bits, unsigned flags)
  55{
  56        struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master);
  57
  58        xspi->data = (xspi->data << bits) | (v & GENMASK(bits - 1, 0));
  59        xspi->data_sz += bits;
  60        if (xspi->data_sz >= 16) {
  61                xtfpga_spi_write32(xspi, XTFPGA_SPI_DATA,
  62                                   xspi->data >> (xspi->data_sz - 16));
  63                xspi->data_sz -= 16;
  64                xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 1);
  65                xtfpga_spi_wait_busy(xspi);
  66                xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
  67        }
  68
  69        return 0;
  70}
  71
  72static void xtfpga_spi_chipselect(struct spi_device *spi, int is_on)
  73{
  74        struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master);
  75
  76        WARN_ON(xspi->data_sz != 0);
  77        xspi->data_sz = 0;
  78}
  79
  80static int xtfpga_spi_probe(struct platform_device *pdev)
  81{
  82        struct xtfpga_spi *xspi;
  83        struct resource *mem;
  84        int ret;
  85        struct spi_master *master;
  86
  87        master = spi_alloc_master(&pdev->dev, sizeof(struct xtfpga_spi));
  88        if (!master)
  89                return -ENOMEM;
  90
  91        master->flags = SPI_MASTER_NO_RX;
  92        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
  93        master->bus_num = pdev->dev.id;
  94        master->dev.of_node = pdev->dev.of_node;
  95
  96        xspi = spi_master_get_devdata(master);
  97        xspi->bitbang.master = master;
  98        xspi->bitbang.chipselect = xtfpga_spi_chipselect;
  99        xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word;
 100
 101        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 102        if (!mem) {
 103                dev_err(&pdev->dev, "No memory resource\n");
 104                ret = -ENODEV;
 105                goto err;
 106        }
 107        xspi->regs = devm_ioremap_resource(&pdev->dev, mem);
 108        if (IS_ERR(xspi->regs)) {
 109                ret = PTR_ERR(xspi->regs);
 110                goto err;
 111        }
 112
 113        xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
 114        usleep_range(1000, 2000);
 115        if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) {
 116                dev_err(&pdev->dev, "Device stuck in busy state\n");
 117                ret = -EBUSY;
 118                goto err;
 119        }
 120
 121        ret = spi_bitbang_start(&xspi->bitbang);
 122        if (ret < 0) {
 123                dev_err(&pdev->dev, "spi_bitbang_start failed\n");
 124                goto err;
 125        }
 126
 127        platform_set_drvdata(pdev, master);
 128        return 0;
 129err:
 130        spi_master_put(master);
 131        return ret;
 132}
 133
 134static int xtfpga_spi_remove(struct platform_device *pdev)
 135{
 136        struct spi_master *master = platform_get_drvdata(pdev);
 137        struct xtfpga_spi *xspi = spi_master_get_devdata(master);
 138
 139        spi_bitbang_stop(&xspi->bitbang);
 140        spi_master_put(master);
 141
 142        return 0;
 143}
 144
 145MODULE_ALIAS("platform:" XTFPGA_SPI_NAME);
 146
 147#ifdef CONFIG_OF
 148static const struct of_device_id xtfpga_spi_of_match[] = {
 149        { .compatible = "cdns,xtfpga-spi", },
 150        {}
 151};
 152MODULE_DEVICE_TABLE(of, xtfpga_spi_of_match);
 153#endif
 154
 155static struct platform_driver xtfpga_spi_driver = {
 156        .probe = xtfpga_spi_probe,
 157        .remove = xtfpga_spi_remove,
 158        .driver = {
 159                .name = XTFPGA_SPI_NAME,
 160                .of_match_table = of_match_ptr(xtfpga_spi_of_match),
 161        },
 162};
 163module_platform_driver(xtfpga_spi_driver);
 164
 165MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
 166MODULE_DESCRIPTION("xtensa xtfpga SPI driver");
 167MODULE_LICENSE("GPL");
 168