From 30cd65523eeef8c8ce9fff9b900b349341ae5f74 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 5 Sep 2014 15:51:56 -0700 Subject: [PATCH 01/12] ARM: debug: Update MSM and QCOM DEBUG_LL help Add another SoC address for apq8064 and use DEBUG_UART_VIRT instead of DEBUG_UART_BASE because the former actually exists. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/Kconfig.debug | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5ddd4906f7a7..737ec256bcc8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -427,7 +427,7 @@ choice Say Y here if you want the debug print routines to direct their output to the serial port on MSM devices. - ARCH DEBUG_UART_PHYS DEBUG_UART_BASE # + ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT # MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1 MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2 MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3 @@ -446,7 +446,8 @@ choice Say Y here if you want the debug print routines to direct their output to the serial port on Qualcomm devices. - ARCH DEBUG_UART_PHYS DEBUG_UART_BASE + ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT + APQ8064 0x16640000 0xf0040000 APQ8084 0xf995e000 0xfa75e000 MSM8X60 0x19c40000 0xf0040000 MSM8960 0x16440000 0xf0040000 From 9edb4b132f1879a24ac2b4495239175fa13b27fe Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 30 Jun 2014 14:49:39 -0700 Subject: [PATCH 02/12] ARM: debug: msm: Support big-endian CPUs If the CPU is in big-endian mode these macros will access the hardware incorrectly. Reverse thins as necessary to fix this. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/include/debug/msm.S | 6 ++++++ 1 file changed, 6 insertions(+) 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 @@ .endm .macro senduart, rd, rx +ARM_BE8(rev \rd, \rd ) #ifdef CONFIG_DEBUG_QCOM_UARTDM @ Write the 1 character to UARTDM_TF str \rd, [\rx, #0x70] @@ -35,24 +36,29 @@ #ifdef CONFIG_DEBUG_QCOM_UARTDM @ check for TX_EMT in UARTDM_SR ldr \rd, [\rx, #0x08] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x08 bne 1002f @ wait for TXREADY in UARTDM_ISR 1001: ldr \rd, [\rx, #0x14] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x80 beq 1001b 1002: @ Clear TX_READY by writing to the UARTDM_CR register mov \rd, #0x300 +ARM_BE8(rev \rd, \rd ) str \rd, [\rx, #0x10] @ Write 0x1 to NCF register mov \rd, #0x1 +ARM_BE8(rev \rd, \rd ) str \rd, [\rx, #0x40] @ UARTDM reg. Read to induce delay ldr \rd, [\rx, #0x08] #else @ wait for TX_READY 1001: ldr \rd, [\rx, #0x08] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x04 beq 1001b #endif From e5ca0feb860baacd635aa684c72821e640a1dfa6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 22 Sep 2014 14:42:39 -0700 Subject: [PATCH 03/12] ARM: qcom: Select ARCH_SUPPORTS_BIG_ENDIAN We can run qcom platforms in big-endian mode. Select the option. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index ee5697ba05bc..29aa8e1970b0 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -1,6 +1,7 @@ menuconfig ARCH_QCOM bool "Qualcomm Support" if ARCH_MULTI_V7 select ARCH_REQUIRE_GPIOLIB + select ARCH_SUPPORTS_BIG_ENDIAN select ARM_GIC select ARM_AMBA select CLKSRC_OF From f76c6916570d8d24a622f2107ef747531148046e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 4 Aug 2014 18:31:43 -0700 Subject: [PATCH 04/12] ARM: qcom: scm: Fix incorrect cache invalidation The cache invalidation in scm_call() correctly rounds down the start address to invalidate the beginning of the cacheline but doesn't properly round up the 'end' address to make it aligned. The last chunk of the buffer won't be invalidated when 'end' is not cacheline size aligned so make sure to invalidate the last few bytes in such situations. It also doesn't do anything about outer caches so make sure to invalidate and flush those as well. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index c536fd6bf827..820c72165e19 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "scm.h" @@ -203,6 +204,7 @@ static int __scm_call(const struct scm_command *cmd) * side in the buffer. */ flush_cache_all(); + outer_flush_all(); ret = smc(cmd_addr); if (ret < 0) ret = scm_remap_error(ret); @@ -210,6 +212,20 @@ static int __scm_call(const struct scm_command *cmd) return ret; } +static void scm_inv_range(unsigned long start, unsigned long end) +{ + start = round_down(start, CACHELINESIZE); + end = round_up(end, CACHELINESIZE); + outer_inv_range(start, end); + while (start < end) { + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) + : "memory"); + start += CACHELINESIZE; + } + dsb(); + isb(); +} + /** * scm_call() - Send an SCM command * @svc_id: service identifier @@ -227,6 +243,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, int ret; struct scm_command *cmd; struct scm_response *rsp; + unsigned long start, end; cmd = alloc_scm_command(cmd_len, resp_len); if (!cmd) @@ -243,17 +260,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, goto out; rsp = scm_command_to_response(cmd); + start = (unsigned long)rsp; + do { - u32 start = (u32)rsp; - u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; - start &= ~(CACHELINESIZE - 1); - while (start < end) { - asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) - : "memory"); - start += CACHELINESIZE; - } + scm_inv_range(start, start + sizeof(*rsp)); } while (!rsp->is_complete); + end = (unsigned long)scm_get_response_buffer(rsp) + resp_len; + scm_inv_range(start, end); + if (resp_buf) memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); out: From 30cbb0c01bc98a2372966b8c5ac0ce1421cd933c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 4 Aug 2014 18:31:44 -0700 Subject: [PATCH 05/12] ARM: qcom: scm: Get cacheline size from CTR Instead of hardcoding the cacheline size as 32, get the cacheline size from the CTR register. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index 820c72165e19..c08786ebf116 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -27,9 +27,6 @@ #include "scm.h" -/* Cache line size for msm8x60 */ -#define CACHELINESIZE 32 - #define SCM_ENOMEM -5 #define SCM_EOPNOTSUPP -4 #define SCM_EINVAL_ADDR -3 @@ -214,13 +211,18 @@ static int __scm_call(const struct scm_command *cmd) static void scm_inv_range(unsigned long start, unsigned long end) { - start = round_down(start, CACHELINESIZE); - end = round_up(end, CACHELINESIZE); + u32 cacheline_size, ctr; + + asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); + cacheline_size = 4 << ((ctr >> 16) & 0xf); + + start = round_down(start, cacheline_size); + end = round_up(end, cacheline_size); outer_inv_range(start, end); while (start < end) { asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) : "memory"); - start += CACHELINESIZE; + start += cacheline_size; } dsb(); isb(); From 404b5a97f5a2a718bb0feccc3712b1ab88f073d5 Mon Sep 17 00:00:00 2001 From: Vikram Mulukutla Date: Mon, 4 Aug 2014 18:31:45 -0700 Subject: [PATCH 06/12] ARM: qcom: scm: Flush the command buffer only instead of the entire cache scm_call flushes the entire cache before calling into the secure world. This is both a performance penalty as well as insufficient on SMP systems where the CPUs possess a write-back L1 cache. Flush only the command and response buffers instead, moving the responsibility of flushing any other cached buffer (being passed to the secure world) to callers. Signed-off-by: Vikram Mulukutla Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index c08786ebf116..ec37b037e69c 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -196,12 +196,12 @@ static int __scm_call(const struct scm_command *cmd) u32 cmd_addr = virt_to_phys(cmd); /* - * Flush the entire cache here so callers don't have to remember - * to flush the cache when passing physical addresses to the secure - * side in the buffer. + * Flush the command buffer so that the secure world sees + * the correct data. */ - flush_cache_all(); - outer_flush_all(); + __cpuc_flush_dcache_area((void *)cmd, cmd->len); + outer_flush_range(cmd_addr, cmd_addr + cmd->len); + ret = smc(cmd_addr); if (ret < 0) ret = scm_remap_error(ret); @@ -238,6 +238,13 @@ static void scm_inv_range(unsigned long start, unsigned long end) * @resp_len: length of the response buffer * * Sends a command to the SCM and waits for the command to finish processing. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking scm_call and invalidated in the cache + * immediately after scm_call returns. Cache maintenance on the command and + * response buffers is taken care of by scm_call; however, callers are + * responsible for any other cached buffers passed over to the secure world. */ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len) From 4139447035463a1ec96ceef268716dd5cec6373c Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Mon, 4 Aug 2014 18:31:49 -0700 Subject: [PATCH 07/12] ARM: qcom: scm: Add logging of actual return code from scm call When an error occurs during an scm call the error returned is remapped so we lose the original error code. This means that when an error occurs we have no idea what actually failed within the secure environment. Add a logging statement that will log the actual error code from scm call allowing us to easily determine what caused the error to occur. Signed-off-by: Olav Haugan Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index ec37b037e69c..a77349d34e78 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -152,6 +152,7 @@ static inline void *scm_get_response_buffer(const struct scm_response *rsp) static int scm_remap_error(int err) { + pr_err("scm_call failed with error code %d\n", err); switch (err) { case SCM_ERROR: return -EIO; From 0c2d96780da958d4d48d116c6daaa85d4495d282 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Thu, 4 Sep 2014 16:35:26 -0600 Subject: [PATCH 08/12] ARM: qcom: Add SCM warmboot flags for quad core targets. Quad core targets like APQ8074, APQ8064, APQ8084 need SCM support set up warm boot addresses in the Secure Monitor. Extend the SCM flags to support warmboot addresses for secondary cores. Signed-off-by: Lina Iyer Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm-boot.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h index 6aabb2428176..02b445c426ce 100644 --- a/arch/arm/mach-qcom/scm-boot.h +++ b/arch/arm/mach-qcom/scm-boot.h @@ -18,6 +18,8 @@ #define SCM_FLAG_COLDBOOT_CPU3 0x20 #define SCM_FLAG_WARMBOOT_CPU0 0x04 #define SCM_FLAG_WARMBOOT_CPU1 0x02 +#define SCM_FLAG_WARMBOOT_CPU2 0x10 +#define SCM_FLAG_WARMBOOT_CPU3 0x40 int scm_set_boot_addr(phys_addr_t addr, int flags); From 65b4ab65538e0da8e03e05d137001f10c78273d0 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 23 Oct 2014 17:35:07 -0700 Subject: [PATCH 09/12] ARM: qcom: scm: Clarify boot interface The secure world only knows about 32-bit wide physical addresses for the boot API. Clarify the kernel interface by explicitly stating a u32 instead of phys_addr_t which could be 32 or 64 bits depending on LPAE or not. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm-boot.c | 4 ++-- arch/arm/mach-qcom/scm-boot.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c index 45cee3e469a5..f2fa32834631 100644 --- a/arch/arm/mach-qcom/scm-boot.c +++ b/arch/arm/mach-qcom/scm-boot.c @@ -24,11 +24,11 @@ /* * Set the cold/warm boot address for one of the CPU cores. */ -int scm_set_boot_addr(phys_addr_t addr, int flags) +int scm_set_boot_addr(u32 addr, int flags) { struct { unsigned int flags; - phys_addr_t addr; + u32 addr; } cmd; cmd.addr = addr; diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h index 02b445c426ce..3e210fb818bb 100644 --- a/arch/arm/mach-qcom/scm-boot.h +++ b/arch/arm/mach-qcom/scm-boot.h @@ -21,6 +21,6 @@ #define SCM_FLAG_WARMBOOT_CPU2 0x10 #define SCM_FLAG_WARMBOOT_CPU3 0x40 -int scm_set_boot_addr(phys_addr_t addr, int flags); +int scm_set_boot_addr(u32 addr, int flags); #endif From 7279db9287f226fbb3f349c3244f8dc4b783e645 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 21 Jan 2015 11:21:15 -0800 Subject: [PATCH 10/12] ARM: qcom: Fix SCM interface for big-endian kernels The secure environment only runs in little-endian mode, so any buffers shared with the secure environment should have their contents converted to little-endian. We also mark such elements with __le32 to allow sparse to catch such problems. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/scm-boot.c | 8 ++++---- arch/arm/mach-qcom/scm.c | 30 ++++++++++++++++-------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c index f2fa32834631..e8ff7beb6218 100644 --- a/arch/arm/mach-qcom/scm-boot.c +++ b/arch/arm/mach-qcom/scm-boot.c @@ -27,12 +27,12 @@ int scm_set_boot_addr(u32 addr, int flags) { struct { - unsigned int flags; - u32 addr; + __le32 flags; + __le32 addr; } cmd; - cmd.addr = addr; - cmd.flags = flags; + cmd.addr = cpu_to_le32(addr); + cmd.flags = cpu_to_le32(flags); return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, &cmd, sizeof(cmd), NULL, 0); } diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index a77349d34e78..1d9cf18c7091 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -61,11 +61,11 @@ static DEFINE_MUTEX(scm_lock); * to access the buffers in a safe manner. */ struct scm_command { - u32 len; - u32 buf_offset; - u32 resp_hdr_offset; - u32 id; - u32 buf[0]; + __le32 len; + __le32 buf_offset; + __le32 resp_hdr_offset; + __le32 id; + __le32 buf[0]; }; /** @@ -75,9 +75,9 @@ struct scm_command { * @is_complete: indicates if the command has finished processing */ struct scm_response { - u32 len; - u32 buf_offset; - u32 is_complete; + __le32 len; + __le32 buf_offset; + __le32 is_complete; }; /** @@ -95,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) struct scm_command *cmd; size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + resp_size; + u32 offset; cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); if (cmd) { - cmd->len = len; - cmd->buf_offset = offsetof(struct scm_command, buf); - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; + cmd->len = cpu_to_le32(len); + offset = offsetof(struct scm_command, buf); + cmd->buf_offset = cpu_to_le32(offset); + cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size); } return cmd; } @@ -125,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd) static inline struct scm_response *scm_command_to_response( const struct scm_command *cmd) { - return (void *)cmd + cmd->resp_hdr_offset; + return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); } /** @@ -147,7 +149,7 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd) */ static inline void *scm_get_response_buffer(const struct scm_response *rsp) { - return (void *)rsp + rsp->buf_offset; + return (void *)rsp + le32_to_cpu(rsp->buf_offset); } static int scm_remap_error(int err) @@ -259,7 +261,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, if (!cmd) return -ENOMEM; - cmd->id = (svc_id << 10) | cmd_id; + cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); if (cmd_buf) memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); From 195b278dbd9d0d88ff3c743d55148022f5738b95 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 21 Jan 2015 11:22:09 -0800 Subject: [PATCH 11/12] ARM: qcom: Drop unnecessary selects from ARCH_QCOM We don't need to force gpiolib on everyone given that it isn't required to actually boot the device and the multiplatform Kconfig already selects ARCH_WANT_OPTIONAL_GPIOLIB. CLKSRC_OF is already selected by CONFIG_ARCH_MULTIPLATFORM too, so we can drop that here. Signed-off-by: Stephen Boyd Signed-off-by: Kumar Gala --- arch/arm/mach-qcom/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index 29aa8e1970b0..48003ea652b9 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -1,10 +1,8 @@ menuconfig ARCH_QCOM bool "Qualcomm Support" if ARCH_MULTI_V7 - select ARCH_REQUIRE_GPIOLIB select ARCH_SUPPORTS_BIG_ENDIAN select ARM_GIC select ARM_AMBA - select CLKSRC_OF select PINCTRL select QCOM_SCM if SMP help From f5d3af9d21f9790ac078276e6c103871c12a3daa Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Wed, 21 Jan 2015 22:39:24 -0600 Subject: [PATCH 12/12] MAINTAINERS: Add co-maintainer for ARM/Qualcomm Support Added myself as a co-maintainer. Updated the files to include the Qualcomm SoC directory. Added linux-soc mailing list. Signed-off-by: Andy Gross Signed-off-by: Kumar Gala --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ddb9ac8d32b3..22873c6e8602 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1290,10 +1290,13 @@ S: Maintained ARM/QUALCOMM SUPPORT M: Kumar Gala +M: Andy Gross M: David Brown L: linux-arm-msm@vger.kernel.org +L: linux-soc@vger.kernel.org S: Maintained F: arch/arm/mach-qcom/ +F: drivers/soc/qcom/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git ARM/RADISYS ENP2611 MACHINE SUPPORT