ASUS TF300T device may not work properly if firmware is asked to fully re-initialize L2 cache after resume from LP2 suspend. The downstream kernel of TF300T uses different opcode to enable cache after resuming from LP2, this opcode also works fine on Nexus 7 and Ouya devices. Supposedly, this may be needed by an older firmware versions.
Unified · Split
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | #define TF_CACHE_ENABLE 1 | 20 | #define TF_CACHE_ENABLE 1 |
| 21 | #define TF_CACHE_DISABLE 2 | 21 | #define TF_CACHE_DISABLE 2 |
| 22 | #define TF_CACHE_REENABLE 4 | ||
| 22 | 23 | ||
| 23 | #define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200 | 24 | #define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200 |
| 24 | 25 | ||
| @@ -29,6 +30,7 @@ · 4 unmodified lines | |||
| 29 | #define TF_CPU_PM_S1 0xffffffe4 | 30 | #define TF_CPU_PM_S1 0xffffffe4 |
| 30 | #define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7 | 31 | #define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7 |
| 31 | 32 | ||
| 33 | static unsigned long tf_idle_mode = TF_PM_MODE_NONE; | ||
| 32 | static unsigned long cpu_boot_addr; | 34 | static unsigned long cpu_boot_addr; |
| 33 | 35 | ||
| 34 | static void tf_generic_smc(u32 type, u32 arg1, u32 arg2) | 36 | static void tf_generic_smc(u32 type, u32 arg1, u32 arg2) |
| @@ -85,25 +87,40 @@ static int tf_prepare_idle(unsigned long mode) · 50 unmodified lines | |||
| 85 | cpu_boot_addr); | 87 | cpu_boot_addr); |
| 86 | break; | 88 | break; |
| 87 | 89 | ||
| 90 | case TF_PM_MODE_NONE: | ||
| 91 | break; | ||
| 92 | |||
| 88 | default: | 93 | default: |
| 89 | return -EINVAL; | 94 | return -EINVAL; |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 97 | tf_idle_mode = mode; | ||
| 98 | |||
| 92 | return 0; | 99 | return 0; |
| 93 | } | 100 | } |
| 94 | 101 | ||
| 95 | #ifdef CONFIG_CACHE_L2X0 | 102 | #ifdef CONFIG_CACHE_L2X0 |
| 96 | static void tf_cache_write_sec(unsigned long val, unsigned int reg) | 103 | static void tf_cache_write_sec(unsigned long val, unsigned int reg) |
| 97 | { | 104 | { |
| 98 | u32 l2x0_way_mask = 0xff; | 105 | u32 enable_op, l2x0_way_mask = 0xff; |
| 99 | 106 | ||
| 100 | switch (reg) { | 107 | switch (reg) { |
| 101 | case L2X0_CTRL: | 108 | case L2X0_CTRL: |
| 102 | if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16) | 109 | if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16) |
| 103 | l2x0_way_mask = 0xffff; | 110 | l2x0_way_mask = 0xffff; |
| 104 | 111 | ||
| 112 | switch (tf_idle_mode) { | ||
| 113 | case TF_PM_MODE_LP2: | ||
| 114 | enable_op = TF_CACHE_REENABLE; | ||
| 115 | break; | ||
| 116 | |||
| 117 | default: | ||
| 118 | enable_op = TF_CACHE_ENABLE; | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | |||
| 105 | if (val == L2X0_CTRL_EN) | 122 | if (val == L2X0_CTRL_EN) |
| 106 | tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE, | 123 | tf_generic_smc(TF_CACHE_MAINT, enable_op, |
| 107 | l2x0_saved_regs.aux_ctrl); | 124 | l2x0_saved_regs.aux_ctrl); |
| 108 | else | 125 | else |
| 109 | tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE, | 126 | tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE, |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #define TF_PM_MODE_LP1_NO_MC_CLK 2 | 32 | #define TF_PM_MODE_LP1_NO_MC_CLK 2 |
| 33 | #define TF_PM_MODE_LP2 3 | 33 | #define TF_PM_MODE_LP2 3 |
| 34 | #define TF_PM_MODE_LP2_NOFLUSH_L2 4 | 34 | #define TF_PM_MODE_LP2_NOFLUSH_L2 4 |
| 35 | #define TF_PM_MODE_NONE 5 | ||
| 35 | 36 | ||
| 36 | struct trusted_foundations_platform_data { | 37 | struct trusted_foundations_platform_data { |
| 37 | unsigned int version_major; | 38 | unsigned int version_major; |