Commit 33eee330cc8a445ff05f39a58af3c87324798230

Authored by Scott Wood
Committed by Andy Fleming
1 parent 3e978f5dc8

powerpc/fsl-corenet: work around erratum A004510

Erratum A004510 says that under certain load conditions, modified
cache lines can be discarded, causing data corruption.

To work around this, several CCSR and DCSR register updates need to be
made in a careful manner, so that there is no other transaction in
corenet when the update is made.

The update is made from a locked cacheline, with a delay before to flush
any previous activity, and a delay after to flush the CCSR/DCSR update.
We can't use a readback because that would be another corenet
transaction, which is not allowed.

We lock the subsequent cacheline to prevent it from being fetched while
we're executing the previous cacheline.  It is filled with nops so that a
branch doesn't cause us to fetch another cacheline.

Ordinarily we are running in a cache-inhibited mapping at this point, so
we temporarily change that.  We make it guarded so that we should never
see a speculative load, and we never do an explicit load.  Thus, only the
I-cache should ever fill from this mapping, and we flush/unlock it
afterward.  Thus we should avoid problems from any potential cache
aliasing between inhibited and non-inhibited mappings.

NOTE that if PAMU is used with this patch, it will need to use a
dedicated LAW as described in the erratum.  This is the responsibility
of the OS that sets up PAMU.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>

Showing 6 changed files with 355 additions and 0 deletions Side-by-side Diff

... ... @@ -383,6 +383,31 @@
383 383 symbol should be set to the TLB1 entry to be used for this
384 384 purpose.
385 385  
  386 + CONFIG_SYS_FSL_ERRATUM_A004510
  387 +
  388 + Enables a workaround for erratum A004510. If set,
  389 + then CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV and
  390 + CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY must be set.
  391 +
  392 + CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
  393 + CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 (optional)
  394 +
  395 + Defines one or two SoC revisions (low 8 bits of SVR)
  396 + for which the A004510 workaround should be applied.
  397 +
  398 + The rest of SVR is either not relevant to the decision
  399 + of whether the erratum is present (e.g. p2040 versus
  400 + p2041) or is implied by the build target, which controls
  401 + whether CONFIG_SYS_FSL_ERRATUM_A004510 is set.
  402 +
  403 + See Freescale App Note 4493 for more information about
  404 + this erratum.
  405 +
  406 + CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
  407 +
  408 + This is the value to write into CCSR offset 0x18600
  409 + according to the A004510 workaround.
  410 +
386 411 - Generic CPU options:
387 412 CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
388 413  
arch/powerpc/cpu/mpc85xx/cmd_errata.c
... ... @@ -124,6 +124,9 @@
124 124 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
125 125 puts("Work-around for Erratum NMG ETSEC129 enabled\n");
126 126 #endif
  127 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
  128 + puts("Work-around for Erratum A004510 enabled\n");
  129 +#endif
127 130 return 0;
128 131 }
129 132  
arch/powerpc/cpu/mpc85xx/release.S
... ... @@ -74,6 +74,33 @@
74 74 mtspr 977,r3
75 75 #endif
76 76  
  77 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
  78 + mfspr r3,SPRN_SVR
  79 + rlwinm r3,r3,0,0xff
  80 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
  81 + cmpw r3,r4
  82 + beq 1f
  83 +
  84 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
  85 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
  86 + cmpw r3,r4
  87 + beq 1f
  88 +#endif
  89 +
  90 + /* Not a supported revision affected by erratum */
  91 + b 2f
  92 +
  93 +1: /* Erratum says set bits 55:60 to 001001 */
  94 + msync
  95 + isync
  96 + mfspr r3,976
  97 + li r4,0x48
  98 + rlwimi r3,r4,0,0x1f8
  99 + mtspr 976,r3
  100 + isync
  101 +2:
  102 +#endif
  103 +
77 104 /* Enable branch prediction */
78 105 lis r3,BUCSR_ENABLE@h
79 106 ori r3,r3,BUCSR_ENABLE@l
arch/powerpc/cpu/mpc85xx/start.S
... ... @@ -86,6 +86,35 @@
86 86 li r1,MSR_DE
87 87 mtmsr r1
88 88  
  89 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
  90 + mfspr r3,SPRN_SVR
  91 + rlwinm r3,r3,0,0xff
  92 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
  93 + cmpw r3,r4
  94 + beq 1f
  95 +
  96 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
  97 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
  98 + cmpw r3,r4
  99 + beq 1f
  100 +#endif
  101 +
  102 + /* Not a supported revision affected by erratum */
  103 + li r27,0
  104 + b 2f
  105 +
  106 +1: li r27,1 /* Remember for later that we have the erratum */
  107 + /* Erratum says set bits 55:60 to 001001 */
  108 + msync
  109 + isync
  110 + mfspr r3,976
  111 + li r4,0x48
  112 + rlwimi r3,r4,0,0x1f8
  113 + mtspr 976,r3
  114 + isync
  115 +2:
  116 +#endif
  117 +
89 118 #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500MC)
90 119 /* ISBC uses L2 as stack.
91 120 * Disable L2 cache here so that u-boot can enable it later
... ... @@ -440,6 +469,14 @@
440 469 mfspr r2, MAS2
441 470 andc r2, r2, r3
442 471 or r2, r2, r1
  472 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
  473 + cmpwi r27,0
  474 + beq 1f
  475 + andi. r15, r2, MAS2_I|MAS2_G /* save the old I/G for later */
  476 + rlwinm r2, r2, 0, ~MAS2_I
  477 + ori r2, r2, MAS2_G
  478 +1:
  479 +#endif
443 480 mtspr MAS2, r2 /* Set the EPN to our PC base address */
444 481  
445 482 mfspr r2, MAS3
... ... @@ -718,6 +755,253 @@
718 755 msync
719 756 tlbwe
720 757 #endif /* #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS) */
  758 +
  759 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
  760 +#define DCSR_LAWBARH0 (CONFIG_SYS_CCSRBAR + 0x1000)
  761 +#define LAW_SIZE_1M 0x13
  762 +#define DCSRBAR_LAWAR (LAW_EN | (0x1d << 20) | LAW_SIZE_1M)
  763 +
  764 + cmpwi r27,0
  765 + beq 9f
  766 +
  767 + /*
  768 + * Create a TLB entry for CCSR
  769 + *
  770 + * We're executing out of TLB1 entry in r14, and that's the only
  771 + * TLB entry that exists. To allocate some TLB entries for our
  772 + * own use, flip a bit high enough that we won't flip it again
  773 + * via incrementing.
  774 + */
  775 +
  776 + xori r8, r14, 32
  777 + lis r0, MAS0_TLBSEL(1)@h
  778 + rlwimi r0, r8, 16, MAS0_ESEL_MSK
  779 + lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@h
  780 + ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@l
  781 + lis r7, CONFIG_SYS_CCSRBAR@h
  782 + ori r7, r7, CONFIG_SYS_CCSRBAR@l
  783 + ori r2, r7, MAS2_I|MAS2_G
  784 + lis r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@h
  785 + ori r3, r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@l
  786 + lis r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
  787 + ori r4, r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
  788 + mtspr MAS0, r0
  789 + mtspr MAS1, r1
  790 + mtspr MAS2, r2
  791 + mtspr MAS3, r3
  792 + mtspr MAS7, r4
  793 + isync
  794 + tlbwe
  795 + isync
  796 + msync
  797 +
  798 + /* Map DCSR temporarily to physical address zero */
  799 + li r0, 0
  800 + lis r3, DCSRBAR_LAWAR@h
  801 + ori r3, r3, DCSRBAR_LAWAR@l
  802 +
  803 + stw r0, 0xc00(r7) /* LAWBARH0 */
  804 + stw r0, 0xc04(r7) /* LAWBARL0 */
  805 + sync
  806 + stw r3, 0xc08(r7) /* LAWAR0 */
  807 +
  808 + /* Read back from LAWAR to ensure the update is complete. */
  809 + lwz r3, 0xc08(r7) /* LAWAR0 */
  810 + isync
  811 +
  812 + /* Create a TLB entry for DCSR at zero */
  813 +
  814 + addi r9, r8, 1
  815 + lis r0, MAS0_TLBSEL(1)@h
  816 + rlwimi r0, r9, 16, MAS0_ESEL_MSK
  817 + lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@h
  818 + ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@l
  819 + li r6, 0 /* DCSR effective address */
  820 + ori r2, r6, MAS2_I|MAS2_G
  821 + li r3, MAS3_SW|MAS3_SR
  822 + li r4, 0
  823 + mtspr MAS0, r0
  824 + mtspr MAS1, r1
  825 + mtspr MAS2, r2
  826 + mtspr MAS3, r3
  827 + mtspr MAS7, r4
  828 + isync
  829 + tlbwe
  830 + isync
  831 + msync
  832 +
  833 + /* enable the timebase */
  834 +#define CTBENR 0xe2084
  835 + li r3, 1
  836 + addis r4, r7, CTBENR@ha
  837 + stw r3, CTBENR@l(r4)
  838 + lwz r3, CTBENR@l(r4)
  839 + twi 0,r3,0
  840 + isync
  841 +
  842 + .macro erratum_set_ccsr offset value
  843 + addis r3, r7, \offset@ha
  844 + lis r4, \value@h
  845 + addi r3, r3, \offset@l
  846 + ori r4, r4, \value@l
  847 + bl erratum_set_value
  848 + .endm
  849 +
  850 + .macro erratum_set_dcsr offset value
  851 + addis r3, r6, \offset@ha
  852 + lis r4, \value@h
  853 + addi r3, r3, \offset@l
  854 + ori r4, r4, \value@l
  855 + bl erratum_set_value
  856 + .endm
  857 +
  858 + erratum_set_dcsr 0xb0e08 0xe0201800
  859 + erratum_set_dcsr 0xb0e18 0xe0201800
  860 + erratum_set_dcsr 0xb0e38 0xe0400000
  861 + erratum_set_dcsr 0xb0008 0x00900000
  862 + erratum_set_dcsr 0xb0e40 0xe00a0000
  863 + erratum_set_ccsr 0x18600 CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
  864 + erratum_set_ccsr 0x10f00 0x415e5000
  865 + erratum_set_ccsr 0x11f00 0x415e5000
  866 +
  867 + /* Make temp mapping uncacheable again, if it was initially */
  868 + bl 2f
  869 +2: mflr r3
  870 + tlbsx 0, r3
  871 + mfspr r4, MAS2
  872 + rlwimi r4, r15, 0, MAS2_I
  873 + rlwimi r4, r15, 0, MAS2_G
  874 + mtspr MAS2, r4
  875 + isync
  876 + tlbwe
  877 + isync
  878 + msync
  879 +
  880 + /* Clear the cache */
  881 + lis r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
  882 + ori r3,r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
  883 + sync
  884 + isync
  885 + mtspr SPRN_L1CSR1,r3
  886 + isync
  887 +2: sync
  888 + mfspr r4,SPRN_L1CSR1
  889 + and. r4,r4,r3
  890 + bne 2b
  891 +
  892 + lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
  893 + ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
  894 + sync
  895 + isync
  896 + mtspr SPRN_L1CSR1,r3
  897 + isync
  898 +2: sync
  899 + mfspr r4,SPRN_L1CSR1
  900 + and. r4,r4,r3
  901 + beq 2b
  902 +
  903 + /* Remove temporary mappings */
  904 + lis r0, MAS0_TLBSEL(1)@h
  905 + rlwimi r0, r9, 16, MAS0_ESEL_MSK
  906 + li r3, 0
  907 + mtspr MAS0, r0
  908 + mtspr MAS1, r3
  909 + isync
  910 + tlbwe
  911 + isync
  912 + msync
  913 +
  914 + li r3, 0
  915 + stw r3, 0xc08(r7) /* LAWAR0 */
  916 + lwz r3, 0xc08(r7)
  917 + isync
  918 +
  919 + lis r0, MAS0_TLBSEL(1)@h
  920 + rlwimi r0, r8, 16, MAS0_ESEL_MSK
  921 + li r3, 0
  922 + mtspr MAS0, r0
  923 + mtspr MAS1, r3
  924 + isync
  925 + tlbwe
  926 + isync
  927 + msync
  928 +
  929 + b 9f
  930 +
  931 + /* r3 = addr, r4 = value, clobbers r5, r11, r12 */
  932 +erratum_set_value:
  933 + /* Lock two cache lines into I-Cache */
  934 + sync
  935 + mfspr r11, SPRN_L1CSR1
  936 + rlwinm r11, r11, 0, ~L1CSR1_ICUL
  937 + sync
  938 + isync
  939 + mtspr SPRN_L1CSR1, r11
  940 + isync
  941 +
  942 + mflr r12
  943 + bl 5f
  944 +5: mflr r5
  945 + addi r5, r5, 2f - 5b
  946 + icbtls 0, 0, r5
  947 + addi r5, r5, 64
  948 +
  949 + sync
  950 + mfspr r11, SPRN_L1CSR1
  951 +3: andi. r11, r11, L1CSR1_ICUL
  952 + bne 3b
  953 +
  954 + icbtls 0, 0, r5
  955 + addi r5, r5, 64
  956 +
  957 + sync
  958 + mfspr r11, SPRN_L1CSR1
  959 +3: andi. r11, r11, L1CSR1_ICUL
  960 + bne 3b
  961 +
  962 + b 2f
  963 + .align 6
  964 + /* Inside a locked cacheline, wait a while, write, then wait a while */
  965 +2: sync
  966 +
  967 + mfspr r5, SPRN_TBRL
  968 + addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */
  969 +4: mfspr r5, SPRN_TBRL
  970 + subf. r5, r5, r11
  971 + bgt 4b
  972 +
  973 + stw r4, 0(r3)
  974 +
  975 + mfspr r5, SPRN_TBRL
  976 + addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */
  977 +4: mfspr r5, SPRN_TBRL
  978 + subf. r5, r5, r11
  979 + bgt 4b
  980 +
  981 + sync
  982 +
  983 + /*
  984 + * Fill out the rest of this cache line and the next with nops,
  985 + * to ensure that nothing outside the locked area will be
  986 + * fetched due to a branch.
  987 + */
  988 + .rept 19
  989 + nop
  990 + .endr
  991 +
  992 + sync
  993 + mfspr r11, SPRN_L1CSR1
  994 + rlwinm r11, r11, 0, ~L1CSR1_ICUL
  995 + sync
  996 + isync
  997 + mtspr SPRN_L1CSR1, r11
  998 + isync
  999 +
  1000 + mtlr r12
  1001 + blr
  1002 +
  1003 +9:
  1004 +#endif
721 1005  
722 1006 create_init_ram_area:
723 1007 lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
arch/powerpc/include/asm/config_mpc85xx.h
... ... @@ -330,6 +330,10 @@
330 330 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
331 331 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
332 332 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
  333 +#define CONFIG_SYS_FSL_ERRATUM_A004510
  334 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
  335 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 0x11
  336 +#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
333 337  
334 338 #elif defined(CONFIG_PPC_P3041)
335 339 #define CONFIG_MAX_CPUS 4
... ... @@ -355,6 +359,10 @@
355 359 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
356 360 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
357 361 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
  362 +#define CONFIG_SYS_FSL_ERRATUM_A004510
  363 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
  364 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 0x11
  365 +#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
358 366  
359 367 #elif defined(CONFIG_PPC_P4080) /* also supports P4040 */
360 368 #define CONFIG_MAX_CPUS 8
... ... @@ -391,6 +399,9 @@
391 399 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
392 400 #define CONFIG_SYS_FSL_RMU
393 401 #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
  402 +#define CONFIG_SYS_FSL_ERRATUM_A004510
  403 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x20
  404 +#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xff000000
394 405  
395 406 #elif defined(CONFIG_PPC_P5020) /* also supports P5010 */
396 407 #define CONFIG_MAX_CPUS 2
... ... @@ -414,6 +425,9 @@
414 425 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
415 426 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
416 427 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
  428 +#define CONFIG_SYS_FSL_ERRATUM_A004510
  429 +#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
  430 +#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xc0000000
417 431  
418 432 #elif defined(CONFIG_BSC9131)
419 433 #define CONFIG_MAX_CPUS 1
arch/powerpc/include/asm/processor.h
... ... @@ -486,11 +486,13 @@
486 486 #define SPRN_L2CFG0 0x207 /* L2 Cache Configuration Register 0 */
487 487 #define SPRN_L1CSR0 0x3f2 /* L1 Data Cache Control and Status Register 0 */
488 488 #define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
  489 +#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */
489 490 #define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
490 491 #define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
491 492 #define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
492 493 #define SPRN_L1CSR1 0x3f3 /* L1 Instruction Cache Control and Status Register 1 */
493 494 #define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */
  495 +#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */
494 496 #define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
495 497 #define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
496 498 #define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */