aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorDeepak Saxena <dsaxena@plexity.net>2005-10-28 10:19:12 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-10-28 10:19:12 -0400
commit0b7cd62ecdc1f09b7df4608a3fee644b1c27985b (patch)
tree3769b043ea6b15ffe7b74a1a5d42903e08b126bc /arch/arm
parent9769c2468d423a1562dd59a5db250bd0a5533ec9 (diff)
[ARM] 3017/1: Add support for 36-bit addresses to create_mapping()
Patch from Deepak Saxena This patch adds support for 36-bit static mapped I/O. While there are no platforms in the tree ATM that use it, it has been tested tested on the IXP2350 NPU and I would like to get the support for that chipset upstream one piece at a time. There are also other Intel chipset ports in development that are waiting on this to go upstream. The patch replaces the print formats for physical addresses with %016llx which will create a bit extraneous output on 32-bit systems, but I think that is cleaner than having #ifdefs, specially since users will only see the output in error cases. Depends on 3016/1. Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mm/mm-armv.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 64db10e806b3..61bc2fa0511e 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -478,20 +478,20 @@ void __init create_mapping(struct map_desc *md)
478 unsigned long virt, length; 478 unsigned long virt, length;
479 int prot_sect, prot_l1, domain; 479 int prot_sect, prot_l1, domain;
480 pgprot_t prot_pte; 480 pgprot_t prot_pte;
481 long off; 481 unsigned long off = (u32)__pfn_to_phys(md->pfn);
482 482
483 if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { 483 if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
484 printk(KERN_WARNING "BUG: not creating mapping for " 484 printk(KERN_WARNING "BUG: not creating mapping for "
485 "0x%08lx at 0x%08lx in user region\n", 485 "0x%016llx at 0x%08lx in user region\n",
486 __pfn_to_phys(md->pfn), md->virtual); 486 __pfn_to_phys((u64)md->pfn), md->virtual);
487 return; 487 return;
488 } 488 }
489 489
490 if ((md->type == MT_DEVICE || md->type == MT_ROM) && 490 if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
491 md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { 491 md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
492 printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " 492 printk(KERN_WARNING "BUG: mapping for 0x%016llx at 0x%08lx "
493 "overlaps vmalloc space\n", 493 "overlaps vmalloc space\n",
494 __pfn_to_phys(md->pfn), md->virtual); 494 __pfn_to_phys((u64)md->pfn), md->virtual);
495 } 495 }
496 496
497 domain = mem_types[md->type].domain; 497 domain = mem_types[md->type].domain;
@@ -499,8 +499,33 @@ void __init create_mapping(struct map_desc *md)
499 prot_l1 = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain); 499 prot_l1 = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
500 prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain); 500 prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
501 501
502 /*
503 * Catch 36-bit addresses
504 */
505 if(md->pfn >= 0x100000) {
506 if(domain) {
507 printk(KERN_ERR "MM: invalid domain in supersection "
508 "mapping for 0x%016llx at 0x%08lx\n",
509 __pfn_to_phys((u64)md->pfn), md->virtual);
510 return;
511 }
512 if((md->virtual | md->length | __pfn_to_phys(md->pfn))
513 & ~SUPERSECTION_MASK) {
514 printk(KERN_ERR "MM: cannot create mapping for "
515 "0x%016llx at 0x%08lx invalid alignment\n",
516 __pfn_to_phys((u64)md->pfn), md->virtual);
517 return;
518 }
519
520 /*
521 * Shift bits [35:32] of address into bits [23:20] of PMD
522 * (See ARMv6 spec).
523 */
524 off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
525 }
526
502 virt = md->virtual; 527 virt = md->virtual;
503 off = __pfn_to_phys(md->pfn) - virt; 528 off -= virt;
504 length = md->length; 529 length = md->length;
505 530
506 if (mem_types[md->type].prot_l1 == 0 && 531 if (mem_types[md->type].prot_l1 == 0 &&
@@ -525,13 +550,22 @@ void __init create_mapping(struct map_desc *md)
525 * of the actual domain assignments in use. 550 * of the actual domain assignments in use.
526 */ 551 */
527 if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { 552 if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
528 /* Align to supersection boundary */ 553 /*
529 while ((virt & ~SUPERSECTION_MASK || (virt + off) & 554 * Align to supersection boundary if !high pages.
530 ~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) { 555 * High pages have already been checked for proper
531 alloc_init_section(virt, virt + off, prot_sect); 556 * alignment above and they will fail the SUPSERSECTION_MASK
532 557 * check because of the way the address is encoded into
533 virt += (PGDIR_SIZE / 2); 558 * offset.
534 length -= (PGDIR_SIZE / 2); 559 */
560 if (md->pfn <= 0x100000) {
561 while ((virt & ~SUPERSECTION_MASK ||
562 (virt + off) & ~SUPERSECTION_MASK) &&
563 length >= (PGDIR_SIZE / 2)) {
564 alloc_init_section(virt, virt + off, prot_sect);
565
566 virt += (PGDIR_SIZE / 2);
567 length -= (PGDIR_SIZE / 2);
568 }
535 } 569 }
536 570
537 while (length >= SUPERSECTION_SIZE) { 571 while (length >= SUPERSECTION_SIZE) {