root/drivers/spi/spi-lp8841-rtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. setsck
  2. setmosi
  3. getmiso
  4. bitbang_txrx_be_cpha0_lsb
  5. spi_lp8841_rtc_transfer_one
  6. spi_lp8841_rtc_set_cs
  7. spi_lp8841_rtc_setup
  8. spi_lp8841_rtc_probe

   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 
  35 struct spi_lp8841_rtc {
  36         void            *iomem;
  37         unsigned long   state;
  38 };
  39 
  40 static inline void
  41 setsck(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 
  50 static inline void
  51 setmosi(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 
  60 static inline int
  61 getmiso(struct spi_lp8841_rtc *data)
  62 {
  63         return ioread8(data->iomem) & SPI_LP8841_RTC_MISO;
  64 }
  65 
  66 static inline u32
  67 bitbang_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 
  98 static int
  99 spi_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 
 137 static void
 138 spi_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 
 152 static int
 153 spi_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
 174 static const struct of_device_id spi_lp8841_rtc_dt_ids[] = {
 175         { .compatible = "icpdas,lp8841-spi-rtc" },
 176         { }
 177 };
 178 
 179 MODULE_DEVICE_TABLE(of, spi_lp8841_rtc_dt_ids);
 180 #endif
 181 
 182 static int
 183 spi_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 
 226 err_put_master:
 227         spi_master_put(master);
 228 
 229         return ret;
 230 }
 231 
 232 MODULE_ALIAS("platform:" DRIVER_NAME);
 233 
 234 static 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 };
 241 module_platform_driver(spi_lp8841_rtc_driver);
 242 
 243 MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC");
 244 MODULE_AUTHOR("Sergei Ianovich");
 245 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */