1 /* 2 * OpenCores tiny SPI master driver 3 * 4 * http://opencores.org/project,tiny_spi 5 * 6 * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw> 7 * 8 * Based on spi_s3c24xx.c, which is: 9 * Copyright (c) 2006 Ben Dooks 10 * Copyright (c) 2006 Simtec Electronics 11 * Ben Dooks <ben@simtec.co.uk> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 */ 17 18 #include <linux/init.h> 19 #include <linux/interrupt.h> 20 #include <linux/errno.h> 21 #include <linux/module.h> 22 #include <linux/platform_device.h> 23 #include <linux/spi/spi.h> 24 #include <linux/spi/spi_bitbang.h> 25 #include <linux/spi/spi_oc_tiny.h> 26 #include <linux/io.h> 27 #include <linux/gpio.h> 28 #include <linux/of.h> 29 30 #define DRV_NAME "spi_oc_tiny" 31 32 #define TINY_SPI_RXDATA 0 33 #define TINY_SPI_TXDATA 4 34 #define TINY_SPI_STATUS 8 35 #define TINY_SPI_CONTROL 12 36 #define TINY_SPI_BAUD 16 37 38 #define TINY_SPI_STATUS_TXE 0x1 39 #define TINY_SPI_STATUS_TXR 0x2 40 41 struct tiny_spi { 42 /* bitbang has to be first */ 43 struct spi_bitbang bitbang; 44 struct completion done; 45 46 void __iomem *base; 47 int irq; 48 unsigned int freq; 49 unsigned int baudwidth; 50 unsigned int baud; 51 unsigned int speed_hz; 52 unsigned int mode; 53 unsigned int len; 54 unsigned int txc, rxc; 55 const u8 *txp; 56 u8 *rxp; 57 int gpio_cs_count; 58 int *gpio_cs; 59 }; 60 61 static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) 62 { 63 return spi_master_get_devdata(sdev->master); 64 } 65 66 static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz) 67 { 68 struct tiny_spi *hw = tiny_spi_to_hw(spi); 69 70 return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1; 71 } 72 73 static void tiny_spi_chipselect(struct spi_device *spi, int is_active) 74 { 75 struct tiny_spi *hw = tiny_spi_to_hw(spi); 76 77 if (hw->gpio_cs_count > 0) { 78 gpio_set_value(hw->gpio_cs[spi->chip_select], 79 (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); 80 } 81 } 82 83 static int tiny_spi_setup_transfer(struct spi_device *spi, 84 struct spi_transfer *t) 85 { 86 struct tiny_spi *hw = tiny_spi_to_hw(spi); 87 unsigned int baud = hw->baud; 88 89 if (t) { 90 if (t->speed_hz && t->speed_hz != hw->speed_hz) 91 baud = tiny_spi_baud(spi, t->speed_hz); 92 } 93 writel(baud, hw->base + TINY_SPI_BAUD); 94 writel(hw->mode, hw->base + TINY_SPI_CONTROL); 95 return 0; 96 } 97 98 static int tiny_spi_setup(struct spi_device *spi) 99 { 100 struct tiny_spi *hw = tiny_spi_to_hw(spi); 101 102 if (spi->max_speed_hz != hw->speed_hz) { 103 hw->speed_hz = spi->max_speed_hz; 104 hw->baud = tiny_spi_baud(spi, hw->speed_hz); 105 } 106 hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA); 107 return 0; 108 } 109 110 static inline void tiny_spi_wait_txr(struct tiny_spi *hw) 111 { 112 while (!(readb(hw->base + TINY_SPI_STATUS) & 113 TINY_SPI_STATUS_TXR)) 114 cpu_relax(); 115 } 116 117 static inline void tiny_spi_wait_txe(struct tiny_spi *hw) 118 { 119 while (!(readb(hw->base + TINY_SPI_STATUS) & 120 TINY_SPI_STATUS_TXE)) 121 cpu_relax(); 122 } 123 124 static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) 125 { 126 struct tiny_spi *hw = tiny_spi_to_hw(spi); 127 const u8 *txp = t->tx_buf; 128 u8 *rxp = t->rx_buf; 129 unsigned int i; 130 131 if (hw->irq >= 0) { 132 /* use interrupt driven data transfer */ 133 hw->len = t->len; 134 hw->txp = t->tx_buf; 135 hw->rxp = t->rx_buf; 136 hw->txc = 0; 137 hw->rxc = 0; 138 139 /* send the first byte */ 140 if (t->len > 1) { 141 writeb(hw->txp ? *hw->txp++ : 0, 142 hw->base + TINY_SPI_TXDATA); 143 hw->txc++; 144 writeb(hw->txp ? *hw->txp++ : 0, 145 hw->base + TINY_SPI_TXDATA); 146 hw->txc++; 147 writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS); 148 } else { 149 writeb(hw->txp ? *hw->txp++ : 0, 150 hw->base + TINY_SPI_TXDATA); 151 hw->txc++; 152 writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS); 153 } 154 155 wait_for_completion(&hw->done); 156 } else if (txp && rxp) { 157 /* we need to tighten the transfer loop */ 158 writeb(*txp++, hw->base + TINY_SPI_TXDATA); 159 if (t->len > 1) { 160 writeb(*txp++, hw->base + TINY_SPI_TXDATA); 161 for (i = 2; i < t->len; i++) { 162 u8 rx, tx = *txp++; 163 tiny_spi_wait_txr(hw); 164 rx = readb(hw->base + TINY_SPI_TXDATA); 165 writeb(tx, hw->base + TINY_SPI_TXDATA); 166 *rxp++ = rx; 167 } 168 tiny_spi_wait_txr(hw); 169 *rxp++ = readb(hw->base + TINY_SPI_TXDATA); 170 } 171 tiny_spi_wait_txe(hw); 172 *rxp++ = readb(hw->base + TINY_SPI_RXDATA); 173 } else if (rxp) { 174 writeb(0, hw->base + TINY_SPI_TXDATA); 175 if (t->len > 1) { 176 writeb(0, 177 hw->base + TINY_SPI_TXDATA); 178 for (i = 2; i < t->len; i++) { 179 u8 rx; 180 tiny_spi_wait_txr(hw); 181 rx = readb(hw->base + TINY_SPI_TXDATA); 182 writeb(0, hw->base + TINY_SPI_TXDATA); 183 *rxp++ = rx; 184 } 185 tiny_spi_wait_txr(hw); 186 *rxp++ = readb(hw->base + TINY_SPI_TXDATA); 187 } 188 tiny_spi_wait_txe(hw); 189 *rxp++ = readb(hw->base + TINY_SPI_RXDATA); 190 } else if (txp) { 191 writeb(*txp++, hw->base + TINY_SPI_TXDATA); 192 if (t->len > 1) { 193 writeb(*txp++, hw->base + TINY_SPI_TXDATA); 194 for (i = 2; i < t->len; i++) { 195 u8 tx = *txp++; 196 tiny_spi_wait_txr(hw); 197 writeb(tx, hw->base + TINY_SPI_TXDATA); 198 } 199 } 200 tiny_spi_wait_txe(hw); 201 } else { 202 writeb(0, hw->base + TINY_SPI_TXDATA); 203 if (t->len > 1) { 204 writeb(0, hw->base + TINY_SPI_TXDATA); 205 for (i = 2; i < t->len; i++) { 206 tiny_spi_wait_txr(hw); 207 writeb(0, hw->base + TINY_SPI_TXDATA); 208 } 209 } 210 tiny_spi_wait_txe(hw); 211 } 212 return t->len; 213 } 214 215 static irqreturn_t tiny_spi_irq(int irq, void *dev) 216 { 217 struct tiny_spi *hw = dev; 218 219 writeb(0, hw->base + TINY_SPI_STATUS); 220 if (hw->rxc + 1 == hw->len) { 221 if (hw->rxp) 222 *hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA); 223 hw->rxc++; 224 complete(&hw->done); 225 } else { 226 if (hw->rxp) 227 *hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA); 228 hw->rxc++; 229 if (hw->txc < hw->len) { 230 writeb(hw->txp ? *hw->txp++ : 0, 231 hw->base + TINY_SPI_TXDATA); 232 hw->txc++; 233 writeb(TINY_SPI_STATUS_TXR, 234 hw->base + TINY_SPI_STATUS); 235 } else { 236 writeb(TINY_SPI_STATUS_TXE, 237 hw->base + TINY_SPI_STATUS); 238 } 239 } 240 return IRQ_HANDLED; 241 } 242 243 #ifdef CONFIG_OF 244 #include <linux/of_gpio.h> 245 246 static int tiny_spi_of_probe(struct platform_device *pdev) 247 { 248 struct tiny_spi *hw = platform_get_drvdata(pdev); 249 struct device_node *np = pdev->dev.of_node; 250 unsigned int i; 251 const __be32 *val; 252 int len; 253 254 if (!np) 255 return 0; 256 hw->gpio_cs_count = of_gpio_count(np); 257 if (hw->gpio_cs_count > 0) { 258 hw->gpio_cs = devm_kzalloc(&pdev->dev, 259 hw->gpio_cs_count * sizeof(unsigned int), 260 GFP_KERNEL); 261 if (!hw->gpio_cs) 262 return -ENOMEM; 263 } 264 for (i = 0; i < hw->gpio_cs_count; i++) { 265 hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL); 266 if (hw->gpio_cs[i] < 0) 267 return -ENODEV; 268 } 269 hw->bitbang.master->dev.of_node = pdev->dev.of_node; 270 val = of_get_property(pdev->dev.of_node, 271 "clock-frequency", &len); 272 if (val && len >= sizeof(__be32)) 273 hw->freq = be32_to_cpup(val); 274 val = of_get_property(pdev->dev.of_node, "baud-width", &len); 275 if (val && len >= sizeof(__be32)) 276 hw->baudwidth = be32_to_cpup(val); 277 return 0; 278 } 279 #else /* !CONFIG_OF */ 280 static int tiny_spi_of_probe(struct platform_device *pdev) 281 { 282 return 0; 283 } 284 #endif /* CONFIG_OF */ 285 286 static int tiny_spi_probe(struct platform_device *pdev) 287 { 288 struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); 289 struct tiny_spi *hw; 290 struct spi_master *master; 291 struct resource *res; 292 unsigned int i; 293 int err = -ENODEV; 294 295 master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); 296 if (!master) 297 return err; 298 299 /* setup the master state. */ 300 master->bus_num = pdev->id; 301 master->num_chipselect = 255; 302 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 303 master->setup = tiny_spi_setup; 304 305 hw = spi_master_get_devdata(master); 306 platform_set_drvdata(pdev, hw); 307 308 /* setup the state for the bitbang driver */ 309 hw->bitbang.master = master; 310 if (!hw->bitbang.master) 311 return err; 312 hw->bitbang.setup_transfer = tiny_spi_setup_transfer; 313 hw->bitbang.chipselect = tiny_spi_chipselect; 314 hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; 315 316 /* find and map our resources */ 317 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 318 hw->base = devm_ioremap_resource(&pdev->dev, res); 319 if (IS_ERR(hw->base)) { 320 err = PTR_ERR(hw->base); 321 goto exit; 322 } 323 /* irq is optional */ 324 hw->irq = platform_get_irq(pdev, 0); 325 if (hw->irq >= 0) { 326 init_completion(&hw->done); 327 err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0, 328 pdev->name, hw); 329 if (err) 330 goto exit; 331 } 332 /* find platform data */ 333 if (platp) { 334 hw->gpio_cs_count = platp->gpio_cs_count; 335 hw->gpio_cs = platp->gpio_cs; 336 if (platp->gpio_cs_count && !platp->gpio_cs) { 337 err = -EBUSY; 338 goto exit; 339 } 340 hw->freq = platp->freq; 341 hw->baudwidth = platp->baudwidth; 342 } else { 343 err = tiny_spi_of_probe(pdev); 344 if (err) 345 goto exit; 346 } 347 for (i = 0; i < hw->gpio_cs_count; i++) { 348 err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev)); 349 if (err) 350 goto exit_gpio; 351 gpio_direction_output(hw->gpio_cs[i], 1); 352 } 353 hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count); 354 355 /* register our spi controller */ 356 err = spi_bitbang_start(&hw->bitbang); 357 if (err) 358 goto exit; 359 dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); 360 361 return 0; 362 363 exit_gpio: 364 while (i-- > 0) 365 gpio_free(hw->gpio_cs[i]); 366 exit: 367 spi_master_put(master); 368 return err; 369 } 370 371 static int tiny_spi_remove(struct platform_device *pdev) 372 { 373 struct tiny_spi *hw = platform_get_drvdata(pdev); 374 struct spi_master *master = hw->bitbang.master; 375 unsigned int i; 376 377 spi_bitbang_stop(&hw->bitbang); 378 for (i = 0; i < hw->gpio_cs_count; i++) 379 gpio_free(hw->gpio_cs[i]); 380 spi_master_put(master); 381 return 0; 382 } 383 384 #ifdef CONFIG_OF 385 static const struct of_device_id tiny_spi_match[] = { 386 { .compatible = "opencores,tiny-spi-rtlsvn2", }, 387 {}, 388 }; 389 MODULE_DEVICE_TABLE(of, tiny_spi_match); 390 #endif /* CONFIG_OF */ 391 392 static struct platform_driver tiny_spi_driver = { 393 .probe = tiny_spi_probe, 394 .remove = tiny_spi_remove, 395 .driver = { 396 .name = DRV_NAME, 397 .owner = THIS_MODULE, 398 .pm = NULL, 399 .of_match_table = of_match_ptr(tiny_spi_match), 400 }, 401 }; 402 module_platform_driver(tiny_spi_driver); 403 404 MODULE_DESCRIPTION("OpenCores tiny SPI driver"); 405 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); 406 MODULE_LICENSE("GPL"); 407 MODULE_ALIAS("platform:" DRV_NAME); 408