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        int ret;
  84        struct spi_master *master;
  85
  86        master = spi_alloc_master(&pdev->dev, sizeof(struct xtfpga_spi));
  87        if (!master)
  88                return -ENOMEM;
  89
  90        master->flags = SPI_MASTER_NO_RX;
  91        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
  92        master->bus_num = pdev->dev.id;
  93        master->dev.of_node = pdev->dev.of_node;
  94
  95        xspi = spi_master_get_devdata(master);
  96        xspi->bitbang.master = master;
  97        xspi->bitbang.chipselect = xtfpga_spi_chipselect;
  98        xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word;
  99        xspi->regs = devm_platform_ioremap_resource(pdev, 0);
 100        if (IS_ERR(xspi->regs)) {
 101                ret = PTR_ERR(xspi->regs);
 102                goto err;
 103        }
 104
 105        xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
 106        usleep_range(1000, 2000);
 107        if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) {
 108                dev_err(&pdev->dev, "Device stuck in busy state\n");
 109                ret = -EBUSY;
 110                goto err;
 111        }
 112
 113        ret = spi_bitbang_start(&xspi->bitbang);
 114        if (ret < 0) {
 115                dev_err(&pdev->dev, "spi_bitbang_start failed\n");
 116                goto err;
 117        }
 118
 119        platform_set_drvdata(pdev, master);
 120        return 0;
 121err:
 122        spi_master_put(master);
 123        return ret;
 124}
 125
 126static int xtfpga_spi_remove(struct platform_device *pdev)
 127{
 128        struct spi_master *master = platform_get_drvdata(pdev);
 129        struct xtfpga_spi *xspi = spi_master_get_devdata(master);
 130
 131        spi_bitbang_stop(&xspi->bitbang);
 132        spi_master_put(master);
 133
 134        return 0;
 135}
 136
 137MODULE_ALIAS("platform:" XTFPGA_SPI_NAME);
 138
 139#ifdef CONFIG_OF
 140static const struct of_device_id xtfpga_spi_of_match[] = {
 141        { .compatible = "cdns,xtfpga-spi", },
 142        {}
 143};
 144MODULE_DEVICE_TABLE(of, xtfpga_spi_of_match);
 145#endif
 146
 147static struct platform_driver xtfpga_spi_driver = {
 148        .probe = xtfpga_spi_probe,
 149        .remove = xtfpga_spi_remove,
 150        .driver = {
 151                .name = XTFPGA_SPI_NAME,
 152                .of_match_table = of_match_ptr(xtfpga_spi_of_match),
 153        },
 154};
 155module_platform_driver(xtfpga_spi_driver);
 156
 157MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
 158MODULE_DESCRIPTION("xtensa xtfpga SPI driver");
 159MODULE_LICENSE("GPL");
 160