]> git.sur5r.net Git - u-boot/blob - drivers/spi/omap3_spi.c
spi: omap3: Make local functions as static
[u-boot] / drivers / spi / omap3_spi.c
1 /*
2  * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
3  *
4  * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
5  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
6  *
7  * Copyright (C) 2007 Atmel Corporation
8  *
9  * Parts taken from linux/drivers/spi/omap2_mcspi.c
10  * Copyright (C) 2005, 2006 Nokia Corporation
11  *
12  * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
13  *
14  * SPDX-License-Identifier:     GPL-2.0+
15  */
16
17 #include <common.h>
18 #include <spi.h>
19 #include <malloc.h>
20 #include <asm/io.h>
21
22 #if defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX)
23 #define OMAP3_MCSPI1_BASE       0x48030100
24 #define OMAP3_MCSPI2_BASE       0x481A0100
25 #else
26 #define OMAP3_MCSPI1_BASE       0x48098000
27 #define OMAP3_MCSPI2_BASE       0x4809A000
28 #define OMAP3_MCSPI3_BASE       0x480B8000
29 #define OMAP3_MCSPI4_BASE       0x480BA000
30 #endif
31
32 /* per-register bitmasks */
33 #define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
34 #define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2)
35 #define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE  BIT(0)
36 #define OMAP3_MCSPI_SYSCONFIG_SOFTRESET BIT(1)
37
38 #define OMAP3_MCSPI_SYSSTATUS_RESETDONE BIT(0)
39
40 #define OMAP3_MCSPI_MODULCTRL_SINGLE    BIT(0)
41 #define OMAP3_MCSPI_MODULCTRL_MS        BIT(2)
42 #define OMAP3_MCSPI_MODULCTRL_STEST     BIT(3)
43
44 #define OMAP3_MCSPI_CHCONF_PHA          BIT(0)
45 #define OMAP3_MCSPI_CHCONF_POL          BIT(1)
46 #define OMAP3_MCSPI_CHCONF_CLKD_MASK    GENMASK(5, 2)
47 #define OMAP3_MCSPI_CHCONF_EPOL         BIT(6)
48 #define OMAP3_MCSPI_CHCONF_WL_MASK      GENMASK(11, 7)
49 #define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY  BIT(12)
50 #define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY  BIT(13)
51 #define OMAP3_MCSPI_CHCONF_TRM_MASK     GENMASK(13, 12)
52 #define OMAP3_MCSPI_CHCONF_DMAW         BIT(14)
53 #define OMAP3_MCSPI_CHCONF_DMAR         BIT(15)
54 #define OMAP3_MCSPI_CHCONF_DPE0         BIT(16)
55 #define OMAP3_MCSPI_CHCONF_DPE1         BIT(17)
56 #define OMAP3_MCSPI_CHCONF_IS           BIT(18)
57 #define OMAP3_MCSPI_CHCONF_TURBO        BIT(19)
58 #define OMAP3_MCSPI_CHCONF_FORCE        BIT(20)
59
60 #define OMAP3_MCSPI_CHSTAT_RXS          BIT(0)
61 #define OMAP3_MCSPI_CHSTAT_TXS          BIT(1)
62 #define OMAP3_MCSPI_CHSTAT_EOT          BIT(2)
63
64 #define OMAP3_MCSPI_CHCTRL_EN           BIT(0)
65 #define OMAP3_MCSPI_CHCTRL_DIS          (0 << 0)
66
67 #define OMAP3_MCSPI_WAKEUPENABLE_WKEN   BIT(0)
68
69 #define OMAP3_MCSPI_MAX_FREQ            48000000
70 #define SPI_WAIT_TIMEOUT                10
71
72 /* OMAP3 McSPI registers */
73 struct mcspi_channel {
74         unsigned int chconf;            /* 0x2C, 0x40, 0x54, 0x68 */
75         unsigned int chstat;            /* 0x30, 0x44, 0x58, 0x6C */
76         unsigned int chctrl;            /* 0x34, 0x48, 0x5C, 0x70 */
77         unsigned int tx;                /* 0x38, 0x4C, 0x60, 0x74 */
78         unsigned int rx;                /* 0x3C, 0x50, 0x64, 0x78 */
79 };
80
81 struct mcspi {
82         unsigned char res1[0x10];
83         unsigned int sysconfig;         /* 0x10 */
84         unsigned int sysstatus;         /* 0x14 */
85         unsigned int irqstatus;         /* 0x18 */
86         unsigned int irqenable;         /* 0x1C */
87         unsigned int wakeupenable;      /* 0x20 */
88         unsigned int syst;              /* 0x24 */
89         unsigned int modulctrl;         /* 0x28 */
90         struct mcspi_channel channel[4];
91         /* channel0: 0x2C - 0x3C, bus 0 & 1 & 2 & 3 */
92         /* channel1: 0x40 - 0x50, bus 0 & 1 */
93         /* channel2: 0x54 - 0x64, bus 0 & 1 */
94         /* channel3: 0x68 - 0x78, bus 0 */
95 };
96
97 struct omap3_spi_slave {
98         struct spi_slave slave;
99         struct mcspi *regs;
100         unsigned int freq;
101         unsigned int mode;
102 };
103
104 static inline struct omap3_spi_slave *to_omap3_spi(struct spi_slave *slave)
105 {
106         return container_of(slave, struct omap3_spi_slave, slave);
107 }
108
109 static void spi_reset(struct omap3_spi_slave *ds)
110 {
111         unsigned int tmp;
112
113         writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
114         do {
115                 tmp = readl(&ds->regs->sysstatus);
116         } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
117
118         writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
119                                  OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
120                                  OMAP3_MCSPI_SYSCONFIG_SMARTIDLE,
121                                  &ds->regs->sysconfig);
122
123         writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
124 }
125
126 static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
127 {
128         writel(val, &ds->regs->channel[ds->slave.cs].chconf);
129         /* Flash post writes to make immediate effect */
130         readl(&ds->regs->channel[ds->slave.cs].chconf);
131 }
132
133 static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
134 {
135         writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
136         /* Flash post writes to make immediate effect */
137         readl(&ds->regs->channel[ds->slave.cs].chctrl);
138 }
139
140 void spi_init()
141 {
142         /* do nothing */
143 }
144
145 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
146                                   unsigned int max_hz, unsigned int mode)
147 {
148         struct omap3_spi_slave  *ds;
149         struct mcspi *regs;
150
151         /*
152          * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
153          * with different number of chip selects (CS, channels):
154          * McSPI1 has 4 CS (bus 0, cs 0 - 3)
155          * McSPI2 has 2 CS (bus 1, cs 0 - 1)
156          * McSPI3 has 2 CS (bus 2, cs 0 - 1)
157          * McSPI4 has 1 CS (bus 3, cs 0)
158          */
159
160         switch (bus) {
161         case 0:
162                 regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
163                 break;
164 #ifdef OMAP3_MCSPI2_BASE
165         case 1:
166                 regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
167                 break;
168 #endif
169 #ifdef OMAP3_MCSPI3_BASE
170         case 2:
171                 regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
172                 break;
173 #endif
174 #ifdef OMAP3_MCSPI4_BASE
175         case 3:
176                 regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
177                 break;
178 #endif
179         default:
180                 printf("SPI error: unsupported bus %i. \
181                         Supported busses 0 - 3\n", bus);
182                 return NULL;
183         }
184
185         if (((bus == 0) && (cs > 3)) ||
186                         ((bus == 1) && (cs > 1)) ||
187                         ((bus == 2) && (cs > 1)) ||
188                         ((bus == 3) && (cs > 0))) {
189                 printf("SPI error: unsupported chip select %i \
190                         on bus %i\n", cs, bus);
191                 return NULL;
192         }
193
194         if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
195                 printf("SPI error: unsupported frequency %i Hz. \
196                         Max frequency is 48 Mhz\n", max_hz);
197                 return NULL;
198         }
199
200         if (mode > SPI_MODE_3) {
201                 printf("SPI error: unsupported SPI mode %i\n", mode);
202                 return NULL;
203         }
204
205         ds = spi_alloc_slave(struct omap3_spi_slave, bus, cs);
206         if (!ds) {
207                 printf("SPI error: malloc of SPI structure failed\n");
208                 return NULL;
209         }
210
211         ds->regs = regs;
212         ds->freq = max_hz;
213         ds->mode = mode;
214
215         return &ds->slave;
216 }
217
218 void spi_free_slave(struct spi_slave *slave)
219 {
220         struct omap3_spi_slave *ds = to_omap3_spi(slave);
221
222         free(ds);
223 }
224
225 int spi_claim_bus(struct spi_slave *slave)
226 {
227         struct omap3_spi_slave *ds = to_omap3_spi(slave);
228         unsigned int conf, div = 0;
229
230         /* McSPI global module configuration */
231
232         /*
233          * setup when switching from (reset default) slave mode
234          * to single-channel master mode
235          */
236         spi_reset(ds);
237         conf = readl(&ds->regs->modulctrl);
238         conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
239         conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
240         writel(conf, &ds->regs->modulctrl);
241
242         /* McSPI individual channel configuration */
243
244         /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
245         if (ds->freq) {
246                 while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
247                                          > ds->freq)
248                         div++;
249         } else
250                 div = 0xC;
251
252         conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
253
254         /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
255          * REVISIT: this controller could support SPI_3WIRE mode.
256          */
257 #ifdef CONFIG_OMAP3_SPI_D0_D1_SWAPPED
258         /*
259          * Some boards have D0 wired as MOSI / D1 as MISO instead of
260          * The normal D0 as MISO / D1 as MOSI.
261          */
262         conf &= ~OMAP3_MCSPI_CHCONF_DPE0;
263         conf |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
264 #else
265         conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
266         conf |= OMAP3_MCSPI_CHCONF_DPE0;
267 #endif
268
269         /* wordlength */
270         conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
271         conf |= (ds->slave.wordlen - 1) << 7;
272
273         /* set chipselect polarity; manage with FORCE */
274         if (!(ds->mode & SPI_CS_HIGH))
275                 conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
276         else
277                 conf &= ~OMAP3_MCSPI_CHCONF_EPOL;
278
279         /* set clock divisor */
280         conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
281         conf |= div << 2;
282
283         /* set SPI mode 0..3 */
284         if (ds->mode & SPI_CPOL)
285                 conf |= OMAP3_MCSPI_CHCONF_POL;
286         else
287                 conf &= ~OMAP3_MCSPI_CHCONF_POL;
288         if (ds->mode & SPI_CPHA)
289                 conf |= OMAP3_MCSPI_CHCONF_PHA;
290         else
291                 conf &= ~OMAP3_MCSPI_CHCONF_PHA;
292
293         /* Transmit & receive mode */
294         conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
295
296         omap3_spi_write_chconf(ds,conf);
297
298         return 0;
299 }
300
301 void spi_release_bus(struct spi_slave *slave)
302 {
303         struct omap3_spi_slave *ds = to_omap3_spi(slave);
304
305         /* Reset the SPI hardware */
306         spi_reset(ds);
307 }
308
309 static int omap3_spi_write(struct spi_slave *slave, unsigned int len,
310                            const void *txp, unsigned long flags)
311 {
312         struct omap3_spi_slave *ds = to_omap3_spi(slave);
313         int i;
314         ulong start;
315         int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
316
317         /* Enable the channel */
318         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
319
320         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
321         chconf |= (ds->slave.wordlen - 1) << 7;
322         chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
323         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
324         omap3_spi_write_chconf(ds,chconf);
325
326         for (i = 0; i < len; i++) {
327                 /* wait till TX register is empty (TXS == 1) */
328                 start = get_timer(0);
329                 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
330                          OMAP3_MCSPI_CHSTAT_TXS)) {
331                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
332                                 printf("SPI TXS timed out, status=0x%08x\n",
333                                        readl(&ds->regs->channel[ds->slave.cs].chstat));
334                                 return -1;
335                         }
336                 }
337                 /* Write the data */
338                 unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
339                 if (ds->slave.wordlen > 16)
340                         writel(((u32 *)txp)[i], tx);
341                 else if (ds->slave.wordlen > 8)
342                         writel(((u16 *)txp)[i], tx);
343                 else
344                         writel(((u8 *)txp)[i], tx);
345         }
346
347         /* wait to finish of transfer */
348         while ((readl(&ds->regs->channel[ds->slave.cs].chstat) &
349                          (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
350                          (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS));
351
352         /* Disable the channel otherwise the next immediate RX will get affected */
353         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
354
355         if (flags & SPI_XFER_END) {
356
357                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
358                 omap3_spi_write_chconf(ds,chconf);
359         }
360         return 0;
361 }
362
363 static int omap3_spi_read(struct spi_slave *slave, unsigned int len,
364                           void *rxp, unsigned long flags)
365 {
366         struct omap3_spi_slave *ds = to_omap3_spi(slave);
367         int i;
368         ulong start;
369         int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
370
371         /* Enable the channel */
372         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
373
374         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
375         chconf |= (ds->slave.wordlen - 1) << 7;
376         chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
377         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
378         omap3_spi_write_chconf(ds,chconf);
379
380         writel(0, &ds->regs->channel[ds->slave.cs].tx);
381
382         for (i = 0; i < len; i++) {
383                 start = get_timer(0);
384                 /* Wait till RX register contains data (RXS == 1) */
385                 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
386                          OMAP3_MCSPI_CHSTAT_RXS)) {
387                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
388                                 printf("SPI RXS timed out, status=0x%08x\n",
389                                        readl(&ds->regs->channel[ds->slave.cs].chstat));
390                                 return -1;
391                         }
392                 }
393
394                 /* Disable the channel to prevent furher receiving */
395                 if(i == (len - 1))
396                         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
397
398                 /* Read the data */
399                 unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
400                 if (ds->slave.wordlen > 16)
401                         ((u32 *)rxp)[i] = readl(rx);
402                 else if (ds->slave.wordlen > 8)
403                         ((u16 *)rxp)[i] = (u16)readl(rx);
404                 else
405                         ((u8 *)rxp)[i] = (u8)readl(rx);
406         }
407
408         if (flags & SPI_XFER_END) {
409                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
410                 omap3_spi_write_chconf(ds,chconf);
411         }
412
413         return 0;
414 }
415
416 /*McSPI Transmit Receive Mode*/
417 static int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
418                           const void *txp, void *rxp, unsigned long flags)
419 {
420         struct omap3_spi_slave *ds = to_omap3_spi(slave);
421         ulong start;
422         int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
423         int i=0;
424
425         /*Enable SPI channel*/
426         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
427
428         /*set TRANSMIT-RECEIVE Mode*/
429         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
430         chconf |= (ds->slave.wordlen - 1) << 7;
431         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
432         omap3_spi_write_chconf(ds,chconf);
433
434         /*Shift in and out 1 byte at time*/
435         for (i=0; i < len; i++){
436                 /* Write: wait for TX empty (TXS == 1)*/
437                 start = get_timer(0);
438                 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
439                          OMAP3_MCSPI_CHSTAT_TXS)) {
440                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
441                                 printf("SPI TXS timed out, status=0x%08x\n",
442                                        readl(&ds->regs->channel[ds->slave.cs].chstat));
443                                 return -1;
444                         }
445                 }
446                 /* Write the data */
447                 unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
448                 if (ds->slave.wordlen > 16)
449                         writel(((u32 *)txp)[i], tx);
450                 else if (ds->slave.wordlen > 8)
451                         writel(((u16 *)txp)[i], tx);
452                 else
453                         writel(((u8 *)txp)[i], tx);
454
455                 /*Read: wait for RX containing data (RXS == 1)*/
456                 start = get_timer(0);
457                 while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
458                          OMAP3_MCSPI_CHSTAT_RXS)) {
459                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
460                                 printf("SPI RXS timed out, status=0x%08x\n",
461                                        readl(&ds->regs->channel[ds->slave.cs].chstat));
462                                 return -1;
463                         }
464                 }
465                 /* Read the data */
466                 unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
467                 if (ds->slave.wordlen > 16)
468                         ((u32 *)rxp)[i] = readl(rx);
469                 else if (ds->slave.wordlen > 8)
470                         ((u16 *)rxp)[i] = (u16)readl(rx);
471                 else
472                         ((u8 *)rxp)[i] = (u8)readl(rx);
473         }
474         /* Disable the channel */
475         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
476
477         /*if transfer must be terminated disable the channel*/
478         if (flags & SPI_XFER_END) {
479                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
480                 omap3_spi_write_chconf(ds,chconf);
481         }
482
483         return 0;
484 }
485
486 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
487              const void *dout, void *din, unsigned long flags)
488 {
489         struct omap3_spi_slave *ds = to_omap3_spi(slave);
490         unsigned int    len;
491         int ret = -1;
492
493         if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
494                 printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
495                 return -1;
496         }
497
498         if (bitlen % ds->slave.wordlen)
499                 return -1;
500
501         len = bitlen / ds->slave.wordlen;
502
503         if (bitlen == 0) {       /* only change CS */
504                 int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
505
506                 if (flags & SPI_XFER_BEGIN) {
507                         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
508                         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
509                         omap3_spi_write_chconf(ds,chconf);
510                 }
511                 if (flags & SPI_XFER_END) {
512                         chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
513                         omap3_spi_write_chconf(ds,chconf);
514                         omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
515                 }
516                 ret = 0;
517         } else {
518                 if (dout != NULL && din != NULL)
519                         ret = omap3_spi_txrx(slave, len, dout, din, flags);
520                 else if (dout != NULL)
521                         ret = omap3_spi_write(slave, len, dout, flags);
522                 else if (din != NULL)
523                         ret = omap3_spi_read(slave, len, din, flags);
524         }
525         return ret;
526 }
527
528 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
529 {
530         return 1;
531 }
532
533 void spi_cs_activate(struct spi_slave *slave)
534 {
535 }
536
537 void spi_cs_deactivate(struct spi_slave *slave)
538 {
539 }