blob: e9123e2c39c5a917f6277e07d5bfd2354fb87da7 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +09002/*
3 * SH QSPI (Quad SPI) driver
4 *
5 * Copyright (C) 2013 Renesas Electronics Corporation
6 * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +09007 */
8
9#include <common.h>
Simon Glass24b852a2015-11-08 23:47:45 -070010#include <console.h>
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +090011#include <malloc.h>
12#include <spi.h>
Marek Vasut9573db62018-04-10 16:58:46 +020013#include <wait_bit.h>
Nobuhiro Iwamatsu22e75d62014-01-08 10:16:25 +090014#include <asm/arch/rmobile.h>
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +090015#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
Jagan Tekiccaa9482015-10-23 01:38:47 +053025#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)
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +090031#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
Jagan Tekiccaa9482015-10-23 01:38:47 +053036#define SPBFCR_TXRST BIT(7)
37#define SPBFCR_RXRST BIT(6)
Marek Vasutea5512e2018-04-10 16:43:47 +020038#define SPBFCR_TXTRG 0x30
39#define SPBFCR_RXTRG 0x07
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +090040
41/* SH QSPI register set */
42struct sh_qspi_regs {
Marek Vasut0e6fa202018-04-10 16:47:38 +020043 u8 spcr;
44 u8 sslp;
45 u8 sppcr;
46 u8 spsr;
47 u32 spdr;
48 u8 spscr;
49 u8 spssr;
50 u8 spbr;
51 u8 spdcr;
52 u8 spckd;
53 u8 sslnd;
54 u8 spnd;
55 u8 dummy0;
56 u16 spcmd0;
57 u16 spcmd1;
58 u16 spcmd2;
59 u16 spcmd3;
60 u8 spbfcr;
61 u8 dummy1;
62 u16 spbdcr;
63 u32 spbmul0;
64 u32 spbmul1;
65 u32 spbmul2;
66 u32 spbmul3;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +090067};
68
69struct sh_qspi_slave {
70 struct spi_slave slave;
71 struct sh_qspi_regs *regs;
72};
73
74static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
75{
76 return container_of(slave, struct sh_qspi_slave, slave);
77}
78
79static void sh_qspi_init(struct sh_qspi_slave *ss)
80{
81 /* QSPI initialize */
82 /* Set master mode only */
83 writeb(SPCR_MSTR, &ss->regs->spcr);
84
85 /* Set SSL signal level */
86 writeb(0x00, &ss->regs->sslp);
87
88 /* Set MOSI signal value when transfer is in idle state */
89 writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
90
91 /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
92 writeb(0x01, &ss->regs->spbr);
93
94 /* Disable Dummy Data Transmission */
95 writeb(0x00, &ss->regs->spdcr);
96
97 /* Set clock delay value */
98 writeb(0x00, &ss->regs->spckd);
99
100 /* Set SSL negation delay value */
101 writeb(0x00, &ss->regs->sslnd);
102
103 /* Set next-access delay value */
104 writeb(0x00, &ss->regs->spnd);
105
106 /* Set equence command */
107 writew(SPCMD_INIT2, &ss->regs->spcmd0);
108
109 /* Reset transfer and receive Buffer */
110 setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
111
112 /* Clear transfer and receive Buffer control bit */
113 clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
114
115 /* Set equence control method. Use equence0 only */
116 writeb(0x00, &ss->regs->spscr);
117
118 /* Enable SPI function */
119 setbits_8(&ss->regs->spcr, SPCR_SPE);
120}
121
122int spi_cs_is_valid(unsigned int bus, unsigned int cs)
123{
124 return 1;
125}
126
127void spi_cs_activate(struct spi_slave *slave)
128{
129 struct sh_qspi_slave *ss = to_sh_qspi(slave);
130
131 /* Set master mode only */
132 writeb(SPCR_MSTR, &ss->regs->spcr);
133
134 /* Set command */
135 writew(SPCMD_INIT1, &ss->regs->spcmd0);
136
137 /* Reset transfer and receive Buffer */
138 setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
139
140 /* Clear transfer and receive Buffer control bit */
141 clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
142
143 /* Set equence control method. Use equence0 only */
144 writeb(0x00, &ss->regs->spscr);
145
146 /* Enable SPI function */
147 setbits_8(&ss->regs->spcr, SPCR_SPE);
148}
149
150void spi_cs_deactivate(struct spi_slave *slave)
151{
152 struct sh_qspi_slave *ss = to_sh_qspi(slave);
153
154 /* Disable SPI Function */
155 clrbits_8(&ss->regs->spcr, SPCR_SPE);
156}
157
158void spi_init(void)
159{
160 /* nothing to do */
161}
162
163struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
164 unsigned int max_hz, unsigned int mode)
165{
166 struct sh_qspi_slave *ss;
167
168 if (!spi_cs_is_valid(bus, cs))
169 return NULL;
170
171 ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
172 if (!ss) {
173 printf("SPI_error: Fail to allocate sh_qspi_slave\n");
174 return NULL;
175 }
176
Nobuhiro Iwamatsu22e75d62014-01-08 10:16:25 +0900177 ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900178
179 /* Init SH QSPI */
180 sh_qspi_init(ss);
181
182 return &ss->slave;
183}
184
185void spi_free_slave(struct spi_slave *slave)
186{
187 struct sh_qspi_slave *spi = to_sh_qspi(slave);
188
189 free(spi);
190}
191
192int spi_claim_bus(struct spi_slave *slave)
193{
194 return 0;
195}
196
197void spi_release_bus(struct spi_slave *slave)
198{
199}
200
201int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
202 void *din, unsigned long flags)
203{
204 struct sh_qspi_slave *ss = to_sh_qspi(slave);
Marek Vasutea5512e2018-04-10 16:43:47 +0200205 u32 nbyte, chunk;
206 int i, ret = 0;
Marek Vasut0e6fa202018-04-10 16:47:38 +0200207 u8 dtdata = 0, drdata;
208 u8 *tdata = &dtdata, *rdata = &drdata;
209 u32 *spbmul0 = &ss->regs->spbmul0;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900210
211 if (dout == NULL && din == NULL) {
212 if (flags & SPI_XFER_END)
213 spi_cs_deactivate(slave);
214 return 0;
215 }
216
217 if (bitlen % 8) {
218 printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
219 return 1;
220 }
221
222 nbyte = bitlen / 8;
223
224 if (flags & SPI_XFER_BEGIN) {
225 spi_cs_activate(slave);
226
227 /* Set 1048576 byte */
228 writel(0x100000, spbmul0);
229 }
230
231 if (flags & SPI_XFER_END)
232 writel(nbyte, spbmul0);
233
234 if (dout != NULL)
Marek Vasut0e6fa202018-04-10 16:47:38 +0200235 tdata = (u8 *)dout;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900236
237 if (din != NULL)
238 rdata = din;
239
240 while (nbyte > 0) {
Marek Vasutea5512e2018-04-10 16:43:47 +0200241 /*
242 * Check if there is 32 Byte chunk and if there is, transfer
243 * it in one burst, otherwise transfer on byte-by-byte basis.
244 */
245 chunk = (nbyte >= 32) ? 32 : 1;
246
247 clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG,
248 chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0);
249
Marek Vasut9573db62018-04-10 16:58:46 +0200250 ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF,
251 true, 1000, true);
252 if (ret)
253 return ret;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900254
Marek Vasutea5512e2018-04-10 16:43:47 +0200255 for (i = 0; i < chunk; i++) {
256 writeb(*tdata, &ss->regs->spdr);
257 if (dout != NULL)
258 tdata++;
259 }
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900260
Marek Vasut9573db62018-04-10 16:58:46 +0200261 ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF,
262 true, 1000, true);
263 if (ret)
264 return ret;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900265
Marek Vasutea5512e2018-04-10 16:43:47 +0200266 for (i = 0; i < chunk; i++) {
267 *rdata = readb(&ss->regs->spdr);
268 if (din != NULL)
269 rdata++;
270 }
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900271
Marek Vasutea5512e2018-04-10 16:43:47 +0200272 nbyte -= chunk;
Nobuhiro Iwamatsu16f47c92013-12-18 15:31:55 +0900273 }
274
275 if (flags & SPI_XFER_END)
276 spi_cs_deactivate(slave);
277
278 return ret;
279}