4 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
6 * Based on spi_s3c24xx.c, which is:
7 * Copyright (c) 2006 Ben Dooks
8 * Copyright (c) 2006 Simtec Electronics
9 * Ben Dooks <ben@simtec.co.uk>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <linux/errno.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/spi/spi.h>
22 #include <linux/spi/spi_bitbang.h>
26 #define DRV_NAME "spi_altera"
28 #define ALTERA_SPI_RXDATA 0
29 #define ALTERA_SPI_TXDATA 4
30 #define ALTERA_SPI_STATUS 8
31 #define ALTERA_SPI_CONTROL 12
32 #define ALTERA_SPI_SLAVE_SEL 20
34 #define ALTERA_SPI_STATUS_ROE_MSK 0x8
35 #define ALTERA_SPI_STATUS_TOE_MSK 0x10
36 #define ALTERA_SPI_STATUS_TMT_MSK 0x20
37 #define ALTERA_SPI_STATUS_TRDY_MSK 0x40
38 #define ALTERA_SPI_STATUS_RRDY_MSK 0x80
39 #define ALTERA_SPI_STATUS_E_MSK 0x100
41 #define ALTERA_SPI_CONTROL_IROE_MSK 0x8
42 #define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
43 #define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
44 #define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
45 #define ALTERA_SPI_CONTROL_IE_MSK 0x100
46 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
49 /* bitbang has to be first */
50 struct spi_bitbang bitbang
;
51 struct completion done
;
61 const unsigned char *tx
;
65 static inline struct altera_spi
*altera_spi_to_hw(struct spi_device
*sdev
)
67 return spi_master_get_devdata(sdev
->master
);
70 static void altera_spi_chipsel(struct spi_device
*spi
, int value
)
72 struct altera_spi
*hw
= altera_spi_to_hw(spi
);
74 if (spi
->mode
& SPI_CS_HIGH
) {
76 case BITBANG_CS_INACTIVE
:
77 writel(1 << spi
->chip_select
,
78 hw
->base
+ ALTERA_SPI_SLAVE_SEL
);
79 hw
->imr
|= ALTERA_SPI_CONTROL_SSO_MSK
;
80 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
83 case BITBANG_CS_ACTIVE
:
84 hw
->imr
&= ~ALTERA_SPI_CONTROL_SSO_MSK
;
85 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
86 writel(0, hw
->base
+ ALTERA_SPI_SLAVE_SEL
);
91 case BITBANG_CS_INACTIVE
:
92 hw
->imr
&= ~ALTERA_SPI_CONTROL_SSO_MSK
;
93 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
96 case BITBANG_CS_ACTIVE
:
97 writel(1 << spi
->chip_select
,
98 hw
->base
+ ALTERA_SPI_SLAVE_SEL
);
99 hw
->imr
|= ALTERA_SPI_CONTROL_SSO_MSK
;
100 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
106 static int altera_spi_setupxfer(struct spi_device
*spi
, struct spi_transfer
*t
)
111 static int altera_spi_setup(struct spi_device
*spi
)
116 static inline unsigned int hw_txbyte(struct altera_spi
*hw
, int count
)
119 switch (hw
->bytes_per_word
) {
121 return hw
->tx
[count
];
123 return (hw
->tx
[count
* 2]
124 | (hw
->tx
[count
* 2 + 1] << 8));
130 static int altera_spi_txrx(struct spi_device
*spi
, struct spi_transfer
*t
)
132 struct altera_spi
*hw
= altera_spi_to_hw(spi
);
137 hw
->bytes_per_word
= (t
->bits_per_word
? : spi
->bits_per_word
) / 8;
138 hw
->len
= t
->len
/ hw
->bytes_per_word
;
141 /* enable receive interrupt */
142 hw
->imr
|= ALTERA_SPI_CONTROL_IRRDY_MSK
;
143 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
145 /* send the first byte */
146 writel(hw_txbyte(hw
, 0), hw
->base
+ ALTERA_SPI_TXDATA
);
148 wait_for_completion(&hw
->done
);
149 /* disable receive interrupt */
150 hw
->imr
&= ~ALTERA_SPI_CONTROL_IRRDY_MSK
;
151 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
153 /* send the first byte */
154 writel(hw_txbyte(hw
, 0), hw
->base
+ ALTERA_SPI_TXDATA
);
159 while (!(readl(hw
->base
+ ALTERA_SPI_STATUS
) &
160 ALTERA_SPI_STATUS_RRDY_MSK
))
163 rxd
= readl(hw
->base
+ ALTERA_SPI_RXDATA
);
165 switch (hw
->bytes_per_word
) {
167 hw
->rx
[hw
->count
] = rxd
;
170 hw
->rx
[hw
->count
* 2] = rxd
;
171 hw
->rx
[hw
->count
* 2 + 1] = rxd
>> 8;
178 if (hw
->count
< hw
->len
)
179 writel(hw_txbyte(hw
, hw
->count
),
180 hw
->base
+ ALTERA_SPI_TXDATA
);
187 return hw
->count
* hw
->bytes_per_word
;
190 static irqreturn_t
altera_spi_irq(int irq
, void *dev
)
192 struct altera_spi
*hw
= dev
;
195 rxd
= readl(hw
->base
+ ALTERA_SPI_RXDATA
);
197 switch (hw
->bytes_per_word
) {
199 hw
->rx
[hw
->count
] = rxd
;
202 hw
->rx
[hw
->count
* 2] = rxd
;
203 hw
->rx
[hw
->count
* 2 + 1] = rxd
>> 8;
210 if (hw
->count
< hw
->len
)
211 writel(hw_txbyte(hw
, hw
->count
), hw
->base
+ ALTERA_SPI_TXDATA
);
218 static int __devinit
altera_spi_probe(struct platform_device
*pdev
)
220 struct altera_spi_platform_data
*platp
= pdev
->dev
.platform_data
;
221 struct altera_spi
*hw
;
222 struct spi_master
*master
;
223 struct resource
*res
;
226 master
= spi_alloc_master(&pdev
->dev
, sizeof(struct altera_spi
));
230 /* setup the master state. */
231 master
->bus_num
= pdev
->id
;
232 master
->num_chipselect
= 16;
233 master
->mode_bits
= SPI_CS_HIGH
;
234 master
->setup
= altera_spi_setup
;
236 hw
= spi_master_get_devdata(master
);
237 platform_set_drvdata(pdev
, hw
);
239 /* setup the state for the bitbang driver */
240 hw
->bitbang
.master
= spi_master_get(master
);
241 if (!hw
->bitbang
.master
)
243 hw
->bitbang
.setup_transfer
= altera_spi_setupxfer
;
244 hw
->bitbang
.chipselect
= altera_spi_chipsel
;
245 hw
->bitbang
.txrx_bufs
= altera_spi_txrx
;
247 /* find and map our resources */
248 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
251 if (!devm_request_mem_region(&pdev
->dev
, res
->start
, resource_size(res
),
254 hw
->base
= devm_ioremap_nocache(&pdev
->dev
, res
->start
,
258 /* program defaults into the registers */
259 hw
->imr
= 0; /* disable spi interrupts */
260 writel(hw
->imr
, hw
->base
+ ALTERA_SPI_CONTROL
);
261 writel(0, hw
->base
+ ALTERA_SPI_STATUS
); /* clear status reg */
262 if (readl(hw
->base
+ ALTERA_SPI_STATUS
) & ALTERA_SPI_STATUS_RRDY_MSK
)
263 readl(hw
->base
+ ALTERA_SPI_RXDATA
); /* flush rxdata */
264 /* irq is optional */
265 hw
->irq
= platform_get_irq(pdev
, 0);
267 init_completion(&hw
->done
);
268 err
= devm_request_irq(&pdev
->dev
, hw
->irq
, altera_spi_irq
, 0,
273 /* find platform data */
275 hw
->bitbang
.master
->dev
.of_node
= pdev
->dev
.of_node
;
277 /* register our spi controller */
278 err
= spi_bitbang_start(&hw
->bitbang
);
281 dev_info(&pdev
->dev
, "base %p, irq %d\n", hw
->base
, hw
->irq
);
288 platform_set_drvdata(pdev
, NULL
);
289 spi_master_put(master
);
293 static int __devexit
altera_spi_remove(struct platform_device
*dev
)
295 struct altera_spi
*hw
= platform_get_drvdata(dev
);
296 struct spi_master
*master
= hw
->bitbang
.master
;
298 spi_bitbang_stop(&hw
->bitbang
);
299 platform_set_drvdata(dev
, NULL
);
300 spi_master_put(master
);
305 static const struct of_device_id altera_spi_match
[] = {
306 { .compatible
= "ALTR,spi-1.0", },
309 MODULE_DEVICE_TABLE(of
, altera_spi_match
);
310 #else /* CONFIG_OF */
311 #define altera_spi_match NULL
312 #endif /* CONFIG_OF */
314 static struct platform_driver altera_spi_driver
= {
315 .probe
= altera_spi_probe
,
316 .remove
= __devexit_p(altera_spi_remove
),
319 .owner
= THIS_MODULE
,
321 .of_match_table
= altera_spi_match
,
325 static int __init
altera_spi_init(void)
327 return platform_driver_register(&altera_spi_driver
);
329 module_init(altera_spi_init
);
331 static void __exit
altera_spi_exit(void)
333 platform_driver_unregister(&altera_spi_driver
);
335 module_exit(altera_spi_exit
);
337 MODULE_DESCRIPTION("Altera SPI driver");
338 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
339 MODULE_LICENSE("GPL");
340 MODULE_ALIAS("platform:" DRV_NAME
);