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