1973b85a447827cc08315450af8978442304acee
[glsdk/glsdk-u-boot.git] / drivers / spi / ti_qspi.c
1 /*
2  * TI QSPI driver
3  *
4  * Copyright (C) 2013, Texas Instruments, Incorporated
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
17 #include <common.h>
18 #include <asm/io.h>
19 #include <asm/arch/omap.h>
20 #include <malloc.h>
21 #include <spi.h>
23 struct qspi_slave {
24         struct spi_slave slave;
25         unsigned int mode;
26         u32 cmd;
27         u32 dc;
28 };
30 #define to_qspi_slave(s) container_of(s, struct qspi_slave, slave)
32 struct qspi_regs {
33         u32 pid;
34         u32 pad0[3];
35         u32 sysconfig;
36         u32 pad1[3];
37         u32 intr_status_raw_set;
38         u32 intr_status_enabled_clear;
39         u32 intr_enable_set;
40         u32 intr_enable_clear;
41         u32 intc_eoi;
42         u32 pad2[3];
43         u32 spi_clock_cntrl;
44         u32 spi_dc;
45         u32 spi_cmd;
46         u32 spi_status;
47         u32 spi_data;
48         u32 spi_setup0;
49         u32 spi_setup1;
50         u32 spi_setup2;
51         u32 spi_setup3;
52         u32 spi_switch;
53         u32 spi_data1;
54         u32 spi_data2;
55         u32 spi_data3;
56 };
58 static struct qspi_regs *qspi = (struct qspi_regs *)QSPI_BASE;
60 #define QSPI_TIMEOUT                    2000000
62 #define QSPI_FCLK                       192000000
64 /* Clock Control */
65 #define QSPI_CLK_EN                     (1 << 31)
66 #define QSPI_CLK_DIV_MAX                0xffff
68 /* Command */
69 #define QSPI_EN_CS(n)                   (n << 28)
70 #define QSPI_WLEN(n)                    ((n-1) << 19)
71 #define QSPI_3_PIN                      (1 << 18)
72 #define QSPI_RD_SNGL                    (1 << 16)
73 #define QSPI_WR_SNGL                    (2 << 16)
74 #define QSPI_INVAL                      (4 << 16)
76 /* Device Control */
77 #define QSPI_DD(m, n)                   (m << (3 + n*8))
78 #define QSPI_CKPHA(n)                   (1 << (2 + n*8))
79 #define QSPI_CSPOL(n)                   (1 << (1 + n*8))
80 #define QSPI_CKPOL(n)                   (1 << (n*8))
82 /* Status */
83 #define QSPI_WC                         (1 << 1)
84 #define QSPI_BUSY                       (1 << 0)
85 #define QSPI_WC_BUSY                    (QSPI_WC | QSPI_BUSY)
86 #define QSPI_XFER_DONE                  QSPI_WC
88 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
89 {
90         return 1;
91 }
93 void spi_cs_activate(struct spi_slave *slave)
94 {
95         /* CS handled in xfer */
96         return;
97 }
99 void spi_cs_deactivate(struct spi_slave *slave)
101         /* CS handled in xfer */
102         return;
105 void spi_init(void)
107         /* nothing to do */
110 void spi_set_speed(struct spi_slave *slave, uint hz)
112         uint clk_div;
114         if (!hz)
115                 clk_div = 0;
116         else
117                 clk_div = (QSPI_FCLK / hz) - 1;
119         debug("%s: hz: %d, clock divider %d\n", __func__, hz, clk_div);
121         /* disable SCLK */
122         writel(readl(&qspi->spi_clock_cntrl) & ~QSPI_CLK_EN, &qspi->spi_clock_cntrl);
124         if (clk_div < 0) {
125                 debug("%s: clock divider < 0, using /1 divider\n", __func__);
126                 clk_div = 0;
127         }
129         if (clk_div > QSPI_CLK_DIV_MAX) {
130                 debug("%s: clock divider >%d , using /%d divider\n",
131                         __func__, QSPI_CLK_DIV_MAX, QSPI_CLK_DIV_MAX + 1);
132                 clk_div = QSPI_CLK_DIV_MAX;
133         }
135         /* enable SCLK */
136         writel(QSPI_CLK_EN | clk_div, &qspi->spi_clock_cntrl);
137         debug("%s: spi_clock_cntrl %08x\n", __func__, readl(&qspi->spi_clock_cntrl));
140 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
141                                   unsigned int max_hz, unsigned int mode)
143         struct qspi_slave *qslave;
145         qslave = spi_alloc_slave(struct qspi_slave, bus, cs);
146         if (!qslave)
147                 return NULL;
149         spi_set_speed(&qslave->slave, max_hz);
150         qslave->mode = mode;
151         debug("%s: bus:%i cs:%i mode:%i\n", __func__, bus, cs, mode);
153         return &qslave->slave;
156 void spi_free_slave(struct spi_slave *slave)
158         struct qspi_slave *qslave = to_qspi_slave(slave);
159         free(qslave);
162 int spi_claim_bus(struct spi_slave *slave)
164         debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
166         writel(0, &qspi->spi_dc);
167         writel(0, &qspi->spi_cmd);
168         writel(0, &qspi->spi_data);
170         return 0;
173 void spi_release_bus(struct spi_slave *slave)
175         debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
177         writel(0, &qspi->spi_dc);
178         writel(0, &qspi->spi_cmd);
179         writel(0, &qspi->spi_data);
182 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
183              void *din, unsigned long flags)
185         struct qspi_slave *qslave = to_qspi_slave(slave);
186         uint words = bitlen >> 3; /* fixed 8-bit word length */
187         const uchar *txp = dout;
188         uchar *rxp = din;
189         uint status;
190         int timeout;
192         debug("%s: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n", __func__,
193                 slave->bus, slave->cs, bitlen, words, flags);
194         if (bitlen == 0)
195                 return -1;
197         if (bitlen % 8) {
198                 flags |= SPI_XFER_END;
199                 return -1;
200         }
202         /* setup command reg */
203         qslave->cmd = 0;
204         qslave->cmd |= QSPI_WLEN(8);
205         qslave->cmd |= QSPI_EN_CS(slave->cs);
206         if (flags & SPI_3WIRE)
207                 qslave->cmd |= QSPI_3_PIN;
208         qslave->cmd |= 0xfff;
210         /* setup device control reg */
211         qslave->dc = 0;
212         if (qslave->mode & SPI_CPHA)
213                 qslave->dc |= QSPI_CKPHA(slave->cs);
214         if (qslave->mode & SPI_CPOL)
215                 qslave->dc |= QSPI_CKPOL(slave->cs);
216         if (qslave->mode & SPI_CS_HIGH)
217                 qslave->dc |= QSPI_CSPOL(slave->cs);
219         while (words--) {
220                 if (txp) {
221                         debug("tx cmd %08x dc %08x data %02x\n",
222                               qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
223                         writel(*txp++, &qspi->spi_data);
224                         writel(qslave->dc, &qspi->spi_dc);
225                         writel(qslave->cmd | QSPI_WR_SNGL, &qspi->spi_cmd);
226                         status = readl(&qspi->spi_status);
227                         timeout = QSPI_TIMEOUT;
228                         while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
229                                 if (--timeout < 0) {
230                                         printf("QSPI tx timed out\n");
231                                         return -1;
232                                 }
233                                 status = readl(&qspi->spi_status);
234                         }
235                         debug("tx done, status %08x\n", status);
236                 }
237                 if (rxp) {
238                         debug("rx cmd %08x dc %08x\n",
239                               qslave->cmd | QSPI_RD_SNGL, qslave->dc);
240                         writel(qslave->dc, &qspi->spi_dc);
241                         writel(qslave->cmd | QSPI_RD_SNGL, &qspi->spi_cmd);
242                         status = readl(&qspi->spi_status);
243                         timeout = QSPI_TIMEOUT;
244                         while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
245                                 if (--timeout < 0) {
246                                         printf("QSPI rx timed out\n");
247                                         return -1;
248                                 }
249                                 status = readl(&qspi->spi_status);
250                         }
251                         *rxp++ = readl(&qspi->spi_data);
252                         debug("rx done, status %08x, read %02x\n",
253                               status, *(rxp-1));
254                 }
255         }
257         /* Terminate frame */
258         if (flags & SPI_XFER_END)
259                 writel(qslave->cmd | QSPI_INVAL, &qspi->spi_cmd);
261         return 0;