mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 10:29:37 +00:00
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: GPGTools - https://gpgtools.org iQIcBAABCgAGBQJUwneSAAoJEF9hYXeAcXzBSMQQAKoE7TK1gHTxXZrZNGvNOLgi v8Dy/jWV07pnMA41JDyW+IgEi8C7X7Byax6G6kCyKHVOk9TkDN3zS4XTxJWGVKa2 0f4QIJcStoHNXvUWe6rYGoW1nOyOae38uCWDY8dY+4x3gaOC3oV34NDmOlVEN5Gi KL0H90pHf8XLlKfx9rblkQT87Cxm/Y76xi0pnCHSyIuxsmAGInXT4zvRb/j4P1lJ 9IEWcp6kELqa2afn/OcXdsWFlvsc/BvMeXq1yl1nFawyfkpItX98wYTZGp9yuz8c MRKp8Ph3lgjvHbA6EME5mumg2/uhLvv+Klbl24bNwHVfxvDyUZwEHdSOFWTboKZW lfY+oe5hiwL68WYruBDqyziYjhe7kTX1/Iw0K/NHn0aWsng52CW/i0GjAaefxl6i FFV3+39vZh1bUNmynX69zPoRSKmB16ibFaTUl4Z7AoGqxq7rM8wRXP7xizAwuULK q8mCAVLEBgtAzqa2T8inM+USbL4K/qnzPEQzPG7Z6JxG05U2t+Huw2YD25wavIhE yvvfxkMli0fojRjp9CI/MbeloA3h0dRdc3zCMF5qkgAjRK4ozQVZ4BhDWn7jCC8/ QTCKxsYj977k6BUdHLTN3Z7/iW7F2HHXQRiJ9+HXLeLiTOSksFXnc2buHD6lwiRI mO6avae7XSGMpNYLa1RB =04jb -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
9b865d9b5c
7 changed files with 77 additions and 39 deletions
|
@ -1291,10 +1291,13 @@ S: Maintained
|
|||
|
||||
ARM/QUALCOMM SUPPORT
|
||||
M: Kumar Gala <galak@codeaurora.org>
|
||||
M: Andy Gross <agross@codeaurora.org>
|
||||
M: David Brown <davidb@codeaurora.org>
|
||||
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
|
||||
|
|
|
@ -438,7 +438,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
|
||||
|
@ -457,7 +457,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,9 +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
|
||||
|
|
|
@ -24,15 +24,15 @@
|
|||
/*
|
||||
* 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;
|
||||
__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);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
#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);
|
||||
int scm_set_boot_addr(u32 addr, int flags);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,13 +22,11 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/outercache.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include "scm.h"
|
||||
|
||||
/* Cache line size for msm8x60 */
|
||||
#define CACHELINESIZE 32
|
||||
|
||||
#define SCM_ENOMEM -5
|
||||
#define SCM_EOPNOTSUPP -4
|
||||
#define SCM_EINVAL_ADDR -3
|
||||
|
@ -63,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];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -77,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -97,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;
|
||||
}
|
||||
|
@ -127,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,11 +149,12 @@ 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)
|
||||
{
|
||||
pr_err("scm_call failed with error code %d\n", err);
|
||||
switch (err) {
|
||||
case SCM_ERROR:
|
||||
return -EIO;
|
||||
|
@ -198,11 +199,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();
|
||||
__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);
|
||||
|
@ -210,6 +212,25 @@ static int __scm_call(const struct scm_command *cmd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void scm_inv_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
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 += cacheline_size;
|
||||
}
|
||||
dsb();
|
||||
isb();
|
||||
}
|
||||
|
||||
/**
|
||||
* scm_call() - Send an SCM command
|
||||
* @svc_id: service identifier
|
||||
|
@ -220,6 +241,13 @@ static int __scm_call(const struct scm_command *cmd)
|
|||
* @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)
|
||||
|
@ -227,12 +255,13 @@ 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)
|
||||
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);
|
||||
|
||||
|
@ -243,17 +272,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:
|
||||
|
|
Loading…
Reference in a new issue