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}