644 lines
16 KiB
C
644 lines
16 KiB
C
#include <linux/io.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/bug.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/smc.h>
|
|
#include <linux/shm_ipc.h>
|
|
#include <soc/samsung/exynos-pmu.h>
|
|
#include <soc/samsung/pmu-cp.h>
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
static u32 exynos_smc_read(enum cp_control reg)
|
|
{
|
|
u32 cp_ctrl;
|
|
u32 cp_ctrl_low;
|
|
u32 cp_ctrl_high;
|
|
|
|
cp_ctrl = exynos_smc(SMC_ID, READ_CTRL, 0, reg);
|
|
if (!(cp_ctrl & 0xffff)) {
|
|
cp_ctrl >>= 16;
|
|
cp_ctrl_low = cp_ctrl;
|
|
} else {
|
|
pr_err("%s: ERR! read Fail: %d\n", __func__, cp_ctrl & 0xffff);
|
|
|
|
return -1;
|
|
}
|
|
|
|
cp_ctrl = exynos_smc(SMC_ID, READ_CTRL, 1, reg);
|
|
if (!(cp_ctrl & 0xffff)) {
|
|
cp_ctrl >>= 16;
|
|
cp_ctrl_high = cp_ctrl;
|
|
} else {
|
|
pr_err("%s: ERR! read Fail: %d\n", __func__, cp_ctrl & 0xffff);
|
|
|
|
return -1;
|
|
}
|
|
|
|
return (cp_ctrl_high << 16) | cp_ctrl_low;
|
|
}
|
|
|
|
static u32 exynos_smc_write(enum cp_control reg, u32 value)
|
|
{
|
|
int ret = 0;
|
|
|
|
ret = exynos_smc(SMC_ID, WRITE_CTRL, value, reg);
|
|
if (ret > 0) {
|
|
pr_err("%s: ERR! CP_CTRL Write Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/* reset cp */
|
|
int exynos_cp_reset(void)
|
|
{
|
|
int ret = 0;
|
|
u32 __maybe_unused cp_ctrl;
|
|
u32 __maybe_unused cp_ctrl2;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
/* set sys_pwr_cfg registers */
|
|
exynos_sys_powerdown_conf_cp();
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
#if defined(CONFIG_SOC_EXYNOS7872)
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | SELECT_DUMP_PC_NO_PG);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Reset Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
} else {
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
#endif
|
|
|
|
/* assert cp_reset */
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | CP_RESET_SET | CP_PWRON);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Reset Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
} else {
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
#else
|
|
#if defined(CONFIG_SOC_EXYNOS7872)
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl |= SELECT_DUMP_PC_NO_PG;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Reset Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl2);
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl, cp_ctrl2);
|
|
#endif
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl |= CP_RESET_SET | CP_PWRON;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Reset Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl2);
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl, cp_ctrl2);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* release cp */
|
|
int exynos_cp_release(void)
|
|
{
|
|
u32 cp_ctrl;
|
|
int ret = 0;
|
|
int wait_count = 0;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_S);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_S, cp_ctrl | CP_START | CP_POWER_ON);
|
|
if (ret < 0)
|
|
pr_err("ERR! CP Release Fail: %d\n", ret);
|
|
else
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_S));
|
|
#else
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_S, &cp_ctrl);
|
|
cp_ctrl |= (CP_START | CP_POWER_ON);
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_S, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("ERR! CP Release Fail: %d\n", ret);
|
|
else {
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_S, &cp_ctrl);
|
|
pr_info("%s, PMU_CP_CTRL_S[0x%08x]\n", __func__, cp_ctrl);
|
|
}
|
|
#endif
|
|
|
|
while (1) {
|
|
wait_count++;
|
|
|
|
/* some delay */
|
|
cpu_relax();
|
|
usleep_range(80, 100);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CENTRAL_SEQ_CP_STATUS, &cp_ctrl);
|
|
cp_ctrl = (cp_ctrl & CENTRAL_SEQ_CP_STATUS_MASK)
|
|
>> CENTRAL_SEQ_CP_STATUS_SHIFT;
|
|
|
|
/* Checek reset deassert */
|
|
if (cp_ctrl == 0x0)
|
|
break;
|
|
|
|
if (wait_count == 100) {
|
|
pr_err("CENTRAL_SEQ_CP_STATUS is not 0x0 within 10ms\n");
|
|
pr_err("CP reset deassert fail\n");
|
|
panic("CP reset deassert fail\n");
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* clear cp active */
|
|
int exynos_cp_active_clear(void)
|
|
{
|
|
u32 cp_ctrl;
|
|
int ret = 0;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | CP_ACTIVE_REQ_CLR);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP active_clear Fail: %d\n", __func__, ret);
|
|
else
|
|
pr_info("%s: cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
#else
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl |= CP_ACTIVE_REQ_CLR;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP active_clear Fail: %d\n", __func__, ret);
|
|
else {
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
pr_info("%s, PMU_CP_CTRL_NS[0x%08x]\n", __func__, cp_ctrl);
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/* clear cp_reset_req from cp */
|
|
int exynos_clear_cp_reset(void)
|
|
{
|
|
u32 cp_ctrl;
|
|
int ret = 0;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | CP_RESET_REQ_CLR);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP clear_cp_reset Fail: %d\n", __func__, ret);
|
|
else
|
|
pr_info("%s: cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
#else
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl |= CP_RESET_REQ_CLR;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP clear_cp_reset Fail: %d\n", __func__, ret);
|
|
else {
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
pr_info("%s, PMU_CP_CTRL_NS[0x%08x]\n", __func__, cp_ctrl);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int exynos_get_cp_power_status(void)
|
|
{
|
|
u32 cp_state;
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
cp_state = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_state == -1)
|
|
return -1;
|
|
#else
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_state);
|
|
#endif
|
|
|
|
if (cp_state & CP_PWRON)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int exynos_cp_init(void)
|
|
{
|
|
u32 __maybe_unused cp_ctrl;
|
|
int ret = 0;
|
|
|
|
pr_info("%s: cp_ctrl init\n", __func__);
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl & ~CP_RESET_SET & ~CP_PWRON);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n", __func__, ret);
|
|
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_S);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_S, cp_ctrl & ~CP_START);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n", __func__, ret);
|
|
#else
|
|
exynos_pmu_cp_init();
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl &= ~CP_RESET_SET;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP_RESET_SET Fail: %d\n", __func__, ret);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl &= ~CP_PWRON;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP_PWRON Fail: %d\n", __func__, ret);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl &= ~CP_START;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! CP_START Fail: %d\n", __func__, ret);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_S, &cp_ctrl);
|
|
pr_err("EXYNOS_PMU_CP_CTRL_S: %08X\n", cp_ctrl);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
pr_err("EXYNOS_PMU_CP_CTRL_NS: %08X\n", cp_ctrl);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int exynos_set_cp_power_onoff(enum cp_mode mode)
|
|
{
|
|
u32 cp_ctrl;
|
|
u32 __maybe_unused cp_ctrl2;
|
|
int ret = 0;
|
|
int wait_count = 0;
|
|
|
|
pr_info("%s: mode[%d]\n", __func__, mode);
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
/* set power on/off */
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
if (mode == CP_POWER_ON) {
|
|
if (!(cp_ctrl & CP_PWRON)) {
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | CP_PWRON);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n", __func__, ret);
|
|
else
|
|
pr_info("%s: CP Power: [0x%08X] -> [0x%08X]\n",
|
|
__func__, cp_ctrl, exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_S);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_S, cp_ctrl | CP_START);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n", __func__, ret);
|
|
else
|
|
pr_info("%s: CP Start: [0x%08X] -> [0x%08X]\n", __func__,
|
|
cp_ctrl, exynos_smc_read(CP_CTRL_S));
|
|
|
|
while (1) {
|
|
wait_count++;
|
|
|
|
/* some delay */
|
|
cpu_relax();
|
|
usleep_range(80, 100);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CENTRAL_SEQ_CP_STATUS, &cp_ctrl);
|
|
cp_ctrl = (cp_ctrl & CENTRAL_SEQ_CP_STATUS_MASK)
|
|
>> CENTRAL_SEQ_CP_STATUS_SHIFT;
|
|
|
|
/* Checek reset deassert */
|
|
if (cp_ctrl == 0x0)
|
|
break;
|
|
|
|
if (wait_count == 100) {
|
|
pr_err("CENTRAL_SEQ_CP_STATUS is not 0x0 within 10ms\n");
|
|
pr_err("CP reset deassert fail\n");
|
|
panic("CP reset deassert fail\n");
|
|
}
|
|
}
|
|
} else {
|
|
/* set sys_pwr_cfg registers */
|
|
exynos_sys_powerdown_conf_cp();
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl & ~CP_PWRON);
|
|
if (ret < 0)
|
|
pr_err("ERR! write Fail: %d\n", ret);
|
|
else
|
|
pr_info("%s: CP Power Down: [0x%08X] -> [0x%08X]\n", __func__,
|
|
cp_ctrl, exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
#else
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
if (mode == CP_POWER_ON) {
|
|
if (!(cp_ctrl & CP_PWRON)) {
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl | CP_PWRON);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n",
|
|
__func__, ret);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl2);
|
|
pr_info("EXYNOS_PMU_CP_CTRL_NS: [0x%08X] -> [0x%08X]\n",
|
|
cp_ctrl, cp_ctrl2);
|
|
}
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_S, &cp_ctrl);
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_S, cp_ctrl | CP_START);
|
|
if (ret < 0)
|
|
pr_err("%s: ERR! write Fail: %d\n", __func__, ret);
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_S, &cp_ctrl2);
|
|
pr_info("EXYNOS_PMU_CP_CTRL_S: [0x%08X] -> [0x%08X]\n",
|
|
cp_ctrl, cp_ctrl2);
|
|
|
|
while (1) {
|
|
wait_count++;
|
|
|
|
/* some delay */
|
|
cpu_relax();
|
|
usleep_range(80, 100);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CENTRAL_SEQ_CP_STATUS, &cp_ctrl);
|
|
cp_ctrl = (cp_ctrl & CENTRAL_SEQ_CP_STATUS_MASK)
|
|
>> CENTRAL_SEQ_CP_STATUS_SHIFT;
|
|
|
|
/* Checek reset deassert */
|
|
if (cp_ctrl == 0x0)
|
|
break;
|
|
|
|
if (wait_count == 100) {
|
|
pr_err("CENTRAL_SEQ_CP_STATUS is not 0x0 within 10ms\n");
|
|
pr_err("CP reset deassert fail\n");
|
|
panic("CP reset deassert fail\n");
|
|
}
|
|
}
|
|
} else {
|
|
/* set sys_pwr_cfg registers */
|
|
exynos_sys_powerdown_conf_cp();
|
|
|
|
ret = exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl &= ~CP_PWRON;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0)
|
|
pr_err("ERR! write Fail: %d\n", ret);
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
void exynos_sys_powerdown_conf_cp(void)
|
|
{
|
|
u32 cp_stat = 0;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
mdelay(10);
|
|
exynos_pmu_read(EXYNOS_PMU_CP_STAT, &cp_stat);
|
|
pr_info("%s : cp_stat : 0x%08x\n", __func__, cp_stat);
|
|
|
|
exynos_pmu_write(EXYNOS_PMU_CENTRAL_SEQ_CP_CONFIGURATION, 0);
|
|
exynos_pmu_write(EXYNOS_PMU_RESET_AHEAD_CP_SYS_PWR_REG, 0);
|
|
exynos_pmu_write(EXYNOS_PMU_CLEANY_BUS_CP_SYS_PWR_REG, cp_stat & CP_PWRDN_DONE);
|
|
exynos_pmu_write(EXYNOS_PMU_LOGIC_RESET_CP_SYS_PWR_REG, 0);
|
|
exynos_pmu_write(EXYNOS_PMU_TCXO_GATE_SYS_PWR_REG, 0);
|
|
exynos_pmu_write(EXYNOS_PMU_CP_DISABLE_ISO_SYS_PWR_REG, 1);
|
|
exynos_pmu_write(EXYNOS_PMU_RESET_ISO_SYS_PWR_REG, 0);
|
|
exynos_pmu_write(EXYNOS_PMU_PC_SYS_PWR_REG, 0);
|
|
}
|
|
|
|
#if defined(CONFIG_CP_SECURE_BOOT)
|
|
int exynos_enable_cp_dump_pc(void)
|
|
{
|
|
int ret = 0;
|
|
u32 __maybe_unused cp_ctrl;
|
|
|
|
pr_err("%s +++", __func__);
|
|
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl | SELECT_DUMP_PC_NO_PG);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! Enable CP dump pc Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
} else {
|
|
pr_err("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int exynos_disable_cp_dump_pc(void)
|
|
{
|
|
int ret = 0;
|
|
u32 __maybe_unused cp_ctrl;
|
|
|
|
pr_err("%s +++", __func__);
|
|
|
|
cp_ctrl = exynos_smc_read(CP_CTRL_NS);
|
|
if (cp_ctrl == -1)
|
|
return -1;
|
|
|
|
ret = exynos_smc_write(CP_CTRL_NS, cp_ctrl & ~SELECT_DUMP_PC_NO_PG);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! Disable CP dump pc Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
} else {
|
|
pr_err("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl,
|
|
exynos_smc_read(CP_CTRL_NS));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
int exynos_enable_cp_dump_pc(void)
|
|
{
|
|
int ret = 0;
|
|
u32 __maybe_unused cp_ctrl;
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl |= SELECT_DUMP_PC_NO_PG;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Enable CP dump pc Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl2);
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl, cp_ctrl2);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int exynos_disable_cp_dump_pc(void)
|
|
{
|
|
int ret = 0;
|
|
u32 __maybe_unused cp_ctrl;
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl);
|
|
cp_ctrl &= ~SELECT_DUMP_PC_NO_PG;
|
|
|
|
ret = exynos_pmu_write(EXYNOS_PMU_CP_CTRL_NS, cp_ctrl);
|
|
if (ret < 0) {
|
|
pr_err("%s: ERR! CP Disable CP dump pc Fail: %d\n", __func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP_CTRL_NS, &cp_ctrl2);
|
|
pr_info("%s, cp_ctrl[0x%08x] -> [0x%08x]\n", __func__, cp_ctrl, cp_ctrl2);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(CONFIG_CP_SECURE_BOOT)
|
|
static void __init set_shdmem_size(unsigned memsz)
|
|
{
|
|
u32 tmp;
|
|
|
|
pr_info("[Modem_IF] Set shared mem size: %d MB\n", memsz);
|
|
|
|
memsz *= 256;
|
|
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MEM_CONFIG0, memsz);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_ADDR_RNG, memsz);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP2AP_MEM_CONFIG0, &tmp);
|
|
pr_info("[Modem_IF] EXYNOS_PMU_CP2AP_MEM_CONFIG0: 0x%X\n", tmp);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP2AP_ADDR_RNG, &tmp);
|
|
pr_info("[Modem_IF] EXYNOS_PMU_CP2AP_ADDR_RNG: 0x%X\n", tmp);
|
|
}
|
|
|
|
static void __init set_shdmem_base(unsigned long base)
|
|
{
|
|
u32 tmp, base_addr;
|
|
|
|
pr_info("[Modem_IF]Set shared mem baseaddr : 0x%x\n", (unsigned int)base);
|
|
|
|
base_addr = (u32)(base >> 12);
|
|
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MEM_CONFIG1, base_addr);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MEM_CONFIG2, base_addr);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP2AP_MEM_CONFIG1, &tmp);
|
|
pr_info("[Modem_IF] EXYNOS_PMU_CP2AP_MEM_CONFIG1: 0x%X\n", tmp);
|
|
|
|
exynos_pmu_read(EXYNOS_PMU_CP2AP_MEM_CONFIG2, &tmp);
|
|
pr_info("[Modem_IF] EXYNOS_PMU_CP2AP_MEM_CONFIG2: 0x%X\n", tmp);
|
|
}
|
|
|
|
#endif
|
|
|
|
int exynos_pmu_cp_init(void)
|
|
{
|
|
|
|
#if !defined(CONFIG_CP_SECURE_BOOT)
|
|
unsigned shm_size;
|
|
unsigned long shm_base;
|
|
|
|
shm_size = shm_get_phys_size();
|
|
shm_base = shm_get_phys_base();
|
|
|
|
/* Change size from byte to Mega byte*/
|
|
shm_size /= 1048510;
|
|
|
|
set_shdmem_size(shm_size);
|
|
set_shdmem_base(shm_base);
|
|
|
|
/* set MIF access window for CP */
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN0, 0xffffffff);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN1, 0xffffffff);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN2, 0xffffffff);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN3, 0xffffffff);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN4, 0xffffffff);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_MIF_ACCESS_WIN5, 0xffffffff);
|
|
|
|
/* set PERI access window for CP */
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN0, 0x20001000);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN1, 0x20001000);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN2, 0x20001000);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN3, 0x20001000);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN4, 0x20001000);
|
|
exynos_pmu_write(EXYNOS_PMU_CP2AP_PERI_ACCESS_WIN5, 0x20001000);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|