Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / drivers / spi / sh_qspi.c
1 /*
2  * SH QSPI (Quad SPI) driver
3  *
4  * Copyright (C) 2013 Renesas Electronics Corporation
5  * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0
8  */
9
10 #include <common.h>
11 #include <malloc.h>
12 #include <spi.h>
13 #include <asm/arch/rmobile.h>
14 #include <asm/io.h>
15
16 /* SH QSPI register bit masks <REG>_<BIT> */
17 #define SPCR_MSTR       0x08
18 #define SPCR_SPE        0x40
19 #define SPSR_SPRFF      0x80
20 #define SPSR_SPTEF      0x20
21 #define SPPCR_IO3FV     0x04
22 #define SPPCR_IO2FV     0x02
23 #define SPPCR_IO1FV     0x01
24 #define SPBDCR_RXBC0    (1 << 0)
25 #define SPCMD_SCKDEN    (1 << 15)
26 #define SPCMD_SLNDEN    (1 << 14)
27 #define SPCMD_SPNDEN    (1 << 13)
28 #define SPCMD_SSLKP     (1 << 7)
29 #define SPCMD_BRDV0     (1 << 2)
30 #define SPCMD_INIT1     SPCMD_SCKDEN | SPCMD_SLNDEN | \
31                         SPCMD_SPNDEN | SPCMD_SSLKP | \
32                         SPCMD_BRDV0
33 #define SPCMD_INIT2     SPCMD_SPNDEN | SPCMD_SSLKP | \
34                         SPCMD_BRDV0
35 #define SPBFCR_TXRST    (1 << 7)
36 #define SPBFCR_RXRST    (1 << 6)
37
38 /* SH QSPI register set */
39 struct sh_qspi_regs {
40         unsigned char spcr;
41         unsigned char sslp;
42         unsigned char sppcr;
43         unsigned char spsr;
44         unsigned long spdr;
45         unsigned char spscr;
46         unsigned char spssr;
47         unsigned char spbr;
48         unsigned char spdcr;
49         unsigned char spckd;
50         unsigned char sslnd;
51         unsigned char spnd;
52         unsigned char dummy0;
53         unsigned short spcmd0;
54         unsigned short spcmd1;
55         unsigned short spcmd2;
56         unsigned short spcmd3;
57         unsigned char spbfcr;
58         unsigned char dummy1;
59         unsigned short spbdcr;
60         unsigned long spbmul0;
61         unsigned long spbmul1;
62         unsigned long spbmul2;
63         unsigned long spbmul3;
64 };
65
66 struct sh_qspi_slave {
67         struct spi_slave        slave;
68         struct sh_qspi_regs     *regs;
69 };
70
71 static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
72 {
73         return container_of(slave, struct sh_qspi_slave, slave);
74 }
75
76 static void sh_qspi_init(struct sh_qspi_slave *ss)
77 {
78         /* QSPI initialize */
79         /* Set master mode only */
80         writeb(SPCR_MSTR, &ss->regs->spcr);
81
82         /* Set SSL signal level */
83         writeb(0x00, &ss->regs->sslp);
84
85         /* Set MOSI signal value when transfer is in idle state */
86         writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
87
88         /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
89         writeb(0x01, &ss->regs->spbr);
90
91         /* Disable Dummy Data Transmission */
92         writeb(0x00, &ss->regs->spdcr);
93
94         /* Set clock delay value */
95         writeb(0x00, &ss->regs->spckd);
96
97         /* Set SSL negation delay value */
98         writeb(0x00, &ss->regs->sslnd);
99
100         /* Set next-access delay value */
101         writeb(0x00, &ss->regs->spnd);
102
103         /* Set equence command */
104         writew(SPCMD_INIT2, &ss->regs->spcmd0);
105
106         /* Reset transfer and receive Buffer */
107         setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
108
109         /* Clear transfer and receive Buffer control bit */
110         clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
111
112         /* Set equence control method. Use equence0 only */
113         writeb(0x00, &ss->regs->spscr);
114
115         /* Enable SPI function */
116         setbits_8(&ss->regs->spcr, SPCR_SPE);
117 }
118
119 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
120 {
121         return 1;
122 }
123
124 void spi_cs_activate(struct spi_slave *slave)
125 {
126         struct sh_qspi_slave *ss = to_sh_qspi(slave);
127
128         /* Set master mode only */
129         writeb(SPCR_MSTR, &ss->regs->spcr);
130
131         /* Set command */
132         writew(SPCMD_INIT1, &ss->regs->spcmd0);
133
134         /* Reset transfer and receive Buffer */
135         setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
136
137         /* Clear transfer and receive Buffer control bit */
138         clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
139
140         /* Set equence control method. Use equence0 only */
141         writeb(0x00, &ss->regs->spscr);
142
143         /* Enable SPI function */
144         setbits_8(&ss->regs->spcr, SPCR_SPE);
145 }
146
147 void spi_cs_deactivate(struct spi_slave *slave)
148 {
149         struct sh_qspi_slave *ss = to_sh_qspi(slave);
150
151         /* Disable SPI Function */
152         clrbits_8(&ss->regs->spcr, SPCR_SPE);
153 }
154
155 void spi_init(void)
156 {
157         /* nothing to do */
158 }
159
160 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
161                 unsigned int max_hz, unsigned int mode)
162 {
163         struct sh_qspi_slave *ss;
164
165         if (!spi_cs_is_valid(bus, cs))
166                 return NULL;
167
168         ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
169         if (!ss) {
170                 printf("SPI_error: Fail to allocate sh_qspi_slave\n");
171                 return NULL;
172         }
173
174         ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
175
176         /* Init SH QSPI */
177         sh_qspi_init(ss);
178
179         return &ss->slave;
180 }
181
182 void spi_free_slave(struct spi_slave *slave)
183 {
184         struct sh_qspi_slave *spi = to_sh_qspi(slave);
185
186         free(spi);
187 }
188
189 int spi_claim_bus(struct spi_slave *slave)
190 {
191         return 0;
192 }
193
194 void spi_release_bus(struct spi_slave *slave)
195 {
196 }
197
198 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
199              void *din, unsigned long flags)
200 {
201         struct sh_qspi_slave *ss = to_sh_qspi(slave);
202         unsigned long nbyte;
203         int ret = 0;
204         unsigned char dtdata = 0, drdata;
205         unsigned char *tdata = &dtdata, *rdata = &drdata;
206         unsigned long *spbmul0 = &ss->regs->spbmul0;
207
208         if (dout == NULL && din == NULL) {
209                 if (flags & SPI_XFER_END)
210                         spi_cs_deactivate(slave);
211                 return 0;
212         }
213
214         if (bitlen % 8) {
215                 printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
216                 return 1;
217         }
218
219         nbyte = bitlen / 8;
220
221         if (flags & SPI_XFER_BEGIN) {
222                 spi_cs_activate(slave);
223
224                 /* Set 1048576 byte */
225                 writel(0x100000, spbmul0);
226         }
227
228         if (flags & SPI_XFER_END)
229                 writel(nbyte, spbmul0);
230
231         if (dout != NULL)
232                 tdata = (unsigned char *)dout;
233
234         if (din != NULL)
235                 rdata = din;
236
237         while (nbyte > 0) {
238                 while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) {
239                         if (ctrlc()) {
240                                 puts("abort\n");
241                                 return 1;
242                         }
243                         udelay(10);
244                 }
245
246                 writeb(*tdata, (unsigned char *)(&ss->regs->spdr));
247
248                 while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) {
249                         if (ctrlc()) {
250                                 puts("abort\n");
251                                 return 1;
252                         }
253                         udelay(1);
254                 }
255
256                 while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) {
257                         if (ctrlc()) {
258                                 puts("abort\n");
259                                 return 1;
260                         }
261                         udelay(10);
262                 }
263
264                 *rdata = readb((unsigned char *)(&ss->regs->spdr));
265
266                 if (dout != NULL)
267                         tdata++;
268                 if (din != NULL)
269                         rdata++;
270
271                 nbyte--;
272         }
273
274         if (flags & SPI_XFER_END)
275                 spi_cs_deactivate(slave);
276
277         return ret;
278 }