ARC: Support for single cycle Close Coupled Mem (CCM)
authorVineet Gupta <vgupta@synopsys.com>
Fri, 18 Jan 2013 09:42:25 +0000 (15:12 +0530)
committerVineet Gupta <vgupta@synopsys.com>
Fri, 15 Feb 2013 17:46:10 +0000 (23:16 +0530)
* Includes mapping of CCMs in address space
* Annotations to move arbitrary code/data into CCM
* Moving some of the critical code/data into CCM
* Runtime detection/reporting

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
arch/arc/Kconfig
arch/arc/include/asm/linkage.h
arch/arc/kernel/entry.S
arch/arc/kernel/setup.c
arch/arc/kernel/vmlinux.lds.S
arch/arc/mm/tlbex.S

index 03183f69084936faaa5aa06505f8b3746c8dc5c6..2611a60cb0598994b1d8de8ee925b578f3a3e343 100644 (file)
@@ -198,6 +198,33 @@ config ARC_CACHE_PAGES
 
 endif  #ARC_CACHE
 
+config ARC_HAS_ICCM
+       bool "Use ICCM"
+       help
+         Single Cycle RAMS to store Fast Path Code
+       default n
+
+config ARC_ICCM_SZ
+       int "ICCM Size in KB"
+       default "64"
+       depends on ARC_HAS_ICCM
+
+config ARC_HAS_DCCM
+       bool "Use DCCM"
+       help
+         Single Cycle RAMS to store Fast Path Data
+       default n
+
+config ARC_DCCM_SZ
+       int "DCCM Size in KB"
+       default "64"
+       depends on ARC_HAS_DCCM
+
+config ARC_DCCM_BASE
+       hex "DCCM map address"
+       default "0xA0000000"
+       depends on ARC_HAS_DCCM
+
 config ARC_HAS_HW_MPY
        bool "Use Hardware Multiplier (Normal or Faster XMAC)"
        default y
index a45d1bb50e41094ae2db62a4d8ab5c62bff24099..0283e9e44e0d8cf368066484a4e502d5f1b399ef 100644 (file)
        .size \ name, ASM_PREV_SYM_ADDR(\name)
 .endm
 
+/* annotation for data we want in DCCM - if enabled in .config */
+.macro ARCFP_DATA nm
+#ifdef CONFIG_ARC_HAS_DCCM
+       .section .data.arcfp
+#else
+       .section .data
+#endif
+       .global \nm
+.endm
+
+/* annotation for data we want in DCCM - if enabled in .config */
+.macro ARCFP_CODE
+#ifdef CONFIG_ARC_HAS_ICCM
+       .section .text.arcfp, "ax",@progbits
+#else
+       .section .text, "ax",@progbits
+#endif
+.endm
+
+#else  /* !__ASSEMBLY__ */
+
+#ifdef CONFIG_ARC_HAS_ICCM
+#define __arcfp_code __attribute__((__section__(".text.arcfp")))
+#else
+#define __arcfp_code __attribute__((__section__(".text")))
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCCM
+#define __arcfp_data __attribute__((__section__(".data.arcfp")))
+#else
+#define __arcfp_data __attribute__((__section__(".data")))
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif
index f8efade153683fbfc5479694de0e543d0b964937..3f628ca9b71a6b7bb38e7c011e450f53593fea39 100644 (file)
@@ -149,7 +149,7 @@ VECTOR   reserved                ; Reserved Exceptions
 
 ;##################### Scratch Mem for IRQ stack switching #############
 
-       .section .data          ; NOT .global
+ARCFP_DATA int1_saved_reg
        .align 32
        .type   int1_saved_reg, @object
        .size   int1_saved_reg, 4
@@ -159,7 +159,7 @@ int1_saved_reg:
 /* Each Interrupt level needs it's own scratch */
 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 
-       .section .data          ; NOT .global
+ARCFP_DATA int2_saved_reg
        .type   int2_saved_reg, @object
        .size   int2_saved_reg, 4
 int2_saved_reg:
index e25538e29fe769feef0734a9eb42401192ff3277..6cc361c6751afb09d3a598c1c9a997ef0cb9d95e 100644 (file)
@@ -64,6 +64,33 @@ void __init read_arc_build_cfg_regs(void)
        cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
        cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
 
+       /* Note that we read the CCM BCRs independent of kernel config
+        * This is to catch the cases where user doesn't know that
+        * CCMs are present in hardware build
+        */
+       {
+               struct bcr_iccm iccm;
+               struct bcr_dccm dccm;
+               struct bcr_dccm_base dccm_base;
+               unsigned int bcr_32bit_val;
+
+               bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR);
+               if (bcr_32bit_val) {
+                       iccm = *((struct bcr_iccm *)&bcr_32bit_val);
+                       cpu->iccm.base_addr = iccm.base << 16;
+                       cpu->iccm.sz = 0x2000 << (iccm.sz - 1);
+               }
+
+               bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR);
+               if (bcr_32bit_val) {
+                       dccm = *((struct bcr_dccm *)&bcr_32bit_val);
+                       cpu->dccm.sz = 0x800 << (dccm.sz);
+
+                       READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base);
+                       cpu->dccm.base_addr = dccm_base.addr << 8;
+               }
+       }
+
        READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem);
 
        read_decode_mmu_bcr();
@@ -211,6 +238,30 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
        return buf;
 }
 
+void __init arc_chk_ccms(void)
+{
+#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
+       struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+
+#ifdef CONFIG_ARC_HAS_DCCM
+       /*
+        * DCCM can be arbit placed in hardware.
+        * Make sure it's placement/sz matches what Linux is built with
+        */
+       if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr)
+               panic("Linux built with incorrect DCCM Base address\n");
+
+       if (CONFIG_ARC_DCCM_SZ != cpu->dccm.sz)
+               panic("Linux built with incorrect DCCM Size\n");
+#endif
+
+#ifdef CONFIG_ARC_HAS_ICCM
+       if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
+               panic("Linux built with incorrect ICCM Size\n");
+#endif
+#endif
+}
+
 /*
  * Ensure that FP hardware and kernel config match
  * -If hardware contains DPFP, kernel needs to save/restore FPU state
@@ -255,7 +306,7 @@ void __init setup_processor(void)
 
        arc_mmu_init();
        arc_cache_init();
-
+       arc_chk_ccms();
 
        printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
 
index 303ea01c85c8e5fd5d53f1e7da932da9897240e6..8d3b0d447498d6d236dfb95c079b606c6a41e461 100644 (file)
@@ -23,6 +23,12 @@ jiffies = jiffies_64;
 
 SECTIONS
 {
+       /*
+        * ICCM starts at 0x8000_0000. So if kernel is relocated to some other
+        * address, make sure peripheral at 0x8z doesn't clash with ICCM
+        * Essentially vector is also in ICCM.
+        */
+
        . = CONFIG_LINUX_LINK_BASE;
 
        _int_vec_base_lds = .;
@@ -31,6 +37,13 @@ SECTIONS
                . = ALIGN(PAGE_SIZE);
        }
 
+#ifdef CONFIG_ARC_HAS_ICCM
+       .text.arcfp : {
+               *(.text.arcfp)
+               . = ALIGN(CONFIG_ARC_ICCM_SZ * 1024);
+       }
+#endif
+
        /*
         * The reason for having a seperate subsection .init.ramfs is to
         * prevent objump from including it in kernel dumps
@@ -134,4 +147,12 @@ SECTIONS
        .debug_loc 0 : { *(.debug_loc) }
        .debug_macinfo 0 : { *(.debug_macinfo) }
 
+#ifdef CONFIG_ARC_HAS_DCCM
+       . = CONFIG_ARC_DCCM_BASE;
+       __arc_dccm_base = .;
+       .data.arcfp : {
+               *(.data.arcfp)
+       }
+       . = ALIGN(CONFIG_ARC_DCCM_SZ * 1024);
+#endif
 }
index 4b1ad2d905cae426fbafa957c8fe0055278004a3..9df765dc7c3abb56755cac6591aa5765ca155587 100644 (file)
@@ -53,8 +53,7 @@
 ; For details refer to comments before TLBMISS_FREEUP_REGS below
 ;--------------------------------------------------------------------------
 
-       .section .data
-       .global ex_saved_reg1
+ARCFP_DATA ex_saved_reg1
        .align 1 << L1_CACHE_SHIFT      ; IMP: Must be Cache Line aligned
        .type   ex_saved_reg1, @object
 #ifdef CONFIG_SMP
@@ -255,7 +254,7 @@ ex_saved_reg1:
 #endif
 .endm
 
-.section .text, "ax",@progbits ;Fast Path Code, candidate for ICCM
+ARCFP_CODE     ;Fast Path Code, candidate for ICCM
 
 ;-----------------------------------------------------------------------------
 ; I-TLB Miss Exception Handler