aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-falcon.c
diff options
context:
space:
mode:
authorThomas Langer <thomas.langer@lantiq.com>2012-05-20 09:46:19 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-07-23 08:56:30 -0400
commit6cd3c7e2b1dc1e3cc28ffcef074d0b8182b6e501 (patch)
tree20bfd21682c45fa286334b66ce411d5331fbf176 /drivers/spi/spi-falcon.c
parent28a33cbc24e4256c143dce96c7d93bf423229f92 (diff)
SPI: MIPS: lantiq: add FALCON spi driver
The external bus unit (EBU) found on the FALCON SoC has spi emulation that is designed for serial flash access. This driver has only been tested with m25p80 type chips. The hardware has no support for other types of spi peripherals. Signed-off-by: Thomas Langer <thomas.langer@lantiq.com> Signed-off-by: John Crispin <blogic@openwrt.org> Cc: spi-devel-general@lists.sourceforge.net Cc: linux-mips@linux-mips.org Acked-by: Grant Likely <grant.likely@secretlab.ca> Patchwork: https://patchwork.linux-mips.org/patch/3844/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/spi/spi-falcon.c')
-rw-r--r--drivers/spi/spi-falcon.c469
1 files changed, 469 insertions, 0 deletions
diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c
new file mode 100644
index 000000000000..8f6aa735a24c
--- /dev/null
+++ b/drivers/spi/spi-falcon.c
@@ -0,0 +1,469 @@
1/*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License version 2 as published
4 * by the Free Software Foundation.
5 *
6 * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
7 */
8
9#include <linux/module.h>
10#include <linux/device.h>
11#include <linux/platform_device.h>
12#include <linux/spi/spi.h>
13#include <linux/delay.h>
14#include <linux/workqueue.h>
15#include <linux/of.h>
16#include <linux/of_platform.h>
17
18#include <lantiq_soc.h>
19
20#define DRV_NAME "sflash-falcon"
21
22#define FALCON_SPI_XFER_BEGIN (1 << 0)
23#define FALCON_SPI_XFER_END (1 << 1)
24
25/* Bus Read Configuration Register0 */
26#define BUSRCON0 0x00000010
27/* Bus Write Configuration Register0 */
28#define BUSWCON0 0x00000018
29/* Serial Flash Configuration Register */
30#define SFCON 0x00000080
31/* Serial Flash Time Register */
32#define SFTIME 0x00000084
33/* Serial Flash Status Register */
34#define SFSTAT 0x00000088
35/* Serial Flash Command Register */
36#define SFCMD 0x0000008C
37/* Serial Flash Address Register */
38#define SFADDR 0x00000090
39/* Serial Flash Data Register */
40#define SFDATA 0x00000094
41/* Serial Flash I/O Control Register */
42#define SFIO 0x00000098
43/* EBU Clock Control Register */
44#define EBUCC 0x000000C4
45
46/* Dummy Phase Length */
47#define SFCMD_DUMLEN_OFFSET 16
48#define SFCMD_DUMLEN_MASK 0x000F0000
49/* Chip Select */
50#define SFCMD_CS_OFFSET 24
51#define SFCMD_CS_MASK 0x07000000
52/* field offset */
53#define SFCMD_ALEN_OFFSET 20
54#define SFCMD_ALEN_MASK 0x00700000
55/* SCK Rise-edge Position */
56#define SFTIME_SCKR_POS_OFFSET 8
57#define SFTIME_SCKR_POS_MASK 0x00000F00
58/* SCK Period */
59#define SFTIME_SCK_PER_OFFSET 0
60#define SFTIME_SCK_PER_MASK 0x0000000F
61/* SCK Fall-edge Position */
62#define SFTIME_SCKF_POS_OFFSET 12
63#define SFTIME_SCKF_POS_MASK 0x0000F000
64/* Device Size */
65#define SFCON_DEV_SIZE_A23_0 0x03000000
66#define SFCON_DEV_SIZE_MASK 0x0F000000
67/* Read Data Position */
68#define SFTIME_RD_POS_MASK 0x000F0000
69/* Data Output */
70#define SFIO_UNUSED_WD_MASK 0x0000000F
71/* Command Opcode mask */
72#define SFCMD_OPC_MASK 0x000000FF
73/* dlen bytes of data to write */
74#define SFCMD_DIR_WRITE 0x00000100
75/* Data Length offset */
76#define SFCMD_DLEN_OFFSET 9
77/* Command Error */
78#define SFSTAT_CMD_ERR 0x20000000
79/* Access Command Pending */
80#define SFSTAT_CMD_PEND 0x00400000
81/* Frequency set to 100MHz. */
82#define EBUCC_EBUDIV_SELF100 0x00000001
83/* Serial Flash */
84#define BUSRCON0_AGEN_SERIAL_FLASH 0xF0000000
85/* 8-bit multiplexed */
86#define BUSRCON0_PORTW_8_BIT_MUX 0x00000000
87/* Serial Flash */
88#define BUSWCON0_AGEN_SERIAL_FLASH 0xF0000000
89/* Chip Select after opcode */
90#define SFCMD_KEEP_CS_KEEP_SELECTED 0x00008000
91
92#define CLOCK_100M 100000000
93#define CLOCK_50M 50000000
94
95struct falcon_sflash {
96 u32 sfcmd; /* for caching of opcode, direction, ... */
97 struct spi_master *master;
98};
99
100int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t,
101 unsigned long flags)
102{
103 struct device *dev = &spi->dev;
104 struct falcon_sflash *priv = spi_master_get_devdata(spi->master);
105 const u8 *txp = t->tx_buf;
106 u8 *rxp = t->rx_buf;
107 unsigned int bytelen = ((8 * t->len + 7) / 8);
108 unsigned int len, alen, dumlen;
109 u32 val;
110 enum {
111 state_init,
112 state_command_prepare,
113 state_write,
114 state_read,
115 state_disable_cs,
116 state_end
117 } state = state_init;
118
119 do {
120 switch (state) {
121 case state_init: /* detect phase of upper layer sequence */
122 {
123 /* initial write ? */
124 if (flags & FALCON_SPI_XFER_BEGIN) {
125 if (!txp) {
126 dev_err(dev,
127 "BEGIN without tx data!\n");
128 return -ENODATA;
129 }
130 /*
131 * Prepare the parts of the sfcmd register,
132 * which should not change during a sequence!
133 * Only exception are the length fields,
134 * especially alen and dumlen.
135 */
136
137 priv->sfcmd = ((spi->chip_select
138 << SFCMD_CS_OFFSET)
139 & SFCMD_CS_MASK);
140 priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED;
141 priv->sfcmd |= *txp;
142 txp++;
143 bytelen--;
144 if (bytelen) {
145 /*
146 * more data:
147 * maybe address and/or dummy
148 */
149 state = state_command_prepare;
150 break;
151 } else {
152 dev_dbg(dev, "write cmd %02X\n",
153 priv->sfcmd & SFCMD_OPC_MASK);
154 }
155 }
156 /* continued write ? */
157 if (txp && bytelen) {
158 state = state_write;
159 break;
160 }
161 /* read data? */
162 if (rxp && bytelen) {
163 state = state_read;
164 break;
165 }
166 /* end of sequence? */
167 if (flags & FALCON_SPI_XFER_END)
168 state = state_disable_cs;
169 else
170 state = state_end;
171 break;
172 }
173 /* collect tx data for address and dummy phase */
174 case state_command_prepare:
175 {
176 /* txp is valid, already checked */
177 val = 0;
178 alen = 0;
179 dumlen = 0;
180 while (bytelen > 0) {
181 if (alen < 3) {
182 val = (val << 8) | (*txp++);
183 alen++;
184 } else if ((dumlen < 15) && (*txp == 0)) {
185 /*
186 * assume dummy bytes are set to 0
187 * from upper layer
188 */
189 dumlen++;
190 txp++;
191 } else {
192 break;
193 }
194 bytelen--;
195 }
196 priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK);
197 priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) |
198 (dumlen << SFCMD_DUMLEN_OFFSET);
199 if (alen > 0)
200 ltq_ebu_w32(val, SFADDR);
201
202 dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n",
203 priv->sfcmd & SFCMD_OPC_MASK,
204 alen, val, dumlen);
205
206 if (bytelen > 0) {
207 /* continue with write */
208 state = state_write;
209 } else if (flags & FALCON_SPI_XFER_END) {
210 /* end of sequence? */
211 state = state_disable_cs;
212 } else {
213 /*
214 * go to end and expect another
215 * call (read or write)
216 */
217 state = state_end;
218 }
219 break;
220 }
221 case state_write:
222 {
223 /* txp still valid */
224 priv->sfcmd |= SFCMD_DIR_WRITE;
225 len = 0;
226 val = 0;
227 do {
228 if (bytelen--)
229 val |= (*txp++) << (8 * len++);
230 if ((flags & FALCON_SPI_XFER_END)
231 && (bytelen == 0)) {
232 priv->sfcmd &=
233 ~SFCMD_KEEP_CS_KEEP_SELECTED;
234 }
235 if ((len == 4) || (bytelen == 0)) {
236 ltq_ebu_w32(val, SFDATA);
237 ltq_ebu_w32(priv->sfcmd
238 | (len<<SFCMD_DLEN_OFFSET),
239 SFCMD);
240 len = 0;
241 val = 0;
242 priv->sfcmd &= ~(SFCMD_ALEN_MASK
243 | SFCMD_DUMLEN_MASK);
244 }
245 } while (bytelen);
246 state = state_end;
247 break;
248 }
249 case state_read:
250 {
251 /* read data */
252 priv->sfcmd &= ~SFCMD_DIR_WRITE;
253 do {
254 if ((flags & FALCON_SPI_XFER_END)
255 && (bytelen <= 4)) {
256 priv->sfcmd &=
257 ~SFCMD_KEEP_CS_KEEP_SELECTED;
258 }
259 len = (bytelen > 4) ? 4 : bytelen;
260 bytelen -= len;
261 ltq_ebu_w32(priv->sfcmd
262 | (len << SFCMD_DLEN_OFFSET), SFCMD);
263 priv->sfcmd &= ~(SFCMD_ALEN_MASK
264 | SFCMD_DUMLEN_MASK);
265 do {
266 val = ltq_ebu_r32(SFSTAT);
267 if (val & SFSTAT_CMD_ERR) {
268 /* reset error status */
269 dev_err(dev, "SFSTAT: CMD_ERR");
270 dev_err(dev, " (%x)\n", val);
271 ltq_ebu_w32(SFSTAT_CMD_ERR,
272 SFSTAT);
273 return -EBADE;
274 }
275 } while (val & SFSTAT_CMD_PEND);
276 val = ltq_ebu_r32(SFDATA);
277 do {
278 *rxp = (val & 0xFF);
279 rxp++;
280 val >>= 8;
281 len--;
282 } while (len);
283 } while (bytelen);
284 state = state_end;
285 break;
286 }
287 case state_disable_cs:
288 {
289 priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED;
290 ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET),
291 SFCMD);
292 val = ltq_ebu_r32(SFSTAT);
293 if (val & SFSTAT_CMD_ERR) {
294 /* reset error status */
295 dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val);
296 ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT);
297 return -EBADE;
298 }
299 state = state_end;
300 break;
301 }
302 case state_end:
303 break;
304 }
305 } while (state != state_end);
306
307 return 0;
308}
309
310static int falcon_sflash_setup(struct spi_device *spi)
311{
312 unsigned int i;
313 unsigned long flags;
314
315 if (spi->chip_select > 0)
316 return -ENODEV;
317
318 spin_lock_irqsave(&ebu_lock, flags);
319
320 if (spi->max_speed_hz >= CLOCK_100M) {
321 /* set EBU clock to 100 MHz */
322 ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC);
323 i = 1; /* divider */
324 } else {
325 /* set EBU clock to 50 MHz */
326 ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC);
327
328 /* search for suitable divider */
329 for (i = 1; i < 7; i++) {
330 if (CLOCK_50M / i <= spi->max_speed_hz)
331 break;
332 }
333 }
334
335 /* setup period of serial clock */
336 ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK
337 | SFTIME_SCKR_POS_MASK
338 | SFTIME_SCK_PER_MASK,
339 (i << SFTIME_SCKR_POS_OFFSET)
340 | (i << (SFTIME_SCK_PER_OFFSET + 1)),
341 SFTIME);
342
343 /*
344 * set some bits of unused_wd, to not trigger HOLD/WP
345 * signals on non QUAD flashes
346 */
347 ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO);
348
349 ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
350 BUSRCON0);
351 ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0);
352 /* set address wrap around to maximum for 24-bit addresses */
353 ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON);
354
355 spin_unlock_irqrestore(&ebu_lock, flags);
356
357 return 0;
358}
359
360static int falcon_sflash_prepare_xfer(struct spi_master *master)
361{
362 return 0;
363}
364
365static int falcon_sflash_unprepare_xfer(struct spi_master *master)
366{
367 return 0;
368}
369
370static int falcon_sflash_xfer_one(struct spi_master *master,
371 struct spi_message *m)
372{
373 struct falcon_sflash *priv = spi_master_get_devdata(master);
374 struct spi_transfer *t;
375 unsigned long spi_flags;
376 unsigned long flags;
377 int ret = 0;
378
379 priv->sfcmd = 0;
380 m->actual_length = 0;
381
382 spi_flags = FALCON_SPI_XFER_BEGIN;
383 list_for_each_entry(t, &m->transfers, transfer_list) {
384 if (list_is_last(&t->transfer_list, &m->transfers))
385 spi_flags |= FALCON_SPI_XFER_END;
386
387 spin_lock_irqsave(&ebu_lock, flags);
388 ret = falcon_sflash_xfer(m->spi, t, spi_flags);
389 spin_unlock_irqrestore(&ebu_lock, flags);
390
391 if (ret)
392 break;
393
394 m->actual_length += t->len;
395
396 WARN_ON(t->delay_usecs || t->cs_change);
397 spi_flags = 0;
398 }
399
400 m->status = ret;
401 m->complete(m->context);
402
403 return 0;
404}
405
406static int __devinit falcon_sflash_probe(struct platform_device *pdev)
407{
408 struct falcon_sflash *priv;
409 struct spi_master *master;
410 int ret;
411
412 if (ltq_boot_select() != BS_SPI) {
413 dev_err(&pdev->dev, "invalid bootstrap options\n");
414 return -ENODEV;
415 }
416
417 master = spi_alloc_master(&pdev->dev, sizeof(*priv));
418 if (!master)
419 return -ENOMEM;
420
421 priv = spi_master_get_devdata(master);
422 priv->master = master;
423
424 master->mode_bits = SPI_MODE_3;
425 master->num_chipselect = 1;
426 master->bus_num = -1;
427 master->setup = falcon_sflash_setup;
428 master->prepare_transfer_hardware = falcon_sflash_prepare_xfer;
429 master->transfer_one_message = falcon_sflash_xfer_one;
430 master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer;
431 master->dev.of_node = pdev->dev.of_node;
432
433 platform_set_drvdata(pdev, priv);
434
435 ret = spi_register_master(master);
436 if (ret)
437 spi_master_put(master);
438 return ret;
439}
440
441static int __devexit falcon_sflash_remove(struct platform_device *pdev)
442{
443 struct falcon_sflash *priv = platform_get_drvdata(pdev);
444
445 spi_unregister_master(priv->master);
446
447 return 0;
448}
449
450static const struct of_device_id falcon_sflash_match[] = {
451 { .compatible = "lantiq,sflash-falcon" },
452 {},
453};
454MODULE_DEVICE_TABLE(of, falcon_sflash_match);
455
456static struct platform_driver falcon_sflash_driver = {
457 .probe = falcon_sflash_probe,
458 .remove = __devexit_p(falcon_sflash_remove),
459 .driver = {
460 .name = DRV_NAME,
461 .owner = THIS_MODULE,
462 .of_match_table = falcon_sflash_match,
463 }
464};
465
466module_platform_driver(falcon_sflash_driver);
467
468MODULE_LICENSE("GPL");
469MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver");