linux/drivers/spi/spi-lp8841-rtc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * SPI master driver for ICP DAS LP-8841 RTC
   4 *
   5 * Copyright (C) 2016 Sergei Ianovich
   6 *
   7 * based on
   8 *
   9 * Dallas DS1302 RTC Support
  10 * Copyright (C) 2002 David McCullough
  11 * Copyright (C) 2003 - 2007 Paul Mundt
  12 */
  13#include <linux/delay.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/of.h>
  18#include <linux/of_device.h>
  19#include <linux/spi/spi.h>
  20
  21#define DRIVER_NAME     "spi_lp8841_rtc"
  22
  23#define SPI_LP8841_RTC_CE       0x01
  24#define SPI_LP8841_RTC_CLK      0x02
  25#define SPI_LP8841_RTC_nWE      0x04
  26#define SPI_LP8841_RTC_MOSI     0x08
  27#define SPI_LP8841_RTC_MISO     0x01
  28
  29/*
  30 * REVISIT If there is support for SPI_3WIRE and SPI_LSB_FIRST in SPI
  31 * GPIO driver, this SPI driver can be replaced by a simple GPIO driver
  32 * providing 3 GPIO pins.
  33 */
  34
  35struct spi_lp8841_rtc {
  36        void            *iomem;
  37        unsigned long   state;
  38};
  39
  40static inline void
  41setsck(struct spi_lp8841_rtc *data, int is_on)
  42{
  43        if (is_on)
  44                data->state |= SPI_LP8841_RTC_CLK;
  45        else
  46                data->state &= ~SPI_LP8841_RTC_CLK;
  47        writeb(data->state, data->iomem);
  48}
  49
  50static inline void
  51setmosi(struct spi_lp8841_rtc *data, int is_on)
  52{
  53        if (is_on)
  54                data->state |= SPI_LP8841_RTC_MOSI;
  55        else
  56                data->state &= ~SPI_LP8841_RTC_MOSI;
  57        writeb(data->state, data->iomem);
  58}
  59
  60static inline int
  61getmiso(struct spi_lp8841_rtc *data)
  62{
  63        return ioread8(data->iomem) & SPI_LP8841_RTC_MISO;
  64}
  65
  66static inline u32
  67bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data,
  68                unsigned usecs, unsigned cpol, unsigned flags,
  69                u32 word, u8 bits)
  70{
  71        /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
  72
  73        u32 shift = 32 - bits;
  74        /* clock starts at inactive polarity */
  75        for (; likely(bits); bits--) {
  76
  77                /* setup LSB (to slave) on leading edge */
  78                if ((flags & SPI_MASTER_NO_TX) == 0)
  79                        setmosi(data, (word & 1));
  80
  81                usleep_range(usecs, usecs + 1); /* T(setup) */
  82
  83                /* sample LSB (from slave) on trailing edge */
  84                word >>= 1;
  85                if ((flags & SPI_MASTER_NO_RX) == 0)
  86                        word |= (getmiso(data) << 31);
  87
  88                setsck(data, !cpol);
  89                usleep_range(usecs, usecs + 1);
  90
  91                setsck(data, cpol);
  92        }
  93
  94        word >>= shift;
  95        return word;
  96}
  97
  98static int
  99spi_lp8841_rtc_transfer_one(struct spi_master *master,
 100                            struct spi_device *spi,
 101                            struct spi_transfer *t)
 102{
 103        struct spi_lp8841_rtc   *data = spi_master_get_devdata(master);
 104        unsigned                count = t->len;
 105        const u8                *tx = t->tx_buf;
 106        u8                      *rx = t->rx_buf;
 107        u8                      word = 0;
 108        int                     ret = 0;
 109
 110        if (tx) {
 111                data->state &= ~SPI_LP8841_RTC_nWE;
 112                writeb(data->state, data->iomem);
 113                while (likely(count > 0)) {
 114                        word = *tx++;
 115                        bitbang_txrx_be_cpha0_lsb(data, 1, 0,
 116                                        SPI_MASTER_NO_RX, word, 8);
 117                        count--;
 118                }
 119        } else if (rx) {
 120                data->state |= SPI_LP8841_RTC_nWE;
 121                writeb(data->state, data->iomem);
 122                while (likely(count > 0)) {
 123                        word = bitbang_txrx_be_cpha0_lsb(data, 1, 0,
 124                                        SPI_MASTER_NO_TX, word, 8);
 125                        *rx++ = word;
 126                        count--;
 127                }
 128        } else {
 129                ret = -EINVAL;
 130        }
 131
 132        spi_finalize_current_transfer(master);
 133
 134        return ret;
 135}
 136
 137static void
 138spi_lp8841_rtc_set_cs(struct spi_device *spi, bool enable)
 139{
 140        struct spi_lp8841_rtc *data = spi_master_get_devdata(spi->master);
 141
 142        data->state = 0;
 143        writeb(data->state, data->iomem);
 144        if (enable) {
 145                usleep_range(4, 5);
 146                data->state |= SPI_LP8841_RTC_CE;
 147                writeb(data->state, data->iomem);
 148                usleep_range(4, 5);
 149        }
 150}
 151
 152static int
 153spi_lp8841_rtc_setup(struct spi_device *spi)
 154{
 155        if ((spi->mode & SPI_CS_HIGH) == 0) {
 156                dev_err(&spi->dev, "unsupported active low chip select\n");
 157                return -EINVAL;
 158        }
 159
 160        if ((spi->mode & SPI_LSB_FIRST) == 0) {
 161                dev_err(&spi->dev, "unsupported MSB first mode\n");
 162                return -EINVAL;
 163        }
 164
 165        if ((spi->mode & SPI_3WIRE) == 0) {
 166                dev_err(&spi->dev, "unsupported wiring. 3 wires required\n");
 167                return -EINVAL;
 168        }
 169
 170        return 0;
 171}
 172
 173#ifdef CONFIG_OF
 174static const struct of_device_id spi_lp8841_rtc_dt_ids[] = {
 175        { .compatible = "icpdas,lp8841-spi-rtc" },
 176        { }
 177};
 178
 179MODULE_DEVICE_TABLE(of, spi_lp8841_rtc_dt_ids);
 180#endif
 181
 182static int
 183spi_lp8841_rtc_probe(struct platform_device *pdev)
 184{
 185        int                             ret;
 186        struct spi_master               *master;
 187        struct spi_lp8841_rtc           *data;
 188
 189        master = spi_alloc_master(&pdev->dev, sizeof(*data));
 190        if (!master)
 191                return -ENOMEM;
 192        platform_set_drvdata(pdev, master);
 193
 194        master->flags = SPI_MASTER_HALF_DUPLEX;
 195        master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST;
 196
 197        master->bus_num = pdev->id;
 198        master->num_chipselect = 1;
 199        master->setup = spi_lp8841_rtc_setup;
 200        master->set_cs = spi_lp8841_rtc_set_cs;
 201        master->transfer_one = spi_lp8841_rtc_transfer_one;
 202        master->bits_per_word_mask = SPI_BPW_MASK(8);
 203#ifdef CONFIG_OF
 204        master->dev.of_node = pdev->dev.of_node;
 205#endif
 206
 207        data = spi_master_get_devdata(master);
 208
 209        data->iomem = devm_platform_ioremap_resource(pdev, 0);
 210        ret = PTR_ERR_OR_ZERO(data->iomem);
 211        if (ret) {
 212                dev_err(&pdev->dev, "failed to get IO address\n");
 213                goto err_put_master;
 214        }
 215
 216        /* register with the SPI framework */
 217        ret = devm_spi_register_master(&pdev->dev, master);
 218        if (ret) {
 219                dev_err(&pdev->dev, "cannot register spi master\n");
 220                goto err_put_master;
 221        }
 222
 223        return ret;
 224
 225
 226err_put_master:
 227        spi_master_put(master);
 228
 229        return ret;
 230}
 231
 232MODULE_ALIAS("platform:" DRIVER_NAME);
 233
 234static struct platform_driver spi_lp8841_rtc_driver = {
 235        .driver = {
 236                .name   = DRIVER_NAME,
 237                .of_match_table = of_match_ptr(spi_lp8841_rtc_dt_ids),
 238        },
 239        .probe          = spi_lp8841_rtc_probe,
 240};
 241module_platform_driver(spi_lp8841_rtc_driver);
 242
 243MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC");
 244MODULE_AUTHOR("Sergei Ianovich");
 245MODULE_LICENSE("GPL");
 246