linux/drivers/spi/spi-realtek-rtl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3#include <linux/module.h>
   4#include <linux/platform_device.h>
   5#include <linux/mod_devicetable.h>
   6#include <linux/spi/spi.h>
   7
   8struct rtspi {
   9        void __iomem *base;
  10};
  11
  12/* SPI Flash Configuration Register */
  13#define RTL_SPI_SFCR                    0x00
  14#define RTL_SPI_SFCR_RBO                BIT(28)
  15#define RTL_SPI_SFCR_WBO                BIT(27)
  16
  17/* SPI Flash Control and Status Register */
  18#define RTL_SPI_SFCSR                   0x08
  19#define RTL_SPI_SFCSR_CSB0              BIT(31)
  20#define RTL_SPI_SFCSR_CSB1              BIT(30)
  21#define RTL_SPI_SFCSR_RDY               BIT(27)
  22#define RTL_SPI_SFCSR_CS                BIT(24)
  23#define RTL_SPI_SFCSR_LEN_MASK          ~(0x03 << 28)
  24#define RTL_SPI_SFCSR_LEN1              (0x00 << 28)
  25#define RTL_SPI_SFCSR_LEN4              (0x03 << 28)
  26
  27/* SPI Flash Data Register */
  28#define RTL_SPI_SFDR                    0x0c
  29
  30#define REG(x)          (rtspi->base + x)
  31
  32
  33static void rt_set_cs(struct spi_device *spi, bool active)
  34{
  35        struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);
  36        u32 value;
  37
  38        /* CS0 bit is active low */
  39        value = readl(REG(RTL_SPI_SFCSR));
  40        if (active)
  41                value |= RTL_SPI_SFCSR_CSB0;
  42        else
  43                value &= ~RTL_SPI_SFCSR_CSB0;
  44        writel(value, REG(RTL_SPI_SFCSR));
  45}
  46
  47static void set_size(struct rtspi *rtspi, int size)
  48{
  49        u32 value;
  50
  51        value = readl(REG(RTL_SPI_SFCSR));
  52        value &= RTL_SPI_SFCSR_LEN_MASK;
  53        if (size == 4)
  54                value |= RTL_SPI_SFCSR_LEN4;
  55        else if (size == 1)
  56                value |= RTL_SPI_SFCSR_LEN1;
  57        writel(value, REG(RTL_SPI_SFCSR));
  58}
  59
  60static inline void wait_ready(struct rtspi *rtspi)
  61{
  62        while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
  63                cpu_relax();
  64}
  65static void send4(struct rtspi *rtspi, const u32 *buf)
  66{
  67        wait_ready(rtspi);
  68        set_size(rtspi, 4);
  69        writel(*buf, REG(RTL_SPI_SFDR));
  70}
  71
  72static void send1(struct rtspi *rtspi, const u8 *buf)
  73{
  74        wait_ready(rtspi);
  75        set_size(rtspi, 1);
  76        writel(buf[0] << 24, REG(RTL_SPI_SFDR));
  77}
  78
  79static void rcv4(struct rtspi *rtspi, u32 *buf)
  80{
  81        wait_ready(rtspi);
  82        set_size(rtspi, 4);
  83        *buf = readl(REG(RTL_SPI_SFDR));
  84}
  85
  86static void rcv1(struct rtspi *rtspi, u8 *buf)
  87{
  88        wait_ready(rtspi);
  89        set_size(rtspi, 1);
  90        *buf = readl(REG(RTL_SPI_SFDR)) >> 24;
  91}
  92
  93static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
  94                        struct spi_transfer *xfer)
  95{
  96        struct rtspi *rtspi = spi_controller_get_devdata(ctrl);
  97        void *rx_buf;
  98        const void *tx_buf;
  99        int cnt;
 100
 101        tx_buf = xfer->tx_buf;
 102        rx_buf = xfer->rx_buf;
 103        cnt = xfer->len;
 104        if (tx_buf) {
 105                while (cnt >= 4) {
 106                        send4(rtspi, tx_buf);
 107                        tx_buf += 4;
 108                        cnt -= 4;
 109                }
 110                while (cnt) {
 111                        send1(rtspi, tx_buf);
 112                        tx_buf++;
 113                        cnt--;
 114                }
 115        } else if (rx_buf) {
 116                while (cnt >= 4) {
 117                        rcv4(rtspi, rx_buf);
 118                        rx_buf += 4;
 119                        cnt -= 4;
 120                }
 121                while (cnt) {
 122                        rcv1(rtspi, rx_buf);
 123                        rx_buf++;
 124                        cnt--;
 125                }
 126        }
 127
 128        spi_finalize_current_transfer(ctrl);
 129
 130        return 0;
 131}
 132
 133static void init_hw(struct rtspi *rtspi)
 134{
 135        u32 value;
 136
 137        /* Turn on big-endian byte ordering */
 138        value = readl(REG(RTL_SPI_SFCR));
 139        value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
 140        writel(value, REG(RTL_SPI_SFCR));
 141
 142        value = readl(REG(RTL_SPI_SFCSR));
 143        /* Permanently disable CS1, since it's never used */
 144        value |= RTL_SPI_SFCSR_CSB1;
 145        /* Select CS0 for use */
 146        value &= RTL_SPI_SFCSR_CS;
 147        writel(value, REG(RTL_SPI_SFCSR));
 148}
 149
 150static int realtek_rtl_spi_probe(struct platform_device *pdev)
 151{
 152        struct spi_controller *ctrl;
 153        struct rtspi *rtspi;
 154        int err;
 155
 156        ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi));
 157        if (!ctrl) {
 158                dev_err(&pdev->dev, "Error allocating SPI controller\n");
 159                return -ENOMEM;
 160        }
 161        platform_set_drvdata(pdev, ctrl);
 162        rtspi = spi_controller_get_devdata(ctrl);
 163
 164        rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
 165        if (IS_ERR(rtspi->base)) {
 166                dev_err(&pdev->dev, "Could not map SPI register address");
 167                return -ENOMEM;
 168        }
 169
 170        init_hw(rtspi);
 171
 172        ctrl->dev.of_node = pdev->dev.of_node;
 173        ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;
 174        ctrl->set_cs = rt_set_cs;
 175        ctrl->transfer_one = transfer_one;
 176
 177        err = devm_spi_register_controller(&pdev->dev, ctrl);
 178        if (err) {
 179                dev_err(&pdev->dev, "Could not register SPI controller\n");
 180                return -ENODEV;
 181        }
 182
 183        return 0;
 184}
 185
 186
 187static const struct of_device_id realtek_rtl_spi_of_ids[] = {
 188        { .compatible = "realtek,rtl8380-spi" },
 189        { .compatible = "realtek,rtl8382-spi" },
 190        { .compatible = "realtek,rtl8391-spi" },
 191        { .compatible = "realtek,rtl8392-spi" },
 192        { .compatible = "realtek,rtl8393-spi" },
 193        { /* sentinel */ }
 194};
 195MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);
 196
 197static struct platform_driver realtek_rtl_spi_driver = {
 198        .probe = realtek_rtl_spi_probe,
 199        .driver = {
 200                .name = "realtek-rtl-spi",
 201                .of_match_table = realtek_rtl_spi_of_ids,
 202        },
 203};
 204
 205module_platform_driver(realtek_rtl_spi_driver);
 206
 207MODULE_LICENSE("GPL v2");
 208MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
 209MODULE_DESCRIPTION("Realtek RTL SPI driver");
 210