diff options
author | Olof Johansson <olof@lixom.net> | 2015-01-23 17:57:23 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-01-23 17:57:23 -0500 |
commit | 9b865d9b5cdaa3fab78f11421243da863d6ee66a (patch) | |
tree | 5f6d052e150532f9ff5e29f57e3a6245e88aa223 | |
parent | 82483ad67e965f6edd61c6c2cdb4ba295cf0af96 (diff) | |
parent | f5d3af9d21f9790ac078276e6c103871c12a3daa (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-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | arch/arm/Kconfig.debug | 5 | ||||
-rw-r--r-- | arch/arm/include/debug/msm.S | 6 | ||||
-rw-r--r-- | arch/arm/mach-qcom/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/mach-qcom/scm-boot.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-qcom/scm-boot.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-qcom/scm.c | 85 |
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 | ||
1292 | ARM/QUALCOMM SUPPORT | 1292 | ARM/QUALCOMM SUPPORT |
1293 | M: Kumar Gala <galak@codeaurora.org> | 1293 | M: Kumar Gala <galak@codeaurora.org> |
1294 | M: Andy Gross <agross@codeaurora.org> | ||
1294 | M: David Brown <davidb@codeaurora.org> | 1295 | M: David Brown <davidb@codeaurora.org> |
1295 | L: linux-arm-msm@vger.kernel.org | 1296 | L: linux-arm-msm@vger.kernel.org |
1297 | L: linux-soc@vger.kernel.org | ||
1296 | S: Maintained | 1298 | S: Maintained |
1297 | F: arch/arm/mach-qcom/ | 1299 | F: arch/arm/mach-qcom/ |
1300 | F: drivers/soc/qcom/ | ||
1298 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git | 1301 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git |
1299 | 1302 | ||
1300 | ARM/RADISYS ENP2611 MACHINE SUPPORT | 1303 | ARM/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 |
26 | ARM_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] |
39 | ARM_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 |
41 | 1001: ldr \rd, [\rx, #0x14] | 43 | 1001: ldr \rd, [\rx, #0x14] |
44 | ARM_BE8(rev \rd, \rd ) | ||
42 | tst \rd, #0x80 | 45 | tst \rd, #0x80 |
43 | beq 1001b | 46 | beq 1001b |
44 | 1002: | 47 | 1002: |
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 |
50 | ARM_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 |
54 | ARM_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 |
55 | 1001: ldr \rd, [\rx, #0x08] | 60 | 1001: ldr \rd, [\rx, #0x08] |
61 | ARM_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 @@ | |||
1 | menuconfig ARCH_QCOM | 1 | menuconfig 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 | */ |
27 | int scm_set_boot_addr(phys_addr_t addr, int flags) | 27 | int 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 | ||
22 | int scm_set_boot_addr(phys_addr_t addr, int flags); | 24 | int 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 | */ |
65 | struct scm_command { | 63 | struct 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 | */ |
79 | struct scm_response { | 77 | struct 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) | |||
127 | static inline struct scm_response *scm_command_to_response( | 127 | static 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 | */ |
150 | static inline void *scm_get_response_buffer(const struct scm_response *rsp) | 150 | static 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 | ||
155 | static int scm_remap_error(int err) | 155 | static 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 | ||
215 | static 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 | */ |
224 | int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, | 252 | int 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); |
259 | out: | 286 | out: |