spi-lp8841-rtc.c (5498B)
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");