1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2018 Rubicon Communications, LLC (Netgate) 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Marvell Xenon SDHCI controller driver. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/bus.h> 38 #include <sys/kernel.h> 39 #include <sys/lock.h> 40 #include <sys/module.h> 41 #include <sys/mutex.h> 42 #include <sys/resource.h> 43 #include <sys/rman.h> 44 #include <sys/sysctl.h> 45 #include <sys/taskqueue.h> 46 47 #include <machine/bus.h> 48 #include <machine/resource.h> 49 50 #include <dev/fdt/fdt_common.h> 51 #include <dev/ofw/ofw_bus.h> 52 #include <dev/ofw/ofw_bus_subr.h> 53 54 #include <dev/mmc/bridge.h> 55 #include <dev/mmc/mmcbrvar.h> 56 #include <dev/mmc/mmcreg.h> 57 58 #include <dev/sdhci/sdhci.h> 59 #include <dev/sdhci/sdhci_xenon.h> 60 61 #include "mmcbr_if.h" 62 #include "sdhci_if.h" 63 64 #include "opt_mmccam.h" 65 66 #define MAX_SLOTS 6 67 68 static struct ofw_compat_data compat_data[] = { 69 { "marvell,armada-3700-sdhci", 1 }, 70 { NULL, 0 } 71 }; 72 73 struct sdhci_xenon_softc { 74 device_t dev; /* Controller device */ 75 int slot_id; /* Controller ID */ 76 phandle_t node; /* FDT node */ 77 uint32_t quirks; /* Chip specific quirks */ 78 uint32_t caps; /* If we override SDHCI_CAPABILITIES */ 79 uint32_t max_clk; /* Max possible freq */ 80 struct resource *irq_res; /* IRQ resource */ 81 void *intrhand; /* Interrupt handle */ 82 83 struct sdhci_slot *slot; /* SDHCI internal data */ 84 struct resource *mem_res; /* Memory resource */ 85 86 uint8_t znr; /* PHY ZNR */ 87 uint8_t zpr; /* PHY ZPR */ 88 bool no_18v; /* No 1.8V support */ 89 bool slow_mode; /* PHY slow mode */ 90 bool wp_inverted; /* WP pin is inverted */ 91 }; 92 93 static uint8_t 94 sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused, 95 bus_size_t off) 96 { 97 struct sdhci_xenon_softc *sc = device_get_softc(dev); 98 99 return (bus_read_1(sc->mem_res, off)); 100 } 101 102 static void 103 sdhci_xenon_write_1(device_t dev, struct sdhci_slot *slot __unused, 104 bus_size_t off, uint8_t val) 105 { 106 struct sdhci_xenon_softc *sc = device_get_softc(dev); 107 108 bus_write_1(sc->mem_res, off, val); 109 } 110 111 static uint16_t 112 sdhci_xenon_read_2(device_t dev, struct sdhci_slot *slot __unused, 113 bus_size_t off) 114 { 115 struct sdhci_xenon_softc *sc = device_get_softc(dev); 116 117 return (bus_read_2(sc->mem_res, off)); 118 } 119 120 static void 121 sdhci_xenon_write_2(device_t dev, struct sdhci_slot *slot __unused, 122 bus_size_t off, uint16_t val) 123 { 124 struct sdhci_xenon_softc *sc = device_get_softc(dev); 125 126 bus_write_2(sc->mem_res, off, val); 127 } 128 129 static uint32_t 130 sdhci_xenon_read_4(device_t dev, struct sdhci_slot *slot __unused, 131 bus_size_t off) 132 { 133 struct sdhci_xenon_softc *sc = device_get_softc(dev); 134 uint32_t val32; 135 136 val32 = bus_read_4(sc->mem_res, off); 137 if (off == SDHCI_CAPABILITIES && sc->no_18v) 138 val32 &= ~SDHCI_CAN_VDD_180; 139 140 return (val32); 141 } 142 143 static void 144 sdhci_xenon_write_4(device_t dev, struct sdhci_slot *slot __unused, 145 bus_size_t off, uint32_t val) 146 { 147 struct sdhci_xenon_softc *sc = device_get_softc(dev); 148 149 bus_write_4(sc->mem_res, off, val); 150 } 151 152 static void 153 sdhci_xenon_read_multi_4(device_t dev, struct sdhci_slot *slot __unused, 154 bus_size_t off, uint32_t *data, bus_size_t count) 155 { 156 struct sdhci_xenon_softc *sc = device_get_softc(dev); 157 158 bus_read_multi_4(sc->mem_res, off, data, count); 159 } 160 161 static void 162 sdhci_xenon_write_multi_4(device_t dev, struct sdhci_slot *slot __unused, 163 bus_size_t off, uint32_t *data, bus_size_t count) 164 { 165 struct sdhci_xenon_softc *sc = device_get_softc(dev); 166 167 bus_write_multi_4(sc->mem_res, off, data, count); 168 } 169 170 static void 171 sdhci_xenon_intr(void *arg) 172 { 173 struct sdhci_xenon_softc *sc = (struct sdhci_xenon_softc *)arg; 174 175 sdhci_generic_intr(sc->slot); 176 } 177 178 static int 179 sdhci_xenon_get_ro(device_t bus, device_t dev) 180 { 181 struct sdhci_xenon_softc *sc = device_get_softc(bus); 182 183 return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted); 184 } 185 186 static int 187 sdhci_xenon_phy_init(device_t brdev, struct mmc_ios *ios) 188 { 189 int i; 190 struct sdhci_xenon_softc *sc; 191 uint32_t reg; 192 193 sc = device_get_softc(brdev); 194 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); 195 reg |= XENON_SAMPL_INV_QSP_PHASE_SELECT; 196 switch (ios->timing) { 197 case bus_timing_normal: 198 case bus_timing_hs: 199 case bus_timing_uhs_sdr12: 200 case bus_timing_uhs_sdr25: 201 case bus_timing_uhs_sdr50: 202 reg |= XENON_TIMING_ADJUST_SLOW_MODE; 203 break; 204 default: 205 reg &= ~XENON_TIMING_ADJUST_SLOW_MODE; 206 } 207 if (sc->slow_mode) 208 reg |= XENON_TIMING_ADJUST_SLOW_MODE; 209 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); 210 211 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); 212 reg |= XENON_PHY_INITIALIZATION; 213 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); 214 215 /* Wait for the eMMC PHY init. */ 216 for (i = 100; i > 0; i--) { 217 DELAY(100); 218 219 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); 220 if ((reg & XENON_PHY_INITIALIZATION) == 0) 221 break; 222 } 223 224 if (i == 0) { 225 device_printf(brdev, "eMMC PHY failed to initialize\n"); 226 return (ETIMEDOUT); 227 } 228 229 return (0); 230 } 231 232 static int 233 sdhci_xenon_phy_set(device_t brdev, struct mmc_ios *ios) 234 { 235 struct sdhci_xenon_softc *sc; 236 uint32_t reg; 237 238 sc = device_get_softc(brdev); 239 /* Setup pad, set bit[28] and bits[26:24] */ 240 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL); 241 reg |= (XENON_FC_DQ_RECEN | XENON_FC_CMD_RECEN | 242 XENON_FC_QSP_RECEN | XENON_OEN_QSN); 243 /* All FC_XX_RECEIVCE should be set as CMOS Type */ 244 reg |= XENON_FC_ALL_CMOS_RECEIVER; 245 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL, reg); 246 247 /* Set CMD and DQ Pull Up */ 248 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1); 249 reg |= (XENON_EMMC_FC_CMD_PU | XENON_EMMC_FC_DQ_PU); 250 reg &= ~(XENON_EMMC_FC_CMD_PD | XENON_EMMC_FC_DQ_PD); 251 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg); 252 253 if (ios->timing == bus_timing_normal) 254 return (sdhci_xenon_phy_init(brdev, ios)); 255 256 /* Clear SDIO mode, no SDIO support for now. */ 257 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST); 258 reg &= ~XENON_TIMING_ADJUST_SDIO_MODE; 259 bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg); 260 261 /* 262 * Set preferred ZNR and ZPR value. 263 * The ZNR and ZPR value vary between different boards. 264 * Define them both in the DTS for the board! 265 */ 266 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2); 267 reg &= ~((XENON_ZNR_MASK << XENON_ZNR_SHIFT) | XENON_ZPR_MASK); 268 reg |= ((sc->znr << XENON_ZNR_SHIFT) | sc->zpr); 269 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2, reg); 270 271 /* Disable the SD clock to set EMMC_PHY_FUNC_CONTROL. */ 272 reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL); 273 reg &= ~SDHCI_CLOCK_CARD_EN; 274 bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg); 275 276 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL); 277 switch (ios->timing) { 278 case bus_timing_mmc_hs400: 279 reg |= (XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) | 280 XENON_CMD_DDR_MODE; 281 reg &= ~XENON_DQ_ASYNC_MODE; 282 break; 283 case bus_timing_uhs_ddr50: 284 case bus_timing_mmc_ddr52: 285 reg |= (XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) | 286 XENON_CMD_DDR_MODE | XENON_DQ_ASYNC_MODE; 287 break; 288 default: 289 reg &= ~((XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) | 290 XENON_CMD_DDR_MODE); 291 reg |= XENON_DQ_ASYNC_MODE; 292 } 293 bus_write_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL, reg); 294 295 /* Enable SD clock. */ 296 reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL); 297 reg |= SDHCI_CLOCK_CARD_EN; 298 bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg); 299 300 if (ios->timing == bus_timing_mmc_hs400) 301 bus_write_4(sc->mem_res, XENON_EMMC_PHY_LOGIC_TIMING_ADJUST, 302 XENON_LOGIC_TIMING_VALUE); 303 else { 304 /* Disable both SDHC Data Strobe and Enhanced Strobe. */ 305 reg = bus_read_4(sc->mem_res, XENON_SLOT_EMMC_CTRL); 306 reg &= ~(XENON_ENABLE_DATA_STROBE | XENON_ENABLE_RESP_STROBE); 307 bus_write_4(sc->mem_res, XENON_SLOT_EMMC_CTRL, reg); 308 309 /* Clear Strobe line Pull down or Pull up. */ 310 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1); 311 reg &= ~(XENON_EMMC_FC_QSP_PD | XENON_EMMC_FC_QSP_PU); 312 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg); 313 } 314 315 return (sdhci_xenon_phy_init(brdev, ios)); 316 } 317 318 static int 319 sdhci_xenon_update_ios(device_t brdev, device_t reqdev) 320 { 321 int err; 322 struct sdhci_xenon_softc *sc; 323 struct mmc_ios *ios; 324 struct sdhci_slot *slot; 325 uint32_t reg; 326 327 err = sdhci_generic_update_ios(brdev, reqdev); 328 if (err != 0) 329 return (err); 330 331 sc = device_get_softc(brdev); 332 slot = device_get_ivars(reqdev); 333 ios = &slot->host.ios; 334 335 /* Update the PHY settings. */ 336 if (ios->clock != 0) 337 sdhci_xenon_phy_set(brdev, ios); 338 339 if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) { 340 /* Enable SDCLK_IDLEOFF. */ 341 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); 342 reg |= 1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id); 343 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); 344 } 345 346 return (0); 347 } 348 349 static int 350 sdhci_xenon_probe(device_t dev) 351 { 352 struct sdhci_xenon_softc *sc = device_get_softc(dev); 353 pcell_t cid; 354 355 sc->quirks = 0; 356 sc->slot_id = 0; 357 sc->max_clk = XENON_MMC_MAX_CLK; 358 359 if (!ofw_bus_status_okay(dev)) 360 return (ENXIO); 361 362 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 363 return (ENXIO); 364 365 sc->node = ofw_bus_get_node(dev); 366 device_set_desc(dev, "Armada Xenon SDHCI controller"); 367 368 /* Allow dts to patch quirks, slots, and max-frequency. */ 369 if ((OF_getencprop(sc->node, "quirks", &cid, sizeof(cid))) > 0) 370 sc->quirks = cid; 371 if ((OF_getencprop(sc->node, "max-frequency", &cid, sizeof(cid))) > 0) 372 sc->max_clk = cid; 373 if (OF_hasprop(sc->node, "no-1-8-v")) 374 sc->no_18v = true; 375 if (OF_hasprop(sc->node, "wp-inverted")) 376 sc->wp_inverted = true; 377 if (OF_hasprop(sc->node, "marvell,xenon-phy-slow-mode")) 378 sc->slow_mode = true; 379 sc->znr = XENON_ZNR_DEF_VALUE; 380 if ((OF_getencprop(sc->node, "marvell,xenon-phy-znr", &cid, 381 sizeof(cid))) > 0) 382 sc->znr = cid & XENON_ZNR_MASK; 383 sc->zpr = XENON_ZPR_DEF_VALUE; 384 if ((OF_getencprop(sc->node, "marvell,xenon-phy-zpr", &cid, 385 sizeof(cid))) > 0) 386 sc->zpr = cid & XENON_ZPR_MASK; 387 388 return (0); 389 } 390 391 static int 392 sdhci_xenon_attach(device_t dev) 393 { 394 struct sdhci_xenon_softc *sc = device_get_softc(dev); 395 struct sdhci_slot *slot; 396 int err, rid; 397 uint32_t reg; 398 399 sc->dev = dev; 400 401 /* Allocate IRQ. */ 402 rid = 0; 403 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 404 RF_ACTIVE); 405 if (sc->irq_res == NULL) { 406 device_printf(dev, "Can't allocate IRQ\n"); 407 return (ENOMEM); 408 } 409 410 /* Allocate memory. */ 411 rid = 0; 412 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 413 &rid, RF_ACTIVE); 414 if (sc->mem_res == NULL) { 415 bus_release_resource(dev, SYS_RES_IRQ, 416 rman_get_rid(sc->irq_res), sc->irq_res); 417 device_printf(dev, "Can't allocate memory for slot\n"); 418 return (ENOMEM); 419 } 420 421 slot = malloc(sizeof(*slot), M_DEVBUF, M_ZERO | M_WAITOK); 422 423 /* Check if the device is flagged as non-removable. */ 424 if (OF_hasprop(sc->node, "non-removable")) { 425 slot->opt |= SDHCI_NON_REMOVABLE; 426 if (bootverbose) 427 device_printf(dev, "Non-removable media\n"); 428 } 429 430 slot->quirks = sc->quirks; 431 slot->caps = sc->caps; 432 slot->max_clk = sc->max_clk; 433 sc->slot = slot; 434 435 if (sdhci_init_slot(dev, sc->slot, 0)) 436 goto fail; 437 438 /* Activate the interrupt */ 439 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 440 NULL, sdhci_xenon_intr, sc, &sc->intrhand); 441 if (err) { 442 device_printf(dev, "Cannot setup IRQ\n"); 443 goto fail; 444 } 445 446 /* Disable Auto Clock Gating. */ 447 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); 448 reg |= XENON_AUTO_CLKGATE_DISABLE; 449 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); 450 451 /* Enable this SD controller. */ 452 reg |= (1 << sc->slot_id); 453 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); 454 455 /* Enable Parallel Transfer. */ 456 reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL); 457 reg |= (1 << sc->slot_id); 458 bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg); 459 460 /* Enable Auto Clock Gating. */ 461 reg &= ~XENON_AUTO_CLKGATE_DISABLE; 462 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); 463 464 /* Disable SDCLK_IDLEOFF before the card initialization. */ 465 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); 466 reg &= ~(1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id)); 467 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); 468 469 /* Mask command conflict errors. */ 470 reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL); 471 reg |= XENON_MASK_CMD_CONFLICT_ERR; 472 bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg); 473 474 /* Process cards detection. */ 475 sdhci_start_slot(sc->slot); 476 477 return (0); 478 479 fail: 480 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), 481 sc->irq_res); 482 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), 483 sc->mem_res); 484 free(sc->slot, M_DEVBUF); 485 sc->slot = NULL; 486 487 return (ENXIO); 488 } 489 490 static int 491 sdhci_xenon_detach(device_t dev) 492 { 493 struct sdhci_xenon_softc *sc = device_get_softc(dev); 494 495 bus_generic_detach(dev); 496 bus_teardown_intr(dev, sc->irq_res, sc->intrhand); 497 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), 498 sc->irq_res); 499 sdhci_cleanup_slot(sc->slot); 500 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), 501 sc->mem_res); 502 free(sc->slot, M_DEVBUF); 503 sc->slot = NULL; 504 505 return (0); 506 } 507 508 static device_method_t sdhci_xenon_methods[] = { 509 /* device_if */ 510 DEVMETHOD(device_probe, sdhci_xenon_probe), 511 DEVMETHOD(device_attach, sdhci_xenon_attach), 512 DEVMETHOD(device_detach, sdhci_xenon_detach), 513 514 /* Bus interface */ 515 DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), 516 DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), 517 518 /* mmcbr_if */ 519 DEVMETHOD(mmcbr_update_ios, sdhci_xenon_update_ios), 520 DEVMETHOD(mmcbr_request, sdhci_generic_request), 521 DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro), 522 DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), 523 DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), 524 525 /* SDHCI registers accessors */ 526 DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1), 527 DEVMETHOD(sdhci_read_2, sdhci_xenon_read_2), 528 DEVMETHOD(sdhci_read_4, sdhci_xenon_read_4), 529 DEVMETHOD(sdhci_read_multi_4, sdhci_xenon_read_multi_4), 530 DEVMETHOD(sdhci_write_1, sdhci_xenon_write_1), 531 DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2), 532 DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4), 533 DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4), 534 535 DEVMETHOD_END 536 }; 537 538 static driver_t sdhci_xenon_driver = { 539 "sdhci_xenon", 540 sdhci_xenon_methods, 541 sizeof(struct sdhci_xenon_softc), 542 }; 543 static devclass_t sdhci_xenon_devclass; 544 545 DRIVER_MODULE(sdhci_xenon, simplebus, sdhci_xenon_driver, sdhci_xenon_devclass, 546 NULL, NULL); 547 548 MODULE_DEPEND(sdhci_xenon, sdhci, 1, 1, 1); 549 #ifndef MMCCAM 550 MMC_DECLARE_BRIDGE(sdhci_xenon); 551 #endif 552