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