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)
75 #define QSPI_RD_QUAD (7 << 16)
77 /* Device Control */
78 #define QSPI_DD(m, n) (m << (3 + n*8))
79 #define QSPI_CKPHA(n) (1 << (2 + n*8))
80 #define QSPI_CSPOL(n) (1 << (1 + n*8))
81 #define QSPI_CKPOL(n) (1 << (n*8))
83 /* Status */
84 #define QSPI_WC (1 << 1)
85 #define QSPI_BUSY (1 << 0)
86 #define QSPI_WC_BUSY (QSPI_WC | QSPI_BUSY)
87 #define QSPI_XFER_DONE QSPI_WC
89 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
90 {
91 return 1;
92 }
94 void spi_cs_activate(struct spi_slave *slave)
95 {
96 /* CS handled in xfer */
97 return;
98 }
100 void spi_cs_deactivate(struct spi_slave *slave)
101 {
102 /* CS handled in xfer */
103 return;
104 }
106 void spi_init(void)
107 {
108 /* nothing to do */
109 }
111 void spi_set_speed(struct spi_slave *slave, uint hz)
112 {
113 uint clk_div;
115 if (!hz)
116 clk_div = 0;
117 else
118 clk_div = (QSPI_FCLK / hz) - 1;
120 debug("%s: hz: %d, clock divider %d\n", __func__, hz, clk_div);
122 /* disable SCLK */
123 writel(readl(&qspi->spi_clock_cntrl) & ~QSPI_CLK_EN, &qspi->spi_clock_cntrl);
125 if (clk_div < 0) {
126 debug("%s: clock divider < 0, using /1 divider\n", __func__);
127 clk_div = 0;
128 }
130 if (clk_div > QSPI_CLK_DIV_MAX) {
131 debug("%s: clock divider >%d , using /%d divider\n",
132 __func__, QSPI_CLK_DIV_MAX, QSPI_CLK_DIV_MAX + 1);
133 clk_div = QSPI_CLK_DIV_MAX;
134 }
136 /* enable SCLK */
137 writel(QSPI_CLK_EN | clk_div, &qspi->spi_clock_cntrl);
138 debug("%s: spi_clock_cntrl %08x\n", __func__, readl(&qspi->spi_clock_cntrl));
139 }
141 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
142 unsigned int max_hz, unsigned int mode)
143 {
144 struct qspi_slave *qslave;
146 qslave = spi_alloc_slave(struct qspi_slave, bus, cs);
147 if (!qslave)
148 return NULL;
150 spi_set_speed(&qslave->slave, max_hz);
151 qslave->mode = mode;
152 debug("%s: bus:%i cs:%i mode:%i\n", __func__, bus, cs, mode);
154 return &qslave->slave;
155 }
157 void spi_free_slave(struct spi_slave *slave)
158 {
159 struct qspi_slave *qslave = to_qspi_slave(slave);
160 free(qslave);
161 }
163 int spi_claim_bus(struct spi_slave *slave)
164 {
165 debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
167 writel(0, &qspi->spi_dc);
168 writel(0, &qspi->spi_cmd);
169 writel(0, &qspi->spi_data);
171 return 0;
172 }
174 void spi_release_bus(struct spi_slave *slave)
175 {
176 debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
178 writel(0, &qspi->spi_dc);
179 writel(0, &qspi->spi_cmd);
180 writel(0, &qspi->spi_data);
181 }
183 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
184 void *din, unsigned long flags)
185 {
186 struct qspi_slave *qslave = to_qspi_slave(slave);
187 uint words = bitlen >> 3; /* fixed 8-bit word length */
188 const uchar *txp = dout;
189 uchar *rxp = din;
190 uint status;
191 int timeout;
193 debug("%s: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n", __func__,
194 slave->bus, slave->cs, bitlen, words, flags);
195 if (bitlen == 0)
196 return -1;
198 if (bitlen % 8) {
199 flags |= SPI_XFER_END;
200 return -1;
201 }
203 /* setup command reg */
204 qslave->cmd = 0;
205 qslave->cmd |= QSPI_WLEN(8);
206 qslave->cmd |= QSPI_EN_CS(slave->cs);
207 if (flags & SPI_3WIRE)
208 qslave->cmd |= QSPI_3_PIN;
209 qslave->cmd |= 0xfff;
211 /* setup device control reg */
212 qslave->dc = 0;
213 if (qslave->mode & SPI_CPHA)
214 qslave->dc |= QSPI_CKPHA(slave->cs);
215 if (qslave->mode & SPI_CPOL)
216 qslave->dc |= QSPI_CKPOL(slave->cs);
217 if (qslave->mode & SPI_CS_HIGH)
218 qslave->dc |= QSPI_CSPOL(slave->cs);
220 while (words--) {
221 if (txp) {
222 debug("tx cmd %08x dc %08x data %02x\n",
223 qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
224 writel(*txp++, &qspi->spi_data);
225 writel(qslave->dc, &qspi->spi_dc);
226 writel(qslave->cmd | QSPI_WR_SNGL, &qspi->spi_cmd);
227 status = readl(&qspi->spi_status);
228 timeout = QSPI_TIMEOUT;
229 while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
230 if (--timeout < 0) {
231 printf("QSPI tx timed out\n");
232 return -1;
233 }
234 status = readl(&qspi->spi_status);
235 }
236 debug("tx done, status %08x\n", status);
237 }
238 if (rxp) {
239 if (flags & SPI_6WIRE) {
240 debug("rx cmd %08x dc %08x\n",
241 qslave->cmd | QSPI_RD_QUAD, qslave->dc);
242 writel(qslave->cmd | QSPI_RD_QUAD,
243 &qspi->spi_cmd);
244 } else {
245 debug("rx cmd %08x dc %08x\n",
246 qslave->cmd | QSPI_RD_SNGL, qslave->dc);
247 writel(qslave->cmd | QSPI_RD_SNGL,
248 &qspi->spi_cmd);
249 }
250 status = readl(&qspi->spi_status);
251 timeout = QSPI_TIMEOUT;
252 while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
253 if (--timeout < 0) {
254 printf("QSPI rx timed out\n");
255 return -1;
256 }
257 status = readl(&qspi->spi_status);
258 }
259 *rxp++ = readl(&qspi->spi_data);
260 debug("rx done, status %08x, read %02x\n",
261 status, *(rxp-1));
262 }
263 }
265 /* Terminate frame */
266 if (flags & SPI_XFER_END)
267 writel(qslave->cmd | QSPI_INVAL, &qspi->spi_cmd);
269 return 0;
270 }