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