aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-01-23 17:57:23 -0500
committerOlof Johansson <olof@lixom.net>2015-01-23 17:57:23 -0500
commit9b865d9b5cdaa3fab78f11421243da863d6ee66a (patch)
tree5f6d052e150532f9ff5e29f57e3a6245e88aa223
parent82483ad67e965f6edd61c6c2cdb4ba295cf0af96 (diff)
parentf5d3af9d21f9790ac078276e6c103871c12a3daa (diff)
Merge tag 'qcom-soc-for-3.20-2' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom into next/soc
merge "qcom SoC changes for v3.20-2" from Kumar Gala: Qualcomm ARM Based SoC Updates for v3.20-2 * Various bug fixes and minor feature additions to scm code * Added big-endian support to debug MSM uart * Added big-endian support to ARCH_QCOM * Cleaned up some Kconfig options associated with ARCH_QCOM * Added Andy Gross as co-maintainer * tag 'qcom-soc-for-3.20-2' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom: MAINTAINERS: Add co-maintainer for ARM/Qualcomm Support ARM: qcom: Drop unnecessary selects from ARCH_QCOM ARM: qcom: Fix SCM interface for big-endian kernels ARM: qcom: scm: Clarify boot interface ARM: qcom: Add SCM warmboot flags for quad core targets. ARM: qcom: scm: Add logging of actual return code from scm call ARM: qcom: scm: Flush the command buffer only instead of the entire cache ARM: qcom: scm: Get cacheline size from CTR ARM: qcom: scm: Fix incorrect cache invalidation ARM: qcom: Select ARCH_SUPPORTS_BIG_ENDIAN ARM: debug: msm: Support big-endian CPUs ARM: debug: Update MSM and QCOM DEBUG_LL help Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/arm/Kconfig.debug5
-rw-r--r--arch/arm/include/debug/msm.S6
-rw-r--r--arch/arm/mach-qcom/Kconfig3
-rw-r--r--arch/arm/mach-qcom/scm-boot.c10
-rw-r--r--arch/arm/mach-qcom/scm-boot.h4
-rw-r--r--arch/arm/mach-qcom/scm.c85
7 files changed, 77 insertions, 39 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c25979a3c43..a087a6ddce36 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1291,10 +1291,13 @@ S: Maintained
1291 1291
1292ARM/QUALCOMM SUPPORT 1292ARM/QUALCOMM SUPPORT
1293M: Kumar Gala <galak@codeaurora.org> 1293M: Kumar Gala <galak@codeaurora.org>
1294M: Andy Gross <agross@codeaurora.org>
1294M: David Brown <davidb@codeaurora.org> 1295M: David Brown <davidb@codeaurora.org>
1295L: linux-arm-msm@vger.kernel.org 1296L: linux-arm-msm@vger.kernel.org
1297L: linux-soc@vger.kernel.org
1296S: Maintained 1298S: Maintained
1297F: arch/arm/mach-qcom/ 1299F: arch/arm/mach-qcom/
1300F: drivers/soc/qcom/
1298T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git 1301T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
1299 1302
1300ARM/RADISYS ENP2611 MACHINE SUPPORT 1303ARM/RADISYS ENP2611 MACHINE SUPPORT
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index e902cedbb2dc..74a873ad493f 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -438,7 +438,7 @@ choice
438 Say Y here if you want the debug print routines to direct 438 Say Y here if you want the debug print routines to direct
439 their output to the serial port on MSM devices. 439 their output to the serial port on MSM devices.
440 440
441 ARCH DEBUG_UART_PHYS DEBUG_UART_BASE # 441 ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT #
442 MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1 442 MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1
443 MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2 443 MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2
444 MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3 444 MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3
@@ -457,7 +457,8 @@ choice
457 Say Y here if you want the debug print routines to direct 457 Say Y here if you want the debug print routines to direct
458 their output to the serial port on Qualcomm devices. 458 their output to the serial port on Qualcomm devices.
459 459
460 ARCH DEBUG_UART_PHYS DEBUG_UART_BASE 460 ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT
461 APQ8064 0x16640000 0xf0040000
461 APQ8084 0xf995e000 0xfa75e000 462 APQ8084 0xf995e000 0xfa75e000
462 MSM8X60 0x19c40000 0xf0040000 463 MSM8X60 0x19c40000 0xf0040000
463 MSM8960 0x16440000 0xf0040000 464 MSM8960 0x16440000 0xf0040000
diff --git a/arch/arm/include/debug/msm.S b/arch/arm/include/debug/msm.S
index 9ef57612811d..e55a9426b496 100644
--- a/arch/arm/include/debug/msm.S
+++ b/arch/arm/include/debug/msm.S
@@ -23,6 +23,7 @@
23 .endm 23 .endm
24 24
25 .macro senduart, rd, rx 25 .macro senduart, rd, rx
26ARM_BE8(rev \rd, \rd )
26#ifdef CONFIG_DEBUG_QCOM_UARTDM 27#ifdef CONFIG_DEBUG_QCOM_UARTDM
27 @ Write the 1 character to UARTDM_TF 28 @ Write the 1 character to UARTDM_TF
28 str \rd, [\rx, #0x70] 29 str \rd, [\rx, #0x70]
@@ -35,24 +36,29 @@
35#ifdef CONFIG_DEBUG_QCOM_UARTDM 36#ifdef CONFIG_DEBUG_QCOM_UARTDM
36 @ check for TX_EMT in UARTDM_SR 37 @ check for TX_EMT in UARTDM_SR
37 ldr \rd, [\rx, #0x08] 38 ldr \rd, [\rx, #0x08]
39ARM_BE8(rev \rd, \rd )
38 tst \rd, #0x08 40 tst \rd, #0x08
39 bne 1002f 41 bne 1002f
40 @ wait for TXREADY in UARTDM_ISR 42 @ wait for TXREADY in UARTDM_ISR
411001: ldr \rd, [\rx, #0x14] 431001: ldr \rd, [\rx, #0x14]
44ARM_BE8(rev \rd, \rd )
42 tst \rd, #0x80 45 tst \rd, #0x80
43 beq 1001b 46 beq 1001b
441002: 471002:
45 @ Clear TX_READY by writing to the UARTDM_CR register 48 @ Clear TX_READY by writing to the UARTDM_CR register
46 mov \rd, #0x300 49 mov \rd, #0x300
50ARM_BE8(rev \rd, \rd )
47 str \rd, [\rx, #0x10] 51 str \rd, [\rx, #0x10]
48 @ Write 0x1 to NCF register 52 @ Write 0x1 to NCF register
49 mov \rd, #0x1 53 mov \rd, #0x1
54ARM_BE8(rev \rd, \rd )
50 str \rd, [\rx, #0x40] 55 str \rd, [\rx, #0x40]
51 @ UARTDM reg. Read to induce delay 56 @ UARTDM reg. Read to induce delay
52 ldr \rd, [\rx, #0x08] 57 ldr \rd, [\rx, #0x08]
53#else 58#else
54 @ wait for TX_READY 59 @ wait for TX_READY
551001: ldr \rd, [\rx, #0x08] 601001: ldr \rd, [\rx, #0x08]
61ARM_BE8(rev \rd, \rd )
56 tst \rd, #0x04 62 tst \rd, #0x04
57 beq 1001b 63 beq 1001b
58#endif 64#endif
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index ee5697ba05bc..48003ea652b9 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -1,9 +1,8 @@
1menuconfig ARCH_QCOM 1menuconfig ARCH_QCOM
2 bool "Qualcomm Support" if ARCH_MULTI_V7 2 bool "Qualcomm Support" if ARCH_MULTI_V7
3 select ARCH_REQUIRE_GPIOLIB 3 select ARCH_SUPPORTS_BIG_ENDIAN
4 select ARM_GIC 4 select ARM_GIC
5 select ARM_AMBA 5 select ARM_AMBA
6 select CLKSRC_OF
7 select PINCTRL 6 select PINCTRL
8 select QCOM_SCM if SMP 7 select QCOM_SCM if SMP
9 help 8 help
diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c
index 45cee3e469a5..e8ff7beb6218 100644
--- a/arch/arm/mach-qcom/scm-boot.c
+++ b/arch/arm/mach-qcom/scm-boot.c
@@ -24,15 +24,15 @@
24/* 24/*
25 * Set the cold/warm boot address for one of the CPU cores. 25 * Set the cold/warm boot address for one of the CPU cores.
26 */ 26 */
27int scm_set_boot_addr(phys_addr_t addr, int flags) 27int scm_set_boot_addr(u32 addr, int flags)
28{ 28{
29 struct { 29 struct {
30 unsigned int flags; 30 __le32 flags;
31 phys_addr_t addr; 31 __le32 addr;
32 } cmd; 32 } cmd;
33 33
34 cmd.addr = addr; 34 cmd.addr = cpu_to_le32(addr);
35 cmd.flags = flags; 35 cmd.flags = cpu_to_le32(flags);
36 return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, 36 return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
37 &cmd, sizeof(cmd), NULL, 0); 37 &cmd, sizeof(cmd), NULL, 0);
38} 38}
diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h
index 6aabb2428176..3e210fb818bb 100644
--- a/arch/arm/mach-qcom/scm-boot.h
+++ b/arch/arm/mach-qcom/scm-boot.h
@@ -18,7 +18,9 @@
18#define SCM_FLAG_COLDBOOT_CPU3 0x20 18#define SCM_FLAG_COLDBOOT_CPU3 0x20
19#define SCM_FLAG_WARMBOOT_CPU0 0x04 19#define SCM_FLAG_WARMBOOT_CPU0 0x04
20#define SCM_FLAG_WARMBOOT_CPU1 0x02 20#define SCM_FLAG_WARMBOOT_CPU1 0x02
21#define SCM_FLAG_WARMBOOT_CPU2 0x10
22#define SCM_FLAG_WARMBOOT_CPU3 0x40
21 23
22int scm_set_boot_addr(phys_addr_t addr, int flags); 24int scm_set_boot_addr(u32 addr, int flags);
23 25
24#endif 26#endif
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
index c536fd6bf827..1d9cf18c7091 100644
--- a/arch/arm/mach-qcom/scm.c
+++ b/arch/arm/mach-qcom/scm.c
@@ -22,13 +22,11 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/err.h> 23#include <linux/err.h>
24 24
25#include <asm/outercache.h>
25#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
26 27
27#include "scm.h" 28#include "scm.h"
28 29
29/* Cache line size for msm8x60 */
30#define CACHELINESIZE 32
31
32#define SCM_ENOMEM -5 30#define SCM_ENOMEM -5
33#define SCM_EOPNOTSUPP -4 31#define SCM_EOPNOTSUPP -4
34#define SCM_EINVAL_ADDR -3 32#define SCM_EINVAL_ADDR -3
@@ -63,11 +61,11 @@ static DEFINE_MUTEX(scm_lock);
63 * to access the buffers in a safe manner. 61 * to access the buffers in a safe manner.
64 */ 62 */
65struct scm_command { 63struct scm_command {
66 u32 len; 64 __le32 len;
67 u32 buf_offset; 65 __le32 buf_offset;
68 u32 resp_hdr_offset; 66 __le32 resp_hdr_offset;
69 u32 id; 67 __le32 id;
70 u32 buf[0]; 68 __le32 buf[0];
71}; 69};
72 70
73/** 71/**
@@ -77,9 +75,9 @@ struct scm_command {
77 * @is_complete: indicates if the command has finished processing 75 * @is_complete: indicates if the command has finished processing
78 */ 76 */
79struct scm_response { 77struct scm_response {
80 u32 len; 78 __le32 len;
81 u32 buf_offset; 79 __le32 buf_offset;
82 u32 is_complete; 80 __le32 is_complete;
83}; 81};
84 82
85/** 83/**
@@ -97,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
97 struct scm_command *cmd; 95 struct scm_command *cmd;
98 size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + 96 size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
99 resp_size; 97 resp_size;
98 u32 offset;
100 99
101 cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); 100 cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
102 if (cmd) { 101 if (cmd) {
103 cmd->len = len; 102 cmd->len = cpu_to_le32(len);
104 cmd->buf_offset = offsetof(struct scm_command, buf); 103 offset = offsetof(struct scm_command, buf);
105 cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; 104 cmd->buf_offset = cpu_to_le32(offset);
105 cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
106 } 106 }
107 return cmd; 107 return cmd;
108} 108}
@@ -127,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd)
127static inline struct scm_response *scm_command_to_response( 127static inline struct scm_response *scm_command_to_response(
128 const struct scm_command *cmd) 128 const struct scm_command *cmd)
129{ 129{
130 return (void *)cmd + cmd->resp_hdr_offset; 130 return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
131} 131}
132 132
133/** 133/**
@@ -149,11 +149,12 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd)
149 */ 149 */
150static inline void *scm_get_response_buffer(const struct scm_response *rsp) 150static inline void *scm_get_response_buffer(const struct scm_response *rsp)
151{ 151{
152 return (void *)rsp + rsp->buf_offset; 152 return (void *)rsp + le32_to_cpu(rsp->buf_offset);
153} 153}
154 154
155static int scm_remap_error(int err) 155static int scm_remap_error(int err)
156{ 156{
157 pr_err("scm_call failed with error code %d\n", err);
157 switch (err) { 158 switch (err) {
158 case SCM_ERROR: 159 case SCM_ERROR:
159 return -EIO; 160 return -EIO;
@@ -198,11 +199,12 @@ static int __scm_call(const struct scm_command *cmd)
198 u32 cmd_addr = virt_to_phys(cmd); 199 u32 cmd_addr = virt_to_phys(cmd);
199 200
200 /* 201 /*
201 * Flush the entire cache here so callers don't have to remember 202 * Flush the command buffer so that the secure world sees
202 * to flush the cache when passing physical addresses to the secure 203 * the correct data.
203 * side in the buffer.
204 */ 204 */
205 flush_cache_all(); 205 __cpuc_flush_dcache_area((void *)cmd, cmd->len);
206 outer_flush_range(cmd_addr, cmd_addr + cmd->len);
207
206 ret = smc(cmd_addr); 208 ret = smc(cmd_addr);
207 if (ret < 0) 209 if (ret < 0)
208 ret = scm_remap_error(ret); 210 ret = scm_remap_error(ret);
@@ -210,6 +212,25 @@ static int __scm_call(const struct scm_command *cmd)
210 return ret; 212 return ret;
211} 213}
212 214
215static void scm_inv_range(unsigned long start, unsigned long end)
216{
217 u32 cacheline_size, ctr;
218
219 asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
220 cacheline_size = 4 << ((ctr >> 16) & 0xf);
221
222 start = round_down(start, cacheline_size);
223 end = round_up(end, cacheline_size);
224 outer_inv_range(start, end);
225 while (start < end) {
226 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
227 : "memory");
228 start += cacheline_size;
229 }
230 dsb();
231 isb();
232}
233
213/** 234/**
214 * scm_call() - Send an SCM command 235 * scm_call() - Send an SCM command
215 * @svc_id: service identifier 236 * @svc_id: service identifier
@@ -220,6 +241,13 @@ static int __scm_call(const struct scm_command *cmd)
220 * @resp_len: length of the response buffer 241 * @resp_len: length of the response buffer
221 * 242 *
222 * Sends a command to the SCM and waits for the command to finish processing. 243 * Sends a command to the SCM and waits for the command to finish processing.
244 *
245 * A note on cache maintenance:
246 * Note that any buffers that are expected to be accessed by the secure world
247 * must be flushed before invoking scm_call and invalidated in the cache
248 * immediately after scm_call returns. Cache maintenance on the command and
249 * response buffers is taken care of by scm_call; however, callers are
250 * responsible for any other cached buffers passed over to the secure world.
223 */ 251 */
224int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, 252int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
225 void *resp_buf, size_t resp_len) 253 void *resp_buf, size_t resp_len)
@@ -227,12 +255,13 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
227 int ret; 255 int ret;
228 struct scm_command *cmd; 256 struct scm_command *cmd;
229 struct scm_response *rsp; 257 struct scm_response *rsp;
258 unsigned long start, end;
230 259
231 cmd = alloc_scm_command(cmd_len, resp_len); 260 cmd = alloc_scm_command(cmd_len, resp_len);
232 if (!cmd) 261 if (!cmd)
233 return -ENOMEM; 262 return -ENOMEM;
234 263
235 cmd->id = (svc_id << 10) | cmd_id; 264 cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
236 if (cmd_buf) 265 if (cmd_buf)
237 memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); 266 memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
238 267
@@ -243,17 +272,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
243 goto out; 272 goto out;
244 273
245 rsp = scm_command_to_response(cmd); 274 rsp = scm_command_to_response(cmd);
275 start = (unsigned long)rsp;
276
246 do { 277 do {
247 u32 start = (u32)rsp; 278 scm_inv_range(start, start + sizeof(*rsp));
248 u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
249 start &= ~(CACHELINESIZE - 1);
250 while (start < end) {
251 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
252 : "memory");
253 start += CACHELINESIZE;
254 }
255 } while (!rsp->is_complete); 279 } while (!rsp->is_complete);
256 280
281 end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
282 scm_inv_range(start, end);
283
257 if (resp_buf) 284 if (resp_buf)
258 memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); 285 memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
259out: 286out: