1 /* 2 * arch/arm/mach-orion5x/common.c 3 * 4 * Core functions for Marvell Orion 5x SoCs 5 * 6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com> 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/platform_device.h> 16 #include <linux/serial_8250.h> 17 #include <linux/mbus.h> 18 #include <linux/mv643xx_eth.h> 19 #include <linux/mv643xx_i2c.h> 20 #include <linux/ata_platform.h> 21 #include <linux/spi/orion_spi.h> 22 #include <net/dsa.h> 23 #include <asm/page.h> 24 #include <asm/setup.h> 25 #include <asm/timex.h> 26 #include <asm/mach/arch.h> 27 #include <asm/mach/map.h> 28 #include <asm/mach/time.h> 29 #include <mach/bridge-regs.h> 30 #include <mach/hardware.h> 31 #include <mach/orion5x.h> 32 #include <plat/ehci-orion.h> 33 #include <plat/mv_xor.h> 34 #include <plat/orion_nand.h> 35 #include <plat/orion_wdt.h> 36 #include <plat/time.h> 37 #include "common.h" 38 39 /***************************************************************************** 40 * I/O Address Mapping 41 ****************************************************************************/ 42 static struct map_desc orion5x_io_desc[] __initdata = { 43 { 44 .virtual = ORION5X_REGS_VIRT_BASE, 45 .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE), 46 .length = ORION5X_REGS_SIZE, 47 .type = MT_DEVICE, 48 }, { 49 .virtual = ORION5X_PCIE_IO_VIRT_BASE, 50 .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE), 51 .length = ORION5X_PCIE_IO_SIZE, 52 .type = MT_DEVICE, 53 }, { 54 .virtual = ORION5X_PCI_IO_VIRT_BASE, 55 .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE), 56 .length = ORION5X_PCI_IO_SIZE, 57 .type = MT_DEVICE, 58 }, { 59 .virtual = ORION5X_PCIE_WA_VIRT_BASE, 60 .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE), 61 .length = ORION5X_PCIE_WA_SIZE, 62 .type = MT_DEVICE, 63 }, 64 }; 65 66 void __init orion5x_map_io(void) 67 { 68 iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc)); 69 } 70 71 72 /***************************************************************************** 73 * EHCI 74 ****************************************************************************/ 75 static struct orion_ehci_data orion5x_ehci_data = { 76 .dram = &orion5x_mbus_dram_info, 77 .phy_version = EHCI_PHY_ORION, 78 }; 79 80 static u64 ehci_dmamask = 0xffffffffUL; 81 82 83 /***************************************************************************** 84 * EHCI0 85 ****************************************************************************/ 86 static struct resource orion5x_ehci0_resources[] = { 87 { 88 .start = ORION5X_USB0_PHYS_BASE, 89 .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1, 90 .flags = IORESOURCE_MEM, 91 }, { 92 .start = IRQ_ORION5X_USB0_CTRL, 93 .end = IRQ_ORION5X_USB0_CTRL, 94 .flags = IORESOURCE_IRQ, 95 }, 96 }; 97 98 static struct platform_device orion5x_ehci0 = { 99 .name = "orion-ehci", 100 .id = 0, 101 .dev = { 102 .dma_mask = &ehci_dmamask, 103 .coherent_dma_mask = 0xffffffff, 104 .platform_data = &orion5x_ehci_data, 105 }, 106 .resource = orion5x_ehci0_resources, 107 .num_resources = ARRAY_SIZE(orion5x_ehci0_resources), 108 }; 109 110 void __init orion5x_ehci0_init(void) 111 { 112 platform_device_register(&orion5x_ehci0); 113 } 114 115 116 /***************************************************************************** 117 * EHCI1 118 ****************************************************************************/ 119 static struct resource orion5x_ehci1_resources[] = { 120 { 121 .start = ORION5X_USB1_PHYS_BASE, 122 .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1, 123 .flags = IORESOURCE_MEM, 124 }, { 125 .start = IRQ_ORION5X_USB1_CTRL, 126 .end = IRQ_ORION5X_USB1_CTRL, 127 .flags = IORESOURCE_IRQ, 128 }, 129 }; 130 131 static struct platform_device orion5x_ehci1 = { 132 .name = "orion-ehci", 133 .id = 1, 134 .dev = { 135 .dma_mask = &ehci_dmamask, 136 .coherent_dma_mask = 0xffffffff, 137 .platform_data = &orion5x_ehci_data, 138 }, 139 .resource = orion5x_ehci1_resources, 140 .num_resources = ARRAY_SIZE(orion5x_ehci1_resources), 141 }; 142 143 void __init orion5x_ehci1_init(void) 144 { 145 platform_device_register(&orion5x_ehci1); 146 } 147 148 149 /***************************************************************************** 150 * GigE 151 ****************************************************************************/ 152 struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = { 153 .dram = &orion5x_mbus_dram_info, 154 }; 155 156 static struct resource orion5x_eth_shared_resources[] = { 157 { 158 .start = ORION5X_ETH_PHYS_BASE + 0x2000, 159 .end = ORION5X_ETH_PHYS_BASE + 0x3fff, 160 .flags = IORESOURCE_MEM, 161 }, { 162 .start = IRQ_ORION5X_ETH_ERR, 163 .end = IRQ_ORION5X_ETH_ERR, 164 .flags = IORESOURCE_IRQ, 165 }, 166 }; 167 168 static struct platform_device orion5x_eth_shared = { 169 .name = MV643XX_ETH_SHARED_NAME, 170 .id = 0, 171 .dev = { 172 .platform_data = &orion5x_eth_shared_data, 173 }, 174 .num_resources = ARRAY_SIZE(orion5x_eth_shared_resources), 175 .resource = orion5x_eth_shared_resources, 176 }; 177 178 static struct resource orion5x_eth_resources[] = { 179 { 180 .name = "eth irq", 181 .start = IRQ_ORION5X_ETH_SUM, 182 .end = IRQ_ORION5X_ETH_SUM, 183 .flags = IORESOURCE_IRQ, 184 }, 185 }; 186 187 static struct platform_device orion5x_eth = { 188 .name = MV643XX_ETH_NAME, 189 .id = 0, 190 .num_resources = 1, 191 .resource = orion5x_eth_resources, 192 .dev = { 193 .coherent_dma_mask = 0xffffffff, 194 }, 195 }; 196 197 void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) 198 { 199 eth_data->shared = &orion5x_eth_shared; 200 orion5x_eth.dev.platform_data = eth_data; 201 202 platform_device_register(&orion5x_eth_shared); 203 platform_device_register(&orion5x_eth); 204 } 205 206 207 /***************************************************************************** 208 * Ethernet switch 209 ****************************************************************************/ 210 static struct resource orion5x_switch_resources[] = { 211 { 212 .start = 0, 213 .end = 0, 214 .flags = IORESOURCE_IRQ, 215 }, 216 }; 217 218 static struct platform_device orion5x_switch_device = { 219 .name = "dsa", 220 .id = 0, 221 .num_resources = 0, 222 .resource = orion5x_switch_resources, 223 }; 224 225 void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq) 226 { 227 int i; 228 229 if (irq != NO_IRQ) { 230 orion5x_switch_resources[0].start = irq; 231 orion5x_switch_resources[0].end = irq; 232 orion5x_switch_device.num_resources = 1; 233 } 234 235 d->netdev = &orion5x_eth.dev; 236 for (i = 0; i < d->nr_chips; i++) 237 d->chip[i].mii_bus = &orion5x_eth_shared.dev; 238 orion5x_switch_device.dev.platform_data = d; 239 240 platform_device_register(&orion5x_switch_device); 241 } 242 243 244 /***************************************************************************** 245 * I2C 246 ****************************************************************************/ 247 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = { 248 .freq_m = 8, /* assumes 166 MHz TCLK */ 249 .freq_n = 3, 250 .timeout = 1000, /* Default timeout of 1 second */ 251 }; 252 253 static struct resource orion5x_i2c_resources[] = { 254 { 255 .start = I2C_PHYS_BASE, 256 .end = I2C_PHYS_BASE + 0x1f, 257 .flags = IORESOURCE_MEM, 258 }, { 259 .start = IRQ_ORION5X_I2C, 260 .end = IRQ_ORION5X_I2C, 261 .flags = IORESOURCE_IRQ, 262 }, 263 }; 264 265 static struct platform_device orion5x_i2c = { 266 .name = MV64XXX_I2C_CTLR_NAME, 267 .id = 0, 268 .num_resources = ARRAY_SIZE(orion5x_i2c_resources), 269 .resource = orion5x_i2c_resources, 270 .dev = { 271 .platform_data = &orion5x_i2c_pdata, 272 }, 273 }; 274 275 void __init orion5x_i2c_init(void) 276 { 277 platform_device_register(&orion5x_i2c); 278 } 279 280 281 /***************************************************************************** 282 * SATA 283 ****************************************************************************/ 284 static struct resource orion5x_sata_resources[] = { 285 { 286 .name = "sata base", 287 .start = ORION5X_SATA_PHYS_BASE, 288 .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1, 289 .flags = IORESOURCE_MEM, 290 }, { 291 .name = "sata irq", 292 .start = IRQ_ORION5X_SATA, 293 .end = IRQ_ORION5X_SATA, 294 .flags = IORESOURCE_IRQ, 295 }, 296 }; 297 298 static struct platform_device orion5x_sata = { 299 .name = "sata_mv", 300 .id = 0, 301 .dev = { 302 .coherent_dma_mask = 0xffffffff, 303 }, 304 .num_resources = ARRAY_SIZE(orion5x_sata_resources), 305 .resource = orion5x_sata_resources, 306 }; 307 308 void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) 309 { 310 sata_data->dram = &orion5x_mbus_dram_info; 311 orion5x_sata.dev.platform_data = sata_data; 312 platform_device_register(&orion5x_sata); 313 } 314 315 316 /***************************************************************************** 317 * SPI 318 ****************************************************************************/ 319 static struct orion_spi_info orion5x_spi_plat_data = { 320 .tclk = 0, 321 .enable_clock_fix = 1, 322 }; 323 324 static struct resource orion5x_spi_resources[] = { 325 { 326 .name = "spi base", 327 .start = SPI_PHYS_BASE, 328 .end = SPI_PHYS_BASE + 0x1f, 329 .flags = IORESOURCE_MEM, 330 }, 331 }; 332 333 static struct platform_device orion5x_spi = { 334 .name = "orion_spi", 335 .id = 0, 336 .dev = { 337 .platform_data = &orion5x_spi_plat_data, 338 }, 339 .num_resources = ARRAY_SIZE(orion5x_spi_resources), 340 .resource = orion5x_spi_resources, 341 }; 342 343 void __init orion5x_spi_init() 344 { 345 platform_device_register(&orion5x_spi); 346 } 347 348 349 /***************************************************************************** 350 * UART0 351 ****************************************************************************/ 352 static struct plat_serial8250_port orion5x_uart0_data[] = { 353 { 354 .mapbase = UART0_PHYS_BASE, 355 .membase = (char *)UART0_VIRT_BASE, 356 .irq = IRQ_ORION5X_UART0, 357 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, 358 .iotype = UPIO_MEM, 359 .regshift = 2, 360 .uartclk = 0, 361 }, { 362 }, 363 }; 364 365 static struct resource orion5x_uart0_resources[] = { 366 { 367 .start = UART0_PHYS_BASE, 368 .end = UART0_PHYS_BASE + 0xff, 369 .flags = IORESOURCE_MEM, 370 }, { 371 .start = IRQ_ORION5X_UART0, 372 .end = IRQ_ORION5X_UART0, 373 .flags = IORESOURCE_IRQ, 374 }, 375 }; 376 377 static struct platform_device orion5x_uart0 = { 378 .name = "serial8250", 379 .id = PLAT8250_DEV_PLATFORM, 380 .dev = { 381 .platform_data = orion5x_uart0_data, 382 }, 383 .resource = orion5x_uart0_resources, 384 .num_resources = ARRAY_SIZE(orion5x_uart0_resources), 385 }; 386 387 void __init orion5x_uart0_init(void) 388 { 389 platform_device_register(&orion5x_uart0); 390 } 391 392 393 /***************************************************************************** 394 * UART1 395 ****************************************************************************/ 396 static struct plat_serial8250_port orion5x_uart1_data[] = { 397 { 398 .mapbase = UART1_PHYS_BASE, 399 .membase = (char *)UART1_VIRT_BASE, 400 .irq = IRQ_ORION5X_UART1, 401 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, 402 .iotype = UPIO_MEM, 403 .regshift = 2, 404 .uartclk = 0, 405 }, { 406 }, 407 }; 408 409 static struct resource orion5x_uart1_resources[] = { 410 { 411 .start = UART1_PHYS_BASE, 412 .end = UART1_PHYS_BASE + 0xff, 413 .flags = IORESOURCE_MEM, 414 }, { 415 .start = IRQ_ORION5X_UART1, 416 .end = IRQ_ORION5X_UART1, 417 .flags = IORESOURCE_IRQ, 418 }, 419 }; 420 421 static struct platform_device orion5x_uart1 = { 422 .name = "serial8250", 423 .id = PLAT8250_DEV_PLATFORM1, 424 .dev = { 425 .platform_data = orion5x_uart1_data, 426 }, 427 .resource = orion5x_uart1_resources, 428 .num_resources = ARRAY_SIZE(orion5x_uart1_resources), 429 }; 430 431 void __init orion5x_uart1_init(void) 432 { 433 platform_device_register(&orion5x_uart1); 434 } 435 436 437 /***************************************************************************** 438 * XOR engine 439 ****************************************************************************/ 440 struct mv_xor_platform_shared_data orion5x_xor_shared_data = { 441 .dram = &orion5x_mbus_dram_info, 442 }; 443 444 static struct resource orion5x_xor_shared_resources[] = { 445 { 446 .name = "xor low", 447 .start = ORION5X_XOR_PHYS_BASE, 448 .end = ORION5X_XOR_PHYS_BASE + 0xff, 449 .flags = IORESOURCE_MEM, 450 }, { 451 .name = "xor high", 452 .start = ORION5X_XOR_PHYS_BASE + 0x200, 453 .end = ORION5X_XOR_PHYS_BASE + 0x2ff, 454 .flags = IORESOURCE_MEM, 455 }, 456 }; 457 458 static struct platform_device orion5x_xor_shared = { 459 .name = MV_XOR_SHARED_NAME, 460 .id = 0, 461 .dev = { 462 .platform_data = &orion5x_xor_shared_data, 463 }, 464 .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources), 465 .resource = orion5x_xor_shared_resources, 466 }; 467 468 static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32); 469 470 static struct resource orion5x_xor0_resources[] = { 471 [0] = { 472 .start = IRQ_ORION5X_XOR0, 473 .end = IRQ_ORION5X_XOR0, 474 .flags = IORESOURCE_IRQ, 475 }, 476 }; 477 478 static struct mv_xor_platform_data orion5x_xor0_data = { 479 .shared = &orion5x_xor_shared, 480 .hw_id = 0, 481 .pool_size = PAGE_SIZE, 482 }; 483 484 static struct platform_device orion5x_xor0_channel = { 485 .name = MV_XOR_NAME, 486 .id = 0, 487 .num_resources = ARRAY_SIZE(orion5x_xor0_resources), 488 .resource = orion5x_xor0_resources, 489 .dev = { 490 .dma_mask = &orion5x_xor_dmamask, 491 .coherent_dma_mask = DMA_BIT_MASK(64), 492 .platform_data = &orion5x_xor0_data, 493 }, 494 }; 495 496 static struct resource orion5x_xor1_resources[] = { 497 [0] = { 498 .start = IRQ_ORION5X_XOR1, 499 .end = IRQ_ORION5X_XOR1, 500 .flags = IORESOURCE_IRQ, 501 }, 502 }; 503 504 static struct mv_xor_platform_data orion5x_xor1_data = { 505 .shared = &orion5x_xor_shared, 506 .hw_id = 1, 507 .pool_size = PAGE_SIZE, 508 }; 509 510 static struct platform_device orion5x_xor1_channel = { 511 .name = MV_XOR_NAME, 512 .id = 1, 513 .num_resources = ARRAY_SIZE(orion5x_xor1_resources), 514 .resource = orion5x_xor1_resources, 515 .dev = { 516 .dma_mask = &orion5x_xor_dmamask, 517 .coherent_dma_mask = DMA_BIT_MASK(64), 518 .platform_data = &orion5x_xor1_data, 519 }, 520 }; 521 522 void __init orion5x_xor_init(void) 523 { 524 platform_device_register(&orion5x_xor_shared); 525 526 /* 527 * two engines can't do memset simultaneously, this limitation 528 * satisfied by removing memset support from one of the engines. 529 */ 530 dma_cap_set(DMA_MEMCPY, orion5x_xor0_data.cap_mask); 531 dma_cap_set(DMA_XOR, orion5x_xor0_data.cap_mask); 532 platform_device_register(&orion5x_xor0_channel); 533 534 dma_cap_set(DMA_MEMCPY, orion5x_xor1_data.cap_mask); 535 dma_cap_set(DMA_MEMSET, orion5x_xor1_data.cap_mask); 536 dma_cap_set(DMA_XOR, orion5x_xor1_data.cap_mask); 537 platform_device_register(&orion5x_xor1_channel); 538 } 539 540 static struct resource orion5x_crypto_res[] = { 541 { 542 .name = "regs", 543 .start = ORION5X_CRYPTO_PHYS_BASE, 544 .end = ORION5X_CRYPTO_PHYS_BASE + 0xffff, 545 .flags = IORESOURCE_MEM, 546 }, { 547 .name = "sram", 548 .start = ORION5X_SRAM_PHYS_BASE, 549 .end = ORION5X_SRAM_PHYS_BASE + SZ_8K - 1, 550 .flags = IORESOURCE_MEM, 551 }, { 552 .name = "crypto interrupt", 553 .start = IRQ_ORION5X_CESA, 554 .end = IRQ_ORION5X_CESA, 555 .flags = IORESOURCE_IRQ, 556 }, 557 }; 558 559 static struct platform_device orion5x_crypto_device = { 560 .name = "mv_crypto", 561 .id = -1, 562 .num_resources = ARRAY_SIZE(orion5x_crypto_res), 563 .resource = orion5x_crypto_res, 564 }; 565 566 static int __init orion5x_crypto_init(void) 567 { 568 int ret; 569 570 ret = orion5x_setup_sram_win(); 571 if (ret) 572 return ret; 573 574 return platform_device_register(&orion5x_crypto_device); 575 } 576 577 /***************************************************************************** 578 * Watchdog 579 ****************************************************************************/ 580 static struct orion_wdt_platform_data orion5x_wdt_data = { 581 .tclk = 0, 582 }; 583 584 static struct platform_device orion5x_wdt_device = { 585 .name = "orion_wdt", 586 .id = -1, 587 .dev = { 588 .platform_data = &orion5x_wdt_data, 589 }, 590 .num_resources = 0, 591 }; 592 593 void __init orion5x_wdt_init(void) 594 { 595 orion5x_wdt_data.tclk = orion5x_tclk; 596 platform_device_register(&orion5x_wdt_device); 597 } 598 599 600 /***************************************************************************** 601 * Time handling 602 ****************************************************************************/ 603 void __init orion5x_init_early(void) 604 { 605 orion_time_set_base(TIMER_VIRT_BASE); 606 } 607 608 int orion5x_tclk; 609 610 int __init orion5x_find_tclk(void) 611 { 612 u32 dev, rev; 613 614 orion5x_pcie_id(&dev, &rev); 615 if (dev == MV88F6183_DEV_ID && 616 (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0) 617 return 133333333; 618 619 return 166666667; 620 } 621 622 static void orion5x_timer_init(void) 623 { 624 orion5x_tclk = orion5x_find_tclk(); 625 626 orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR, 627 IRQ_ORION5X_BRIDGE, orion5x_tclk); 628 } 629 630 struct sys_timer orion5x_timer = { 631 .init = orion5x_timer_init, 632 }; 633 634 635 /***************************************************************************** 636 * General 637 ****************************************************************************/ 638 /* 639 * Identify device ID and rev from PCIe configuration header space '0'. 640 */ 641 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name) 642 { 643 orion5x_pcie_id(dev, rev); 644 645 if (*dev == MV88F5281_DEV_ID) { 646 if (*rev == MV88F5281_REV_D2) { 647 *dev_name = "MV88F5281-D2"; 648 } else if (*rev == MV88F5281_REV_D1) { 649 *dev_name = "MV88F5281-D1"; 650 } else if (*rev == MV88F5281_REV_D0) { 651 *dev_name = "MV88F5281-D0"; 652 } else { 653 *dev_name = "MV88F5281-Rev-Unsupported"; 654 } 655 } else if (*dev == MV88F5182_DEV_ID) { 656 if (*rev == MV88F5182_REV_A2) { 657 *dev_name = "MV88F5182-A2"; 658 } else { 659 *dev_name = "MV88F5182-Rev-Unsupported"; 660 } 661 } else if (*dev == MV88F5181_DEV_ID) { 662 if (*rev == MV88F5181_REV_B1) { 663 *dev_name = "MV88F5181-Rev-B1"; 664 } else if (*rev == MV88F5181L_REV_A1) { 665 *dev_name = "MV88F5181L-Rev-A1"; 666 } else { 667 *dev_name = "MV88F5181(L)-Rev-Unsupported"; 668 } 669 } else if (*dev == MV88F6183_DEV_ID) { 670 if (*rev == MV88F6183_REV_B0) { 671 *dev_name = "MV88F6183-Rev-B0"; 672 } else { 673 *dev_name = "MV88F6183-Rev-Unsupported"; 674 } 675 } else { 676 *dev_name = "Device-Unknown"; 677 } 678 } 679 680 void __init orion5x_init(void) 681 { 682 char *dev_name; 683 u32 dev, rev; 684 685 orion5x_id(&dev, &rev, &dev_name); 686 printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk); 687 688 orion5x_eth_shared_data.t_clk = orion5x_tclk; 689 orion5x_spi_plat_data.tclk = orion5x_tclk; 690 orion5x_uart0_data[0].uartclk = orion5x_tclk; 691 orion5x_uart1_data[0].uartclk = orion5x_tclk; 692 693 /* 694 * Setup Orion address map 695 */ 696 orion5x_setup_cpu_mbus_bridge(); 697 698 /* 699 * Don't issue "Wait for Interrupt" instruction if we are 700 * running on D0 5281 silicon. 701 */ 702 if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) { 703 printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n"); 704 disable_hlt(); 705 } 706 707 /* 708 * The 5082/5181l/5182/6082/6082l/6183 have crypto 709 * while 5180n/5181/5281 don't have crypto. 710 */ 711 if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) || 712 dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID) 713 orion5x_crypto_init(); 714 715 /* 716 * Register watchdog driver 717 */ 718 orion5x_wdt_init(); 719 } 720 721 /* 722 * Many orion-based systems have buggy bootloader implementations. 723 * This is a common fixup for bogus memory tags. 724 */ 725 void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t, 726 char **from, struct meminfo *meminfo) 727 { 728 for (; t->hdr.size; t = tag_next(t)) 729 if (t->hdr.tag == ATAG_MEM && 730 (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK || 731 t->u.mem.start & ~PAGE_MASK)) { 732 printk(KERN_WARNING 733 "Clearing invalid memory bank %dKB@0x%08x\n", 734 t->u.mem.size / 1024, t->u.mem.start); 735 t->hdr.tag = 0; 736 } 737 } 738