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