1 /*-
2 * Copyright (c) 2018 Thomas Skibo <thomasskibo@yahoo.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/conf.h>
31 #include <sys/kernel.h>
32 #include <sys/module.h>
33 #include <sys/sysctl.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/resource.h>
37 #include <sys/rman.h>
38 #include <sys/uio.h>
39
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <machine/stdarg.h>
43
44 #include <dev/fdt/fdt_common.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47
48 #include <dev/spibus/spi.h>
49 #include <dev/spibus/spibusvar.h>
50
51 #include "spibus_if.h"
52
53 static struct ofw_compat_data compat_data[] = {
54 {"xlnx,zy7_spi", 1},
55 {"xlnx,zynq-spi-1.0", 1},
56 {"cdns,spi-r1p6", 1},
57 {NULL, 0}
58 };
59
60 struct zy7_spi_softc {
61 device_t dev;
62 device_t child;
63 struct mtx sc_mtx;
64 struct resource *mem_res;
65 struct resource *irq_res;
66 void *intrhandle;
67
68 uint32_t cfg_reg_shadow;
69 uint32_t spi_clock;
70 uint32_t ref_clock;
71 unsigned int spi_clk_real_freq;
72 unsigned int rx_overflows;
73 unsigned int tx_underflows;
74 unsigned int interrupts;
75 unsigned int stray_ints;
76 struct spi_command *cmd;
77 int tx_bytes; /* tx_cmd_sz + tx_data_sz */
78 int tx_bytes_sent;
79 int rx_bytes; /* rx_cmd_sz + rx_data_sz */
80 int rx_bytes_rcvd;
81 int busy;
82 };
83
84 #define ZY7_SPI_DEFAULT_SPI_CLOCK 50000000
85
86 #define SPI_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
87 #define SPI_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
88 #define SPI_SC_LOCK_INIT(sc) \
89 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), NULL, MTX_DEF)
90 #define SPI_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
91 #define SPI_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
92
93 #define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
94 #define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
95
96 /*
97 * SPI device registers.
98 * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
99 * (v1.12.1) December 6, 2017. Xilinx doc UG585.
100 */
101 #define ZY7_SPI_CONFIG_REG 0x0000
102 #define ZY7_SPI_CONFIG_MODEFAIL_GEN_EN (1 << 17)
103 #define ZY7_SPI_CONFIG_MAN_STRT (1 << 16)
104 #define ZY7_SPI_CONFIG_MAN_STRT_EN (1 << 15)
105 #define ZY7_SPI_CONFIG_MAN_CS (1 << 14)
106 #define ZY7_SPI_CONFIG_CS_MASK (0xf << 10)
107 #define ZY7_SPI_CONFIG_CS(x) ((0xf ^ (1 << (x))) << 10)
108 #define ZY7_SPI_CONFIG_PERI_SEL (1 << 9)
109 #define ZY7_SPI_CONFIG_REF_CLK (1 << 8)
110 #define ZY7_SPI_CONFIG_BAUD_RATE_DIV_MASK (7 << 3)
111 #define ZY7_SPI_CONFIG_BAUD_RATE_DIV_SHIFT 3
112 #define ZY7_SPI_CONFIG_BAUD_RATE_DIV(x) ((x) << 3) /* divide by 2<<x */
113 #define ZY7_SPI_CONFIG_CLK_PH (1 << 2) /* clock phase */
114 #define ZY7_SPI_CONFIG_CLK_POL (1 << 1) /* clock polatiry */
115 #define ZY7_SPI_CONFIG_MODE_SEL (1 << 0) /* master enable */
116
117 #define ZY7_SPI_INTR_STAT_REG 0x0004
118 #define ZY7_SPI_INTR_EN_REG 0x0008
119 #define ZY7_SPI_INTR_DIS_REG 0x000c
120 #define ZY7_SPI_INTR_MASK_REG 0x0010
121 #define ZY7_SPI_INTR_TX_FIFO_UNDERFLOW (1 << 6)
122 #define ZY7_SPI_INTR_RX_FIFO_FULL (1 << 5)
123 #define ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY (1 << 4)
124 #define ZY7_SPI_INTR_TX_FIFO_FULL (1 << 3)
125 #define ZY7_SPI_INTR_TX_FIFO_NOT_FULL (1 << 2)
126 #define ZY7_SPI_INTR_MODE_FAULT (1 << 1)
127 #define ZY7_SPI_INTR_RX_OVERFLOW (1 << 0)
128
129 #define ZY7_SPI_EN_REG 0x0014
130 #define ZY7_SPI_ENABLE (1 << 0)
131
132 #define ZY7_SPI_DELAY_CTRL_REG 0x0018
133 #define ZY7_SPI_DELAY_CTRL_BTWN_MASK (0xff << 16)
134 #define ZY7_SPI_DELAY_CTRL_BTWN_SHIFT 16
135 #define ZY7_SPI_DELAY_CTRL_AFTER_MASK (0xff << 8)
136 #define ZY7_SPI_DELAY_CTRL_AFTER_SHIFT 8
137 #define ZY7_SPI_DELAY_CTRL_INIT_MASK (0xff << 0)
138 #define ZY7_SPI_DELAY_CTRL_INIT_SHIFT 0
139
140 #define ZY7_SPI_TX_DATA_REG 0x001c
141 #define ZY7_SPI_RX_DATA_REG 0x0020
142
143 #define ZY7_SPI_SLV_IDLE_COUNT_REG 0x0024
144
145 #define ZY7_SPI_TX_THRESH_REG 0x0028
146 #define ZY7_SPI_RX_THRESH_REG 0x002c
147
148 /* Fill hardware fifo with command and data bytes. */
149 static void
zy7_spi_write_fifo(struct zy7_spi_softc * sc,int nbytes)150 zy7_spi_write_fifo(struct zy7_spi_softc *sc, int nbytes)
151 {
152 uint8_t byte;
153
154 while (nbytes > 0) {
155 if (sc->tx_bytes_sent < sc->cmd->tx_cmd_sz)
156 /* Writing command. */
157 byte = *((uint8_t *)sc->cmd->tx_cmd +
158 sc->tx_bytes_sent);
159 else
160 /* Writing data. */
161 byte = *((uint8_t *)sc->cmd->tx_data +
162 (sc->tx_bytes_sent - sc->cmd->tx_cmd_sz));
163
164 WR4(sc, ZY7_SPI_TX_DATA_REG, (uint32_t)byte);
165
166 sc->tx_bytes_sent++;
167 nbytes--;
168 }
169 }
170
171 /* Read hardware fifo data into command response and data buffers. */
172 static void
zy7_spi_read_fifo(struct zy7_spi_softc * sc)173 zy7_spi_read_fifo(struct zy7_spi_softc *sc)
174 {
175 uint8_t byte;
176
177 do {
178 byte = RD4(sc, ZY7_SPI_RX_DATA_REG) & 0xff;
179
180 if (sc->rx_bytes_rcvd < sc->cmd->rx_cmd_sz)
181 /* Reading command. */
182 *((uint8_t *)sc->cmd->rx_cmd + sc->rx_bytes_rcvd) =
183 byte;
184 else
185 /* Reading data. */
186 *((uint8_t *)sc->cmd->rx_data +
187 (sc->rx_bytes_rcvd - sc->cmd->rx_cmd_sz)) =
188 byte;
189
190 sc->rx_bytes_rcvd++;
191
192 } while (sc->rx_bytes_rcvd < sc->rx_bytes &&
193 (RD4(sc, ZY7_SPI_INTR_STAT_REG) &
194 ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY) != 0);
195 }
196
197 /* End a transfer early by draining rx fifo and disabling interrupts. */
198 static void
zy7_spi_abort_transfer(struct zy7_spi_softc * sc)199 zy7_spi_abort_transfer(struct zy7_spi_softc *sc)
200 {
201 /* Drain receive fifo. */
202 while ((RD4(sc, ZY7_SPI_INTR_STAT_REG) &
203 ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY) != 0)
204 (void)RD4(sc, ZY7_SPI_RX_DATA_REG);
205
206 /* Shut down interrupts. */
207 WR4(sc, ZY7_SPI_INTR_DIS_REG,
208 ZY7_SPI_INTR_RX_OVERFLOW |
209 ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY |
210 ZY7_SPI_INTR_TX_FIFO_NOT_FULL);
211 }
212
213 static void
zy7_spi_intr(void * arg)214 zy7_spi_intr(void *arg)
215 {
216 struct zy7_spi_softc *sc = (struct zy7_spi_softc *)arg;
217 uint32_t istatus;
218
219 SPI_SC_LOCK(sc);
220
221 sc->interrupts++;
222
223 istatus = RD4(sc, ZY7_SPI_INTR_STAT_REG);
224
225 /* Stray interrupts can happen if a transfer gets interrupted. */
226 if (!sc->busy) {
227 sc->stray_ints++;
228 SPI_SC_UNLOCK(sc);
229 return;
230 }
231
232 if ((istatus & ZY7_SPI_INTR_RX_OVERFLOW) != 0) {
233 device_printf(sc->dev, "rx fifo overflow!\n");
234 sc->rx_overflows++;
235
236 /* Clear status bit. */
237 WR4(sc, ZY7_SPI_INTR_STAT_REG,
238 ZY7_SPI_INTR_RX_OVERFLOW);
239 }
240
241 /* Empty receive fifo before any more transmit data is sent. */
242 if (sc->rx_bytes_rcvd < sc->rx_bytes &&
243 (istatus & ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY) != 0) {
244 zy7_spi_read_fifo(sc);
245 if (sc->rx_bytes_rcvd == sc->rx_bytes)
246 /* Disable receive interrupts. */
247 WR4(sc, ZY7_SPI_INTR_DIS_REG,
248 ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY |
249 ZY7_SPI_INTR_RX_OVERFLOW);
250 }
251
252 /* Count tx underflows. They probably shouldn't happen. */
253 if ((istatus & ZY7_SPI_INTR_TX_FIFO_UNDERFLOW) != 0) {
254 sc->tx_underflows++;
255
256 /* Clear status bit. */
257 WR4(sc, ZY7_SPI_INTR_STAT_REG,
258 ZY7_SPI_INTR_TX_FIFO_UNDERFLOW);
259 }
260
261 /* Fill transmit fifo. */
262 if (sc->tx_bytes_sent < sc->tx_bytes &&
263 (istatus & ZY7_SPI_INTR_TX_FIFO_NOT_FULL) != 0) {
264 zy7_spi_write_fifo(sc, MIN(96, sc->tx_bytes -
265 sc->tx_bytes_sent));
266
267 if (sc->tx_bytes_sent == sc->tx_bytes) {
268 /* Disable transmit FIFO interrupt, enable receive
269 * FIFO interrupt.
270 */
271 WR4(sc, ZY7_SPI_INTR_DIS_REG,
272 ZY7_SPI_INTR_TX_FIFO_NOT_FULL);
273 WR4(sc, ZY7_SPI_INTR_EN_REG,
274 ZY7_SPI_INTR_RX_FIFO_NOT_EMPTY);
275 }
276 }
277
278 /* Finished with transfer? */
279 if (sc->tx_bytes_sent == sc->tx_bytes &&
280 sc->rx_bytes_rcvd == sc->rx_bytes) {
281 /* De-assert CS. */
282 sc->cfg_reg_shadow &=
283 ~(ZY7_SPI_CONFIG_CLK_PH | ZY7_SPI_CONFIG_CLK_POL);
284 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CS_MASK;
285 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow);
286
287 wakeup(sc->dev);
288 }
289
290 SPI_SC_UNLOCK(sc);
291 }
292
293 /* Initialize hardware. */
294 static int
zy7_spi_init_hw(struct zy7_spi_softc * sc)295 zy7_spi_init_hw(struct zy7_spi_softc *sc)
296 {
297 uint32_t baud_div;
298
299 /* Find best clock divider. Divide by 2 not supported. */
300 baud_div = 1;
301 while ((sc->ref_clock >> (baud_div + 1)) > sc->spi_clock &&
302 baud_div < 8)
303 baud_div++;
304 if (baud_div >= 8) {
305 device_printf(sc->dev, "cannot configure clock divider: ref=%d"
306 " spi=%d.\n", sc->ref_clock, sc->spi_clock);
307 return (EINVAL);
308 }
309 sc->spi_clk_real_freq = sc->ref_clock >> (baud_div + 1);
310
311 /* Set up configuration register. */
312 sc->cfg_reg_shadow =
313 ZY7_SPI_CONFIG_MAN_CS |
314 ZY7_SPI_CONFIG_CS_MASK |
315 ZY7_SPI_CONFIG_BAUD_RATE_DIV(baud_div) |
316 ZY7_SPI_CONFIG_MODE_SEL;
317 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow);
318
319 /* Set thresholds. */
320 WR4(sc, ZY7_SPI_TX_THRESH_REG, 32);
321 WR4(sc, ZY7_SPI_RX_THRESH_REG, 1);
322
323 /* Clear and disable all interrupts. */
324 WR4(sc, ZY7_SPI_INTR_STAT_REG, ~0);
325 WR4(sc, ZY7_SPI_INTR_DIS_REG, ~0);
326
327 /* Enable SPI. */
328 WR4(sc, ZY7_SPI_EN_REG, ZY7_SPI_ENABLE);
329
330 return (0);
331 }
332
333 static void
zy7_spi_add_sysctls(device_t dev)334 zy7_spi_add_sysctls(device_t dev)
335 {
336 struct zy7_spi_softc *sc = device_get_softc(dev);
337 struct sysctl_ctx_list *ctx;
338 struct sysctl_oid_list *child;
339
340 ctx = device_get_sysctl_ctx(dev);
341 child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
342
343 SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "spi_clk_real_freq", CTLFLAG_RD,
344 &sc->spi_clk_real_freq, 0, "SPI clock real frequency");
345
346 SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_overflows", CTLFLAG_RD,
347 &sc->rx_overflows, 0, "RX FIFO overflow events");
348
349 SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_underflows", CTLFLAG_RD,
350 &sc->tx_underflows, 0, "TX FIFO underflow events");
351
352 SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "interrupts", CTLFLAG_RD,
353 &sc->interrupts, 0, "interrupt calls");
354
355 SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "stray_ints", CTLFLAG_RD,
356 &sc->stray_ints, 0, "stray interrupts");
357 }
358
359 static int
zy7_spi_probe(device_t dev)360 zy7_spi_probe(device_t dev)
361 {
362
363 if (!ofw_bus_status_okay(dev))
364 return (ENXIO);
365
366 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
367 return (ENXIO);
368
369 device_set_desc(dev, "Zynq SPI Controller");
370
371 return (BUS_PROBE_DEFAULT);
372 }
373
374 static int zy7_spi_detach(device_t);
375
376 static int
zy7_spi_attach(device_t dev)377 zy7_spi_attach(device_t dev)
378 {
379 struct zy7_spi_softc *sc;
380 int rid, err;
381 phandle_t node;
382 pcell_t cell;
383
384 sc = device_get_softc(dev);
385 sc->dev = dev;
386
387 SPI_SC_LOCK_INIT(sc);
388
389 /* Get ref-clock and spi-clock properties. */
390 node = ofw_bus_get_node(dev);
391 if (OF_getprop(node, "ref-clock", &cell, sizeof(cell)) > 0)
392 sc->ref_clock = fdt32_to_cpu(cell);
393 else {
394 device_printf(dev, "must have ref-clock property\n");
395 return (ENXIO);
396 }
397 if (OF_getprop(node, "spi-clock", &cell, sizeof(cell)) > 0)
398 sc->spi_clock = fdt32_to_cpu(cell);
399 else
400 sc->spi_clock = ZY7_SPI_DEFAULT_SPI_CLOCK;
401
402 /* Get memory resource. */
403 rid = 0;
404 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
405 RF_ACTIVE);
406 if (sc->mem_res == NULL) {
407 device_printf(dev, "could not allocate memory resources.\n");
408 zy7_spi_detach(dev);
409 return (ENOMEM);
410 }
411
412 /* Allocate IRQ. */
413 rid = 0;
414 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
415 RF_ACTIVE);
416 if (sc->irq_res == NULL) {
417 device_printf(dev, "could not allocate IRQ resource.\n");
418 zy7_spi_detach(dev);
419 return (ENOMEM);
420 }
421
422 /* Activate the interrupt. */
423 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
424 NULL, zy7_spi_intr, sc, &sc->intrhandle);
425 if (err) {
426 device_printf(dev, "could not setup IRQ.\n");
427 zy7_spi_detach(dev);
428 return (err);
429 }
430
431 /* Configure the device. */
432 err = zy7_spi_init_hw(sc);
433 if (err) {
434 zy7_spi_detach(dev);
435 return (err);
436 }
437
438 sc->child = device_add_child(dev, "spibus", -1);
439
440 zy7_spi_add_sysctls(dev);
441
442 /* Attach spibus driver as a child later when interrupts work. */
443 bus_delayed_attach_children(dev);
444
445 return (0);
446 }
447
448 static int
zy7_spi_detach(device_t dev)449 zy7_spi_detach(device_t dev)
450 {
451 struct zy7_spi_softc *sc = device_get_softc(dev);
452
453 if (device_is_attached(dev))
454 bus_generic_detach(dev);
455
456 /* Delete child bus. */
457 if (sc->child)
458 device_delete_child(dev, sc->child);
459
460 /* Disable hardware. */
461 if (sc->mem_res != NULL) {
462 /* Disable SPI. */
463 WR4(sc, ZY7_SPI_EN_REG, 0);
464
465 /* Clear and disable all interrupts. */
466 WR4(sc, ZY7_SPI_INTR_STAT_REG, ~0);
467 WR4(sc, ZY7_SPI_INTR_DIS_REG, ~0);
468 }
469
470 /* Teardown and release interrupt. */
471 if (sc->irq_res != NULL) {
472 if (sc->intrhandle)
473 bus_teardown_intr(dev, sc->irq_res, sc->intrhandle);
474 bus_release_resource(dev, SYS_RES_IRQ,
475 rman_get_rid(sc->irq_res), sc->irq_res);
476 }
477
478 /* Release memory resource. */
479 if (sc->mem_res != NULL)
480 bus_release_resource(dev, SYS_RES_MEMORY,
481 rman_get_rid(sc->mem_res), sc->mem_res);
482
483 SPI_SC_LOCK_DESTROY(sc);
484
485 return (0);
486 }
487
488 static phandle_t
zy7_spi_get_node(device_t bus,device_t dev)489 zy7_spi_get_node(device_t bus, device_t dev)
490 {
491
492 return (ofw_bus_get_node(bus));
493 }
494
495 static int
zy7_spi_transfer(device_t dev,device_t child,struct spi_command * cmd)496 zy7_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
497 {
498 struct zy7_spi_softc *sc = device_get_softc(dev);
499 uint32_t cs;
500 uint32_t mode;
501 int err = 0;
502
503 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
504 ("TX/RX command sizes should be equal"));
505 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
506 ("TX/RX data sizes should be equal"));
507
508 /* Get chip select and mode for this child. */
509 spibus_get_cs(child, &cs);
510 cs &= ~SPIBUS_CS_HIGH;
511 if (cs > 2) {
512 device_printf(dev, "Invalid chip select %d requested by %s",
513 cs, device_get_nameunit(child));
514 return (EINVAL);
515 }
516 spibus_get_mode(child, &mode);
517
518 SPI_SC_LOCK(sc);
519
520 /* Wait for controller available. */
521 while (sc->busy != 0) {
522 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zspi0", 0);
523 if (err) {
524 SPI_SC_UNLOCK(sc);
525 return (err);
526 }
527 }
528
529 /* Start transfer. */
530 sc->busy = 1;
531 sc->cmd = cmd;
532 sc->tx_bytes = sc->cmd->tx_cmd_sz + sc->cmd->tx_data_sz;
533 sc->tx_bytes_sent = 0;
534 sc->rx_bytes = sc->cmd->rx_cmd_sz + sc->cmd->rx_data_sz;
535 sc->rx_bytes_rcvd = 0;
536
537 /* Enable interrupts. zy7_spi_intr() will handle transfer. */
538 WR4(sc, ZY7_SPI_INTR_EN_REG,
539 ZY7_SPI_INTR_TX_FIFO_NOT_FULL |
540 ZY7_SPI_INTR_RX_OVERFLOW);
541
542 /* Handle polarity and phase. */
543 if (mode == SPIBUS_MODE_CPHA || mode == SPIBUS_MODE_CPOL_CPHA)
544 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CLK_PH;
545 if (mode == SPIBUS_MODE_CPOL || mode == SPIBUS_MODE_CPOL_CPHA)
546 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CLK_POL;
547
548 /* Assert CS. */
549 sc->cfg_reg_shadow &= ~ZY7_SPI_CONFIG_CS_MASK;
550 sc->cfg_reg_shadow |= ZY7_SPI_CONFIG_CS(cs);
551 WR4(sc, ZY7_SPI_CONFIG_REG, sc->cfg_reg_shadow);
552
553 /* Wait for completion. */
554 err = mtx_sleep(dev, &sc->sc_mtx, 0, "zspi1", hz * 2);
555 if (err)
556 zy7_spi_abort_transfer(sc);
557
558 /* Release controller. */
559 sc->busy = 0;
560 wakeup_one(dev);
561
562 SPI_SC_UNLOCK(sc);
563
564 return (err);
565 }
566
567 static device_method_t zy7_spi_methods[] = {
568 /* Device interface */
569 DEVMETHOD(device_probe, zy7_spi_probe),
570 DEVMETHOD(device_attach, zy7_spi_attach),
571 DEVMETHOD(device_detach, zy7_spi_detach),
572
573 /* SPI interface */
574 DEVMETHOD(spibus_transfer, zy7_spi_transfer),
575
576 /* ofw_bus interface */
577 DEVMETHOD(ofw_bus_get_node, zy7_spi_get_node),
578
579 DEVMETHOD_END
580 };
581
582 static driver_t zy7_spi_driver = {
583 "zy7_spi",
584 zy7_spi_methods,
585 sizeof(struct zy7_spi_softc),
586 };
587 static devclass_t zy7_spi_devclass;
588
589 DRIVER_MODULE(zy7_spi, simplebus, zy7_spi_driver, zy7_spi_devclass, 0, 0);
590 DRIVER_MODULE(ofw_spibus, zy7_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0);
591 SIMPLEBUS_PNP_INFO(compat_data);
592 MODULE_DEPEND(zy7_spi, ofw_spibus, 1, 1, 1);
593