]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/freescale/imx/imx_spi.c
MFV r349535: less v551.
[FreeBSD/FreeBSD.git] / sys / arm / freescale / imx / imx_spi.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Ian Lepore <ian@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.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 /*
33  * Driver for imx Enhanced Configurable SPI; master-mode only.
34  */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bus.h>
39 #include <sys/gpio.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/module.h>
43 #include <sys/mutex.h>
44 #include <sys/rman.h>
45 #include <sys/sysctl.h>
46 #include <machine/bus.h>
47 #include <machine/cpu.h>
48 #include <machine/intr.h>
49
50 #include <arm/freescale/imx/imx_ccmvar.h>
51
52 #include <dev/gpio/gpiobusvar.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <dev/ofw/ofw_bus_subr.h>
55 #include <dev/ofw/openfirm.h>
56 #include <dev/spibus/spi.h>
57 #include <dev/spibus/spibusvar.h>
58
59 #include "spibus_if.h"
60
61 #define ECSPI_RXDATA            0x00
62 #define ECSPI_TXDATA            0x04
63 #define ECSPI_CTLREG            0x08
64 #define   CTLREG_BLEN_SHIFT       20
65 #define   CTLREG_BLEN_MASK        0x0fff
66 #define   CTLREG_CSEL_SHIFT       18
67 #define   CTLREG_CSEL_MASK        0x03
68 #define   CTLREG_DRCTL_SHIFT      16
69 #define   CTLREG_DRCTL_MASK       0x03
70 #define   CTLREG_PREDIV_SHIFT     12
71 #define   CTLREG_PREDIV_MASK      0x0f
72 #define   CTLREG_POSTDIV_SHIFT    8
73 #define   CTLREG_POSTDIV_MASK     0x0f
74 #define   CTLREG_CMODE_SHIFT      4
75 #define   CTLREG_CMODE_MASK       0x0f
76 #define   CTLREG_CMODES_MASTER    (CTLREG_CMODE_MASK << CTLREG_CMODE_SHIFT)
77 #define   CTLREG_SMC              (1u << 3)
78 #define   CTLREG_XCH              (1u << 2)
79 #define   CTLREG_HT               (1u << 1)
80 #define   CTLREG_EN               (1u << 0)
81 #define ECSPI_CFGREG            0x0c
82 #define   CFGREG_HTLEN_SHIFT      24
83 #define   CFGREG_SCLKCTL_SHIFT    20
84 #define   CFGREG_DATACTL_SHIFT    16
85 #define   CFGREG_SSPOL_SHIFT      12
86 #define   CFGREG_SSCTL_SHIFT       8
87 #define   CFGREG_SCLKPOL_SHIFT     4 
88 #define   CFGREG_SCLKPHA_SHIFT     0
89 #define   CFGREG_MASK              0x0f /* all CFGREG fields are 4 bits */
90 #define ECSPI_INTREG            0x10
91 #define   INTREG_TCEN             (1u << 7)
92 #define   INTREG_ROEN             (1u << 6)
93 #define   INTREG_RFEN             (1u << 5)
94 #define   INTREG_RDREN            (1u << 4)
95 #define   INTREG_RREN             (1u << 3)
96 #define   INTREG_TFEN             (1u << 2)
97 #define   INTREG_TDREN            (1u << 1)
98 #define   INTREG_TEEN             (1u << 0)
99 #define ECSPI_DMAREG            0x14
100 #define   DMA_RX_THRESH_SHIFT     16
101 #define   DMA_RX_THRESH_MASK      0x3f
102 #define   DMA_TX_THRESH_SHIFT     0
103 #define   DMA_TX_THRESH_MASK      0x3f
104 #define ECSPI_STATREG           0x18
105 #define   SREG_TC                 (1u << 7)
106 #define   SREG_RO                 (1u << 6)
107 #define   SREG_RF                 (1u << 5)
108 #define   SREG_RDR                (1u << 4)
109 #define   SREG_RR                 (1u << 3)
110 #define   SREG_TF                 (1u << 2)
111 #define   SREG_TDR                (1u << 1)
112 #define   SREG_TE                 (1u << 0)
113 #define ECSPI_PERIODREG         0x1c
114 #define ECSPI_TESTREG           0x20
115
116 #define CS_MAX          4       /* Max number of chip selects. */
117 #define CS_MASK         0x03    /* Mask flag bits out of chipsel. */
118
119 #define FIFO_SIZE       64
120 #define FIFO_RXTHRESH   32
121 #define FIFO_TXTHRESH   32
122
123 struct spi_softc {
124         device_t                dev;
125         device_t                spibus;
126         struct mtx              mtx;
127         struct resource         *memres;
128         struct resource         *intres;
129         void                    *inthandle;
130         gpio_pin_t              cspins[CS_MAX];
131         u_int                   debug;
132         u_int                   basefreq;
133         uint32_t                ctlreg;
134         uint32_t                intreg;
135         uint32_t                fifocnt;
136         uint8_t                 *rxbuf;
137         uint32_t                rxidx;
138         uint32_t                rxlen;
139         uint8_t                 *txbuf;
140         uint32_t                txidx;
141         uint32_t                txlen;
142 };
143
144 static struct ofw_compat_data compat_data[] = {
145         {"fsl,imx51-ecspi",  true},
146         {"fsl,imx53-ecspi",  true},
147         {"fsl,imx6dl-ecspi", true},
148         {"fsl,imx6q-ecspi",  true},
149         {"fsl,imx6sx-ecspi", true},
150         {"fsl,imx6ul-ecspi", true},
151         {NULL,               false}
152 };
153
154 static inline uint32_t
155 RD4(struct spi_softc *sc, bus_size_t offset)
156 {
157
158         return (bus_read_4(sc->memres, offset));
159 }
160
161 static inline void
162 WR4(struct spi_softc *sc, bus_size_t offset, uint32_t value)
163 {
164
165         bus_write_4(sc->memres, offset, value);
166 }
167
168 static u_int
169 spi_calc_clockdiv(struct spi_softc *sc, u_int busfreq)
170 {
171         u_int post, pre;
172
173         /* Returning 0 effectively sets both dividers to 1. */
174         if (sc->basefreq <= busfreq)
175                 return (0);
176
177         /*
178          * Brute-force this; all real-world bus speeds are going to be found on
179          * the 1st or 2nd time through this loop.
180          */
181         for (post = 0; post < 16; ++post) {
182                 pre = ((sc->basefreq >> post) / busfreq) - 1;
183                 if (pre < 16)
184                         break;
185         }
186         if (post == 16) {
187                 /* The lowest we can go is ~115 Hz. */
188                 pre = 15;
189                 post = 15;
190         }
191
192         if (sc->debug >= 2) {
193                 device_printf(sc->dev,
194                     "base %u bus %u; pre %u, post %u; actual busfreq %u\n",
195                     sc->basefreq, busfreq, pre, post,
196                     (sc->basefreq / (pre + 1)) / (1 << post));
197         }
198
199         return (pre << CTLREG_PREDIV_SHIFT) | (post << CTLREG_POSTDIV_SHIFT);
200 }
201
202 static void
203 spi_set_chipsel(struct spi_softc *sc, u_int cs, bool active)
204 {
205         bool pinactive;
206
207         /*
208          * This is kinda crazy... the gpio pins for chipsel are defined as
209          * active-high in the dts, but are supposed to be treated as active-low
210          * by this driver.  So to turn on chipsel we have to invert the value
211          * passed to gpio_pin_set_active().  Then, to make it more fun, any
212          * slave can say its chipsel is active-high, so if that option is
213          * on, we have to invert the value again.
214          */
215         pinactive = !active ^ (bool)(cs & SPIBUS_CS_HIGH);
216
217         if (sc->debug >= 2) {
218                 device_printf(sc->dev, "chipsel %u changed to %u\n",
219                     (cs & ~SPIBUS_CS_HIGH), pinactive);
220         }
221
222         /*
223          * Change the pin, then do a dummy read of its current state to ensure
224          * that the state change reaches the hardware before proceeding.
225          */
226         gpio_pin_set_active(sc->cspins[cs & ~SPIBUS_CS_HIGH], pinactive);
227         gpio_pin_is_active(sc->cspins[cs & ~SPIBUS_CS_HIGH], &pinactive);
228 }
229
230 static void
231 spi_hw_setup(struct spi_softc *sc, u_int cs, u_int mode, u_int freq)
232 {
233         uint32_t reg;
234
235         /*
236          * Set up control register, and write it first to bring the device out
237          * of reset.
238          */
239         sc->ctlreg  = CTLREG_EN | CTLREG_CMODES_MASTER | CTLREG_SMC;
240         sc->ctlreg |= spi_calc_clockdiv(sc, freq);
241         sc->ctlreg |= 7 << CTLREG_BLEN_SHIFT; /* XXX byte at a time */
242         WR4(sc, ECSPI_CTLREG, sc->ctlreg);
243
244         /*
245          * Set up the config register.  Note that we do all transfers with the
246          * SPI hardware's chip-select set to zero.  The actual chip select is
247          * handled with a gpio pin.
248          */
249         reg = 0;
250         if (cs & SPIBUS_CS_HIGH)
251                 reg |= 1u << CFGREG_SSPOL_SHIFT;
252         if (mode & SPIBUS_MODE_CPHA)
253                 reg |= 1u << CFGREG_SCLKPHA_SHIFT;
254         if (mode & SPIBUS_MODE_CPOL) {
255                 reg |= 1u << CFGREG_SCLKPOL_SHIFT;
256                 reg |= 1u << CFGREG_SCLKCTL_SHIFT;
257         }
258         WR4(sc, ECSPI_CFGREG, reg);
259
260         /*
261          * Set up the rx/tx FIFO interrupt thresholds.
262          */
263         reg  = (FIFO_RXTHRESH << DMA_RX_THRESH_SHIFT);
264         reg |= (FIFO_TXTHRESH << DMA_TX_THRESH_SHIFT);
265         WR4(sc, ECSPI_DMAREG, reg);
266
267         /*
268          * Do a dummy read, to make sure the preceding writes reach the spi
269          * hardware before we assert any gpio chip select.
270          */
271         (void)RD4(sc, ECSPI_CFGREG);
272 }
273
274 static void
275 spi_empty_rxfifo(struct spi_softc *sc)
276 {
277
278         while (sc->rxidx < sc->rxlen && (RD4(sc, ECSPI_STATREG) & SREG_RR)) {
279                 sc->rxbuf[sc->rxidx++] = (uint8_t)RD4(sc, ECSPI_RXDATA);
280                 --sc->fifocnt;
281         }
282 }
283
284 static void
285 spi_fill_txfifo(struct spi_softc *sc)
286 {
287
288         while (sc->txidx < sc->txlen && sc->fifocnt < FIFO_SIZE) {
289                 WR4(sc, ECSPI_TXDATA, sc->txbuf[sc->txidx++]);
290                 ++sc->fifocnt;
291         }
292
293         /*
294          * If we're out of data, disable tx data ready (threshold) interrupts,
295          * and enable tx fifo empty interrupts.
296          */
297         if (sc->txidx == sc->txlen)
298                 sc->intreg = (sc->intreg & ~INTREG_TDREN) | INTREG_TEEN;
299 }
300
301 static void
302 spi_intr(void *arg)
303 {
304         struct spi_softc *sc = arg;
305         uint32_t intreg, status;
306
307         mtx_lock(&sc->mtx);
308
309         sc = arg;
310         intreg = sc->intreg;
311         status = RD4(sc, ECSPI_STATREG);
312         WR4(sc, ECSPI_STATREG, status); /* Clear w1c bits. */
313
314         /*
315          * If we get an overflow error, just signal that the transfer is done
316          * and wakeup the waiting thread, which will see that txidx != txlen and
317          * return an IO error to the caller.
318          */
319         if (__predict_false(status & SREG_RO)) {
320                 if (sc->debug || bootverbose) {
321                         device_printf(sc->dev, "rxoverflow rxidx %u txidx %u\n",
322                             sc->rxidx, sc->txidx);
323                 }
324                 sc->intreg = 0;
325                 wakeup(sc);
326                 mtx_unlock(&sc->mtx);
327                 return;
328         }
329
330         if (status & SREG_RR)
331                 spi_empty_rxfifo(sc);
332
333         if (status & SREG_TDR)
334                 spi_fill_txfifo(sc);
335
336         /*
337          * If we're out of bytes to send...
338          *  - If Transfer Complete is set (shift register is empty) and we've
339          *    received everything we expect, we're all done.
340          *  - Else if Tx Fifo Empty is set, we need to stop waiting for that and
341          *    switch to waiting for Transfer Complete (wait for shift register
342          *    to empty out), and also for Receive Ready (last of incoming data).
343          */
344         if (sc->txidx == sc->txlen) {
345                 if ((status & SREG_TC) && sc->fifocnt == 0) {
346                         sc->intreg = 0;
347                         wakeup(sc);
348                 } else if (status & SREG_TE) {
349                         sc->intreg &= ~(sc->intreg & ~INTREG_TEEN);
350                         sc->intreg |= INTREG_TCEN | INTREG_RREN;
351                 }
352         }
353
354         /*
355          * If interrupt flags changed, write the new flags to the hardware and
356          * do a dummy readback to ensure the changes reach the hardware before
357          * we exit the isr.
358          */
359         if (sc->intreg != intreg) {
360                 WR4(sc, ECSPI_INTREG, sc->intreg);
361                 (void)RD4(sc, ECSPI_INTREG);
362         }
363
364         if (sc->debug >= 3) {
365                 device_printf(sc->dev,
366                     "spi_intr, sreg 0x%08x intreg was 0x%08x now 0x%08x\n",
367                     status, intreg, sc->intreg);
368         }
369
370         mtx_unlock(&sc->mtx);
371 }
372
373 static int
374 spi_xfer_buf(struct spi_softc *sc, void *rxbuf, void *txbuf, uint32_t len)
375 {
376         int err;
377
378         if (sc->debug >= 1) {
379                 device_printf(sc->dev,
380                     "spi_xfer_buf, rxbuf %p txbuf %p len %u\n",
381                     rxbuf, txbuf, len);
382         }
383
384         if (len == 0)
385                 return (0);
386
387         sc->rxbuf = rxbuf;
388         sc->rxlen = len;
389         sc->rxidx = 0;
390         sc->txbuf = txbuf;
391         sc->txlen = len;
392         sc->txidx = 0;
393         sc->intreg = INTREG_RDREN | INTREG_TDREN;
394         spi_fill_txfifo(sc);
395
396         /* Enable interrupts last; spi_fill_txfifo() can change sc->intreg */
397         WR4(sc, ECSPI_INTREG, sc->intreg);
398
399         err = 0;
400         while (err == 0 && sc->intreg != 0)
401                 err = msleep(sc, &sc->mtx, 0, "imxspi", 10 * hz);
402
403         if (sc->rxidx != sc->rxlen || sc->txidx != sc->txlen)
404                 err = EIO;
405
406         return (err);
407 }
408
409 static int
410 spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
411 {
412         struct spi_softc *sc = device_get_softc(dev);
413         uint32_t cs, mode, clock;
414         int err;
415
416         spibus_get_cs(child, &cs);
417         spibus_get_clock(child, &clock);
418         spibus_get_mode(child, &mode);
419
420         if (cs > CS_MAX || sc->cspins[cs] == NULL) {
421                 if (sc->debug || bootverbose)
422                         device_printf(sc->dev, "Invalid chip select %u\n", cs);
423                 return (EINVAL);
424         }
425
426         mtx_lock(&sc->mtx);
427         device_busy(sc->dev);
428
429         if (sc->debug >= 1) {
430                 device_printf(sc->dev,
431                     "spi_transfer, cs 0x%x clock %u mode %u\n",
432                     cs, clock, mode);
433         }
434
435         /* Set up the hardware and select the device. */
436         spi_hw_setup(sc, cs, mode, clock);
437         spi_set_chipsel(sc, cs, true);
438
439         /* Transfer command then data bytes. */
440         err = 0;
441         if (cmd->tx_cmd_sz > 0)
442                 err = spi_xfer_buf(sc, cmd->rx_cmd, cmd->tx_cmd,
443                     cmd->tx_cmd_sz);
444         if (cmd->tx_data_sz > 0 && err == 0)
445                 err = spi_xfer_buf(sc, cmd->rx_data, cmd->tx_data,
446                     cmd->tx_data_sz);
447
448         /* Deselect the device, turn off (and reset) hardware. */
449         spi_set_chipsel(sc, cs, false);
450         WR4(sc, ECSPI_CTLREG, 0);
451
452         device_unbusy(sc->dev);
453         mtx_unlock(&sc->mtx);
454
455         return (err);
456 }
457
458 static phandle_t
459 spi_get_node(device_t bus, device_t dev)
460 {
461
462         /*
463          * Share our controller node with our spibus child; it instantiates
464          * devices by walking the children contained within our node.
465          */
466         return ofw_bus_get_node(bus);
467 }
468
469 static int
470 spi_detach(device_t dev)
471 {
472         struct spi_softc *sc = device_get_softc(dev);
473         int error, idx;
474
475         if ((error = bus_generic_detach(sc->dev)) != 0)
476                 return (error);
477
478         if (sc->spibus != NULL)
479                 device_delete_child(dev, sc->spibus);
480
481         for (idx = 0; idx < nitems(sc->cspins); ++idx) {
482                 if (sc->cspins[idx] != NULL)
483                         gpio_pin_release(sc->cspins[idx]);
484         }
485
486         if (sc->inthandle != NULL)
487                 bus_teardown_intr(sc->dev, sc->intres, sc->inthandle);
488         if (sc->intres != NULL)
489                 bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->intres);
490         if (sc->memres != NULL)
491                 bus_release_resource(sc->dev, SYS_RES_MEMORY, 0, sc->memres);
492
493         mtx_destroy(&sc->mtx);
494
495         return (0);
496 }
497
498 static int
499 spi_attach(device_t dev)
500 {
501         struct spi_softc *sc = device_get_softc(dev);
502         phandle_t node;
503         int err, idx, rid;
504
505         sc->dev = dev;
506         sc->basefreq = imx_ccm_ecspi_hz();
507
508         mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
509
510         /* Set up debug-enable sysctl. */
511         SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev), 
512             SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
513             OID_AUTO, "debug", CTLFLAG_RWTUN, &sc->debug, 0,
514             "Enable debug, higher values = more info");
515
516         /* Allocate mmio register access resources. */
517         rid = 0;
518         sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
519             RF_ACTIVE);
520         if (sc->memres == NULL) {
521                 device_printf(sc->dev, "could not allocate registers\n");
522                 spi_detach(sc->dev);
523                 return (ENXIO);
524         }
525
526         /* Allocate interrupt resources and set up handler. */
527         rid = 0;
528         sc->intres = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &rid,
529             RF_ACTIVE);
530         if (sc->intres == NULL) {
531                 device_printf(sc->dev, "could not allocate interrupt\n");
532                 device_detach(sc->dev);
533                 return (ENXIO);
534         }
535         err = bus_setup_intr(sc->dev, sc->intres, INTR_TYPE_MISC | INTR_MPSAFE,
536             NULL, spi_intr, sc, &sc->inthandle);
537         if (err != 0) {
538                 device_printf(sc->dev, "could not setup interrupt handler");
539                 device_detach(sc->dev);
540                 return (ENXIO);
541         }
542
543         /* Allocate gpio pins for configured chip selects. */
544         node = ofw_bus_get_node(sc->dev);
545         for (idx = 0; idx < nitems(sc->cspins); ++idx) {
546                 err = gpio_pin_get_by_ofw_propidx(sc->dev, node, "cs-gpios",
547                     idx, &sc->cspins[idx]);
548                 if (err == 0) {
549                         gpio_pin_setflags(sc->cspins[idx], GPIO_PIN_OUTPUT);
550                 } else if (sc->debug >= 2) {
551                         device_printf(sc->dev,
552                             "cannot configure gpio for chip select %u\n", idx);
553                 }
554         }
555
556         /*
557          * Hardware init: put all channels into Master mode, turn off the enable
558          * bit (gates off clocks); we only enable the hardware while xfers run.
559          */
560         WR4(sc, ECSPI_CTLREG, CTLREG_CMODES_MASTER);
561
562         /*
563          * Add the spibus driver as a child, and setup a one-shot intrhook to
564          * attach it after interrupts are working.  It will attach actual SPI
565          * devices as its children, and those devices may need to do IO during
566          * their attach. We can't do IO until timers and interrupts are working.
567          */
568         sc->spibus = device_add_child(dev, "spibus", -1);
569         config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev);
570
571         return (0);
572 }
573
574 static int
575 spi_probe(device_t dev)
576 {
577
578         if (!ofw_bus_status_okay(dev))
579                 return (ENXIO);
580
581         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
582                 return (ENXIO);
583
584         device_set_desc(dev, "i.MX ECSPI Master");
585         return (BUS_PROBE_DEFAULT);
586 }
587
588 static device_method_t spi_methods[] = {
589         DEVMETHOD(device_probe,         spi_probe),
590         DEVMETHOD(device_attach,        spi_attach),
591         DEVMETHOD(device_detach,        spi_detach),
592
593         /* spibus_if  */
594         DEVMETHOD(spibus_transfer,      spi_transfer),
595
596         /* ofw_bus_if */
597         DEVMETHOD(ofw_bus_get_node,     spi_get_node),
598
599         DEVMETHOD_END
600 };
601
602 static driver_t spi_driver = {
603         "imx_spi",
604         spi_methods,
605         sizeof(struct spi_softc),
606 };
607
608 static devclass_t spi_devclass;
609
610 DRIVER_MODULE(imx_spi, simplebus, spi_driver, spi_devclass, 0, 0);
611 DRIVER_MODULE(ofw_spibus, imx_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0);
612 MODULE_DEPEND(imx_spi, ofw_spibus, 1, 1, 1);
613 SIMPLEBUS_PNP_INFO(compat_data);