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 void *iomem; 189 190 master = spi_alloc_master(&pdev->dev, sizeof(*data)); 191 if (!master) 192 return -ENOMEM; 193 platform_set_drvdata(pdev, master); 194 195 master->flags = SPI_MASTER_HALF_DUPLEX; 196 master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST; 197 198 master->bus_num = pdev->id; 199 master->num_chipselect = 1; 200 master->setup = spi_lp8841_rtc_setup; 201 master->set_cs = spi_lp8841_rtc_set_cs; 202 master->transfer_one = spi_lp8841_rtc_transfer_one; 203 master->bits_per_word_mask = SPI_BPW_MASK(8); 204 #ifdef CONFIG_OF 205 master->dev.of_node = pdev->dev.of_node; 206 #endif 207 208 data = spi_master_get_devdata(master); 209 210 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 211 data->iomem = devm_ioremap_resource(&pdev->dev, iomem); 212 ret = PTR_ERR_OR_ZERO(data->iomem); 213 if (ret) { 214 dev_err(&pdev->dev, "failed to get IO address\n"); 215 goto err_put_master; 216 } 217 218 /* register with the SPI framework */ 219 ret = devm_spi_register_master(&pdev->dev, master); 220 if (ret) { 221 dev_err(&pdev->dev, "cannot register spi master\n"); 222 goto err_put_master; 223 } 224 225 return ret; 226 227 228 err_put_master: 229 spi_master_put(master); 230 231 return ret; 232 } 233 234 MODULE_ALIAS("platform:" DRIVER_NAME); 235 236 static struct platform_driver spi_lp8841_rtc_driver = { 237 .driver = { 238 .name = DRIVER_NAME, 239 .of_match_table = of_match_ptr(spi_lp8841_rtc_dt_ids), 240 }, 241 .probe = spi_lp8841_rtc_probe, 242 }; 243 module_platform_driver(spi_lp8841_rtc_driver); 244 245 MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC"); 246 MODULE_AUTHOR("Sergei Ianovich"); 247 MODULE_LICENSE("GPL"); 248