forked from rubenslte/android_kernel_samsung_msm8226
msm: smem: split out shared memory functionality
For historical reasons, the low level shared memory functionality exists in a combined driver with the higher level communication protocols. Move the low level shared memory functionality out into its own driver to improve clarity and ease maintenance. Change-Id: Ie55ecda7ef923c1f19a277ba8a47660f7a14e7b5 Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
This commit is contained in:
@@ -75,7 +75,7 @@ target += smd_rpc_sym.c
|
||||
$(obj)/smd_rpc_sym.c: $(src)/smd_rpc_sym $(src)/mkrpcsym.pl
|
||||
$(call if_changed,mkrpcsym)
|
||||
|
||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
|
||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o smem.o
|
||||
obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_gpio.o
|
||||
obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_gpio_test.o smp2p_spinlock_test.o
|
||||
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
#include <mach/scm-io.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "clock-pll.h"
|
||||
#include "smd_private.h"
|
||||
|
||||
#ifdef CONFIG_MSM_SECURE_IO
|
||||
#undef readl_relaxed
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
#define __ASM_ARCH_MSM_SMD_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
typedef struct smd_channel smd_channel_t;
|
||||
|
||||
@@ -40,13 +42,13 @@ typedef struct smd_channel smd_channel_t;
|
||||
* SMD, the entry will only exist in this enum.
|
||||
*/
|
||||
enum {
|
||||
SMD_APPS = SMSM_APPS,
|
||||
SMD_MODEM = SMSM_MODEM,
|
||||
SMD_Q6 = SMSM_Q6,
|
||||
SMD_WCNSS = SMSM_WCNSS,
|
||||
SMD_DSPS = SMSM_DSPS,
|
||||
SMD_MODEM_Q6_FW,
|
||||
SMD_RPM,
|
||||
SMD_APPS = SMEM_APPS,
|
||||
SMD_MODEM = SMEM_MODEM,
|
||||
SMD_Q6 = SMEM_Q6,
|
||||
SMD_DSPS = SMEM_DSPS,
|
||||
SMD_WCNSS = SMEM_WCNSS,
|
||||
SMD_MODEM_Q6_FW = SMEM_MODEM_Q6_FW,
|
||||
SMD_RPM = SMEM_RPM,
|
||||
NUM_SMD_SUBSYSTEMS,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ARCH_ARM_MACH_MSM_SMEM_H_
|
||||
#define _ARCH_ARM_MACH_MSM_SMEM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
SMEM_APPS,
|
||||
SMEM_MODEM,
|
||||
SMEM_Q6,
|
||||
SMEM_DSPS,
|
||||
SMEM_WCNSS,
|
||||
SMEM_MODEM_Q6_FW,
|
||||
SMEM_RPM,
|
||||
NUM_SMEM_SUBSYSTEMS,
|
||||
};
|
||||
|
||||
#define SMEM_NUM_SMD_STREAM_CHANNELS 64
|
||||
#define SMEM_NUM_SMD_BLOCK_CHANNELS 64
|
||||
|
||||
enum {
|
||||
/* fixed items */
|
||||
SMEM_PROC_COMM = 0,
|
||||
SMEM_HEAP_INFO,
|
||||
SMEM_ALLOCATION_TABLE,
|
||||
SMEM_VERSION_INFO,
|
||||
SMEM_HW_RESET_DETECT,
|
||||
SMEM_AARM_WARM_BOOT,
|
||||
SMEM_DIAG_ERR_MESSAGE,
|
||||
SMEM_SPINLOCK_ARRAY,
|
||||
SMEM_MEMORY_BARRIER_LOCATION,
|
||||
SMEM_FIXED_ITEM_LAST = SMEM_MEMORY_BARRIER_LOCATION,
|
||||
|
||||
/* dynamic items */
|
||||
SMEM_AARM_PARTITION_TABLE,
|
||||
SMEM_AARM_BAD_BLOCK_TABLE,
|
||||
SMEM_RESERVE_BAD_BLOCKS,
|
||||
SMEM_WM_UUID,
|
||||
SMEM_CHANNEL_ALLOC_TBL,
|
||||
SMEM_SMD_BASE_ID,
|
||||
SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_STREAM_CHANNELS,
|
||||
SMEM_SMEM_LOG_EVENTS,
|
||||
SMEM_SMEM_STATIC_LOG_IDX,
|
||||
SMEM_SMEM_STATIC_LOG_EVENTS,
|
||||
SMEM_SMEM_SLOW_CLOCK_SYNC,
|
||||
SMEM_SMEM_SLOW_CLOCK_VALUE,
|
||||
SMEM_BIO_LED_BUF,
|
||||
SMEM_SMSM_SHARED_STATE,
|
||||
SMEM_SMSM_INT_INFO,
|
||||
SMEM_SMSM_SLEEP_DELAY,
|
||||
SMEM_SMSM_LIMIT_SLEEP,
|
||||
SMEM_SLEEP_POWER_COLLAPSE_DISABLED,
|
||||
SMEM_KEYPAD_KEYS_PRESSED,
|
||||
SMEM_KEYPAD_STATE_UPDATED,
|
||||
SMEM_KEYPAD_STATE_IDX,
|
||||
SMEM_GPIO_INT,
|
||||
SMEM_MDDI_LCD_IDX,
|
||||
SMEM_MDDI_HOST_DRIVER_STATE,
|
||||
SMEM_MDDI_LCD_DISP_STATE,
|
||||
SMEM_LCD_CUR_PANEL,
|
||||
SMEM_MARM_BOOT_SEGMENT_INFO,
|
||||
SMEM_AARM_BOOT_SEGMENT_INFO,
|
||||
SMEM_SLEEP_STATIC,
|
||||
SMEM_SCORPION_FREQUENCY,
|
||||
SMEM_SMD_PROFILES,
|
||||
SMEM_TSSC_BUSY,
|
||||
SMEM_HS_SUSPEND_FILTER_INFO,
|
||||
SMEM_BATT_INFO,
|
||||
SMEM_APPS_BOOT_MODE,
|
||||
SMEM_VERSION_FIRST,
|
||||
SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
|
||||
SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
|
||||
SMEM_OSS_RRCASN1_BUF1,
|
||||
SMEM_OSS_RRCASN1_BUF2,
|
||||
SMEM_ID_VENDOR0,
|
||||
SMEM_ID_VENDOR1,
|
||||
SMEM_ID_VENDOR2,
|
||||
SMEM_HW_SW_BUILD_ID,
|
||||
SMEM_SMD_BLOCK_PORT_BASE_ID,
|
||||
SMEM_SMD_BLOCK_PORT_PROC0_HEAP = SMEM_SMD_BLOCK_PORT_BASE_ID +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_SMD_BLOCK_PORT_PROC1_HEAP = SMEM_SMD_BLOCK_PORT_PROC0_HEAP +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_I2C_MUTEX = SMEM_SMD_BLOCK_PORT_PROC1_HEAP +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_SCLK_CONVERSION,
|
||||
SMEM_SMD_SMSM_INTR_MUX,
|
||||
SMEM_SMSM_CPU_INTR_MASK,
|
||||
SMEM_APPS_DEM_SLAVE_DATA,
|
||||
SMEM_QDSP6_DEM_SLAVE_DATA,
|
||||
SMEM_CLKREGIM_BSP,
|
||||
SMEM_CLKREGIM_SOURCES,
|
||||
SMEM_SMD_FIFO_BASE_ID,
|
||||
SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
|
||||
SMEM_NUM_SMD_STREAM_CHANNELS,
|
||||
SMEM_POWER_ON_STATUS_INFO,
|
||||
SMEM_DAL_AREA,
|
||||
SMEM_SMEM_LOG_POWER_IDX,
|
||||
SMEM_SMEM_LOG_POWER_WRAP,
|
||||
SMEM_SMEM_LOG_POWER_EVENTS,
|
||||
SMEM_ERR_CRASH_LOG,
|
||||
SMEM_ERR_F3_TRACE_LOG,
|
||||
SMEM_SMD_BRIDGE_ALLOC_TABLE,
|
||||
SMEM_SMDLITE_TABLE,
|
||||
SMEM_SD_IMG_UPGRADE_STATUS,
|
||||
SMEM_SEFS_INFO,
|
||||
SMEM_RESET_LOG,
|
||||
SMEM_RESET_LOG_SYMBOLS,
|
||||
SMEM_MODEM_SW_BUILD_ID,
|
||||
SMEM_SMEM_LOG_MPROC_WRAP,
|
||||
SMEM_BOOT_INFO_FOR_APPS,
|
||||
SMEM_SMSM_SIZE_INFO,
|
||||
SMEM_SMD_LOOPBACK_REGISTER,
|
||||
SMEM_SSR_REASON_MSS0,
|
||||
SMEM_SSR_REASON_WCNSS0,
|
||||
SMEM_SSR_REASON_LPASS0,
|
||||
SMEM_SSR_REASON_DSPS0,
|
||||
SMEM_SSR_REASON_VCODEC0,
|
||||
SMEM_SMP2P_APPS_BASE = 427,
|
||||
SMEM_SMP2P_MODEM_BASE = SMEM_SMP2P_APPS_BASE + 8, /* 435 */
|
||||
SMEM_SMP2P_AUDIO_BASE = SMEM_SMP2P_MODEM_BASE + 8, /* 443 */
|
||||
SMEM_SMP2P_WIRLESS_BASE = SMEM_SMP2P_AUDIO_BASE + 8, /* 451 */
|
||||
SMEM_SMP2P_POWER_BASE = SMEM_SMP2P_WIRLESS_BASE + 8, /* 459 */
|
||||
SMEM_FLASH_DEVICE_INFO = SMEM_SMP2P_POWER_BASE + 8, /* 467 */
|
||||
SMEM_BAM_PIPE_MEMORY, /* 468 */
|
||||
SMEM_IMAGE_VERSION_TABLE, /* 469 */
|
||||
SMEM_LC_DEBUGGER, /* 470 */
|
||||
SMEM_NUM_ITEMS,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_SMD
|
||||
void *smem_alloc(unsigned id, unsigned size);
|
||||
void *smem_alloc2(unsigned id, unsigned size_in);
|
||||
void *smem_get_entry(unsigned id, unsigned *size);
|
||||
void *smem_find(unsigned id, unsigned size);
|
||||
/**
|
||||
* smem_virt_to_phys() - Convert SMEM address to physical address.
|
||||
*
|
||||
* @smem_address: Virtual address returned by smem_alloc()/smem_alloc2()
|
||||
* @returns: Physical address (or NULL if there is a failure)
|
||||
*
|
||||
* This function should only be used if an SMEM item needs to be handed
|
||||
* off to a DMA engine.
|
||||
*/
|
||||
phys_addr_t smem_virt_to_phys(void *smem_address);
|
||||
|
||||
#else
|
||||
static inline void *smem_alloc(unsigned id, unsigned size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void *smem_alloc2(unsigned id, unsigned size_in)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void *smem_get_entry(unsigned id, unsigned *size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void *smem_find(unsigned id, unsigned size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline phys_addr_t smem_virt_to_phys(void *smem_address)
|
||||
{
|
||||
return (phys_addr_t) NULL;
|
||||
}
|
||||
#endif /* CONFIG_MSM_SMD */
|
||||
#endif /* _ARCH_ARM_MACH_MSM_SMEM_H_ */
|
||||
@@ -14,6 +14,9 @@
|
||||
#define _ARCH_ARM_MACH_MSM_SMSM_H_
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#if defined(CONFIG_MSM_N_WAY_SMSM)
|
||||
enum {
|
||||
SMSM_APPS_STATE,
|
||||
@@ -37,11 +40,11 @@ enum {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SMSM_APPS,
|
||||
SMSM_MODEM,
|
||||
SMSM_Q6,
|
||||
SMSM_WCNSS,
|
||||
SMSM_DSPS,
|
||||
SMSM_APPS = SMEM_APPS,
|
||||
SMSM_MODEM = SMEM_MODEM,
|
||||
SMSM_Q6 = SMEM_Q6,
|
||||
SMSM_DSPS = SMEM_DSPS,
|
||||
SMSM_WCNSS = SMEM_WCNSS,
|
||||
};
|
||||
extern uint32_t SMSM_NUM_HOSTS;
|
||||
|
||||
@@ -97,119 +100,6 @@ extern uint32_t SMSM_NUM_HOSTS;
|
||||
#define SMSM_SUBSYS2AP_STATUS 0x00008000
|
||||
|
||||
|
||||
#define SMEM_NUM_SMD_STREAM_CHANNELS 64
|
||||
#define SMEM_NUM_SMD_BLOCK_CHANNELS 64
|
||||
|
||||
enum {
|
||||
/* fixed items */
|
||||
SMEM_PROC_COMM = 0,
|
||||
SMEM_HEAP_INFO,
|
||||
SMEM_ALLOCATION_TABLE,
|
||||
SMEM_VERSION_INFO,
|
||||
SMEM_HW_RESET_DETECT,
|
||||
SMEM_AARM_WARM_BOOT,
|
||||
SMEM_DIAG_ERR_MESSAGE,
|
||||
SMEM_SPINLOCK_ARRAY,
|
||||
SMEM_MEMORY_BARRIER_LOCATION,
|
||||
SMEM_FIXED_ITEM_LAST = SMEM_MEMORY_BARRIER_LOCATION,
|
||||
|
||||
/* dynamic items */
|
||||
SMEM_AARM_PARTITION_TABLE,
|
||||
SMEM_AARM_BAD_BLOCK_TABLE,
|
||||
SMEM_RESERVE_BAD_BLOCKS,
|
||||
SMEM_WM_UUID,
|
||||
SMEM_CHANNEL_ALLOC_TBL,
|
||||
SMEM_SMD_BASE_ID,
|
||||
SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_STREAM_CHANNELS,
|
||||
SMEM_SMEM_LOG_EVENTS,
|
||||
SMEM_SMEM_STATIC_LOG_IDX,
|
||||
SMEM_SMEM_STATIC_LOG_EVENTS,
|
||||
SMEM_SMEM_SLOW_CLOCK_SYNC,
|
||||
SMEM_SMEM_SLOW_CLOCK_VALUE,
|
||||
SMEM_BIO_LED_BUF,
|
||||
SMEM_SMSM_SHARED_STATE,
|
||||
SMEM_SMSM_INT_INFO,
|
||||
SMEM_SMSM_SLEEP_DELAY,
|
||||
SMEM_SMSM_LIMIT_SLEEP,
|
||||
SMEM_SLEEP_POWER_COLLAPSE_DISABLED,
|
||||
SMEM_KEYPAD_KEYS_PRESSED,
|
||||
SMEM_KEYPAD_STATE_UPDATED,
|
||||
SMEM_KEYPAD_STATE_IDX,
|
||||
SMEM_GPIO_INT,
|
||||
SMEM_MDDI_LCD_IDX,
|
||||
SMEM_MDDI_HOST_DRIVER_STATE,
|
||||
SMEM_MDDI_LCD_DISP_STATE,
|
||||
SMEM_LCD_CUR_PANEL,
|
||||
SMEM_MARM_BOOT_SEGMENT_INFO,
|
||||
SMEM_AARM_BOOT_SEGMENT_INFO,
|
||||
SMEM_SLEEP_STATIC,
|
||||
SMEM_SCORPION_FREQUENCY,
|
||||
SMEM_SMD_PROFILES,
|
||||
SMEM_TSSC_BUSY,
|
||||
SMEM_HS_SUSPEND_FILTER_INFO,
|
||||
SMEM_BATT_INFO,
|
||||
SMEM_APPS_BOOT_MODE,
|
||||
SMEM_VERSION_FIRST,
|
||||
SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
|
||||
SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
|
||||
SMEM_OSS_RRCASN1_BUF1,
|
||||
SMEM_OSS_RRCASN1_BUF2,
|
||||
SMEM_ID_VENDOR0,
|
||||
SMEM_ID_VENDOR1,
|
||||
SMEM_ID_VENDOR2,
|
||||
SMEM_HW_SW_BUILD_ID,
|
||||
SMEM_SMD_BLOCK_PORT_BASE_ID,
|
||||
SMEM_SMD_BLOCK_PORT_PROC0_HEAP = SMEM_SMD_BLOCK_PORT_BASE_ID +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_SMD_BLOCK_PORT_PROC1_HEAP = SMEM_SMD_BLOCK_PORT_PROC0_HEAP +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_I2C_MUTEX = SMEM_SMD_BLOCK_PORT_PROC1_HEAP +
|
||||
SMEM_NUM_SMD_BLOCK_CHANNELS,
|
||||
SMEM_SCLK_CONVERSION,
|
||||
SMEM_SMD_SMSM_INTR_MUX,
|
||||
SMEM_SMSM_CPU_INTR_MASK,
|
||||
SMEM_APPS_DEM_SLAVE_DATA,
|
||||
SMEM_QDSP6_DEM_SLAVE_DATA,
|
||||
SMEM_CLKREGIM_BSP,
|
||||
SMEM_CLKREGIM_SOURCES,
|
||||
SMEM_SMD_FIFO_BASE_ID,
|
||||
SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
|
||||
SMEM_NUM_SMD_STREAM_CHANNELS,
|
||||
SMEM_POWER_ON_STATUS_INFO,
|
||||
SMEM_DAL_AREA,
|
||||
SMEM_SMEM_LOG_POWER_IDX,
|
||||
SMEM_SMEM_LOG_POWER_WRAP,
|
||||
SMEM_SMEM_LOG_POWER_EVENTS,
|
||||
SMEM_ERR_CRASH_LOG,
|
||||
SMEM_ERR_F3_TRACE_LOG,
|
||||
SMEM_SMD_BRIDGE_ALLOC_TABLE,
|
||||
SMEM_SMDLITE_TABLE,
|
||||
SMEM_SD_IMG_UPGRADE_STATUS,
|
||||
SMEM_SEFS_INFO,
|
||||
SMEM_RESET_LOG,
|
||||
SMEM_RESET_LOG_SYMBOLS,
|
||||
SMEM_MODEM_SW_BUILD_ID,
|
||||
SMEM_SMEM_LOG_MPROC_WRAP,
|
||||
SMEM_BOOT_INFO_FOR_APPS,
|
||||
SMEM_SMSM_SIZE_INFO,
|
||||
SMEM_SMD_LOOPBACK_REGISTER,
|
||||
SMEM_SSR_REASON_MSS0,
|
||||
SMEM_SSR_REASON_WCNSS0,
|
||||
SMEM_SSR_REASON_LPASS0,
|
||||
SMEM_SSR_REASON_DSPS0,
|
||||
SMEM_SSR_REASON_VCODEC0,
|
||||
SMEM_SMP2P_APPS_BASE = 427,
|
||||
SMEM_SMP2P_MODEM_BASE = SMEM_SMP2P_APPS_BASE + 8, /* 435 */
|
||||
SMEM_SMP2P_AUDIO_BASE = SMEM_SMP2P_MODEM_BASE + 8, /* 443 */
|
||||
SMEM_SMP2P_WIRLESS_BASE = SMEM_SMP2P_AUDIO_BASE + 8, /* 451 */
|
||||
SMEM_SMP2P_POWER_BASE = SMEM_SMP2P_WIRLESS_BASE + 8, /* 459 */
|
||||
SMEM_FLASH_DEVICE_INFO = SMEM_SMP2P_POWER_BASE + 8, /* 467 */
|
||||
SMEM_BAM_PIPE_MEMORY, /* 468 */
|
||||
SMEM_IMAGE_VERSION_TABLE, /* 469 */
|
||||
SMEM_LC_DEBUGGER, /* 470 */
|
||||
SMEM_NUM_ITEMS,
|
||||
};
|
||||
|
||||
enum {
|
||||
SMEM_APPS_Q6_SMSM = 3,
|
||||
SMEM_Q6_APPS_SMSM = 5,
|
||||
@@ -217,9 +107,6 @@ enum {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_SMD
|
||||
void *smem_alloc(unsigned id, unsigned size);
|
||||
void *smem_alloc2(unsigned id, unsigned size_in);
|
||||
void *smem_get_entry(unsigned id, unsigned *size);
|
||||
int smsm_change_state(uint32_t smsm_entry,
|
||||
uint32_t clear_mask, uint32_t set_mask);
|
||||
|
||||
@@ -254,36 +141,8 @@ void smd_sleep_exit(void);
|
||||
|
||||
|
||||
int smsm_check_for_modem_crash(void);
|
||||
void *smem_find(unsigned id, unsigned size);
|
||||
void *smem_get_entry(unsigned id, unsigned *size);
|
||||
|
||||
/**
|
||||
* smem_virt_to_phys() - Convert SMEM address to physical address.
|
||||
*
|
||||
* @smem_address: Virtual address returned by smem_alloc()/smem_alloc2()
|
||||
* @returns: Physical address (or NULL if there is a failure)
|
||||
*
|
||||
* This function should only be used if an SMEM item needs to be handed
|
||||
* off to a DMA engine.
|
||||
*/
|
||||
phys_addr_t smem_virt_to_phys(void *smem_address);
|
||||
|
||||
#else
|
||||
static inline void *smem_alloc(unsigned id, unsigned size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *smem_alloc2(unsigned id, unsigned size_in)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *smem_get_entry(unsigned id, unsigned *size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int smsm_change_state(uint32_t smsm_entry,
|
||||
uint32_t clear_mask, uint32_t set_mask)
|
||||
{
|
||||
@@ -347,13 +206,5 @@ static inline int smsm_check_for_modem_crash(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline void *smem_find(unsigned id, unsigned size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline phys_addr_t smem_virt_to_phys(void *smem_address)
|
||||
{
|
||||
return (phys_addr_t) NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/memory.h>
|
||||
#include <mach/msm_memtypes.h>
|
||||
#include <mach/socinfo.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include "smd_private.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM8960)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -16,6 +16,7 @@
|
||||
#define __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
|
||||
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#define MAX_KEY_EVENTS 10
|
||||
#define MAX_SEC_KEY_PAYLOAD 32
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* bootloader.
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2008-2009,2011 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2008-2009,2011,2013 The Linux Foundation. All rights reserved.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <mach/board.h>
|
||||
#ifdef CONFIG_MSM_SMD
|
||||
#include "smd_private.h"
|
||||
#include <mach/msm_smem.h>
|
||||
#endif
|
||||
|
||||
/* configuration tags specific to msm */
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "scm-pas.h"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <mach/msm_bus.h>
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "scm-pas.h"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "scm-pas.h"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/subsystem_notif.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "sysmon.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "peripheral-loader.h"
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <mach/subsystem_notif.h>
|
||||
#include <mach/scm.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "pil-q6v5.h"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <mach/clk.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "pil-q6v5.h"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <mach/subsystem_restart.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "peripheral-loader.h"
|
||||
#include "scm-pas.h"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* MSM Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2008-2012 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2008-2013 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@@ -44,9 +44,10 @@
|
||||
#endif
|
||||
#include <mach/socinfo.h>
|
||||
#include <mach/proc_comm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "smd_rpcrouter.h"
|
||||
#include "acpuclock.h"
|
||||
#include "clock.h"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/remote_spinlock.h>
|
||||
#include <mach/dal.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include "smd_private.h"
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#ifdef CONFIG_MSM_SDIO_SMEM
|
||||
#include <mach/sdio_smem.h>
|
||||
#endif
|
||||
#include "smd_private.h"
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
enum {
|
||||
RMT_STORAGE_EVNT_OPEN = 0,
|
||||
|
||||
+2
-265
@@ -47,11 +47,13 @@
|
||||
#include <mach/msm_ipc_logging.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "modem_notifier.h"
|
||||
#include "smem_private.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
|
||||
|| defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
|
||||
@@ -175,16 +177,6 @@ static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct smem_area {
|
||||
phys_addr_t phys_addr;
|
||||
resource_size_t size;
|
||||
void __iomem *virt_addr;
|
||||
};
|
||||
static uint32_t num_smem_areas;
|
||||
static struct smem_area *smem_areas;
|
||||
static struct ramdump_segment *smem_ramdump_segments;
|
||||
static void *smem_ramdump_dev;
|
||||
static void *smem_phys_to_virt(phys_addr_t base, unsigned offset);
|
||||
static void *smd_dev;
|
||||
|
||||
struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
|
||||
@@ -380,9 +372,6 @@ static inline void smd_write_intr(unsigned int val,
|
||||
|
||||
#define SMD_LOOPBACK_CID 100
|
||||
|
||||
#define SMEM_SPINLOCK_SMEM_ALLOC "S:3"
|
||||
static remote_spinlock_t remote_spinlock;
|
||||
|
||||
static LIST_HEAD(smd_ch_list_loopback);
|
||||
static void smd_fake_irq_handler(unsigned long arg);
|
||||
static void smsm_cb_snapshot(uint32_t use_wakelock);
|
||||
@@ -392,7 +381,6 @@ static void notify_smsm_cb_clients_worker(struct work_struct *work);
|
||||
static DECLARE_WORK(smsm_cb_work, notify_smsm_cb_clients_worker);
|
||||
static DEFINE_MUTEX(smsm_lock);
|
||||
static struct smsm_state_info *smsm_states;
|
||||
static int spinlocks_initialized;
|
||||
|
||||
/**
|
||||
* Variables to indicate smd module initialization.
|
||||
@@ -2408,222 +2396,6 @@ int smd_is_pkt_avail(smd_channel_t *ch)
|
||||
}
|
||||
EXPORT_SYMBOL(smd_is_pkt_avail);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* smem_phys_to_virt() - Convert a physical base and offset to virtual address
|
||||
*
|
||||
* @base: physical base address to check
|
||||
* @offset: offset from the base to get the final address
|
||||
* @returns: virtual SMEM address; NULL for failure
|
||||
*
|
||||
* Takes a physical address and an offset and checks if the resulting physical
|
||||
* address would fit into one of the smem regions. If so, returns the
|
||||
* corresponding virtual address. Otherwise returns NULL.
|
||||
*/
|
||||
static void *smem_phys_to_virt(phys_addr_t base, unsigned offset)
|
||||
{
|
||||
int i;
|
||||
phys_addr_t phys_addr;
|
||||
resource_size_t size;
|
||||
|
||||
if (OVERFLOW_ADD_UNSIGNED(phys_addr_t, base, offset))
|
||||
return NULL;
|
||||
|
||||
if (!smem_areas) {
|
||||
/*
|
||||
* Early boot - no area configuration yet, so default
|
||||
* to using the main memory region.
|
||||
*
|
||||
* To remove the MSM_SHARED_RAM_BASE and the static
|
||||
* mapping of SMEM in the future, add dump_stack()
|
||||
* to identify the early callers of smem_get_entry()
|
||||
* (which calls this function) and replace those calls
|
||||
* with a new function that knows how to lookup the
|
||||
* SMEM base address before SMEM has been probed.
|
||||
*/
|
||||
phys_addr = msm_shared_ram_phys;
|
||||
size = MSM_SHARED_RAM_SIZE;
|
||||
|
||||
if (base >= phys_addr && base + offset < phys_addr + size) {
|
||||
if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
|
||||
(uintptr_t)MSM_SHARED_RAM_BASE, offset)) {
|
||||
pr_err("%s: overflow %p %x\n", __func__,
|
||||
MSM_SHARED_RAM_BASE, offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return MSM_SHARED_RAM_BASE + offset;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_smem_areas; ++i) {
|
||||
phys_addr = smem_areas[i].phys_addr;
|
||||
size = smem_areas[i].size;
|
||||
|
||||
if (base < phys_addr || base + offset >= phys_addr + size)
|
||||
continue;
|
||||
|
||||
if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
|
||||
(uintptr_t)smem_areas[i].virt_addr, offset)) {
|
||||
pr_err("%s: overflow %p %x\n", __func__,
|
||||
smem_areas[i].virt_addr, offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return smem_areas[i].virt_addr + offset;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* smem_virt_to_phys() - Convert SMEM address to physical address.
|
||||
*
|
||||
* @smem_address: Address of SMEM item (returned by smem_alloc(), etc)
|
||||
* @returns: Physical address (or NULL if there is a failure)
|
||||
*
|
||||
* This function should only be used if an SMEM item needs to be handed
|
||||
* off to a DMA engine.
|
||||
*/
|
||||
phys_addr_t smem_virt_to_phys(void *smem_address)
|
||||
{
|
||||
phys_addr_t phys_addr = 0;
|
||||
int i;
|
||||
void *vend;
|
||||
|
||||
if (!smem_areas)
|
||||
return phys_addr;
|
||||
|
||||
for (i = 0; i < num_smem_areas; ++i) {
|
||||
vend = (void *)(smem_areas[i].virt_addr + smem_areas[i].size);
|
||||
|
||||
if (smem_address >= smem_areas[i].virt_addr &&
|
||||
smem_address < vend) {
|
||||
phys_addr = smem_address - smem_areas[i].virt_addr;
|
||||
phys_addr += smem_areas[i].phys_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phys_addr;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_virt_to_phys);
|
||||
|
||||
/* smem_alloc returns the pointer to smem item if it is already allocated.
|
||||
* Otherwise, it returns NULL.
|
||||
*/
|
||||
void *smem_alloc(unsigned id, unsigned size)
|
||||
{
|
||||
return smem_find(id, size);
|
||||
}
|
||||
EXPORT_SYMBOL(smem_alloc);
|
||||
|
||||
/* smem_alloc2 returns the pointer to smem item. If it is not allocated,
|
||||
* it allocates it and then returns the pointer to it.
|
||||
*/
|
||||
void *smem_alloc2(unsigned id, unsigned size_in)
|
||||
{
|
||||
struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
|
||||
struct smem_heap_entry *toc = shared->heap_toc;
|
||||
unsigned long flags;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!shared->heap_info.initialized) {
|
||||
pr_err("%s: smem heap info not initialized\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (id >= SMEM_NUM_ITEMS)
|
||||
return NULL;
|
||||
|
||||
size_in = ALIGN(size_in, 8);
|
||||
remote_spin_lock_irqsave(&remote_spinlock, flags);
|
||||
if (toc[id].allocated) {
|
||||
SMD_DBG("%s: %u already allocated\n", __func__, id);
|
||||
if (size_in != toc[id].size)
|
||||
pr_err("%s: wrong size %u (expected %u)\n",
|
||||
__func__, toc[id].size, size_in);
|
||||
else
|
||||
ret = (void *)(MSM_SHARED_RAM_BASE + toc[id].offset);
|
||||
} else if (id > SMEM_FIXED_ITEM_LAST) {
|
||||
SMD_DBG("%s: allocating %u\n", __func__, id);
|
||||
if (shared->heap_info.heap_remaining >= size_in) {
|
||||
toc[id].offset = shared->heap_info.free_offset;
|
||||
toc[id].size = size_in;
|
||||
wmb();
|
||||
toc[id].allocated = 1;
|
||||
|
||||
shared->heap_info.free_offset += size_in;
|
||||
shared->heap_info.heap_remaining -= size_in;
|
||||
ret = (void *)(MSM_SHARED_RAM_BASE + toc[id].offset);
|
||||
} else
|
||||
pr_err("%s: not enough memory %u (required %u)\n",
|
||||
__func__, shared->heap_info.heap_remaining,
|
||||
size_in);
|
||||
}
|
||||
wmb();
|
||||
remote_spin_unlock_irqrestore(&remote_spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_alloc2);
|
||||
|
||||
void *smem_get_entry(unsigned id, unsigned *size)
|
||||
{
|
||||
struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
|
||||
struct smem_heap_entry *toc = shared->heap_toc;
|
||||
int use_spinlocks = spinlocks_initialized;
|
||||
void *ret = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (id >= SMEM_NUM_ITEMS)
|
||||
return ret;
|
||||
|
||||
if (use_spinlocks)
|
||||
remote_spin_lock_irqsave(&remote_spinlock, flags);
|
||||
/* toc is in device memory and cannot be speculatively accessed */
|
||||
if (toc[id].allocated) {
|
||||
phys_addr_t phys_base;
|
||||
|
||||
*size = toc[id].size;
|
||||
barrier();
|
||||
|
||||
phys_base = toc[id].reserved & BASE_ADDR_MASK;
|
||||
if (!phys_base)
|
||||
phys_base = (phys_addr_t)msm_shared_ram_phys;
|
||||
ret = smem_phys_to_virt(phys_base, toc[id].offset);
|
||||
} else {
|
||||
*size = 0;
|
||||
}
|
||||
if (use_spinlocks)
|
||||
remote_spin_unlock_irqrestore(&remote_spinlock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_get_entry);
|
||||
|
||||
void *smem_find(unsigned id, unsigned size_in)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
|
||||
ptr = smem_get_entry(id, &size);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
size_in = ALIGN(size_in, 8);
|
||||
if (size_in != size) {
|
||||
pr_err("smem_find(%d, %d): wrong size %d\n",
|
||||
id, size_in, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_find);
|
||||
|
||||
static int smsm_cb_init(void)
|
||||
{
|
||||
struct smsm_state_info *state_info;
|
||||
@@ -3313,17 +3085,6 @@ int smsm_state_cb_deregister(uint32_t smsm_entry, uint32_t mask,
|
||||
}
|
||||
EXPORT_SYMBOL(smsm_state_cb_deregister);
|
||||
|
||||
/**
|
||||
* smem_get_remote_spinlock - Remote spinlock pointer for unit testing.
|
||||
*
|
||||
* @returns: pointer to SMEM remote spinlock
|
||||
*/
|
||||
remote_spinlock_t *smem_get_remote_spinlock(void)
|
||||
{
|
||||
return &remote_spinlock;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_get_remote_spinlock);
|
||||
|
||||
int smd_module_init_notifier_register(struct notifier_block *nb)
|
||||
{
|
||||
int ret;
|
||||
@@ -4126,23 +3887,6 @@ static int restart_notifier_cb(struct notifier_block *this,
|
||||
remote_spin_release(&remote_spinlock, notifier->processor);
|
||||
remote_spin_release_all(notifier->processor);
|
||||
|
||||
if (smem_ramdump_dev) {
|
||||
int ret;
|
||||
|
||||
SMD_INFO("%s: saving ramdump\n", __func__);
|
||||
/*
|
||||
* XPU protection does not currently allow the
|
||||
* auxiliary memory regions to be dumped. If this
|
||||
* changes, then num_smem_areas + 1 should be passed
|
||||
* into do_elf_ramdump() to dump all regions.
|
||||
*/
|
||||
ret = do_elf_ramdump(smem_ramdump_dev,
|
||||
smem_ramdump_segments, 1);
|
||||
if (ret < 0)
|
||||
pr_err("%s: unable to dump smem %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
|
||||
smd_channel_reset(notifier->processor);
|
||||
}
|
||||
|
||||
@@ -4155,13 +3899,6 @@ static __init int modem_restart_late_init(void)
|
||||
void *handle;
|
||||
struct restart_notifier_block *nb;
|
||||
|
||||
smem_ramdump_dev = create_ramdump_device("smem-smd", smd_dev);
|
||||
if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
|
||||
pr_err("%s: Unable to create smem ramdump device.\n",
|
||||
__func__);
|
||||
smem_ramdump_dev = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
|
||||
nb = &restart_notifiers[i];
|
||||
handle = subsys_notif_register_notifier(nb->name, &nb->nb);
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "smem_private.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
|
||||
@@ -34,37 +34,6 @@
|
||||
#define VERSION_MODEM 9
|
||||
#define VERSION_DSPS 10
|
||||
|
||||
#define SMD_HEAP_SIZE 512
|
||||
|
||||
struct smem_heap_info {
|
||||
unsigned initialized;
|
||||
unsigned free_offset;
|
||||
unsigned heap_remaining;
|
||||
unsigned reserved;
|
||||
};
|
||||
|
||||
struct smem_heap_entry {
|
||||
unsigned allocated;
|
||||
unsigned offset;
|
||||
unsigned size;
|
||||
unsigned reserved; /* bits 1:0 reserved, bits 31:2 aux smem base addr */
|
||||
};
|
||||
#define BASE_ADDR_MASK 0xfffffffc
|
||||
|
||||
struct smem_proc_comm {
|
||||
unsigned command;
|
||||
unsigned status;
|
||||
unsigned data1;
|
||||
unsigned data2;
|
||||
};
|
||||
|
||||
struct smem_shared {
|
||||
struct smem_proc_comm proc_comm[4];
|
||||
unsigned version[32];
|
||||
struct smem_heap_info heap_info;
|
||||
struct smem_heap_entry heap_toc[SMD_HEAP_SIZE];
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MSM_SMD_PKG4)
|
||||
struct smsm_interrupt_info {
|
||||
uint32_t aArm_en_mask;
|
||||
@@ -313,7 +282,4 @@ struct interrupt_stat {
|
||||
uint32_t smsm_interrupt_id;
|
||||
};
|
||||
extern struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
|
||||
|
||||
/* used for unit testing spinlocks */
|
||||
remote_spinlock_t *smem_get_remote_spinlock(void);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include <mach/ramdump.h>
|
||||
#include <mach/subsystem_notif.h>
|
||||
|
||||
#include "smem_private.h"
|
||||
|
||||
/**
|
||||
* OVERFLOW_ADD_UNSIGNED() - check for unsigned overflow
|
||||
*
|
||||
* @type: type to check for overflow
|
||||
* @a: left value to use
|
||||
* @b: right value to use
|
||||
* @returns: true if a + b will result in overflow; false otherwise
|
||||
*/
|
||||
#define OVERFLOW_ADD_UNSIGNED(type, a, b) \
|
||||
(((type)~0 - (a)) < (b) ? true : false)
|
||||
|
||||
enum {
|
||||
MSM_SMEM_DEBUG = 1U << 0,
|
||||
MSM_SMEM_INFO = 1U << 1,
|
||||
};
|
||||
|
||||
static int msm_smem_debug_mask;
|
||||
module_param_named(debug_mask, msm_smem_debug_mask,
|
||||
int, S_IRUGO | S_IWUSR | S_IWGRP);
|
||||
|
||||
#define SMEM_DBG(x...) do { \
|
||||
if (msm_smem_debug_mask & MSM_SMEM_DEBUG) \
|
||||
pr_debug(x); \
|
||||
} while (0)
|
||||
|
||||
remote_spinlock_t remote_spinlock;
|
||||
int spinlocks_initialized;
|
||||
uint32_t num_smem_areas;
|
||||
struct smem_area *smem_areas;
|
||||
struct ramdump_segment *smem_ramdump_segments;
|
||||
|
||||
static void *smem_ramdump_dev;
|
||||
|
||||
struct restart_notifier_block {
|
||||
unsigned processor;
|
||||
char *name;
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
static int restart_notifier_cb(struct notifier_block *this,
|
||||
unsigned long code,
|
||||
void *data);
|
||||
|
||||
static struct restart_notifier_block restart_notifiers[] = {
|
||||
{SMEM_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
|
||||
{SMEM_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
|
||||
{SMEM_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
|
||||
{SMEM_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
|
||||
{SMEM_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
|
||||
{SMEM_Q6, "adsp", .nb.notifier_call = restart_notifier_cb},
|
||||
};
|
||||
|
||||
/**
|
||||
* smem_phys_to_virt() - Convert a physical base and offset to virtual address
|
||||
*
|
||||
* @base: physical base address to check
|
||||
* @offset: offset from the base to get the final address
|
||||
* @returns: virtual SMEM address; NULL for failure
|
||||
*
|
||||
* Takes a physical address and an offset and checks if the resulting physical
|
||||
* address would fit into one of the smem regions. If so, returns the
|
||||
* corresponding virtual address. Otherwise returns NULL.
|
||||
*/
|
||||
static void *smem_phys_to_virt(phys_addr_t base, unsigned offset)
|
||||
{
|
||||
int i;
|
||||
phys_addr_t phys_addr;
|
||||
resource_size_t size;
|
||||
|
||||
if (OVERFLOW_ADD_UNSIGNED(phys_addr_t, base, offset))
|
||||
return NULL;
|
||||
|
||||
if (!smem_areas) {
|
||||
/*
|
||||
* Early boot - no area configuration yet, so default
|
||||
* to using the main memory region.
|
||||
*
|
||||
* To remove the MSM_SHARED_RAM_BASE and the static
|
||||
* mapping of SMEM in the future, add dump_stack()
|
||||
* to identify the early callers of smem_get_entry()
|
||||
* (which calls this function) and replace those calls
|
||||
* with a new function that knows how to lookup the
|
||||
* SMEM base address before SMEM has been probed.
|
||||
*/
|
||||
phys_addr = msm_shared_ram_phys;
|
||||
size = MSM_SHARED_RAM_SIZE;
|
||||
|
||||
if (base >= phys_addr && base + offset < phys_addr + size) {
|
||||
if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
|
||||
(uintptr_t)MSM_SHARED_RAM_BASE, offset)) {
|
||||
pr_err("%s: overflow %p %x\n", __func__,
|
||||
MSM_SHARED_RAM_BASE, offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return MSM_SHARED_RAM_BASE + offset;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_smem_areas; ++i) {
|
||||
phys_addr = smem_areas[i].phys_addr;
|
||||
size = smem_areas[i].size;
|
||||
|
||||
if (base < phys_addr || base + offset >= phys_addr + size)
|
||||
continue;
|
||||
|
||||
if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
|
||||
(uintptr_t)smem_areas[i].virt_addr, offset)) {
|
||||
pr_err("%s: overflow %p %x\n", __func__,
|
||||
smem_areas[i].virt_addr, offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return smem_areas[i].virt_addr + offset;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* smem_virt_to_phys() - Convert SMEM address to physical address.
|
||||
*
|
||||
* @smem_address: Address of SMEM item (returned by smem_alloc(), etc)
|
||||
* @returns: Physical address (or NULL if there is a failure)
|
||||
*
|
||||
* This function should only be used if an SMEM item needs to be handed
|
||||
* off to a DMA engine.
|
||||
*/
|
||||
phys_addr_t smem_virt_to_phys(void *smem_address)
|
||||
{
|
||||
phys_addr_t phys_addr = 0;
|
||||
int i;
|
||||
void *vend;
|
||||
|
||||
if (!smem_areas)
|
||||
return phys_addr;
|
||||
|
||||
for (i = 0; i < num_smem_areas; ++i) {
|
||||
vend = (void *)(smem_areas[i].virt_addr + smem_areas[i].size);
|
||||
|
||||
if (smem_address >= smem_areas[i].virt_addr &&
|
||||
smem_address < vend) {
|
||||
phys_addr = smem_address - smem_areas[i].virt_addr;
|
||||
phys_addr += smem_areas[i].phys_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phys_addr;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_virt_to_phys);
|
||||
|
||||
/* smem_alloc returns the pointer to smem item if it is already allocated.
|
||||
* Otherwise, it returns NULL.
|
||||
*/
|
||||
void *smem_alloc(unsigned id, unsigned size)
|
||||
{
|
||||
return smem_find(id, size);
|
||||
}
|
||||
EXPORT_SYMBOL(smem_alloc);
|
||||
|
||||
void *smem_find(unsigned id, unsigned size_in)
|
||||
{
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
|
||||
ptr = smem_get_entry(id, &size);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
size_in = ALIGN(size_in, 8);
|
||||
if (size_in != size) {
|
||||
pr_err("smem_find(%d, %d): wrong size %d\n",
|
||||
id, size_in, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_find);
|
||||
|
||||
/* smem_alloc2 returns the pointer to smem item. If it is not allocated,
|
||||
* it allocates it and then returns the pointer to it.
|
||||
*/
|
||||
void *smem_alloc2(unsigned id, unsigned size_in)
|
||||
{
|
||||
struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
|
||||
struct smem_heap_entry *toc = shared->heap_toc;
|
||||
unsigned long flags;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!shared->heap_info.initialized) {
|
||||
pr_err("%s: smem heap info not initialized\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (id >= SMEM_NUM_ITEMS)
|
||||
return NULL;
|
||||
|
||||
size_in = ALIGN(size_in, 8);
|
||||
remote_spin_lock_irqsave(&remote_spinlock, flags);
|
||||
if (toc[id].allocated) {
|
||||
SMEM_DBG("%s: %u already allocated\n", __func__, id);
|
||||
if (size_in != toc[id].size)
|
||||
pr_err("%s: wrong size %u (expected %u)\n",
|
||||
__func__, toc[id].size, size_in);
|
||||
else
|
||||
ret = (void *)(MSM_SHARED_RAM_BASE + toc[id].offset);
|
||||
} else if (id > SMEM_FIXED_ITEM_LAST) {
|
||||
SMEM_DBG("%s: allocating %u\n", __func__, id);
|
||||
if (shared->heap_info.heap_remaining >= size_in) {
|
||||
toc[id].offset = shared->heap_info.free_offset;
|
||||
toc[id].size = size_in;
|
||||
wmb();
|
||||
toc[id].allocated = 1;
|
||||
|
||||
shared->heap_info.free_offset += size_in;
|
||||
shared->heap_info.heap_remaining -= size_in;
|
||||
ret = (void *)(MSM_SHARED_RAM_BASE + toc[id].offset);
|
||||
} else
|
||||
pr_err("%s: not enough memory %u (required %u)\n",
|
||||
__func__, shared->heap_info.heap_remaining,
|
||||
size_in);
|
||||
}
|
||||
wmb();
|
||||
remote_spin_unlock_irqrestore(&remote_spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_alloc2);
|
||||
|
||||
void *smem_get_entry(unsigned id, unsigned *size)
|
||||
{
|
||||
struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
|
||||
struct smem_heap_entry *toc = shared->heap_toc;
|
||||
int use_spinlocks = spinlocks_initialized;
|
||||
void *ret = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (id >= SMEM_NUM_ITEMS)
|
||||
return ret;
|
||||
|
||||
if (use_spinlocks)
|
||||
remote_spin_lock_irqsave(&remote_spinlock, flags);
|
||||
/* toc is in device memory and cannot be speculatively accessed */
|
||||
if (toc[id].allocated) {
|
||||
phys_addr_t phys_base;
|
||||
|
||||
*size = toc[id].size;
|
||||
barrier();
|
||||
|
||||
phys_base = toc[id].reserved & BASE_ADDR_MASK;
|
||||
if (!phys_base)
|
||||
phys_base = (phys_addr_t)msm_shared_ram_phys;
|
||||
ret = smem_phys_to_virt(phys_base, toc[id].offset);
|
||||
} else {
|
||||
*size = 0;
|
||||
}
|
||||
if (use_spinlocks)
|
||||
remote_spin_unlock_irqrestore(&remote_spinlock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_get_entry);
|
||||
|
||||
|
||||
/**
|
||||
* smem_get_remote_spinlock - Remote spinlock pointer for unit testing.
|
||||
*
|
||||
* @returns: pointer to SMEM remote spinlock
|
||||
*/
|
||||
remote_spinlock_t *smem_get_remote_spinlock(void)
|
||||
{
|
||||
return &remote_spinlock;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_get_remote_spinlock);
|
||||
|
||||
static int restart_notifier_cb(struct notifier_block *this,
|
||||
unsigned long code,
|
||||
void *data)
|
||||
{
|
||||
if (code == SUBSYS_AFTER_SHUTDOWN) {
|
||||
struct restart_notifier_block *notifier;
|
||||
|
||||
notifier = container_of(this,
|
||||
struct restart_notifier_block, nb);
|
||||
SMEM_DBG("%s: ssrestart for processor %d ('%s')\n",
|
||||
__func__, notifier->processor,
|
||||
notifier->name);
|
||||
|
||||
remote_spin_release(&remote_spinlock, notifier->processor);
|
||||
remote_spin_release_all(notifier->processor);
|
||||
|
||||
if (smem_ramdump_dev) {
|
||||
int ret;
|
||||
|
||||
SMEM_DBG("%s: saving ramdump\n", __func__);
|
||||
/*
|
||||
* XPU protection does not currently allow the
|
||||
* auxiliary memory regions to be dumped. If this
|
||||
* changes, then num_smem_areas + 1 should be passed
|
||||
* into do_elf_ramdump() to dump all regions.
|
||||
*/
|
||||
ret = do_elf_ramdump(smem_ramdump_dev,
|
||||
smem_ramdump_segments, 1);
|
||||
if (ret < 0)
|
||||
pr_err("%s: unable to dump smem %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static __init int modem_restart_late_init(void)
|
||||
{
|
||||
int i;
|
||||
void *handle;
|
||||
struct restart_notifier_block *nb;
|
||||
|
||||
smem_ramdump_dev = create_ramdump_device("smem", NULL);
|
||||
if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
|
||||
pr_err("%s: Unable to create smem ramdump device.\n",
|
||||
__func__);
|
||||
smem_ramdump_dev = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
|
||||
nb = &restart_notifiers[i];
|
||||
handle = subsys_notif_register_notifier(nb->name, &nb->nb);
|
||||
SMEM_DBG("%s: registering notif for '%s', handle=%p\n",
|
||||
__func__, nb->name, handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(modem_restart_late_init);
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/smem_log.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include <asm/arch_timer.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_
|
||||
#define _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_
|
||||
|
||||
#include <linux/remote_spinlock.h>
|
||||
|
||||
#include <mach/ramdump.h>
|
||||
|
||||
#define SMEM_SPINLOCK_SMEM_ALLOC "S:3"
|
||||
extern remote_spinlock_t remote_spinlock;
|
||||
extern int spinlocks_initialized;
|
||||
|
||||
#define SMD_HEAP_SIZE 512
|
||||
|
||||
struct smem_heap_info {
|
||||
unsigned initialized;
|
||||
unsigned free_offset;
|
||||
unsigned heap_remaining;
|
||||
unsigned reserved;
|
||||
};
|
||||
|
||||
struct smem_heap_entry {
|
||||
unsigned allocated;
|
||||
unsigned offset;
|
||||
unsigned size;
|
||||
unsigned reserved; /* bits 1:0 reserved, bits 31:2 aux smem base addr */
|
||||
};
|
||||
#define BASE_ADDR_MASK 0xfffffffc
|
||||
|
||||
struct smem_proc_comm {
|
||||
unsigned command;
|
||||
unsigned status;
|
||||
unsigned data1;
|
||||
unsigned data2;
|
||||
};
|
||||
|
||||
struct smem_shared {
|
||||
struct smem_proc_comm proc_comm[4];
|
||||
unsigned version[32];
|
||||
struct smem_heap_info heap_info;
|
||||
struct smem_heap_entry heap_toc[SMD_HEAP_SIZE];
|
||||
};
|
||||
|
||||
struct smem_area {
|
||||
phys_addr_t phys_addr;
|
||||
resource_size_t size;
|
||||
void __iomem *virt_addr;
|
||||
};
|
||||
|
||||
extern uint32_t num_smem_areas;
|
||||
extern struct smem_area *smem_areas;
|
||||
|
||||
extern struct ramdump_segment *smem_ramdump_segments;
|
||||
|
||||
/* used for unit testing spinlocks */
|
||||
remote_spinlock_t *smem_get_remote_spinlock(void);
|
||||
#endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include <mach/msm_ipc_logging.h>
|
||||
#include "smp2p_private_api.h"
|
||||
#include "smp2p_private.h"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <linux/termios.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/remote_spinlock.h>
|
||||
#include "smd_private.h"
|
||||
#include "smem_private.h"
|
||||
#include "smp2p_private.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/remote_spinlock.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include "smd_private.h"
|
||||
#include <mach/msm_smem.h>
|
||||
#include "smem_private.h"
|
||||
#include "smp2p_private.h"
|
||||
#include "smp2p_test_common.h"
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <mach/socinfo.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#include "smd_private.h"
|
||||
#include "boot_stats.h"
|
||||
|
||||
#define BUILD_ID_LENGTH 32
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
#include <mach/socinfo.h>
|
||||
|
||||
#if defined(CONFIG_MSM_SMD)
|
||||
#include "smd_private.h"
|
||||
#include <mach/msm_smem.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#endif
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* linux/arch/arm/mach-msm/gpio.c
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <asm/mach/irq.h>
|
||||
#include <mach/gpiomux.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include <mach/proc_comm.h>
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <mach/iommu_hw-v0.h>
|
||||
#include <mach/msm_iommu_priv.h>
|
||||
#include <mach/iommu.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
|
||||
#define MRC(reg, processor, op1, crn, crm, op2) \
|
||||
__asm__ __volatile__ ( \
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <mach/sps.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#define PAGE_SIZE_2K 2048
|
||||
#define PAGE_SIZE_4K 4096
|
||||
#define WRITE 1
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/msm_smem.h>
|
||||
#include "ipa_i.h"
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user