2 * OpenCores tiny SPI master driver
4 * http://opencores.org/project,tiny_spi
6 * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
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>
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.
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>
26 #include <linux/gpio.h>
29 #define DRV_NAME "spi_oc_tiny"
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
37 #define TINY_SPI_STATUS_TXE 0x1
38 #define TINY_SPI_STATUS_TXR 0x2
41 /* bitbang has to be first */
42 struct spi_bitbang bitbang
;
43 struct completion done
;
48 unsigned int baudwidth
;
50 unsigned int speed_hz
;
53 unsigned int txc
, rxc
;
56 unsigned int gpio_cs_count
;
60 static inline struct tiny_spi
*tiny_spi_to_hw(struct spi_device
*sdev
)
62 return spi_master_get_devdata(sdev
->master
);
65 static unsigned int tiny_spi_baud(struct spi_device
*spi
, unsigned int hz
)
67 struct tiny_spi
*hw
= tiny_spi_to_hw(spi
);
69 return min(DIV_ROUND_UP(hw
->freq
, hz
* 2), (1U << hw
->baudwidth
)) - 1;
72 static void tiny_spi_chipselect(struct spi_device
*spi
, int is_active
)
74 struct tiny_spi
*hw
= tiny_spi_to_hw(spi
);
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
);
82 static int tiny_spi_setup_transfer(struct spi_device
*spi
,
83 struct spi_transfer
*t
)
85 struct tiny_spi
*hw
= tiny_spi_to_hw(spi
);
86 unsigned int baud
= hw
->baud
;
89 if (t
->speed_hz
&& t
->speed_hz
!= hw
->speed_hz
)
90 baud
= tiny_spi_baud(spi
, t
->speed_hz
);
92 writel(baud
, hw
->base
+ TINY_SPI_BAUD
);
93 writel(hw
->mode
, hw
->base
+ TINY_SPI_CONTROL
);
97 static int tiny_spi_setup(struct spi_device
*spi
)
99 struct tiny_spi
*hw
= tiny_spi_to_hw(spi
);
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
);
105 hw
->mode
= spi
->mode
& (SPI_CPOL
| SPI_CPHA
);
109 static inline void tiny_spi_wait_txr(struct tiny_spi
*hw
)
111 while (!(readb(hw
->base
+ TINY_SPI_STATUS
) &
112 TINY_SPI_STATUS_TXR
))
116 static inline void tiny_spi_wait_txe(struct tiny_spi
*hw
)
118 while (!(readb(hw
->base
+ TINY_SPI_STATUS
) &
119 TINY_SPI_STATUS_TXE
))
123 static int tiny_spi_txrx_bufs(struct spi_device
*spi
, struct spi_transfer
*t
)
125 struct tiny_spi
*hw
= tiny_spi_to_hw(spi
);
126 const u8
*txp
= t
->tx_buf
;
131 /* use intrrupt driven data transfer */
138 /* send the first byte */
140 writeb(hw
->txp
? *hw
->txp
++ : 0,
141 hw
->base
+ TINY_SPI_TXDATA
);
143 writeb(hw
->txp
? *hw
->txp
++ : 0,
144 hw
->base
+ TINY_SPI_TXDATA
);
146 writeb(TINY_SPI_STATUS_TXR
, hw
->base
+ TINY_SPI_STATUS
);
148 writeb(hw
->txp
? *hw
->txp
++ : 0,
149 hw
->base
+ TINY_SPI_TXDATA
);
151 writeb(TINY_SPI_STATUS_TXE
, hw
->base
+ TINY_SPI_STATUS
);
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
);
159 writeb(*txp
++, hw
->base
+ TINY_SPI_TXDATA
);
160 for (i
= 2; i
< t
->len
; i
++) {
162 tiny_spi_wait_txr(hw
);
163 rx
= readb(hw
->base
+ TINY_SPI_TXDATA
);
164 writeb(tx
, hw
->base
+ TINY_SPI_TXDATA
);
167 tiny_spi_wait_txr(hw
);
168 *rxp
++ = readb(hw
->base
+ TINY_SPI_TXDATA
);
170 tiny_spi_wait_txe(hw
);
171 *rxp
++ = readb(hw
->base
+ TINY_SPI_RXDATA
);
173 writeb(0, hw
->base
+ TINY_SPI_TXDATA
);
176 hw
->base
+ TINY_SPI_TXDATA
);
177 for (i
= 2; i
< t
->len
; i
++) {
179 tiny_spi_wait_txr(hw
);
180 rx
= readb(hw
->base
+ TINY_SPI_TXDATA
);
181 writeb(0, hw
->base
+ TINY_SPI_TXDATA
);
184 tiny_spi_wait_txr(hw
);
185 *rxp
++ = readb(hw
->base
+ TINY_SPI_TXDATA
);
187 tiny_spi_wait_txe(hw
);
188 *rxp
++ = readb(hw
->base
+ TINY_SPI_RXDATA
);
190 writeb(*txp
++, hw
->base
+ TINY_SPI_TXDATA
);
192 writeb(*txp
++, hw
->base
+ TINY_SPI_TXDATA
);
193 for (i
= 2; i
< t
->len
; i
++) {
195 tiny_spi_wait_txr(hw
);
196 writeb(tx
, hw
->base
+ TINY_SPI_TXDATA
);
199 tiny_spi_wait_txe(hw
);
201 writeb(0, hw
->base
+ TINY_SPI_TXDATA
);
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
);
209 tiny_spi_wait_txe(hw
);
214 static irqreturn_t
tiny_spi_irq(int irq
, void *dev
)
216 struct tiny_spi
*hw
= dev
;
218 writeb(0, hw
->base
+ TINY_SPI_STATUS
);
219 if (hw
->rxc
+ 1 == hw
->len
) {
221 *hw
->rxp
++ = readb(hw
->base
+ TINY_SPI_RXDATA
);
226 *hw
->rxp
++ = readb(hw
->base
+ TINY_SPI_TXDATA
);
228 if (hw
->txc
< hw
->len
) {
229 writeb(hw
->txp
? *hw
->txp
++ : 0,
230 hw
->base
+ TINY_SPI_TXDATA
);
232 writeb(TINY_SPI_STATUS_TXR
,
233 hw
->base
+ TINY_SPI_STATUS
);
235 writeb(TINY_SPI_STATUS_TXE
,
236 hw
->base
+ TINY_SPI_STATUS
);
243 #include <linux/of_gpio.h>
245 static int __devinit
tiny_spi_of_probe(struct platform_device
*pdev
)
247 struct tiny_spi
*hw
= platform_get_drvdata(pdev
);
248 struct device_node
*np
= pdev
->dev
.of_node
;
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),
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)
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
);
278 #else /* !CONFIG_OF */
279 static int __devinit
tiny_spi_of_probe(struct platform_device
*pdev
)
283 #endif /* CONFIG_OF */
285 static int __devinit
tiny_spi_probe(struct platform_device
*pdev
)
287 struct tiny_spi_platform_data
*platp
= pdev
->dev
.platform_data
;
289 struct spi_master
*master
;
290 struct resource
*res
;
294 master
= spi_alloc_master(&pdev
->dev
, sizeof(struct tiny_spi
));
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
;
304 hw
= spi_master_get_devdata(master
);
305 platform_set_drvdata(pdev
, hw
);
307 /* setup the state for the bitbang driver */
308 hw
->bitbang
.master
= spi_master_get(master
);
309 if (!hw
->bitbang
.master
)
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
;
315 /* find and map our resources */
316 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
319 if (!devm_request_mem_region(&pdev
->dev
, res
->start
, resource_size(res
),
322 hw
->base
= devm_ioremap_nocache(&pdev
->dev
, res
->start
,
326 /* irq is optional */
327 hw
->irq
= platform_get_irq(pdev
, 0);
329 init_completion(&hw
->done
);
330 err
= devm_request_irq(&pdev
->dev
, hw
->irq
, tiny_spi_irq
, 0,
335 /* find platform data */
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
)
341 hw
->freq
= platp
->freq
;
342 hw
->baudwidth
= platp
->baudwidth
;
344 err
= tiny_spi_of_probe(pdev
);
348 for (i
= 0; i
< hw
->gpio_cs_count
; i
++) {
349 err
= gpio_request(hw
->gpio_cs
[i
], dev_name(&pdev
->dev
));
352 gpio_direction_output(hw
->gpio_cs
[i
], 1);
354 hw
->bitbang
.master
->num_chipselect
= max(1U, hw
->gpio_cs_count
);
356 /* register our spi controller */
357 err
= spi_bitbang_start(&hw
->bitbang
);
360 dev_info(&pdev
->dev
, "base %p, irq %d\n", hw
->base
, hw
->irq
);
366 gpio_free(hw
->gpio_cs
[i
]);
370 platform_set_drvdata(pdev
, NULL
);
371 spi_master_put(master
);
375 static int __devexit
tiny_spi_remove(struct platform_device
*pdev
)
377 struct tiny_spi
*hw
= platform_get_drvdata(pdev
);
378 struct spi_master
*master
= hw
->bitbang
.master
;
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
);
390 static const struct of_device_id tiny_spi_match
[] = {
391 { .compatible
= "opencores,tiny-spi-rtlsvn2", },
394 MODULE_DEVICE_TABLE(of
, tiny_spi_match
);
395 #else /* CONFIG_OF */
396 #define tiny_spi_match NULL
397 #endif /* CONFIG_OF */
399 static struct platform_driver tiny_spi_driver
= {
400 .probe
= tiny_spi_probe
,
401 .remove
= __devexit_p(tiny_spi_remove
),
404 .owner
= THIS_MODULE
,
406 .of_match_table
= tiny_spi_match
,
410 static int __init
tiny_spi_init(void)
412 return platform_driver_register(&tiny_spi_driver
);
414 module_init(tiny_spi_init
);
416 static void __exit
tiny_spi_exit(void)
418 platform_driver_unregister(&tiny_spi_driver
);
420 module_exit(tiny_spi_exit
);
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
);