0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/of.h>
0011
0012 #include <linux/firmware/trusted_foundations.h>
0013
0014 #include <asm/firmware.h>
0015 #include <asm/hardware/cache-l2x0.h>
0016 #include <asm/outercache.h>
0017
0018 #define TF_CACHE_MAINT 0xfffff100
0019
0020 #define TF_CACHE_ENABLE 1
0021 #define TF_CACHE_DISABLE 2
0022 #define TF_CACHE_REENABLE 4
0023
0024 #define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
0025
0026 #define TF_CPU_PM 0xfffffffc
0027 #define TF_CPU_PM_S3 0xffffffe3
0028 #define TF_CPU_PM_S2 0xffffffe6
0029 #define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5
0030 #define TF_CPU_PM_S1 0xffffffe4
0031 #define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7
0032
0033 static unsigned long tf_idle_mode = TF_PM_MODE_NONE;
0034 static unsigned long cpu_boot_addr;
0035
0036 static void tf_generic_smc(u32 type, u32 arg1, u32 arg2)
0037 {
0038 register u32 r0 asm("r0") = type;
0039 register u32 r1 asm("r1") = arg1;
0040 register u32 r2 asm("r2") = arg2;
0041
0042 asm volatile(
0043 ".arch_extension sec\n\t"
0044 "stmfd sp!, {r4 - r11}\n\t"
0045 __asmeq("%0", "r0")
0046 __asmeq("%1", "r1")
0047 __asmeq("%2", "r2")
0048 "mov r3, #0\n\t"
0049 "mov r4, #0\n\t"
0050 "smc #0\n\t"
0051 "ldmfd sp!, {r4 - r11}\n\t"
0052 :
0053 : "r" (r0), "r" (r1), "r" (r2)
0054 : "memory", "r3", "r12", "lr");
0055 }
0056
0057 static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
0058 {
0059 cpu_boot_addr = boot_addr;
0060 tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0);
0061
0062 return 0;
0063 }
0064
0065 static int tf_prepare_idle(unsigned long mode)
0066 {
0067 switch (mode) {
0068 case TF_PM_MODE_LP0:
0069 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr);
0070 break;
0071
0072 case TF_PM_MODE_LP1:
0073 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr);
0074 break;
0075
0076 case TF_PM_MODE_LP1_NO_MC_CLK:
0077 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK,
0078 cpu_boot_addr);
0079 break;
0080
0081 case TF_PM_MODE_LP2:
0082 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr);
0083 break;
0084
0085 case TF_PM_MODE_LP2_NOFLUSH_L2:
0086 tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2,
0087 cpu_boot_addr);
0088 break;
0089
0090 case TF_PM_MODE_NONE:
0091 break;
0092
0093 default:
0094 return -EINVAL;
0095 }
0096
0097 tf_idle_mode = mode;
0098
0099 return 0;
0100 }
0101
0102 #ifdef CONFIG_CACHE_L2X0
0103 static void tf_cache_write_sec(unsigned long val, unsigned int reg)
0104 {
0105 u32 enable_op, l2x0_way_mask = 0xff;
0106
0107 switch (reg) {
0108 case L2X0_CTRL:
0109 if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16)
0110 l2x0_way_mask = 0xffff;
0111
0112 switch (tf_idle_mode) {
0113 case TF_PM_MODE_LP2:
0114 enable_op = TF_CACHE_REENABLE;
0115 break;
0116
0117 default:
0118 enable_op = TF_CACHE_ENABLE;
0119 break;
0120 }
0121
0122 if (val == L2X0_CTRL_EN)
0123 tf_generic_smc(TF_CACHE_MAINT, enable_op,
0124 l2x0_saved_regs.aux_ctrl);
0125 else
0126 tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE,
0127 l2x0_way_mask);
0128 break;
0129
0130 default:
0131 break;
0132 }
0133 }
0134
0135 static int tf_init_cache(void)
0136 {
0137 outer_cache.write_sec = tf_cache_write_sec;
0138
0139 return 0;
0140 }
0141 #endif
0142
0143 static const struct firmware_ops trusted_foundations_ops = {
0144 .set_cpu_boot_addr = tf_set_cpu_boot_addr,
0145 .prepare_idle = tf_prepare_idle,
0146 #ifdef CONFIG_CACHE_L2X0
0147 .l2x0_init = tf_init_cache,
0148 #endif
0149 };
0150
0151 void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
0152 {
0153
0154
0155
0156
0157 register_firmware_ops(&trusted_foundations_ops);
0158 }
0159
0160 void of_register_trusted_foundations(void)
0161 {
0162 struct device_node *node;
0163 struct trusted_foundations_platform_data pdata;
0164 int err;
0165
0166 node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
0167 if (!node)
0168 return;
0169
0170 err = of_property_read_u32(node, "tlm,version-major",
0171 &pdata.version_major);
0172 if (err != 0)
0173 panic("Trusted Foundation: missing version-major property\n");
0174 err = of_property_read_u32(node, "tlm,version-minor",
0175 &pdata.version_minor);
0176 if (err != 0)
0177 panic("Trusted Foundation: missing version-minor property\n");
0178 register_trusted_foundations(&pdata);
0179 }
0180
0181 bool trusted_foundations_registered(void)
0182 {
0183 return firmware_ops == &trusted_foundations_ops;
0184 }