arm: mach-omap2: am33xx: Add device structure for spi
[platform/kernel/u-boot.git] / drivers / spi / omap3_spi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Jagan Teki <jteki@openedev.com>
4  *                    Christophe Ricard <christophe.ricard@gmail.com>
5  *
6  * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
7  *
8  * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
9  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
10  *
11  * Copyright (C) 2007 Atmel Corporation
12  *
13  * Parts taken from linux/drivers/spi/omap2_mcspi.c
14  * Copyright (C) 2005, 2006 Nokia Corporation
15  *
16  * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
17  */
18
19 #include <common.h>
20 #include <dm.h>
21 #include <spi.h>
22 #include <malloc.h>
23 #include <asm/io.h>
24 #include <linux/bitops.h>
25 #include <omap3_spi.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 struct omap2_mcspi_platform_config {
30         unsigned int regs_offset;
31 };
32
33 struct omap3_spi_priv {
34         struct mcspi *regs;
35         unsigned int cs;
36         unsigned int freq;
37         unsigned int mode;
38         unsigned int wordlen;
39         unsigned int pin_dir:1;
40 };
41
42 static void omap3_spi_write_chconf(struct omap3_spi_priv *priv, int val)
43 {
44         writel(val, &priv->regs->channel[priv->cs].chconf);
45         /* Flash post writes to make immediate effect */
46         readl(&priv->regs->channel[priv->cs].chconf);
47 }
48
49 static void omap3_spi_set_enable(struct omap3_spi_priv *priv, int enable)
50 {
51         writel(enable, &priv->regs->channel[priv->cs].chctrl);
52         /* Flash post writes to make immediate effect */
53         readl(&priv->regs->channel[priv->cs].chctrl);
54 }
55
56 static int omap3_spi_write(struct omap3_spi_priv *priv, unsigned int len,
57                            const void *txp, unsigned long flags)
58 {
59         ulong start;
60         int i, chconf;
61
62         chconf = readl(&priv->regs->channel[priv->cs].chconf);
63
64         /* Enable the channel */
65         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
66
67         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
68         chconf |= (priv->wordlen - 1) << 7;
69         chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
70         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
71         omap3_spi_write_chconf(priv, chconf);
72
73         for (i = 0; i < len; i++) {
74                 /* wait till TX register is empty (TXS == 1) */
75                 start = get_timer(0);
76                 while (!(readl(&priv->regs->channel[priv->cs].chstat) &
77                          OMAP3_MCSPI_CHSTAT_TXS)) {
78                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
79                                 printf("SPI TXS timed out, status=0x%08x\n",
80                                         readl(&priv->regs->channel[priv->cs].chstat));
81                                 return -1;
82                         }
83                 }
84                 /* Write the data */
85                 unsigned int *tx = &priv->regs->channel[priv->cs].tx;
86                 if (priv->wordlen > 16)
87                         writel(((u32 *)txp)[i], tx);
88                 else if (priv->wordlen > 8)
89                         writel(((u16 *)txp)[i], tx);
90                 else
91                         writel(((u8 *)txp)[i], tx);
92         }
93
94         /* wait to finish of transfer */
95         while ((readl(&priv->regs->channel[priv->cs].chstat) &
96                         (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
97                         (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS))
98                 ;
99
100         /* Disable the channel otherwise the next immediate RX will get affected */
101         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
102
103         if (flags & SPI_XFER_END) {
104
105                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
106                 omap3_spi_write_chconf(priv, chconf);
107         }
108         return 0;
109 }
110
111 static int omap3_spi_read(struct omap3_spi_priv *priv, unsigned int len,
112                           void *rxp, unsigned long flags)
113 {
114         int i, chconf;
115         ulong start;
116
117         chconf = readl(&priv->regs->channel[priv->cs].chconf);
118
119         /* Enable the channel */
120         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
121
122         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
123         chconf |= (priv->wordlen - 1) << 7;
124         chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
125         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
126         omap3_spi_write_chconf(priv, chconf);
127
128         writel(0, &priv->regs->channel[priv->cs].tx);
129
130         for (i = 0; i < len; i++) {
131                 start = get_timer(0);
132                 /* Wait till RX register contains data (RXS == 1) */
133                 while (!(readl(&priv->regs->channel[priv->cs].chstat) &
134                          OMAP3_MCSPI_CHSTAT_RXS)) {
135                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
136                                 printf("SPI RXS timed out, status=0x%08x\n",
137                                         readl(&priv->regs->channel[priv->cs].chstat));
138                                 return -1;
139                         }
140                 }
141
142                 /* Disable the channel to prevent furher receiving */
143                 if (i == (len - 1))
144                         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
145
146                 /* Read the data */
147                 unsigned int *rx = &priv->regs->channel[priv->cs].rx;
148                 if (priv->wordlen > 16)
149                         ((u32 *)rxp)[i] = readl(rx);
150                 else if (priv->wordlen > 8)
151                         ((u16 *)rxp)[i] = (u16)readl(rx);
152                 else
153                         ((u8 *)rxp)[i] = (u8)readl(rx);
154         }
155
156         if (flags & SPI_XFER_END) {
157                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
158                 omap3_spi_write_chconf(priv, chconf);
159         }
160
161         return 0;
162 }
163
164 /*McSPI Transmit Receive Mode*/
165 static int omap3_spi_txrx(struct omap3_spi_priv *priv, unsigned int len,
166                           const void *txp, void *rxp, unsigned long flags)
167 {
168         ulong start;
169         int chconf, i = 0;
170
171         chconf = readl(&priv->regs->channel[priv->cs].chconf);
172
173         /*Enable SPI channel*/
174         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
175
176         /*set TRANSMIT-RECEIVE Mode*/
177         chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
178         chconf |= (priv->wordlen - 1) << 7;
179         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
180         omap3_spi_write_chconf(priv, chconf);
181
182         /*Shift in and out 1 byte at time*/
183         for (i=0; i < len; i++){
184                 /* Write: wait for TX empty (TXS == 1)*/
185                 start = get_timer(0);
186                 while (!(readl(&priv->regs->channel[priv->cs].chstat) &
187                          OMAP3_MCSPI_CHSTAT_TXS)) {
188                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
189                                 printf("SPI TXS timed out, status=0x%08x\n",
190                                         readl(&priv->regs->channel[priv->cs].chstat));
191                                 return -1;
192                         }
193                 }
194                 /* Write the data */
195                 unsigned int *tx = &priv->regs->channel[priv->cs].tx;
196                 if (priv->wordlen > 16)
197                         writel(((u32 *)txp)[i], tx);
198                 else if (priv->wordlen > 8)
199                         writel(((u16 *)txp)[i], tx);
200                 else
201                         writel(((u8 *)txp)[i], tx);
202
203                 /*Read: wait for RX containing data (RXS == 1)*/
204                 start = get_timer(0);
205                 while (!(readl(&priv->regs->channel[priv->cs].chstat) &
206                          OMAP3_MCSPI_CHSTAT_RXS)) {
207                         if (get_timer(start) > SPI_WAIT_TIMEOUT) {
208                                 printf("SPI RXS timed out, status=0x%08x\n",
209                                         readl(&priv->regs->channel[priv->cs].chstat));
210                                 return -1;
211                         }
212                 }
213                 /* Read the data */
214                 unsigned int *rx = &priv->regs->channel[priv->cs].rx;
215                 if (priv->wordlen > 16)
216                         ((u32 *)rxp)[i] = readl(rx);
217                 else if (priv->wordlen > 8)
218                         ((u16 *)rxp)[i] = (u16)readl(rx);
219                 else
220                         ((u8 *)rxp)[i] = (u8)readl(rx);
221         }
222         /* Disable the channel */
223         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
224
225         /*if transfer must be terminated disable the channel*/
226         if (flags & SPI_XFER_END) {
227                 chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
228                 omap3_spi_write_chconf(priv, chconf);
229         }
230
231         return 0;
232 }
233
234 static int _spi_xfer(struct omap3_spi_priv *priv, unsigned int bitlen,
235                      const void *dout, void *din, unsigned long flags)
236 {
237         unsigned int    len;
238         int ret = -1;
239
240         if (priv->wordlen < 4 || priv->wordlen > 32) {
241                 printf("omap3_spi: invalid wordlen %d\n", priv->wordlen);
242                 return -1;
243         }
244
245         if (bitlen % priv->wordlen)
246                 return -1;
247
248         len = bitlen / priv->wordlen;
249
250         if (bitlen == 0) {       /* only change CS */
251                 int chconf = readl(&priv->regs->channel[priv->cs].chconf);
252
253                 if (flags & SPI_XFER_BEGIN) {
254                         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
255                         chconf |= OMAP3_MCSPI_CHCONF_FORCE;
256                         omap3_spi_write_chconf(priv, chconf);
257                 }
258                 if (flags & SPI_XFER_END) {
259                         chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
260                         omap3_spi_write_chconf(priv, chconf);
261                         omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
262                 }
263                 ret = 0;
264         } else {
265                 if (dout != NULL && din != NULL)
266                         ret = omap3_spi_txrx(priv, len, dout, din, flags);
267                 else if (dout != NULL)
268                         ret = omap3_spi_write(priv, len, dout, flags);
269                 else if (din != NULL)
270                         ret = omap3_spi_read(priv, len, din, flags);
271         }
272         return ret;
273 }
274
275 static void _omap3_spi_set_speed(struct omap3_spi_priv *priv)
276 {
277         uint32_t confr, div = 0;
278
279         confr = readl(&priv->regs->channel[priv->cs].chconf);
280
281         /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
282         if (priv->freq) {
283                 while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
284                                         > priv->freq)
285                         div++;
286         } else {
287                  div = 0xC;
288         }
289
290         /* set clock divisor */
291         confr &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
292         confr |= div << 2;
293
294         omap3_spi_write_chconf(priv, confr);
295 }
296
297 static void _omap3_spi_set_mode(struct omap3_spi_priv *priv)
298 {
299         uint32_t confr;
300
301         confr = readl(&priv->regs->channel[priv->cs].chconf);
302
303         /* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
304          * REVISIT: this controller could support SPI_3WIRE mode.
305          */
306         if (priv->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
307                 confr &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
308                 confr |= OMAP3_MCSPI_CHCONF_DPE0;
309         } else {
310                 confr &= ~OMAP3_MCSPI_CHCONF_DPE0;
311                 confr |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
312         }
313
314         /* set SPI mode 0..3 */
315         confr &= ~(OMAP3_MCSPI_CHCONF_POL | OMAP3_MCSPI_CHCONF_PHA);
316         if (priv->mode & SPI_CPHA)
317                 confr |= OMAP3_MCSPI_CHCONF_PHA;
318         if (priv->mode & SPI_CPOL)
319                 confr |= OMAP3_MCSPI_CHCONF_POL;
320
321         /* set chipselect polarity; manage with FORCE */
322         if (!(priv->mode & SPI_CS_HIGH))
323                 confr |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
324         else
325                 confr &= ~OMAP3_MCSPI_CHCONF_EPOL;
326
327         /* Transmit & receive mode */
328         confr &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
329
330         omap3_spi_write_chconf(priv, confr);
331 }
332
333 static void _omap3_spi_set_wordlen(struct omap3_spi_priv *priv)
334 {
335         unsigned int confr;
336
337         /* McSPI individual channel configuration */
338         confr = readl(&priv->regs->channel[priv->cs].chconf);
339
340         /* wordlength */
341         confr &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
342         confr |= (priv->wordlen - 1) << 7;
343
344         omap3_spi_write_chconf(priv, confr);
345 }
346
347 static void spi_reset(struct mcspi *regs)
348 {
349         unsigned int tmp;
350
351         writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &regs->sysconfig);
352         do {
353                 tmp = readl(&regs->sysstatus);
354         } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
355
356         writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
357                OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
358                OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, &regs->sysconfig);
359
360         writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &regs->wakeupenable);
361 }
362
363 static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv)
364 {
365         unsigned int conf;
366         /*
367          * setup when switching from (reset default) slave mode
368          * to single-channel master mode
369          */
370         conf = readl(&priv->regs->modulctrl);
371         conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
372         conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
373
374         writel(conf, &priv->regs->modulctrl);
375 }
376
377 static int omap3_spi_claim_bus(struct udevice *dev)
378 {
379         struct udevice *bus = dev->parent;
380         struct omap3_spi_priv *priv = dev_get_priv(bus);
381         struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
382
383         priv->cs = slave_plat->cs;
384         priv->freq = slave_plat->max_hz;
385
386         _omap3_spi_claim_bus(priv);
387
388         return 0;
389 }
390
391 static int omap3_spi_release_bus(struct udevice *dev)
392 {
393         struct udevice *bus = dev->parent;
394         struct omap3_spi_priv *priv = dev_get_priv(bus);
395
396         writel(OMAP3_MCSPI_MODULCTRL_MS, &priv->regs->modulctrl);
397
398         return 0;
399 }
400
401 static int omap3_spi_set_wordlen(struct udevice *dev, unsigned int wordlen)
402 {
403         struct udevice *bus = dev->parent;
404         struct omap3_spi_priv *priv = dev_get_priv(bus);
405         struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
406
407         priv->cs = slave_plat->cs;
408         priv->wordlen = wordlen;
409         _omap3_spi_set_wordlen(priv);
410
411         return 0;
412 }
413
414 static int omap3_spi_probe(struct udevice *dev)
415 {
416         struct omap3_spi_priv *priv = dev_get_priv(dev);
417         const void *blob = gd->fdt_blob;
418         int node = dev_of_offset(dev);
419
420         struct omap2_mcspi_platform_config* data =
421                 (struct omap2_mcspi_platform_config*)dev_get_driver_data(dev);
422
423         priv->regs = (struct mcspi *)(dev_read_addr(dev) + data->regs_offset);
424         if (fdtdec_get_bool(blob, node, "ti,pindir-d0-out-d1-in"))
425                 priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
426         else
427                 priv->pin_dir = MCSPI_PINDIR_D0_IN_D1_OUT;
428         priv->wordlen = SPI_DEFAULT_WORDLEN;
429
430         spi_reset(priv->regs);
431
432         return 0;
433 }
434
435 static int omap3_spi_xfer(struct udevice *dev, unsigned int bitlen,
436                             const void *dout, void *din, unsigned long flags)
437 {
438         struct udevice *bus = dev->parent;
439         struct omap3_spi_priv *priv = dev_get_priv(bus);
440
441         return _spi_xfer(priv, bitlen, dout, din, flags);
442 }
443
444 static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed)
445 {
446
447         struct omap3_spi_priv *priv = dev_get_priv(dev);
448
449         priv->freq = speed;
450         _omap3_spi_set_speed(priv);
451
452         return 0;
453 }
454
455 static int omap3_spi_set_mode(struct udevice *dev, uint mode)
456 {
457         struct omap3_spi_priv *priv = dev_get_priv(dev);
458
459         priv->mode = mode;
460
461         _omap3_spi_set_mode(priv);
462
463         return 0;
464 }
465
466 static const struct dm_spi_ops omap3_spi_ops = {
467         .claim_bus      = omap3_spi_claim_bus,
468         .release_bus    = omap3_spi_release_bus,
469         .set_wordlen    = omap3_spi_set_wordlen,
470         .xfer       = omap3_spi_xfer,
471         .set_speed      = omap3_spi_set_speed,
472         .set_mode       = omap3_spi_set_mode,
473         /*
474          * cs_info is not needed, since we require all chip selects to be
475          * in the device tree explicitly
476          */
477 };
478
479 static struct omap2_mcspi_platform_config omap2_pdata = {
480         .regs_offset = 0,
481 };
482
483 static struct omap2_mcspi_platform_config omap4_pdata = {
484         .regs_offset = OMAP4_MCSPI_REG_OFFSET,
485 };
486
487 static const struct udevice_id omap3_spi_ids[] = {
488         { .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata },
489         { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },
490         { }
491 };
492
493 U_BOOT_DRIVER(omap3_spi) = {
494         .name   = "omap3_spi",
495         .id     = UCLASS_SPI,
496         .of_match = omap3_spi_ids,
497         .probe = omap3_spi_probe,
498         .ops    = &omap3_spi_ops,
499         .priv_auto_alloc_size = sizeof(struct omap3_spi_priv),
500 };