spi.c (289b5607da2eace36026fc68a470040743fca9eb) | spi.c (1f40866feb2135a4cf764a07b1b90a8a3398ff0a) |
---|---|
1/*- | 1/*- |
2 * SPDX-License-Identifier: BSD-2-Clause 3 * |
|
2 * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 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. --- 9 unchanged lines hidden (view full) --- 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 | 4 * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 |
27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 | |
30#include "opt_acpi.h" 31 32#include <sys/param.h> 33#include <sys/bus.h> 34#include <sys/kernel.h> 35#include <sys/module.h> 36#include <sys/proc.h> 37#include <sys/rman.h> 38 39#include <machine/bus.h> 40#include <machine/resource.h> 41 42#include <dev/spibus/spi.h> 43#include <dev/spibus/spibusvar.h> 44 | 29#include "opt_acpi.h" 30 31#include <sys/param.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/proc.h> 36#include <sys/rman.h> 37 38#include <machine/bus.h> 39#include <machine/resource.h> 40 41#include <dev/spibus/spi.h> 42#include <dev/spibus/spibusvar.h> 43 |
45#include <contrib/dev/acpica/include/acpi.h> 46#include <contrib/dev/acpica/include/accommon.h> | 44#include <dev/intel/spi.h> |
47 | 45 |
48#include <dev/acpica/acpivar.h> 49 50#include "spibus_if.h" 51 | |
52/** 53 * Macros for driver mutex locking 54 */ 55#define INTELSPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 56#define INTELSPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 57#define INTELSPI_LOCK_INIT(_sc) \ 58 mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ 59 "intelspi", MTX_DEF) --- 6 unchanged lines hidden (view full) --- 66#define INTELSPI_READ(_sc, _off) \ 67 bus_read_4((_sc)->sc_mem_res, (_off)) 68 69#define INTELSPI_BUSY 0x1 70#define TX_FIFO_THRESHOLD 2 71#define RX_FIFO_THRESHOLD 2 72#define CLOCK_DIV_10MHZ 5 73#define DATA_SIZE_8BITS 8 | 46/** 47 * Macros for driver mutex locking 48 */ 49#define INTELSPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 50#define INTELSPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 51#define INTELSPI_LOCK_INIT(_sc) \ 52 mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ 53 "intelspi", MTX_DEF) --- 6 unchanged lines hidden (view full) --- 60#define INTELSPI_READ(_sc, _off) \ 61 bus_read_4((_sc)->sc_mem_res, (_off)) 62 63#define INTELSPI_BUSY 0x1 64#define TX_FIFO_THRESHOLD 2 65#define RX_FIFO_THRESHOLD 2 66#define CLOCK_DIV_10MHZ 5 67#define DATA_SIZE_8BITS 8 |
68#define MAX_CLOCK_RATE 50000000 |
|
74 75#define CS_LOW 0 76#define CS_HIGH 1 77 78#define INTELSPI_SSPREG_SSCR0 0x0 | 69 70#define CS_LOW 0 71#define CS_HIGH 1 72 73#define INTELSPI_SSPREG_SSCR0 0x0 |
79#define SSCR0_SCR(n) (((n) - 1) << 8) | 74#define SSCR0_SCR(n) ((((n) - 1) & 0xfff) << 8) |
80#define SSCR0_SSE (1 << 7) 81#define SSCR0_FRF_SPI (0 << 4) 82#define SSCR0_DSS(n) (((n) - 1) << 0) 83#define INTELSPI_SSPREG_SSCR1 0x4 84#define SSCR1_TINTE (1 << 19) 85#define SSCR1_RFT(n) (((n) - 1) << 10) 86#define SSCR1_RFT_MASK (0xf << 10) 87#define SSCR1_TFT(n) (((n) - 1) << 6) 88#define SSCR1_SPI_SPH (1 << 4) 89#define SSCR1_SPI_SPO (1 << 3) 90#define SSCR1_MODE_MASK (SSCR1_SPI_SPO | SSCR1_SPI_SPH) | 75#define SSCR0_SSE (1 << 7) 76#define SSCR0_FRF_SPI (0 << 4) 77#define SSCR0_DSS(n) (((n) - 1) << 0) 78#define INTELSPI_SSPREG_SSCR1 0x4 79#define SSCR1_TINTE (1 << 19) 80#define SSCR1_RFT(n) (((n) - 1) << 10) 81#define SSCR1_RFT_MASK (0xf << 10) 82#define SSCR1_TFT(n) (((n) - 1) << 6) 83#define SSCR1_SPI_SPH (1 << 4) 84#define SSCR1_SPI_SPO (1 << 3) 85#define SSCR1_MODE_MASK (SSCR1_SPI_SPO | SSCR1_SPI_SPH) |
91#define SSCR1_MODE_0 (0) 92#define SSCR1_MODE_1 (SSCR1_SPI_SPH) 93#define SSCR1_MODE_2 (SSCR1_SPI_SPO) 94#define SSCR1_MODE_3 (SSCR1_SPI_SPO | SSCR1_SPI_SPH) | |
95#define SSCR1_TIE (1 << 1) 96#define SSCR1_RIE (1 << 0) 97#define INTELSPI_SSPREG_SSSR 0x8 98#define SSSR_RFL_MASK (0xf << 12) 99#define SSSR_TFL_MASK (0xf << 8) 100#define SSSR_RNE (1 << 3) 101#define SSSR_TNF (1 << 2) 102#define INTELSPI_SSPREG_SSITR 0xC 103#define INTELSPI_SSPREG_SSDR 0x10 104#define INTELSPI_SSPREG_SSTO 0x28 105#define INTELSPI_SSPREG_SSPSP 0x2C 106#define INTELSPI_SSPREG_SSTSA 0x30 107#define INTELSPI_SSPREG_SSRSA 0x34 108#define INTELSPI_SSPREG_SSTSS 0x38 109#define INTELSPI_SSPREG_SSACD 0x3C 110#define INTELSPI_SSPREG_ITF 0x40 111#define INTELSPI_SSPREG_SITF 0x44 112#define INTELSPI_SSPREG_SIRF 0x48 | 86#define SSCR1_TIE (1 << 1) 87#define SSCR1_RIE (1 << 0) 88#define INTELSPI_SSPREG_SSSR 0x8 89#define SSSR_RFL_MASK (0xf << 12) 90#define SSSR_TFL_MASK (0xf << 8) 91#define SSSR_RNE (1 << 3) 92#define SSSR_TNF (1 << 2) 93#define INTELSPI_SSPREG_SSITR 0xC 94#define INTELSPI_SSPREG_SSDR 0x10 95#define INTELSPI_SSPREG_SSTO 0x28 96#define INTELSPI_SSPREG_SSPSP 0x2C 97#define INTELSPI_SSPREG_SSTSA 0x30 98#define INTELSPI_SSPREG_SSRSA 0x34 99#define INTELSPI_SSPREG_SSTSS 0x38 100#define INTELSPI_SSPREG_SSACD 0x3C 101#define INTELSPI_SSPREG_ITF 0x40 102#define INTELSPI_SSPREG_SITF 0x44 103#define INTELSPI_SSPREG_SIRF 0x48 |
113#define INTELSPI_SSPREG_PRV_CLOCK_PARAMS 0x400 114#define INTELSPI_SSPREG_RESETS 0x404 115#define INTELSPI_SSPREG_GENERAL 0x408 116#define INTELSPI_SSPREG_SSP_REG 0x40C 117#define INTELSPI_SSPREG_SPI_CS_CTRL 0x418 | 104#define SPI_CS_CTRL(sc) \ 105 (intelspi_infos[sc->sc_vers].reg_lpss_base + \ 106 intelspi_infos[sc->sc_vers].reg_cs_ctrl) |
118#define SPI_CS_CTRL_CS_MASK (3) 119#define SPI_CS_CTRL_SW_MODE (1 << 0) 120#define SPI_CS_CTRL_HW_MODE (1 << 0) 121#define SPI_CS_CTRL_CS_HIGH (1 << 1) | 107#define SPI_CS_CTRL_CS_MASK (3) 108#define SPI_CS_CTRL_SW_MODE (1 << 0) 109#define SPI_CS_CTRL_HW_MODE (1 << 0) 110#define SPI_CS_CTRL_CS_HIGH (1 << 1) |
122#define SPI_CS_CTRL_CS_LOW (0 << 1) | |
123 | 111 |
124struct intelspi_softc { 125 ACPI_HANDLE sc_handle; 126 device_t sc_dev; 127 struct mtx sc_mtx; 128 int sc_mem_rid; 129 struct resource *sc_mem_res; 130 int sc_irq_rid; 131 struct resource *sc_irq_res; 132 void *sc_irq_ih; 133 struct spi_command *sc_cmd; 134 uint32_t sc_len; 135 uint32_t sc_read; 136 uint32_t sc_flags; 137 uint32_t sc_written; 138}; 139 140static int intelspi_probe(device_t dev); 141static int intelspi_attach(device_t dev); 142static int intelspi_detach(device_t dev); | |
143static void intelspi_intr(void *); 144 145static int 146intelspi_txfifo_full(struct intelspi_softc *sc) 147{ 148 uint32_t sssr; 149 150 INTELSPI_ASSERT_LOCKED(sc); --- 138 unchanged lines hidden (view full) --- 289static void 290intelspi_init(struct intelspi_softc *sc) 291{ 292 uint32_t reg; 293 294 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, 0); 295 296 /* Manual CS control */ | 112static void intelspi_intr(void *); 113 114static int 115intelspi_txfifo_full(struct intelspi_softc *sc) 116{ 117 uint32_t sssr; 118 119 INTELSPI_ASSERT_LOCKED(sc); --- 138 unchanged lines hidden (view full) --- 258static void 259intelspi_init(struct intelspi_softc *sc) 260{ 261 uint32_t reg; 262 263 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, 0); 264 265 /* Manual CS control */ |
297 reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL); | 266 reg = INTELSPI_READ(sc, SPI_CS_CTRL(sc)); |
298 reg &= ~(SPI_CS_CTRL_CS_MASK); 299 reg |= (SPI_CS_CTRL_SW_MODE | SPI_CS_CTRL_CS_HIGH); | 267 reg &= ~(SPI_CS_CTRL_CS_MASK); 268 reg |= (SPI_CS_CTRL_SW_MODE | SPI_CS_CTRL_CS_HIGH); |
300 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg); | 269 INTELSPI_WRITE(sc, SPI_CS_CTRL(sc), reg); |
301 302 /* Set TX/RX FIFO IRQ threshold levels */ 303 reg = SSCR1_TFT(TX_FIFO_THRESHOLD) | SSCR1_RFT(RX_FIFO_THRESHOLD); | 270 271 /* Set TX/RX FIFO IRQ threshold levels */ 272 reg = SSCR1_TFT(TX_FIFO_THRESHOLD) | SSCR1_RFT(RX_FIFO_THRESHOLD); |
304 /* 305 * Set SPI mode. This should be part of transaction or sysctl 306 */ 307 reg |= SSCR1_MODE_0; | |
308 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg); 309 | 273 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg); 274 |
310 /* 311 * Parent clock on Minowboard Turbot is 50MHz 312 * divide it by 5 to set to more or less reasonable 313 * value. But this should be part of transaction config 314 * or sysctl 315 */ | |
316 reg = SSCR0_SCR(CLOCK_DIV_10MHZ); 317 /* Put SSP in SPI mode */ 318 reg |= SSCR0_FRF_SPI; 319 /* Data size */ 320 reg |= SSCR0_DSS(DATA_SIZE_8BITS); 321 /* Enable SSP */ 322 reg |= SSCR0_SSE; 323 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, reg); 324} 325 326static void 327intelspi_set_cs(struct intelspi_softc *sc, int level) 328{ 329 uint32_t reg; 330 | 275 reg = SSCR0_SCR(CLOCK_DIV_10MHZ); 276 /* Put SSP in SPI mode */ 277 reg |= SSCR0_FRF_SPI; 278 /* Data size */ 279 reg |= SSCR0_DSS(DATA_SIZE_8BITS); 280 /* Enable SSP */ 281 reg |= SSCR0_SSE; 282 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, reg); 283} 284 285static void 286intelspi_set_cs(struct intelspi_softc *sc, int level) 287{ 288 uint32_t reg; 289 |
331 reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL); | 290 reg = INTELSPI_READ(sc, SPI_CS_CTRL(sc)); |
332 reg &= ~(SPI_CS_CTRL_CS_MASK); 333 reg |= SPI_CS_CTRL_SW_MODE; 334 335 if (level == CS_HIGH) 336 reg |= SPI_CS_CTRL_CS_HIGH; | 291 reg &= ~(SPI_CS_CTRL_CS_MASK); 292 reg |= SPI_CS_CTRL_SW_MODE; 293 294 if (level == CS_HIGH) 295 reg |= SPI_CS_CTRL_CS_HIGH; |
337 else 338 reg |= SPI_CS_CTRL_CS_LOW; 339 340 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg); | 296 297 INTELSPI_WRITE(sc, SPI_CS_CTRL(sc), reg); |
341} 342 | 298} 299 |
343static int | 300int |
344intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd) 345{ 346 struct intelspi_softc *sc; | 301intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd) 302{ 303 struct intelspi_softc *sc; |
347 int err; 348 uint32_t sscr1; | 304 int err, poll_limit; 305 uint32_t sscr0, sscr1, mode, clock, cs_delay; 306 bool restart = false; |
349 350 sc = device_get_softc(dev); 351 err = 0; 352 353 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 354 ("TX/RX command sizes should be equal")); 355 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 356 ("TX/RX data sizes should be equal")); 357 358 INTELSPI_LOCK(sc); 359 360 /* If the controller is in use wait until it is available. */ 361 while (sc->sc_flags & INTELSPI_BUSY) { | 307 308 sc = device_get_softc(dev); 309 err = 0; 310 311 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 312 ("TX/RX command sizes should be equal")); 313 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 314 ("TX/RX data sizes should be equal")); 315 316 INTELSPI_LOCK(sc); 317 318 /* If the controller is in use wait until it is available. */ 319 while (sc->sc_flags & INTELSPI_BUSY) { |
320 if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP) 321 return (EBUSY); |
|
362 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0); 363 if (err == EINTR) { 364 INTELSPI_UNLOCK(sc); 365 return (err); 366 } 367 } 368 369 /* Now we have control over SPI controller. */ 370 sc->sc_flags = INTELSPI_BUSY; 371 | 322 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0); 323 if (err == EINTR) { 324 INTELSPI_UNLOCK(sc); 325 return (err); 326 } 327 } 328 329 /* Now we have control over SPI controller. */ 330 sc->sc_flags = INTELSPI_BUSY; 331 |
332 /* Configure the clock rate and SPI mode. */ 333 spibus_get_clock(child, &clock); 334 spibus_get_mode(child, &mode); 335 336 if (clock != sc->sc_clock || mode != sc->sc_mode) { 337 sscr0 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR0); 338 sscr0 &= ~SSCR0_SSE; 339 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, sscr0); 340 restart = true; 341 } 342 343 if (clock != sc->sc_clock) { 344 sscr0 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR0); 345 sscr0 &= ~SSCR0_SCR(0xfff); 346 if (clock == 0) 347 sscr0 |= SSCR0_SCR(CLOCK_DIV_10MHZ); 348 else 349 sscr0 |= SSCR0_SCR(howmany(MAX_CLOCK_RATE, min(MAX_CLOCK_RATE, clock))); 350 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, sscr0); 351 sc->sc_clock = clock; 352 } 353 354 if (mode != sc->sc_mode) { 355 sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1); 356 sscr1 &= ~SSCR1_MODE_MASK; 357 if (mode & SPIBUS_MODE_CPHA) 358 sscr1 |= SSCR1_SPI_SPH; 359 if (mode & SPIBUS_MODE_CPOL) 360 sscr1 |= SSCR1_SPI_SPO; 361 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1); 362 sc->sc_mode = mode; 363 } 364 365 if (restart) { 366 sscr0 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR0); 367 sscr0 |= SSCR0_SSE; 368 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, sscr0); 369 } 370 |
|
372 /* Save a pointer to the SPI command. */ 373 sc->sc_cmd = cmd; 374 sc->sc_read = 0; 375 sc->sc_written = 0; 376 sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz; 377 378 /* Enable CS */ 379 intelspi_set_cs(sc, CS_LOW); | 371 /* Save a pointer to the SPI command. */ 372 sc->sc_cmd = cmd; 373 sc->sc_read = 0; 374 sc->sc_written = 0; 375 sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz; 376 377 /* Enable CS */ 378 intelspi_set_cs(sc, CS_LOW); |
379 380 /* Wait the CS delay */ 381 spibus_get_cs_delay(child, &cs_delay); 382 DELAY(cs_delay); 383 |
|
380 /* Transfer as much as possible to FIFOs */ | 384 /* Transfer as much as possible to FIFOs */ |
381 if (!intelspi_transact(sc)) { 382 /* If FIFO is not large enough - enable interrupts */ 383 sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1); 384 sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE); 385 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1); | 385 if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP) { 386 /* We cannot wait with mtx_sleep if we're called from e.g. an ithread */ 387 poll_limit = 2000; 388 while (!intelspi_transact(sc) && poll_limit-- > 0) 389 DELAY(1000); 390 if (poll_limit == 0) { 391 device_printf(dev, "polling was stuck, transaction not finished\n"); 392 err = EIO; 393 } 394 } else { 395 if (!intelspi_transact(sc)) { 396 /* If FIFO is not large enough - enable interrupts */ 397 sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1); 398 sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE); 399 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1); |
386 | 400 |
387 /* and wait for transaction to complete */ 388 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2); | 401 /* and wait for transaction to complete */ 402 err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2); 403 } |
389 } 390 | 404 } 405 |
391 /* de-asser CS */ 392 intelspi_set_cs(sc, CS_HIGH); | 406 /* De-assert CS */ 407 if ((cmd->flags & SPI_FLAG_KEEP_CS) == 0) 408 intelspi_set_cs(sc, CS_HIGH); |
393 394 /* Clear transaction details */ 395 sc->sc_cmd = NULL; 396 sc->sc_read = 0; 397 sc->sc_written = 0; 398 sc->sc_len = 0; 399 400 /* Make sure the SPI engine and interrupts are disabled. */ --- 13 unchanged lines hidden (view full) --- 414 if (err == EWOULDBLOCK) { 415 device_printf(sc->sc_dev, "transfer timeout\n"); 416 err = EIO; 417 } 418 419 return (err); 420} 421 | 409 410 /* Clear transaction details */ 411 sc->sc_cmd = NULL; 412 sc->sc_read = 0; 413 sc->sc_written = 0; 414 sc->sc_len = 0; 415 416 /* Make sure the SPI engine and interrupts are disabled. */ --- 13 unchanged lines hidden (view full) --- 430 if (err == EWOULDBLOCK) { 431 device_printf(sc->sc_dev, "transfer timeout\n"); 432 err = EIO; 433 } 434 435 return (err); 436} 437 |
422static int 423intelspi_probe(device_t dev) 424{ 425 static char *gpio_ids[] = { "80860F0E", NULL }; 426 int rv; 427 428 if (acpi_disabled("spi") ) 429 return (ENXIO); 430 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL); 431 if (rv <= 0) 432 device_set_desc(dev, "Intel SPI Controller"); 433 return (rv); 434} 435 436static int | 438int |
437intelspi_attach(device_t dev) 438{ 439 struct intelspi_softc *sc; 440 441 sc = device_get_softc(dev); 442 sc->sc_dev = dev; | 439intelspi_attach(device_t dev) 440{ 441 struct intelspi_softc *sc; 442 443 sc = device_get_softc(dev); 444 sc->sc_dev = dev; |
443 sc->sc_handle = acpi_get_handle(dev); | |
444 445 INTELSPI_LOCK_INIT(sc); 446 | 445 446 INTELSPI_LOCK_INIT(sc); 447 |
447 sc->sc_mem_rid = 0; | |
448 sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev, 449 SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE); 450 if (sc->sc_mem_res == NULL) { 451 device_printf(dev, "can't allocate memory resource\n"); 452 goto error; 453 } 454 | 448 sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev, 449 SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE); 450 if (sc->sc_mem_res == NULL) { 451 device_printf(dev, "can't allocate memory resource\n"); 452 goto error; 453 } 454 |
455 sc->sc_irq_rid = 0; | |
456 sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev, | 455 sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev, |
457 SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE); | 456 SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE | RF_SHAREABLE); |
458 if (sc->sc_irq_res == NULL) { 459 device_printf(dev, "can't allocate IRQ resource\n"); 460 goto error; 461 } 462 463 /* Hook up our interrupt handler. */ 464 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 465 NULL, intelspi_intr, sc, &sc->sc_irq_ih)) { 466 device_printf(dev, "cannot setup the interrupt handler\n"); 467 goto error; 468 } 469 470 intelspi_init(sc); 471 472 device_add_child(dev, "spibus", -1); 473 | 457 if (sc->sc_irq_res == NULL) { 458 device_printf(dev, "can't allocate IRQ resource\n"); 459 goto error; 460 } 461 462 /* Hook up our interrupt handler. */ 463 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 464 NULL, intelspi_intr, sc, &sc->sc_irq_ih)) { 465 device_printf(dev, "cannot setup the interrupt handler\n"); 466 goto error; 467 } 468 469 intelspi_init(sc); 470 471 device_add_child(dev, "spibus", -1); 472 |
474 return (bus_generic_attach(dev)); | 473 return (bus_delayed_attach_children(dev)); |
475 476error: 477 INTELSPI_LOCK_DESTROY(sc); 478 479 if (sc->sc_mem_res != NULL) 480 bus_release_resource(dev, SYS_RES_MEMORY, 481 sc->sc_mem_rid, sc->sc_mem_res); 482 483 if (sc->sc_irq_res != NULL) 484 bus_release_resource(dev, SYS_RES_IRQ, 485 sc->sc_irq_rid, sc->sc_irq_res); 486 487 return (ENXIO); 488} 489 | 474 475error: 476 INTELSPI_LOCK_DESTROY(sc); 477 478 if (sc->sc_mem_res != NULL) 479 bus_release_resource(dev, SYS_RES_MEMORY, 480 sc->sc_mem_rid, sc->sc_mem_res); 481 482 if (sc->sc_irq_res != NULL) 483 bus_release_resource(dev, SYS_RES_IRQ, 484 sc->sc_irq_rid, sc->sc_irq_res); 485 486 return (ENXIO); 487} 488 |
490static int | 489int |
491intelspi_detach(device_t dev) 492{ 493 struct intelspi_softc *sc; 494 495 sc = device_get_softc(dev); 496 497 INTELSPI_LOCK_DESTROY(sc); 498 --- 6 unchanged lines hidden (view full) --- 505 506 if (sc->sc_irq_res != NULL) 507 bus_release_resource(dev, SYS_RES_IRQ, 508 sc->sc_irq_rid, sc->sc_irq_res); 509 510 return (bus_generic_detach(dev)); 511} 512 | 490intelspi_detach(device_t dev) 491{ 492 struct intelspi_softc *sc; 493 494 sc = device_get_softc(dev); 495 496 INTELSPI_LOCK_DESTROY(sc); 497 --- 6 unchanged lines hidden (view full) --- 504 505 if (sc->sc_irq_res != NULL) 506 bus_release_resource(dev, SYS_RES_IRQ, 507 sc->sc_irq_rid, sc->sc_irq_res); 508 509 return (bus_generic_detach(dev)); 510} 511 |
513static device_method_t intelspi_methods[] = { 514 /* Device interface */ 515 DEVMETHOD(device_probe, intelspi_probe), 516 DEVMETHOD(device_attach, intelspi_attach), 517 DEVMETHOD(device_detach, intelspi_detach), | 512int 513intelspi_suspend(device_t dev) 514{ 515 struct intelspi_softc *sc; 516 int err, i; |
518 | 517 |
519 /* SPI interface */ 520 DEVMETHOD(spibus_transfer, intelspi_transfer), | 518 sc = device_get_softc(dev); |
521 | 519 |
522 DEVMETHOD_END 523}; | 520 err = bus_generic_suspend(dev); 521 if (err) 522 return (err); |
524 | 523 |
525static driver_t intelspi_driver = { 526 "spi", 527 intelspi_methods, 528 sizeof(struct intelspi_softc), 529}; | 524 for (i = 0; i < 9; i++) { 525 unsigned long offset = i * sizeof(uint32_t); 526 sc->sc_regs[i] = INTELSPI_READ(sc, 527 intelspi_infos[sc->sc_vers].reg_lpss_base + offset); 528 } |
530 | 529 |
531DRIVER_MODULE(intelspi, acpi, intelspi_driver, 0, 0); 532MODULE_DEPEND(intelspi, acpi, 1, 1, 1); 533MODULE_DEPEND(intelspi, spibus, 1, 1, 1); | 530 /* Shutdown just in case */ 531 INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, 0); 532 533 return (0); 534} 535 536int 537intelspi_resume(device_t dev) 538{ 539 struct intelspi_softc *sc; 540 int i; 541 542 sc = device_get_softc(dev); 543 544 for (i = 0; i < 9; i++) { 545 unsigned long offset = i * sizeof(uint32_t); 546 INTELSPI_WRITE(sc, 547 intelspi_infos[sc->sc_vers].reg_lpss_base + offset, 548 sc->sc_regs[i]); 549 } 550 551 intelspi_init(sc); 552 553 /* Ensure the next transfer would reconfigure these */ 554 sc->sc_clock = 0; 555 sc->sc_mode = 0; 556 557 return (bus_generic_resume(dev)); 558} |