cf618e046d8cd5b07ebb41e8b99dbeb31ed67e6a
[openwrt.git] / target / linux / lantiq / patches-3.0 / 130-falcon-spi-flash.patch
1 --- a/drivers/spi/Makefile
2 +++ b/drivers/spi/Makefile
3 @@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_SH_SCI)              += spi_sh_sci.
4  obj-$(CONFIG_SPI_SH_MSIOF)             += spi_sh_msiof.o
5  obj-$(CONFIG_SPI_STMP3XXX)             += spi_stmp.o
6  obj-$(CONFIG_SPI_NUC900)               += spi_nuc900.o
7 +obj-$(CONFIG_SPI_FALCON)               += spi_falcon.o
8  
9  # special build for s3c24xx spi driver with fiq support
10  spi_s3c24xx_hw-y                       := spi_s3c24xx.o
11 --- /dev/null
12 +++ b/drivers/spi/spi_falcon.c
13 @@ -0,0 +1,471 @@
14 +/*
15 + *   This program is free software; you can redistribute it and/or modify
16 + *   it under the terms of the GNU General Public License as published by
17 + *   the Free Software Foundation; either version 2 of the License, or
18 + *   (at your option) any later version.
19 + *
20 + *   This program is distributed in the hope that it will be useful,
21 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
22 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 + *   GNU General Public License for more details.
24 + *
25 + *   You should have received a copy of the GNU General Public License
26 + *   along with this program; if not, write to the Free Software
27 + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
28 + */
29 +
30 +#include <linux/module.h>
31 +#include <linux/device.h>
32 +#include <linux/platform_device.h>
33 +#include <linux/spi/spi.h>
34 +#include <linux/delay.h>
35 +#include <linux/workqueue.h>
36 +
37 +#include <lantiq.h> /* ebu_lock */
38 +#include <falcon/ebu_reg.h>
39 +#include <falcon/sys1_reg.h>
40 +
41 +#define DRV_NAME                       "falcon_spi"
42 +
43 +#define FALCON_SPI_XFER_BEGIN          (1 << 0)
44 +#define FALCON_SPI_XFER_END            (1 << 1)
45 +
46 +/* mapping for access macros */
47 +#define reg_r32(reg)                   __raw_readl(reg)
48 +#define reg_w32(val, reg)              __raw_writel(val, reg)
49 +#define reg_w32_mask(clear, set, reg)  reg_w32((reg_r32(reg) \
50 +                                                & ~(clear)) | (set), reg)
51 +#define reg_r32_table(reg, idx)                reg_r32(&((uint32_t *)&reg)[idx])
52 +#define reg_w32_table(val, reg, idx)   reg_w32(val, &((uint32_t *)&reg)[idx])
53 +
54 +#define ebu                            (priv->ebu_membase)
55 +#define sys1                           (priv->sys1_membase)
56 +
57 +struct falcon_spi {
58 +       u32 sfcmd; /* for caching of opcode, direction, ... */
59 +
60 +       struct spi_master *master;
61 +
62 +       struct gpon_reg_ebu __iomem *ebu_membase;
63 +       struct gpon_reg_sys1 __iomem *sys1_membase;
64 +};
65 +
66 +int falcon_spi_xfer(struct spi_device *spi,
67 +                   struct spi_transfer *t,
68 +                   unsigned long flags)
69 +{
70 +       struct device *dev = &spi->dev;
71 +       struct falcon_spi *priv = spi_master_get_devdata(spi->master);
72 +       const u8 *txp = t->tx_buf;
73 +       u8 *rxp = t->rx_buf;
74 +       unsigned int bytelen = ((8 * t->len + 7) / 8);
75 +       unsigned int len, alen, dumlen;
76 +       u32 val;
77 +       enum {
78 +               state_init,
79 +               state_command_prepare,
80 +               state_write,
81 +               state_read,
82 +               state_disable_cs,
83 +               state_end
84 +       } state = state_init;
85 +
86 +       do {
87 +               switch (state) {
88 +               case state_init: /* detect phase of upper layer sequence */
89 +               {
90 +                       /* initial write ? */
91 +                       if (flags & FALCON_SPI_XFER_BEGIN) {
92 +                               if (!txp) {
93 +                                       dev_err(dev,
94 +                                               "BEGIN without tx data!\n");
95 +                                       return -1;
96 +                               }
97 +                               /*
98 +                                * Prepare the parts of the sfcmd register,
99 +                                * which should not
100 +                                * change during a sequence!
101 +                                * Only exception are the length fields,
102 +                                * especially alen and dumlen.
103 +                                */
104 +
105 +                               priv->sfcmd = ((spi->chip_select
106 +                                               << SFCMD_CS_OFFSET)
107 +                                              & SFCMD_CS_MASK);
108 +                               priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED;
109 +                               priv->sfcmd |= *txp;
110 +                               txp++;
111 +                               bytelen--;
112 +                               if (bytelen) {
113 +                                       /* more data:
114 +                                        * maybe address and/or dummy */
115 +                                       state = state_command_prepare;
116 +                                       break;
117 +                               } else {
118 +                                       dev_dbg(dev, "write cmd %02X\n",
119 +                                               priv->sfcmd & SFCMD_OPC_MASK);
120 +                               }
121 +                       }
122 +                       /* continued write ? */
123 +                       if (txp && bytelen) {
124 +                               state = state_write;
125 +                               break;
126 +                       }
127 +                       /* read data? */
128 +                       if (rxp && bytelen) {
129 +                               state = state_read;
130 +                               break;
131 +                       }
132 +                       /* end of sequence? */
133 +                       if (flags & FALCON_SPI_XFER_END)
134 +                               state = state_disable_cs;
135 +                       else
136 +                               state = state_end;
137 +                       break;
138 +               }
139 +               case state_command_prepare: /* collect tx data for
140 +                                              address and dummy phase */
141 +               {
142 +                       /* txp is valid, already checked */
143 +                       val = 0;
144 +                       alen = 0;
145 +                       dumlen = 0;
146 +                       while (bytelen > 0) {
147 +                               if (alen < 3) {
148 +                                       val = (val<<8)|(*txp++);
149 +                                       alen++;
150 +                               } else if ((dumlen < 15) && (*txp == 0)) {
151 +                                       /*
152 +                                        * assume dummy bytes are set to 0
153 +                                        * from upper layer
154 +                                        */
155 +                                       dumlen++;
156 +                                       txp++;
157 +                               } else
158 +                                       break;
159 +                               bytelen--;
160 +                       }
161 +                       priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK);
162 +                       priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) |
163 +                                        (dumlen << SFCMD_DUMLEN_OFFSET);
164 +                       if (alen > 0)
165 +                               ebu_w32(val, sfaddr);
166 +
167 +                       dev_dbg(dev, "write cmd %02X, alen=%d "
168 +                               "(addr=%06X) dumlen=%d\n",
169 +                               priv->sfcmd & SFCMD_OPC_MASK,
170 +                               alen, val, dumlen);
171 +
172 +                       if (bytelen > 0) {
173 +                               /* continue with write */
174 +                               state = state_write;
175 +                       } else if (flags & FALCON_SPI_XFER_END) {
176 +                               /* end of sequence? */
177 +                               state = state_disable_cs;
178 +                       } else {
179 +                               /* go to end and expect another
180 +                                * call (read or write) */
181 +                               state = state_end;
182 +                       }
183 +                       break;
184 +               }
185 +               case state_write:
186 +               {
187 +                       /* txp still valid */
188 +                       priv->sfcmd |= SFCMD_DIR_WRITE;
189 +                       len = 0;
190 +                       val = 0;
191 +                       do {
192 +                               if (bytelen--)
193 +                                       val |= (*txp++) << (8 * len++);
194 +                               if ((flags & FALCON_SPI_XFER_END)
195 +                                   && (bytelen == 0)) {
196 +                                       priv->sfcmd &=
197 +                                               ~SFCMD_KEEP_CS_KEEP_SELECTED;
198 +                               }
199 +                               if ((len == 4) || (bytelen == 0)) {
200 +                                       ebu_w32(val, sfdata);
201 +                                       ebu_w32(priv->sfcmd
202 +                                               | (len<<SFCMD_DLEN_OFFSET),
203 +                                               sfcmd);
204 +                                       len = 0;
205 +                                       val = 0;
206 +                                       priv->sfcmd &= ~(SFCMD_ALEN_MASK
207 +                                                        | SFCMD_DUMLEN_MASK);
208 +                               }
209 +                       } while (bytelen);
210 +                       state = state_end;
211 +                       break;
212 +               }
213 +               case state_read:
214 +               {
215 +                       /* read data */
216 +                       priv->sfcmd &= ~SFCMD_DIR_WRITE;
217 +                       do {
218 +                               if ((flags & FALCON_SPI_XFER_END)
219 +                                   && (bytelen <= 4)) {
220 +                                       priv->sfcmd &=
221 +                                               ~SFCMD_KEEP_CS_KEEP_SELECTED;
222 +                               }
223 +                               len = (bytelen > 4) ? 4 : bytelen;
224 +                               bytelen -= len;
225 +                               ebu_w32(priv->sfcmd
226 +                                       |(len<<SFCMD_DLEN_OFFSET), sfcmd);
227 +                               priv->sfcmd &= ~(SFCMD_ALEN_MASK
228 +                                                | SFCMD_DUMLEN_MASK);
229 +                               do {
230 +                                       val = ebu_r32(sfstat);
231 +                                       if (val & SFSTAT_CMD_ERR) {
232 +                                               /* reset error status */
233 +                                               dev_err(dev, "SFSTAT: CMD_ERR "
234 +                                                       "(%x)\n", val);
235 +                                               ebu_w32(SFSTAT_CMD_ERR, sfstat);
236 +                                               return -1;
237 +                                       }
238 +                               } while (val & SFSTAT_CMD_PEND);
239 +                               val = ebu_r32(sfdata);
240 +                               do {
241 +                                       *rxp = (val & 0xFF);
242 +                                       rxp++;
243 +                                       val >>= 8;
244 +                                       len--;
245 +                               } while (len);
246 +                       } while (bytelen);
247 +                       state = state_end;
248 +                       break;
249 +               }
250 +               case state_disable_cs:
251 +               {
252 +                       priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED;
253 +                       ebu_w32(priv->sfcmd | (0<<SFCMD_DLEN_OFFSET), sfcmd);
254 +                       val = ebu_r32(sfstat);
255 +                       if (val & SFSTAT_CMD_ERR) {
256 +                               /* reset error status */
257 +                               dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val);
258 +                               ebu_w32(SFSTAT_CMD_ERR, sfstat);
259 +                               return -1;
260 +                       }
261 +                       state = state_end;
262 +                       break;
263 +               }
264 +               case state_end:
265 +                       break;
266 +               }
267 +       } while (state != state_end);
268 +
269 +       return 0;
270 +}
271 +
272 +static int falcon_spi_setup(struct spi_device *spi)
273 +{
274 +       struct device *dev = &spi->dev;
275 +       struct falcon_spi *priv = spi_master_get_devdata(spi->master);
276 +       const u32 ebuclk = 100*1000*1000;
277 +       unsigned int i;
278 +       unsigned long flags;
279 +
280 +       dev_dbg(dev, "setup\n");
281 +
282 +       if (spi->master->bus_num > 0 || spi->chip_select > 0)
283 +               return -ENODEV;
284 +
285 +       spin_lock_irqsave(&ebu_lock, flags);
286 +
287 +       if (ebuclk < spi->max_speed_hz) {
288 +               /* set EBU clock to 100 MHz */
289 +               sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, ebucc);
290 +               i = 1; /* divider */
291 +       } else {
292 +               /* set EBU clock to 50 MHz */
293 +               sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, ebucc);
294 +
295 +               /* search for suitable divider */
296 +               for (i = 1; i < 7; i++) {
297 +                       if (ebuclk / i <= spi->max_speed_hz)
298 +                               break;
299 +               }
300 +       }
301 +
302 +       /* setup period of serial clock */
303 +       ebu_w32_mask(SFTIME_SCKF_POS_MASK
304 +                    | SFTIME_SCKR_POS_MASK
305 +                    | SFTIME_SCK_PER_MASK,
306 +                    (i << SFTIME_SCKR_POS_OFFSET)
307 +                    | (i << (SFTIME_SCK_PER_OFFSET + 1)),
308 +                    sftime);
309 +
310 +       /* set some bits of unused_wd, to not trigger HOLD/WP
311 +        * signals on non QUAD flashes */
312 +       ebu_w32((SFIO_UNUSED_WD_MASK & (0x8|0x4)), sfio);
313 +
314 +       ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
315 +               busrcon0);
316 +       ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, buswcon0);
317 +       /* set address wrap around to maximum for 24-bit addresses */
318 +       ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, sfcon);
319 +
320 +       spin_unlock_irqrestore(&ebu_lock, flags);
321 +
322 +       return 0;
323 +}
324 +
325 +static int falcon_spi_transfer(struct spi_device *spi, struct spi_message *m)
326 +{
327 +       struct falcon_spi *priv = spi_master_get_devdata(spi->master);
328 +       struct spi_transfer *t;
329 +       unsigned long spi_flags;
330 +       unsigned long flags;
331 +       int ret = 0;
332 +
333 +       priv->sfcmd = 0;
334 +       m->actual_length = 0;
335 +
336 +       spi_flags = FALCON_SPI_XFER_BEGIN;
337 +       list_for_each_entry(t, &m->transfers, transfer_list) {
338 +               if (list_is_last(&t->transfer_list, &m->transfers))
339 +                       spi_flags |= FALCON_SPI_XFER_END;
340 +
341 +               spin_lock_irqsave(&ebu_lock, flags);
342 +               ret = falcon_spi_xfer(spi, t, spi_flags);
343 +               spin_unlock_irqrestore(&ebu_lock, flags);
344 +
345 +               if (ret)
346 +                       break;
347 +
348 +               m->actual_length += t->len;
349 +
350 +               if (t->delay_usecs || t->cs_change)
351 +                       BUG();
352 +
353 +               spi_flags = 0;
354 +       }
355 +
356 +       m->status = ret;
357 +       m->complete(m->context);
358 +
359 +       return 0;
360 +}
361 +
362 +static void falcon_spi_cleanup(struct spi_device *spi)
363 +{
364 +       struct device *dev = &spi->dev;
365 +
366 +       dev_dbg(dev, "cleanup\n");
367 +}
368 +
369 +static int __devinit falcon_spi_probe(struct platform_device *pdev)
370 +{
371 +       struct device *dev = &pdev->dev;
372 +       struct falcon_spi *priv;
373 +       struct spi_master *master;
374 +       struct resource *memres_ebu, *memres_sys1;
375 +       int ret;
376 +
377 +       dev_dbg(dev, "probing\n");
378 +
379 +       memres_ebu = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ebu");
380 +       memres_sys1 = platform_get_resource_byname(pdev, IORESOURCE_MEM,
381 +                                                  "sys1");
382 +
383 +       if (!memres_ebu || !memres_sys1) {
384 +               dev_err(dev, "no resources\n");
385 +               return -ENODEV;
386 +       }
387 +
388 +       master = spi_alloc_master(&pdev->dev, sizeof(*priv));
389 +       if (!master) {
390 +               dev_err(dev, "no memory for spi_master\n");
391 +               return -ENOMEM;
392 +       }
393 +
394 +       priv = spi_master_get_devdata(master);
395 +
396 +       priv->ebu_membase = ioremap_nocache(memres_ebu->start & ~KSEG1,
397 +                                           resource_size(memres_ebu));
398 +
399 +       if (!priv->ebu_membase) {
400 +               dev_err(dev, "can't map ebu memory\n");
401 +
402 +               ret = -ENOMEM;
403 +               goto free_master;
404 +       }
405 +
406 +       priv->sys1_membase = ioremap_nocache(memres_sys1->start & ~KSEG1,
407 +                                           resource_size(memres_sys1));
408 +
409 +       if (!priv->sys1_membase) {
410 +               dev_err(dev, "can't map sys1 memory\n");
411 +
412 +               ret = -ENOMEM;
413 +               goto unmap_ebu;
414 +       }
415 +
416 +       priv->master = master;
417 +
418 +       master->mode_bits = SPI_MODE_3;
419 +       master->num_chipselect = 1;
420 +       master->bus_num = 0;
421 +
422 +       master->setup = falcon_spi_setup;
423 +       master->transfer = falcon_spi_transfer;
424 +       master->cleanup = falcon_spi_cleanup;
425 +
426 +       platform_set_drvdata(pdev, priv);
427 +
428 +       ret = spi_register_master(master);
429 +       if (ret)
430 +               goto unmap_sys1;
431 +
432 +       return 0;
433 +
434 +unmap_sys1:
435 +       iounmap(priv->sys1_membase);
436 +
437 +unmap_ebu:
438 +       iounmap(priv->ebu_membase);
439 +
440 +free_master:
441 +       spi_master_put(master);
442 +
443 +       return ret;
444 +}
445 +
446 +static int __devexit falcon_spi_remove(struct platform_device *pdev)
447 +{
448 +       struct device *dev = &pdev->dev;
449 +       struct falcon_spi *priv = platform_get_drvdata(pdev);
450 +
451 +       dev_dbg(dev, "removed\n");
452 +
453 +       spi_unregister_master(priv->master);
454 +
455 +       iounmap(priv->sys1_membase);
456 +       iounmap(priv->ebu_membase);
457 +
458 +       return 0;
459 +}
460 +
461 +static struct platform_driver falcon_spi_driver = {
462 +       .probe  = falcon_spi_probe,
463 +       .remove = __devexit_p(falcon_spi_remove),
464 +       .driver = {
465 +               .name   = DRV_NAME,
466 +               .owner  = THIS_MODULE
467 +       }
468 +};
469 +
470 +static int __init falcon_spi_init(void)
471 +{
472 +       return platform_driver_register(&falcon_spi_driver);
473 +}
474 +
475 +static void __exit falcon_spi_exit(void)
476 +{
477 +       platform_driver_unregister(&falcon_spi_driver);
478 +}
479 +
480 +module_init(falcon_spi_init);
481 +module_exit(falcon_spi_exit);
482 +
483 +MODULE_LICENSE("GPL");
484 +MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
485 --- a/drivers/spi/Kconfig
486 +++ b/drivers/spi/Kconfig
487 @@ -219,6 +219,10 @@ config SPI_MPC52xx
488           This drivers supports the MPC52xx SPI controller in master SPI
489           mode.
490  
491 +config SPI_FALCON
492 +       tristate "Falcon SPI controller support"
493 +       depends on SOC_FALCON
494 +
495  config SPI_MPC52xx_PSC
496         tristate "Freescale MPC52xx PSC SPI controller"
497         depends on PPC_MPC52xx && EXPERIMENTAL