1/*- 2 * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/kernel.h> 35#include <sys/lock.h> 36#include <sys/module.h> 37#include <sys/mutex.h> 38#include <sys/rman.h> 39#include <sys/resource.h> 40#include <machine/bus.h> 41 42#include <dev/ofw/ofw_bus.h> 43#include <dev/ofw/ofw_bus_subr.h> 44 45#include <dev/spibus/spi.h> 46#include <dev/spibus/spibusvar.h> 47 48#include <dev/extres/clk/clk.h> 49#include <dev/extres/hwreset/hwreset.h> 50 51#include "spibus_if.h" 52 53#define AW_SPI_GCR 0x04 /* Global Control Register */ 54#define AW_SPI_GCR_EN (1 << 0) /* ENable */ 55#define AW_SPI_GCR_MODE_MASTER (1 << 1) /* 1 = Master, 0 = Slave */ 56#define AW_SPI_GCR_TP_EN (1 << 7) /* 1 = Stop transmit when FIFO is full */ 57#define AW_SPI_GCR_SRST (1 << 31) /* Soft Reset */ 58 59#define AW_SPI_TCR 0x08 /* Transfer Control register */ 60#define AW_SPI_TCR_XCH (1 << 31) /* Initiate transfer */ 61#define AW_SPI_TCR_SDDM (1 << 14) /* Sending Delay Data Mode */ 62#define AW_SPI_TCR_SDM (1 << 13) /* Master Sample Data Mode */ 63#define AW_SPI_TCR_FBS (1 << 12) /* First Transmit Bit Select (1 == LSB) */ 64#define AW_SPI_TCR_SDC (1 << 11) /* Master Sample Data Control */ 65#define AW_SPI_TCR_RPSM (1 << 10) /* Rapid Mode Select */ 66#define AW_SPI_TCR_DDB (1 << 9) /* Dummy Burst Type */ 67#define AW_SPI_TCR_SSSEL_MASK 0x30 /* Chip select */ 68#define AW_SPI_TCR_SSSEL_SHIFT 4 69#define AW_SPI_TCR_SS_LEVEL (1 << 7) /* 1 == CS High */ 70#define AW_SPI_TCR_SS_OWNER (1 << 6) /* 1 == Software controlled */ 71#define AW_SPI_TCR_SPOL (1 << 2) /* 1 == Active low */ 72#define AW_SPI_TCR_CPOL (1 << 1) /* 1 == Active low */ 73#define AW_SPI_TCR_CPHA (1 << 0) /* 1 == Phase 1 */ 74 75#define AW_SPI_IER 0x10 /* Interrupt Control Register */ 76#define AW_SPI_IER_SS (1 << 13) /* Chip select went from valid to invalid */ 77#define AW_SPI_IER_TC (1 << 12) /* Transfer complete */ 78#define AW_SPI_IER_TF_UDR (1 << 11) /* TXFIFO underrun */ 79#define AW_SPI_IER_TF_OVF (1 << 10) /* TXFIFO overrun */ 80#define AW_SPI_IER_RF_UDR (1 << 9) /* RXFIFO underrun */ 81#define AW_SPI_IER_RF_OVF (1 << 8) /* RXFIFO overrun */ 82#define AW_SPI_IER_TF_FULL (1 << 6) /* TXFIFO Full */ 83#define AW_SPI_IER_TF_EMP (1 << 5) /* TXFIFO Empty */ 84#define AW_SPI_IER_TF_ERQ (1 << 4) /* TXFIFO Empty Request */ 85#define AW_SPI_IER_RF_FULL (1 << 2) /* RXFIFO Full */ 86#define AW_SPI_IER_RF_EMP (1 << 1) /* RXFIFO Empty */ 87#define AW_SPI_IER_RF_ERQ (1 << 0) /* RXFIFO Empty Request */ 88 89#define AW_SPI_ISR 0x14 /* Interrupt Status Register */ 90 91#define AW_SPI_FCR 0x18 /* FIFO Control Register */ 92#define AW_SPI_FCR_TX_RST (1 << 31) /* Reset TX FIFO */ 93#define AW_SPI_FCR_TX_TRIG_MASK 0xFF0000 /* TX FIFO Trigger level */ 94#define AW_SPI_FCR_TX_TRIG_SHIFT 16 95#define AW_SPI_FCR_RX_RST (1 << 15) /* Reset RX FIFO */ 96#define AW_SPI_FCR_RX_TRIG_MASK 0xFF /* RX FIFO Trigger level */ 97#define AW_SPI_FCR_RX_TRIG_SHIFT 0 98 99#define AW_SPI_FSR 0x1C /* FIFO Status Register */ 100#define AW_SPI_FSR_TB_WR (1 << 31) 101#define AW_SPI_FSR_TB_CNT_MASK 0x70000000 102#define AW_SPI_FSR_TB_CNT_SHIFT 28 103#define AW_SPI_FSR_TF_CNT_MASK 0xFF0000 104#define AW_SPI_FSR_TF_CNT_SHIFT 16 105#define AW_SPI_FSR_RB_WR (1 << 15) 106#define AW_SPI_FSR_RB_CNT_MASK 0x7000 107#define AW_SPI_FSR_RB_CNT_SHIFT 12 108#define AW_SPI_FSR_RF_CNT_MASK 0xFF 109#define AW_SPI_FSR_RF_CNT_SHIFT 0 110 111#define AW_SPI_WCR 0x20 /* Wait Clock Counter Register */ 112 113#define AW_SPI_CCR 0x24 /* Clock Rate Control Register */ 114#define AW_SPI_CCR_DRS (1 << 12) /* Clock divider select */ 115#define AW_SPI_CCR_CDR1_MASK 0xF00 116#define AW_SPI_CCR_CDR1_SHIFT 8 117#define AW_SPI_CCR_CDR2_MASK 0xFF 118#define AW_SPI_CCR_CDR2_SHIFT 0 119 120#define AW_SPI_MBC 0x30 /* Burst Counter Register */ 121#define AW_SPI_MTC 0x34 /* Transmit Counter Register */ 122#define AW_SPI_BCC 0x38 /* Burst Control Register */ 123#define AW_SPI_MDMA_CTL 0x88 /* Normal DMA Control Register */ 124#define AW_SPI_TXD 0x200 /* TX Data Register */ 125#define AW_SPI_RDX 0x300 /* RX Data Register */ 126 127#define AW_SPI_MAX_CS 4 128#define AW_SPI_FIFO_SIZE 64 129 130static struct ofw_compat_data compat_data[] = { 131 { "allwinner,sun8i-h3-spi", 1 }, 132 { NULL, 0 } 133}; 134 135static struct resource_spec aw_spi_spec[] = { 136 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 137 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 138 { -1, 0 } 139}; 140 141struct aw_spi_softc { 142 device_t dev; 143 device_t spibus; 144 struct resource *res[2]; 145 struct mtx mtx; 146 clk_t clk_ahb; 147 clk_t clk_mod; 148 uint64_t mod_freq; 149 hwreset_t rst_ahb; 150 void * intrhand; 151 int transfer; 152 153 uint8_t *rxbuf; 154 uint32_t rxcnt; 155 uint8_t *txbuf; 156 uint32_t txcnt; 157 uint32_t txlen; 158 uint32_t rxlen; 159}; 160 161#define AW_SPI_LOCK(sc) mtx_lock(&(sc)->mtx) 162#define AW_SPI_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 163#define AW_SPI_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED) 164#define AW_SPI_READ_1(sc, reg) bus_read_1((sc)->res[0], (reg)) 165#define AW_SPI_WRITE_1(sc, reg, val) bus_write_1((sc)->res[0], (reg), (val)) 166#define AW_SPI_READ_4(sc, reg) bus_read_4((sc)->res[0], (reg)) 167#define AW_SPI_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val)) 168 169static int aw_spi_probe(device_t dev); 170static int aw_spi_attach(device_t dev); 171static int aw_spi_detach(device_t dev); 172static void aw_spi_intr(void *arg); 173 174static int 175aw_spi_probe(device_t dev) 176{ 177 if (!ofw_bus_status_okay(dev)) 178 return (ENXIO); 179 180 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 181 return (ENXIO); 182 183 device_set_desc(dev, "Allwinner SPI"); 184 return (BUS_PROBE_DEFAULT); 185} 186 187static int 188aw_spi_attach(device_t dev) 189{ 190 struct aw_spi_softc *sc; 191 int error; 192 193 sc = device_get_softc(dev); 194 sc->dev = dev; 195 196 mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 197 198 if (bus_alloc_resources(dev, aw_spi_spec, sc->res) != 0) { 199 device_printf(dev, "cannot allocate resources for device\n"); 200 error = ENXIO; 201 goto fail; 202 } 203 204 if (bus_setup_intr(dev, sc->res[1], 205 INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_spi_intr, sc, 206 &sc->intrhand)) { 207 bus_release_resources(dev, aw_spi_spec, sc->res); 208 device_printf(dev, "cannot setup interrupt handler\n"); 209 return (ENXIO); 210 } 211 212 /* De-assert reset */ 213 if (hwreset_get_by_ofw_idx(dev, 0, 0, &sc->rst_ahb) == 0) { 214 error = hwreset_deassert(sc->rst_ahb); 215 if (error != 0) { 216 device_printf(dev, "cannot de-assert reset\n"); 217 goto fail; 218 } 219 } 220 221 /* Activate the module clock. */ 222 error = clk_get_by_ofw_name(dev, 0, "ahb", &sc->clk_ahb); 223 if (error != 0) { 224 device_printf(dev, "cannot get ahb clock\n"); 225 goto fail; 226 } 227 error = clk_get_by_ofw_name(dev, 0, "mod", &sc->clk_mod); 228 if (error != 0) { 229 device_printf(dev, "cannot get mod clock\n"); 230 goto fail; 231 } 232 error = clk_enable(sc->clk_ahb); 233 if (error != 0) { 234 device_printf(dev, "cannot enable ahb clock\n"); 235 goto fail; 236 } 237 error = clk_enable(sc->clk_mod); 238 if (error != 0) { 239 device_printf(dev, "cannot enable mod clock\n"); 240 goto fail; 241 } 242 243 sc->spibus = device_add_child(dev, "spibus", -1); 244 245 return (bus_generic_attach(dev)); 246 247fail: 248 aw_spi_detach(dev); 249 return (error); 250} 251 252static int 253aw_spi_detach(device_t dev) 254{ 255 struct aw_spi_softc *sc; 256 257 sc = device_get_softc(dev); 258 259 bus_generic_detach(sc->dev); 260 if (sc->spibus != NULL) 261 device_delete_child(dev, sc->spibus); 262 263 if (sc->clk_mod != NULL) 264 clk_release(sc->clk_mod); 265 if (sc->clk_ahb) 266 clk_release(sc->clk_ahb); 267 if (sc->rst_ahb) 268 hwreset_assert(sc->rst_ahb); 269 270 if (sc->intrhand != NULL) 271 bus_teardown_intr(sc->dev, sc->res[1], sc->intrhand); 272 273 bus_release_resources(dev, aw_spi_spec, sc->res); 274 mtx_destroy(&sc->mtx); 275 276 return (0); 277} 278 279static phandle_t 280aw_spi_get_node(device_t bus, device_t dev) 281{ 282 283 return ofw_bus_get_node(bus); 284} 285 286static void 287aw_spi_setup_mode(struct aw_spi_softc *sc, uint32_t mode) 288{ 289 uint32_t reg; 290 291 /* We only support master mode */ 292 reg = AW_SPI_READ_4(sc, AW_SPI_GCR); 293 reg |= AW_SPI_GCR_MODE_MASTER; 294 AW_SPI_WRITE_4(sc, AW_SPI_GCR, reg); 295 296 /* Setup the modes */ 297 reg = AW_SPI_READ_4(sc, AW_SPI_TCR); 298 if (mode & SPIBUS_MODE_CPHA) 299 reg |= AW_SPI_TCR_CPHA; 300 if (mode & SPIBUS_MODE_CPOL) 301 reg |= AW_SPI_TCR_CPOL; 302 303 AW_SPI_WRITE_4(sc, AW_SPI_TCR, reg); 304} 305 306static void 307aw_spi_setup_cs(struct aw_spi_softc *sc, uint32_t cs, bool low) 308{ 309 uint32_t reg; 310 311 /* Setup CS */ 312 reg = AW_SPI_READ_4(sc, AW_SPI_TCR); 313 reg &= ~(AW_SPI_TCR_SSSEL_MASK); 314 reg |= cs << AW_SPI_TCR_SSSEL_SHIFT; 315 reg |= AW_SPI_TCR_SS_OWNER; 316 if (low) 317 reg &= ~(AW_SPI_TCR_SS_LEVEL); 318 else 319 reg |= AW_SPI_TCR_SS_LEVEL; 320 321 AW_SPI_WRITE_4(sc, AW_SPI_TCR, reg); 322} 323 324static uint64_t 325aw_spi_clock_test_cdr1(struct aw_spi_softc *sc, uint64_t clock, uint32_t *ccr) 326{ 327 uint64_t cur, best = 0; 328 int i, max, best_div; 329 330 max = AW_SPI_CCR_CDR1_MASK >> AW_SPI_CCR_CDR1_SHIFT; 331 for (i = 0; i < max; i++) { 332 cur = sc->mod_freq / (1 << i); 333 if ((clock - cur) < (clock - best)) { 334 best = cur; 335 best_div = i; 336 } 337 } 338 339 *ccr = (best_div << AW_SPI_CCR_CDR1_SHIFT); 340 return (best); 341} 342 343static uint64_t 344aw_spi_clock_test_cdr2(struct aw_spi_softc *sc, uint64_t clock, uint32_t *ccr) 345{ 346 uint64_t cur, best = 0; 347 int i, max, best_div; 348 349 max = ((AW_SPI_CCR_CDR2_MASK) >> AW_SPI_CCR_CDR2_SHIFT); 350 for (i = 0; i < max; i++) { 351 cur = sc->mod_freq / (2 * i + 1); 352 if ((clock - cur) < (clock - best)) { 353 best = cur; 354 best_div = i; 355 } 356 } 357 358 *ccr = AW_SPI_CCR_DRS | (best_div << AW_SPI_CCR_CDR2_SHIFT); 359 return (best); 360} 361 362static void 363aw_spi_setup_clock(struct aw_spi_softc *sc, uint64_t clock) 364{ 365 uint64_t best_ccr1, best_ccr2; 366 uint32_t ccr, ccr1, ccr2; 367 368 best_ccr1 = aw_spi_clock_test_cdr1(sc, clock, &ccr1); 369 best_ccr2 = aw_spi_clock_test_cdr2(sc, clock, &ccr2); 370 371 if (best_ccr1 == clock) { 372 ccr = ccr1; 373 } else if (best_ccr2 == clock) { 374 ccr = ccr2; 375 } else { 376 if ((clock - best_ccr1) < (clock - best_ccr2)) 377 ccr = ccr1; 378 else 379 ccr = ccr2; 380 } 381 382 AW_SPI_WRITE_4(sc, AW_SPI_CCR, ccr); 383} 384 385static inline void 386aw_spi_fill_txfifo(struct aw_spi_softc *sc) 387{ 388 uint32_t reg, txcnt; 389 int i; 390 391 if (sc->txcnt == sc->txlen) 392 return; 393 394 reg = AW_SPI_READ_4(sc, AW_SPI_FSR); 395 reg &= AW_SPI_FSR_TF_CNT_MASK; 396 txcnt = reg >> AW_SPI_FSR_TF_CNT_SHIFT; 397 398 for (i = 0; i < (AW_SPI_FIFO_SIZE - txcnt); i++) { 399 AW_SPI_WRITE_1(sc, AW_SPI_TXD, sc->txbuf[sc->txcnt++]); 400 if (sc->txcnt == sc->txlen) 401 break; 402 } 403 404 return; 405} 406 407static inline void 408aw_spi_read_rxfifo(struct aw_spi_softc *sc) 409{ 410 uint32_t reg; 411 uint8_t val; 412 int i; 413 414 if (sc->rxcnt == sc->rxlen) 415 return; 416 417 reg = AW_SPI_READ_4(sc, AW_SPI_FSR); 418 reg = (reg & AW_SPI_FSR_RF_CNT_MASK) >> AW_SPI_FSR_RF_CNT_SHIFT; 419 420 for (i = 0; i < reg; i++) { 421 val = AW_SPI_READ_1(sc, AW_SPI_RDX); 422 if (sc->rxcnt < sc->rxlen) 423 sc->rxbuf[sc->rxcnt++] = val; 424 } 425} 426 427static void 428aw_spi_intr(void *arg) 429{ 430 struct aw_spi_softc *sc; 431 uint32_t intr; 432 433 sc = (struct aw_spi_softc *)arg; 434 435 intr = AW_SPI_READ_4(sc, AW_SPI_ISR); 436 437 if (intr & AW_SPI_IER_RF_FULL) 438 aw_spi_read_rxfifo(sc); 439 440 if (intr & AW_SPI_IER_TF_EMP) { 441 aw_spi_fill_txfifo(sc); 442 /* 443 * If we don't have anything else to write 444 * disable TXFifo interrupts 445 */ 446 if (sc->txcnt == sc->txlen) 447 AW_SPI_WRITE_4(sc, AW_SPI_IER, AW_SPI_IER_TC | 448 AW_SPI_IER_RF_FULL); 449 } 450 451 if (intr & AW_SPI_IER_TC) { 452 /* read the rest of the data from the fifo */ 453 aw_spi_read_rxfifo(sc); 454 455 /* Disable the interrupts */ 456 AW_SPI_WRITE_4(sc, AW_SPI_IER, 0); 457 sc->transfer = 0; 458 wakeup(sc); 459 } 460 461 /* Clear Interrupts */ 462 AW_SPI_WRITE_4(sc, AW_SPI_ISR, intr); 463} 464 465static int 466aw_spi_xfer(struct aw_spi_softc *sc, void *rxbuf, void *txbuf, uint32_t txlen, uint32_t rxlen) 467{ 468 uint32_t reg; 469 int error = 0, timeout; 470 471 sc->rxbuf = rxbuf; 472 sc->rxcnt = 0; 473 sc->txbuf = txbuf; 474 sc->txcnt = 0; 475 sc->txlen = txlen; 476 sc->rxlen = rxlen; 477 478 /* Reset the FIFOs */ 479 AW_SPI_WRITE_4(sc, AW_SPI_FCR, AW_SPI_FCR_TX_RST | AW_SPI_FCR_RX_RST); 480 481 for (timeout = 1000; timeout > 0; timeout--) { 482 reg = AW_SPI_READ_4(sc, AW_SPI_FCR); 483 if (reg == 0) 484 break; 485 } 486 if (timeout == 0) { 487 device_printf(sc->dev, "Cannot reset the FIFOs\n"); 488 return (EIO); 489 } 490 491 /* Write the counters */ 492 AW_SPI_WRITE_4(sc, AW_SPI_MBC, txlen); 493 AW_SPI_WRITE_4(sc, AW_SPI_MTC, txlen); 494 AW_SPI_WRITE_4(sc, AW_SPI_BCC, txlen); 495 496 /* First fill */ 497 aw_spi_fill_txfifo(sc); 498 499 /* Start transmit */ 500 reg = AW_SPI_READ_4(sc, AW_SPI_TCR); 501 reg |= AW_SPI_TCR_XCH; 502 AW_SPI_WRITE_4(sc, AW_SPI_TCR, reg); 503 504 /* 505 * Enable interrupts for : 506 * Transmit complete 507 * TX Fifo empty 508 * RX Fifo full 509 */ 510 AW_SPI_WRITE_4(sc, AW_SPI_IER, AW_SPI_IER_TC | 511 AW_SPI_IER_TF_EMP | AW_SPI_IER_RF_FULL); 512 513 sc->transfer = 1; 514 515 while (error == 0 && sc->transfer != 0) 516 error = msleep(sc, &sc->mtx, 0, "aw_spi", 10 * hz); 517 518 return (0); 519} 520 521static int 522aw_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) 523{ 524 struct aw_spi_softc *sc; 525 uint32_t cs, mode, clock, reg; 526 int err = 0; 527 528 sc = device_get_softc(dev); 529 530 spibus_get_cs(child, &cs); 531 spibus_get_clock(child, &clock); 532 spibus_get_mode(child, &mode); 533 534 /* The minimum divider is 2 so set the clock at twice the needed speed */ 535 clk_set_freq(sc->clk_mod, 2 * clock, CLK_SET_ROUND_DOWN); 536 clk_get_freq(sc->clk_mod, &sc->mod_freq); 537 if (cs >= AW_SPI_MAX_CS) { 538 device_printf(dev, "Invalid cs %d\n", cs); 539 return (EINVAL); 540 } 541 542 mtx_lock(&sc->mtx); 543 544 /* Enable and reset the module */ 545 reg = AW_SPI_READ_4(sc, AW_SPI_GCR); 546 reg |= AW_SPI_GCR_EN | AW_SPI_GCR_SRST; 547 AW_SPI_WRITE_4(sc, AW_SPI_GCR, reg); 548 549 /* Setup clock, CS and mode */ 550 aw_spi_setup_clock(sc, clock); 551 aw_spi_setup_mode(sc, mode); 552 if (cs & SPIBUS_CS_HIGH) 553 aw_spi_setup_cs(sc, cs, false); 554 else 555 aw_spi_setup_cs(sc, cs, true); 556 557 /* xfer */ 558 err = 0; 559 if (cmd->tx_cmd_sz > 0) 560 err = aw_spi_xfer(sc, cmd->rx_cmd, cmd->tx_cmd, 561 cmd->tx_cmd_sz, cmd->rx_cmd_sz); 562 if (cmd->tx_data_sz > 0 && err == 0) 563 err = aw_spi_xfer(sc, cmd->rx_data, cmd->tx_data, 564 cmd->tx_data_sz, cmd->rx_data_sz); 565 566 if (cs & SPIBUS_CS_HIGH) 567 aw_spi_setup_cs(sc, cs, true); 568 else 569 aw_spi_setup_cs(sc, cs, false); 570 571 /* Disable the module */ 572 reg = AW_SPI_READ_4(sc, AW_SPI_GCR); 573 reg &= ~AW_SPI_GCR_EN; 574 AW_SPI_WRITE_4(sc, AW_SPI_GCR, reg); 575 576 mtx_unlock(&sc->mtx); 577 578 return (err); 579} 580 581static device_method_t aw_spi_methods[] = { 582 /* Device interface */ 583 DEVMETHOD(device_probe, aw_spi_probe), 584 DEVMETHOD(device_attach, aw_spi_attach), 585 DEVMETHOD(device_detach, aw_spi_detach), 586 587 /* spibus_if */ 588 DEVMETHOD(spibus_transfer, aw_spi_transfer), 589 590 /* ofw_bus_if */ 591 DEVMETHOD(ofw_bus_get_node, aw_spi_get_node), 592 593 DEVMETHOD_END 594}; 595 596static driver_t aw_spi_driver = { 597 "aw_spi", 598 aw_spi_methods, 599 sizeof(struct aw_spi_softc), 600}; 601 602static devclass_t aw_spi_devclass; 603 604DRIVER_MODULE(aw_spi, simplebus, aw_spi_driver, aw_spi_devclass, 0, 0); 605DRIVER_MODULE(ofw_spibus, aw_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0); 606MODULE_DEPEND(aw_spi, ofw_spibus, 1, 1, 1); 607SIMPLEBUS_PNP_INFO(compat_data); 608