Root/target/linux/cns3xxx/patches-3.3/052-cns3xxx_spi.patch

1--- a/drivers/spi/Kconfig
2+++ b/drivers/spi/Kconfig
3@@ -117,6 +117,13 @@ config SPI_BUTTERFLY
4       inexpensive battery powered microcontroller evaluation board.
5       This same cable can be used to flash new firmware.
6 
7+config SPI_CNS3XXX
8+ tristate "CNS3XXX SPI controller"
9+ depends on ARCH_CNS3XXX && SPI_MASTER
10+ select SPI_BITBANG
11+ help
12+ This enables using the CNS3XXX SPI controller in master mode.
13+
14 config SPI_COLDFIRE_QSPI
15     tristate "Freescale Coldfire QSPI controller"
16     depends on (M520x || M523x || M5249 || M527x || M528x || M532x)
17--- a/drivers/spi/Makefile
18+++ b/drivers/spi/Makefile
19@@ -18,6 +18,7 @@ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.
20 obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
21 obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
22 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
23+obj-$(CONFIG_SPI_CNS3XXX) += spi_cns3xxx.o
24 obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
25 obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
26 obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
27--- /dev/null
28+++ b/drivers/spi/spi_cns3xxx.c
29@@ -0,0 +1,449 @@
30+/*******************************************************************************
31+ *
32+ * CNS3XXX SPI controller driver (master mode only)
33+ *
34+ * Copyright (c) 2008 Cavium Networks
35+ * Copyright 2011 Gateworks Corporation
36+ * Chris Lang <clang@gateworks.com>
37+ *
38+ * This file is free software; you can redistribute it and/or modify
39+ * it under the terms of the GNU General Public License, Version 2, as
40+ * published by the Free Software Foundation.
41+ *
42+ * This file is distributed in the hope that it will be useful,
43+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
44+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
45+ * NONINFRINGEMENT. See the GNU General Public License for more details.
46+ *
47+ * You should have received a copy of the GNU General Public License
48+ * along with this file; if not, write to the Free Software
49+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
50+ * visit http://www.gnu.org/licenses/.
51+ *
52+ * This file may also be available under a different license from Cavium.
53+ * Contact Cavium Networks for more information
54+ *
55+ ******************************************************************************/
56+
57+#include <linux/init.h>
58+#include <linux/spinlock.h>
59+#include <linux/workqueue.h>
60+#include <linux/interrupt.h>
61+#include <linux/delay.h>
62+#include <linux/errno.h>
63+#include <linux/err.h>
64+#include <linux/clk.h>
65+#include <linux/platform_device.h>
66+
67+#include <linux/spi/spi.h>
68+#include <linux/spi/spi_bitbang.h>
69+#include <linux/mtd/partitions.h>
70+#include <linux/dma-mapping.h>
71+#include <linux/slab.h>
72+
73+#include <asm/io.h>
74+#include <asm/memory.h>
75+#include <asm/dma.h>
76+#include <asm/delay.h>
77+#include <mach/cns3xxx.h>
78+#include <linux/module.h>
79+#include <mach/pm.h>
80+
81+/*
82+ * define access macros
83+ */
84+#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(CNS3XXX_SSP_BASE_VIRT + reg_offset)))
85+
86+#define SPI_CONFIGURATION_REG SPI_MEM_MAP_VALUE(0x40)
87+#define SPI_SERVICE_STATUS_REG SPI_MEM_MAP_VALUE(0x44)
88+#define SPI_BIT_RATE_CONTROL_REG SPI_MEM_MAP_VALUE(0x48)
89+#define SPI_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x4C)
90+#define SPI_TRANSMIT_BUFFER_REG SPI_MEM_MAP_VALUE(0x50)
91+#define SPI_RECEIVE_CONTROL_REG SPI_MEM_MAP_VALUE(0x54)
92+#define SPI_RECEIVE_BUFFER_REG SPI_MEM_MAP_VALUE(0x58)
93+#define SPI_FIFO_TRANSMIT_CONFIG_REG SPI_MEM_MAP_VALUE(0x5C)
94+#define SPI_FIFO_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x60)
95+#define SPI_FIFO_RECEIVE_CONFIG_REG SPI_MEM_MAP_VALUE(0x64)
96+#define SPI_INTERRUPT_STATUS_REG SPI_MEM_MAP_VALUE(0x68)
97+#define SPI_INTERRUPT_ENABLE_REG SPI_MEM_MAP_VALUE(0x6C)
98+
99+#define SPI_TRANSMIT_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x50)
100+#define SPI_RECEIVE_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x58)
101+
102+/* Structure for SPI controller of CNS3XXX SOCs */
103+struct cns3xxx_spi {
104+ /* bitbang has to be first */
105+ struct spi_bitbang bitbang;
106+ struct completion done;
107+ wait_queue_head_t wait;
108+
109+ int len;
110+ int count;
111+ int last_in_message_list;
112+
113+ /* data buffers */
114+ const unsigned char *tx;
115+ unsigned char *rx;
116+
117+ struct spi_master *master;
118+ struct platform_device *pdev;
119+ struct device *dev;
120+};
121+
122+static inline u8 cns3xxx_spi_bus_idle(void)
123+{
124+ return ((SPI_SERVICE_STATUS_REG & 0x1) ? 0 : 1);
125+}
126+
127+static inline u8 cns3xxx_spi_tx_buffer_empty(void)
128+{
129+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 3)) ? 1 : 0);
130+}
131+
132+static inline u8 cns3xxx_spi_rx_buffer_full(void)
133+{
134+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 2)) ? 1 : 0);
135+}
136+
137+u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data,
138+ u32 * rx_data)
139+{
140+ u8 rx_channel;
141+ u8 rx_eof;
142+
143+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
144+
145+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
146+
147+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
148+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
149+
150+ SPI_TRANSMIT_BUFFER_REG = tx_data;
151+
152+ while (!cns3xxx_spi_rx_buffer_full()) ; // do nothing
153+
154+ rx_channel = SPI_RECEIVE_CONTROL_REG & 0x3;
155+ rx_eof = (SPI_RECEIVE_CONTROL_REG & (0x1 << 2)) ? 1 : 0;
156+
157+ *rx_data = SPI_RECEIVE_BUFFER_REG;
158+
159+ if ((tx_channel != rx_channel) || (tx_eof != rx_eof)) {
160+ return 0;
161+ } else {
162+ return 1;
163+ }
164+}
165+
166+u8 cns3xxx_spi_tx(u8 tx_channel, u8 tx_eof, u32 tx_data)
167+{
168+
169+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
170+
171+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
172+
173+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
174+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
175+
176+ SPI_TRANSMIT_BUFFER_REG = tx_data;
177+
178+ return 1;
179+}
180+
181+static inline struct cns3xxx_spi *to_hw(struct spi_device *sdev)
182+{
183+ return spi_master_get_devdata(sdev->master);
184+}
185+
186+static int cns3xxx_spi_setup_transfer(struct spi_device *spi,
187+ struct spi_transfer *t)
188+{
189+ return 0;
190+}
191+
192+static void cns3xxx_spi_chipselect(struct spi_device *spi, int value)
193+{
194+ unsigned int spi_config;
195+
196+ switch (value) {
197+ case BITBANG_CS_INACTIVE:
198+ break;
199+
200+ case BITBANG_CS_ACTIVE:
201+ spi_config = SPI_CONFIGURATION_REG;
202+
203+ if (spi->mode & SPI_CPHA)
204+ spi_config |= (0x1 << 13);
205+ else
206+ spi_config &= ~(0x1 << 13);
207+
208+ if (spi->mode & SPI_CPOL)
209+ spi_config |= (0x1 << 14);
210+ else
211+ spi_config &= ~(0x1 << 14);
212+
213+ /* write new configration */
214+ SPI_CONFIGURATION_REG = spi_config;
215+
216+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
217+ SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3);
218+
219+ break;
220+ }
221+}
222+
223+static int cns3xxx_spi_setup(struct spi_device *spi)
224+{
225+ if (!spi->bits_per_word)
226+ spi->bits_per_word = 8;
227+
228+ return 0;
229+}
230+
231+static int cns3xxx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
232+{
233+ struct cns3xxx_spi *hw = to_hw(spi);
234+
235+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf,
236+ t->len);
237+
238+ hw->tx = t->tx_buf;
239+ hw->rx = t->rx_buf;
240+ hw->len = t->len;
241+ hw->count = 0;
242+ hw->last_in_message_list = t->last_in_message_list;
243+
244+ init_completion(&hw->done);
245+
246+ if (hw->tx) {
247+ int i;
248+ u32 rx_data;
249+ for (i = 0; i < (hw->len - 1); i++) {
250+ dev_dbg(&spi->dev,
251+ "[SPI_CNS3XXX_DEBUG] hw->tx[%02d]: 0x%02x\n", i,
252+ hw->tx[i]);
253+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
254+ &rx_data);
255+ if (hw->rx) {
256+ hw->rx[i] = rx_data;
257+ dev_dbg(&spi->dev,
258+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
259+ i, hw->rx[i]);
260+ }
261+ }
262+
263+ if (t->last_in_message_list) {
264+ cns3xxx_spi_tx_rx(spi->chip_select, 1, hw->tx[i],
265+ &rx_data);
266+ if (hw->rx) {
267+ hw->rx[i] = rx_data;
268+ dev_dbg(&spi->dev,
269+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
270+ i, hw->rx[i]);
271+ }
272+ } else {
273+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
274+ &rx_data);
275+ }
276+ goto done;
277+ }
278+
279+ if (hw->rx) {
280+ int i;
281+ u32 rx_data;
282+ for (i = 0; i < (hw->len - 1); i++) {
283+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
284+ hw->rx[i] = rx_data;
285+ dev_dbg(&spi->dev,
286+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n", i,
287+ hw->rx[i]);
288+ }
289+
290+ if (t->last_in_message_list) {
291+ cns3xxx_spi_tx_rx(spi->chip_select, 1, 0xff, &rx_data);
292+ } else {
293+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
294+ }
295+ hw->rx[i] = rx_data;
296+ dev_dbg(&spi->dev, "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
297+ i, hw->rx[i]);
298+ }
299+done:
300+ return hw->len;
301+}
302+
303+static void __init cns3xxx_spi_initial(void)
304+{
305+ u32 __iomem *gpiob = __io(CNS3XXX_MISC_BASE_VIRT + 0x0018);
306+ u32 gpiob_pins = __raw_readl(gpiob);
307+
308+ /* MMC/SD pins share with GPIOA */
309+ gpiob_pins |= 0xf80;
310+ __raw_writel(gpiob_pins, gpiob);
311+
312+ /* share pin config. */
313+ //PM_PLL_HM_PD_CTRL_REG &= ~(0x1 << 5);
314+ //HAL_MISC_ENABLE_SPI_PINS();
315+ cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SPI_PCM_I2C));
316+ cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SPI_PCM_I2C));
317+
318+ SPI_CONFIGURATION_REG = (((0x0 & 0x3) << 0) | /* 8bits shift length */
319+ (0x0 << 9) | /* SPI mode */
320+ (0x0 << 10) | /* disable FIFO */
321+ (0x1 << 11) | /* SPI master mode */
322+ (0x0 << 12) | /* disable SPI loopback mode */
323+ (0x1 << 13) | /* clock phase */
324+ (0x1 << 14) | /* clock polarity */
325+ (0x0 << 24) | /* disable - SPI data swap */
326+ (0x1 << 29) | /* enable - 2IO Read mode */
327+ (0x0 << 30) | /* disable - SPI high speed read for system boot up */
328+ (0x0 << 31)); /* disable - SPI */
329+
330+ /* Set SPI bit rate PCLK/2 */
331+ SPI_BIT_RATE_CONTROL_REG = 0x1;
332+
333+ /* Set SPI Tx channel 0 */
334+ SPI_TRANSMIT_CONTROL_REG = 0x0;
335+
336+ /* Set Tx FIFO Threshold, Tx FIFO has 2 words */
337+ SPI_FIFO_TRANSMIT_CONFIG_REG &= ~(0x03 << 4);
338+ SPI_FIFO_TRANSMIT_CONFIG_REG |= ((0x0 & 0x03) << 4);
339+
340+ /* Set Rx FIFO Threshold, Rx FIFO has 2 words */
341+ SPI_FIFO_RECEIVE_CONFIG_REG &= ~(0x03 << 4);
342+ SPI_FIFO_RECEIVE_CONFIG_REG |= ((0x0 & 0x03) << 4);
343+
344+ /* Disable all interrupt */
345+ SPI_INTERRUPT_ENABLE_REG = 0x0;
346+
347+ /* Clear spurious interrupt sources */
348+ SPI_INTERRUPT_STATUS_REG = (0x0F << 4);
349+
350+ /* Enable SPI */
351+ SPI_CONFIGURATION_REG |= (0x1 << 31);
352+
353+ return;
354+}
355+
356+static int __devinit cns3xxx_spi_probe(struct platform_device *pdev)
357+{
358+ struct spi_master *master;
359+ struct cns3xxx_spi *hw;
360+ int err = 0;
361+
362+ printk("%s: setup CNS3XXX SPI Controller\n", __FUNCTION__);
363+
364+ /* Allocate master with space for cns3xxx_spi */
365+ master = spi_alloc_master(&pdev->dev, sizeof(struct cns3xxx_spi));
366+ if (master == NULL) {
367+ dev_err(&pdev->dev, "No memory for spi_master\n");
368+ err = -ENOMEM;
369+ goto err_nomem;
370+ }
371+
372+ hw = spi_master_get_devdata(master);
373+ memset(hw, 0, sizeof(struct cns3xxx_spi));
374+
375+ hw->master = spi_master_get(master);
376+ hw->dev = &pdev->dev;
377+
378+ platform_set_drvdata(pdev, hw);
379+ init_completion(&hw->done);
380+
381+ /* setup the master state. */
382+
383+ master->num_chipselect = 4;
384+ master->bus_num = 1;
385+
386+ /* setup the state for the bitbang driver */
387+
388+ hw->bitbang.master = hw->master;
389+ hw->bitbang.setup_transfer = cns3xxx_spi_setup_transfer;
390+ hw->bitbang.chipselect = cns3xxx_spi_chipselect;
391+ hw->bitbang.txrx_bufs = cns3xxx_spi_txrx;
392+ hw->bitbang.master->setup = cns3xxx_spi_setup;
393+
394+ dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
395+
396+ /* SPI controller initializations */
397+ cns3xxx_spi_initial();
398+
399+ /* register SPI controller */
400+
401+ err = spi_bitbang_start(&hw->bitbang);
402+ if (err) {
403+ dev_err(&pdev->dev, "Failed to register SPI master\n");
404+ goto err_register;
405+ }
406+
407+ return 0;
408+
409+err_register:
410+ spi_master_put(hw->master);;
411+
412+err_nomem:
413+ return err;
414+}
415+
416+static int __devexit cns3xxx_spi_remove(struct platform_device *dev)
417+{
418+ struct cns3xxx_spi *hw = platform_get_drvdata(dev);
419+
420+ platform_set_drvdata(dev, NULL);
421+
422+ spi_unregister_master(hw->master);
423+
424+ spi_master_put(hw->master);
425+ return 0;
426+}
427+
428+#ifdef CONFIG_PM
429+
430+static int cns3xxx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
431+{
432+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
433+
434+ return 0;
435+}
436+
437+static int cns3xxx_spi_resume(struct platform_device *pdev)
438+{
439+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
440+
441+ return 0;
442+}
443+
444+#else
445+#define cns3xxx_spi_suspend NULL
446+#define cns3xxx_spi_resume NULL
447+#endif
448+
449+static struct platform_driver cns3xxx_spi_driver = {
450+ .probe = cns3xxx_spi_probe,
451+ .remove = __devexit_p(cns3xxx_spi_remove),
452+ .suspend = cns3xxx_spi_suspend,
453+ .resume = cns3xxx_spi_resume,
454+ .driver = {
455+ .name = "cns3xxx_spi",
456+ .owner = THIS_MODULE,
457+ },
458+};
459+
460+static int __init cns3xxx_spi_init(void)
461+{
462+ return platform_driver_register(&cns3xxx_spi_driver);
463+}
464+
465+static void __exit cns3xxx_spi_exit(void)
466+{
467+ platform_driver_unregister(&cns3xxx_spi_driver);
468+}
469+
470+module_init(cns3xxx_spi_init);
471+module_exit(cns3xxx_spi_exit);
472+
473+MODULE_AUTHOR("Cavium Networks");
474+MODULE_DESCRIPTION("CNS3XXX SPI Controller Driver");
475+MODULE_LICENSE("GPL");
476+MODULE_ALIAS("platform:cns3xxx_spi");
477+
478+EXPORT_SYMBOL_GPL(cns3xxx_spi_tx_rx);
479--- a/include/linux/spi/spi.h
480+++ b/include/linux/spi/spi.h
481@@ -508,6 +508,13 @@ struct spi_transfer {
482     u32 speed_hz;
483 
484     struct list_head transfer_list;
485+
486+#ifdef CONFIG_ARCH_CNS3XXX
487+ unsigned last_in_message_list;
488+#ifdef CONFIG_SPI_CNS3XXX_2IOREAD
489+ u8 dio_read;
490+#endif
491+#endif
492 };
493 
494 /**
495--- a/drivers/spi/spi-bitbang.c
496+++ b/drivers/spi/spi-bitbang.c
497@@ -330,6 +330,12 @@ static void bitbang_work(struct work_str
498                  */
499                 if (!m->is_dma_mapped)
500                     t->rx_dma = t->tx_dma = 0;
501+
502+ if (t->transfer_list.next == &m->transfers)
503+ t->last_in_message_list = 1;
504+ else
505+ t->last_in_message_list = 0;
506+
507                 status = bitbang->txrx_bufs(spi, t);
508             }
509             if (status > 0)
510

Archive Download this file



interactive