1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 /*
4 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
5 */
6
7 #include <device/mmio.h>
8 #include <assert.h>
9 #include <console/console.h>
10 #include <endian.h>
11 #include <soc/addressmap.h>
12 #include <soc/spi.h>
13 #include <soc/clock.h>
14 #include <spi-generic.h>
15 #include <spi_flash.h>
16 #include <timer.h>
17
18 union cavium_spi_cfg {
19 u64 u;
20 struct {
21 u64 enable : 1;
22 u64 idlelow : 1;
23 u64 clk_cont : 1;
24 u64 wireor : 1;
25 u64 lsbfirst : 1;
26 u64 : 2;
27 u64 cshi : 1;
28 u64 idleclks : 2;
29 u64 tristate : 1;
30 u64 cslate : 1;
31 u64 csena : 4; /* Must be one */
32 u64 clkdiv : 13;
33 u64 : 35;
34 } s;
35 };
36
37 union cavium_spi_sts {
38 u64 u;
39 struct {
40 u64 busy : 1;
41 u64 mpi_intr : 1;
42 u64 : 6;
43 u64 rxnum : 5;
44 u64 : 51;
45 } s;
46 };
47
48 union cavium_spi_tx {
49 u64 u;
50 struct {
51 u64 totnum : 5;
52 u64 : 3;
53 u64 txnum : 5;
54 u64 : 3;
55 u64 leavecs : 1;
56 u64 : 3;
57 u64 csid : 2;
58 u64 : 42;
59 } s;
60 };
61
62 struct cavium_spi {
63 union cavium_spi_cfg cfg;
64 union cavium_spi_sts sts;
65 union cavium_spi_tx tx;
66 u64 rsvd1;
67 u64 sts_w1s;
68 u64 rsvd2;
69 u64 int_ena_w1c;
70 u64 int_ena_w1s;
71 u64 wide_dat;
72 u8 rsvd4[0x38];
73 u64 dat[8];
74 };
75
76 check_member(cavium_spi, cfg, 0);
77 check_member(cavium_spi, sts, 0x8);
78 check_member(cavium_spi, tx, 0x10);
79 check_member(cavium_spi, dat[7], 0xb8);
80
81 struct cavium_spi_slave {
82 struct cavium_spi *regs;
83 int cs;
84 };
85
86 #define SPI_TIMEOUT_US 5000
87
88 static struct cavium_spi_slave cavium_spi_slaves[] = {
89 {
90 .regs = (struct cavium_spi *)MPI_PF_BAR0,
91 .cs = 0,
92 },
93 };
94
to_cavium_spi(const struct spi_slave * slave)95 static struct cavium_spi_slave *to_cavium_spi(const struct spi_slave *slave)
96 {
97 assert(slave->bus < ARRAY_SIZE(cavium_spi_slaves));
98 return &cavium_spi_slaves[slave->bus];
99 }
100
101 /**
102 * Enable the SPI controller. Pins are driven.
103 *
104 * @param bus The SPI bus to operate on
105 */
spi_enable(const size_t bus)106 void spi_enable(const size_t bus)
107 {
108 union cavium_spi_cfg cfg;
109
110 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
111 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
112 return;
113
114 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
115
116 cfg.u = read64(®s->cfg);
117 cfg.s.csena = 0xf;
118 cfg.s.enable = 1;
119 write64(®s->cfg, cfg.u);
120 }
121
122 /**
123 * Disable the SPI controller. Pins are tristated.
124 *
125 * @param bus The SPI bus to operate on
126 */
spi_disable(const size_t bus)127 void spi_disable(const size_t bus)
128 {
129 union cavium_spi_cfg cfg;
130
131 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
132 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
133 return;
134
135 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
136
137 cfg.u = read64(®s->cfg);
138 cfg.s.csena = 0xf;
139 cfg.s.enable = 0;
140 write64(®s->cfg, cfg.u);
141 }
142
143 /**
144 * Set SPI Chip select line and level if asserted.
145 *
146 * @param bus The SPI bus to operate on
147 * @param chip_select The chip select pin to use (0 - 3)
148 * @param assert_is_low CS pin state is low when asserted
149 */
spi_set_cs(const size_t bus,const size_t chip_select,const size_t assert_is_low)150 void spi_set_cs(const size_t bus,
151 const size_t chip_select,
152 const size_t assert_is_low)
153 {
154 union cavium_spi_cfg cfg;
155
156 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
157 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
158 return;
159
160 cavium_spi_slaves[bus].cs = chip_select & 0x3;
161 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
162
163 cfg.u = read64(®s->cfg);
164 cfg.s.csena = 0xf;
165 cfg.s.cshi = !assert_is_low;
166 write64(®s->cfg, cfg.u);
167
168 //FIXME: CS2/3: Change pin mux here
169 }
170
171 /**
172 * Set SPI clock frequency.
173 *
174 * @param bus The SPI bus to operate on
175 * @param speed_hz The SPI frequency in Hz
176 * @param idle_low The SPI clock idles low
177 * @param idle_cycles Number of CLK cycles between two commands (0 - 3)
178
179 */
spi_set_clock(const size_t bus,const size_t speed_hz,const size_t idle_low,const size_t idle_cycles)180 void spi_set_clock(const size_t bus,
181 const size_t speed_hz,
182 const size_t idle_low,
183 const size_t idle_cycles)
184 {
185 union cavium_spi_cfg cfg;
186
187 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
188 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
189 return;
190
191 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
192 const uint64_t sclk = thunderx_get_io_clock();
193
194 cfg.u = read64(®s->cfg);
195 cfg.s.csena = 0xf;
196 cfg.s.clk_cont = 0;
197 cfg.s.idlelow = !!idle_low;
198 cfg.s.idleclks = idle_cycles & 0x3;
199 cfg.s.clkdiv = MIN(sclk / (2ULL * speed_hz), 0x1fff);
200 write64(®s->cfg, cfg.u);
201
202 printk(BIOS_DEBUG, "SPI: set clock to %lld kHz\n",
203 (sclk / (2ULL * cfg.s.clkdiv)) >> 10);
204 }
205
206 /**
207 * Get current SPI clock frequency in Hz.
208 *
209 * @param bus The SPI bus to operate on
210 */
spi_get_clock(const size_t bus)211 uint64_t spi_get_clock(const size_t bus)
212 {
213 union cavium_spi_cfg cfg;
214
215 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
216 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
217 return 0;
218
219 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
220 const uint64_t sclk = thunderx_get_io_clock();
221
222 cfg.u = read64(®s->cfg);
223
224 return (sclk / (2ULL * cfg.s.clkdiv));
225 }
226
227 /**
228 * Set SPI LSB/MSB first.
229 *
230 * @param bus The SPI bus to operate on
231 * @param lsb_first The SPI operates LSB first
232 *
233 */
spi_set_lsbmsb(const size_t bus,const size_t lsb_first)234 void spi_set_lsbmsb(const size_t bus, const size_t lsb_first)
235 {
236 union cavium_spi_cfg cfg;
237
238 assert(bus < ARRAY_SIZE(cavium_spi_slaves));
239 if (bus >= ARRAY_SIZE(cavium_spi_slaves))
240 return;
241
242 struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
243
244 cfg.u = read64(®s->cfg);
245 cfg.s.csena = 0xf;
246 cfg.s.lsbfirst = !!lsb_first;
247 write64(®s->cfg, cfg.u);
248 }
249
250 /**
251 * Init SPI with custom parameters and enable SPI controller.
252 *
253 * @param bus The SPI bus to operate on
254 * @param speed_hz The SPI frequency in Hz
255 * @param idle_low The SPI clock idles low
256 * @param idle_cycles Number of CLK cycles between two commands (0 - 3)
257 * @param lsb_first The SPI operates LSB first
258 * @param chip_select The chip select pin to use (0 - 3)
259 * @param assert_is_low CS pin state is low when asserted
260 */
spi_init_custom(const size_t bus,const size_t speed_hz,const size_t idle_low,const size_t idle_cycles,const size_t lsb_first,const size_t chip_select,const size_t assert_is_low)261 void spi_init_custom(const size_t bus,
262 const size_t speed_hz,
263 const size_t idle_low,
264 const size_t idle_cycles,
265 const size_t lsb_first,
266 const size_t chip_select,
267 const size_t assert_is_low)
268 {
269 spi_disable(bus);
270 spi_set_clock(bus, speed_hz, idle_low, idle_cycles);
271 spi_set_lsbmsb(bus, lsb_first);
272 spi_set_cs(bus, chip_select, assert_is_low);
273 spi_enable(bus);
274 }
275
276 /**
277 * Init all SPI controllers with default values and enable all SPI controller.
278 *
279 */
spi_init(void)280 void spi_init(void)
281 {
282 for (size_t i = 0; i < ARRAY_SIZE(cavium_spi_slaves); i++) {
283 spi_disable(i);
284 spi_set_clock(i, 12500000, 0, 0);
285 spi_set_lsbmsb(i, 0);
286 spi_set_cs(i, 0, 1);
287 spi_enable(i);
288 }
289 }
290
cavium_spi_wait(struct cavium_spi * regs)291 static int cavium_spi_wait(struct cavium_spi *regs)
292 {
293 struct stopwatch sw;
294 union cavium_spi_sts sts;
295
296 stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_US);
297 do {
298 sts.u = read64(®s->sts);
299 if (!sts.s.busy)
300 return 0;
301 } while (!stopwatch_expired(&sw));
302 printk(BIOS_DEBUG, "SPI: Timed out after %uus\n", SPI_TIMEOUT_US);
303 return -1;
304 }
305
do_xfer(const struct spi_slave * slave,struct spi_op * vector,int leavecs)306 static int do_xfer(const struct spi_slave *slave, struct spi_op *vector,
307 int leavecs)
308 {
309 struct cavium_spi *regs = to_cavium_spi(slave)->regs;
310 uint8_t *out_buf = (uint8_t *)vector->dout;
311 size_t bytesout = vector->bytesout;
312 uint8_t *in_buf = (uint8_t *)vector->din;
313 size_t bytesin = vector->bytesin;
314 union cavium_spi_sts sts;
315 union cavium_spi_tx tx;
316
317 /**
318 * The CN81xx SPI controller is half-duplex and has 8 data registers.
319 * If >8 bytes remain in the transfer then we must set LEAVECS = 1 so
320 * that the /CS remains asserted. Once <=8 bytes remain we must set
321 * LEAVECS = 0 so that /CS is de-asserted, thus completing the transfer.
322 */
323 while (bytesout) {
324 size_t out_now = MIN(bytesout, 8);
325 unsigned int i;
326
327 for (i = 0; i < out_now; i++)
328 write64(®s->dat[i], out_buf[i] & 0xff);
329
330 tx.u = 0;
331 tx.s.csid = to_cavium_spi(slave)->cs;
332 if (leavecs || ((bytesout > 8) || bytesin))
333 tx.s.leavecs = 1;
334 /* number of bytes to transmit goes in both TXNUM and TOTNUM */
335 tx.s.totnum = out_now;
336 tx.s.txnum = out_now;
337 write64(®s->tx, tx.u);
338
339 /* check status */
340 if (cavium_spi_wait(regs) < 0)
341 return -1;
342
343 bytesout -= out_now;
344 out_buf += out_now;
345 }
346
347 while (bytesin) {
348 size_t in_now = MIN(bytesin, 8);
349 unsigned int i;
350
351 tx.u = 0;
352 tx.s.csid = to_cavium_spi(slave)->cs;
353 if (leavecs || (bytesin > 8))
354 tx.s.leavecs = 1;
355 tx.s.totnum = in_now;
356 write64(®s->tx, tx.u);
357
358 /* check status */
359 if (cavium_spi_wait(regs) < 0)
360 return -1;
361
362 sts.u = read64(®s->sts);
363 if (sts.s.rxnum != in_now) {
364 printk(BIOS_ERR,
365 "SPI: Incorrect number of bytes received: %u.\n",
366 sts.s.rxnum);
367 return -1;
368 }
369
370 for (i = 0; i < in_now; i++) {
371 *in_buf = (uint8_t)((read64(®s->dat[i]) & 0xff));
372 in_buf++;
373 }
374 bytesin -= in_now;
375 }
376
377 return 0;
378 }
379
spi_ctrlr_xfer_vector(const struct spi_slave * slave,struct spi_op vectors[],size_t count)380 static int spi_ctrlr_xfer_vector(const struct spi_slave *slave,
381 struct spi_op vectors[], size_t count)
382 {
383 int i;
384
385 for (i = 0; i < count; i++) {
386 if (do_xfer(slave, &vectors[i], count - 1 == i ? 0 : 1)) {
387 printk(BIOS_ERR,
388 "SPI: Failed to transfer %zu vectors.\n", count);
389 return -1;
390 }
391 }
392
393 return 0;
394 }
395 static const struct spi_ctrlr spi_ctrlr = {
396 .xfer_vector = spi_ctrlr_xfer_vector,
397 .max_xfer_size = SPI_CTRLR_DEFAULT_MAX_XFER_SIZE,
398 };
399
400 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
401 {
402 .ctrlr = &spi_ctrlr,
403 .bus_start = 0,
404 .bus_end = ARRAY_SIZE(cavium_spi_slaves) - 1,
405 },
406 };
407 const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
408