Merge "power: reset: Skip emmc_dload sysfs entry creation"
This commit is contained in:
commit
c68dd38b5e
2 changed files with 165 additions and 38 deletions
|
@ -46,6 +46,12 @@ Required properties:
|
|||
-compatible: "qcom,msm-imem-restart_reason
|
||||
-reg: start address and size of restart_reason region in imem
|
||||
|
||||
Download Mode Type:
|
||||
-------------------
|
||||
Required properties:
|
||||
-compatible: "qcom,msm-imem-dload-type"
|
||||
-reg: start address and size of dload type region in imem
|
||||
|
||||
Download Mode:
|
||||
--------------
|
||||
Required properties:
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#define EMERGENCY_DLOAD_MAGIC1 0x322A4F99
|
||||
#define EMERGENCY_DLOAD_MAGIC2 0xC67E4350
|
||||
#define EMERGENCY_DLOAD_MAGIC3 0x77777777
|
||||
#define EMMC_DLOAD_TYPE 0x2
|
||||
|
||||
#define SCM_IO_DISABLE_PMIC_ARBITER 1
|
||||
#define SCM_IO_DEASSERT_PS_HOLD 2
|
||||
|
@ -46,12 +47,20 @@
|
|||
|
||||
|
||||
static int restart_mode;
|
||||
void *restart_reason;
|
||||
static void *restart_reason, *dload_type_addr;
|
||||
static bool scm_pmic_arbiter_disable_supported;
|
||||
static bool scm_deassert_ps_hold_supported;
|
||||
/* Download mode master kill-switch */
|
||||
static void __iomem *msm_ps_hold;
|
||||
static phys_addr_t tcsr_boot_misc_detect;
|
||||
static void scm_disable_sdi(void);
|
||||
|
||||
/* Runtime could be only changed value once.
|
||||
* There is no API from TZ to re-enable the registers.
|
||||
* So the SDI cannot be re-enabled when it already by-passed.
|
||||
*/
|
||||
static int download_mode = 1;
|
||||
static struct kobject dload_kobj;
|
||||
|
||||
#ifdef CONFIG_QCOM_DLOAD_MODE
|
||||
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
|
||||
|
@ -64,9 +73,23 @@ static void *emergency_dload_mode_addr;
|
|||
static bool scm_dload_supported;
|
||||
|
||||
static int dload_set(const char *val, struct kernel_param *kp);
|
||||
static int download_mode = 1;
|
||||
/* interface for exporting attributes */
|
||||
struct reset_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf);
|
||||
size_t (*store)(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
};
|
||||
#define to_reset_attr(_attr) \
|
||||
container_of(_attr, struct reset_attribute, attr)
|
||||
#define RESET_ATTR(_name, _mode, _show, _store) \
|
||||
static struct reset_attribute reset_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
module_param_call(download_mode, dload_set, param_get_int,
|
||||
&download_mode, 0644);
|
||||
|
||||
static int panic_prep_restart(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
|
@ -170,7 +193,10 @@ static int dload_set(const char *val, struct kernel_param *kp)
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
#define set_dload_mode(x) do {} while (0)
|
||||
static void set_dload_mode(int on)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void enable_emergency_dload_mode(void)
|
||||
{
|
||||
|
@ -183,6 +209,26 @@ static bool get_dload_mode(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void scm_disable_sdi(void)
|
||||
{
|
||||
int ret;
|
||||
struct scm_desc desc = {
|
||||
.args[0] = 1,
|
||||
.args[1] = 0,
|
||||
.arginfo = SCM_ARGS(2),
|
||||
};
|
||||
|
||||
/* Needed to bypass debug image on some chips */
|
||||
if (!is_scm_armv8())
|
||||
ret = scm_call_atomic2(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
|
||||
else
|
||||
ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART), &desc);
|
||||
if (ret)
|
||||
pr_err("Failed to disable secure wdog debug: %d\n", ret);
|
||||
}
|
||||
|
||||
void msm_set_restart_mode(int mode)
|
||||
{
|
||||
restart_mode = mode;
|
||||
|
@ -320,13 +366,6 @@ static void deassert_ps_hold(void)
|
|||
|
||||
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||
{
|
||||
int ret;
|
||||
struct scm_desc desc = {
|
||||
.args[0] = 1,
|
||||
.args[1] = 0,
|
||||
.arginfo = SCM_ARGS(2),
|
||||
};
|
||||
|
||||
pr_notice("Going down for restart now\n");
|
||||
|
||||
msm_restart_prepare(cmd);
|
||||
|
@ -341,16 +380,7 @@ static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
|||
msm_trigger_wdog_bite();
|
||||
#endif
|
||||
|
||||
/* Needed to bypass debug image on some chips */
|
||||
if (!is_scm_armv8())
|
||||
ret = scm_call_atomic2(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
|
||||
else
|
||||
ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART), &desc);
|
||||
if (ret)
|
||||
pr_err("Failed to disable secure wdog debug: %d\n", ret);
|
||||
|
||||
scm_disable_sdi();
|
||||
halt_spmi_pmic_arbiter();
|
||||
deassert_ps_hold();
|
||||
|
||||
|
@ -359,27 +389,11 @@ static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
|||
|
||||
static void do_msm_poweroff(void)
|
||||
{
|
||||
int ret;
|
||||
struct scm_desc desc = {
|
||||
.args[0] = 1,
|
||||
.args[1] = 0,
|
||||
.arginfo = SCM_ARGS(2),
|
||||
};
|
||||
|
||||
pr_notice("Powering off the SoC\n");
|
||||
#ifdef CONFIG_QCOM_DLOAD_MODE
|
||||
|
||||
set_dload_mode(0);
|
||||
#endif
|
||||
scm_disable_sdi();
|
||||
qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
|
||||
/* Needed to bypass debug image on some chips */
|
||||
if (!is_scm_armv8())
|
||||
ret = scm_call_atomic2(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
|
||||
else
|
||||
ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
|
||||
SCM_WDOG_DEBUG_BOOT_PART), &desc);
|
||||
if (ret)
|
||||
pr_err("Failed to disable wdog debug: %d\n", ret);
|
||||
|
||||
halt_spmi_pmic_arbiter();
|
||||
deassert_ps_hold();
|
||||
|
@ -389,6 +403,84 @@ static void do_msm_poweroff(void)
|
|||
return;
|
||||
}
|
||||
|
||||
static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct reset_attribute *reset_attr = to_reset_attr(attr);
|
||||
ssize_t ret = -EIO;
|
||||
|
||||
if (reset_attr->show)
|
||||
ret = reset_attr->show(kobj, attr, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct reset_attribute *reset_attr = to_reset_attr(attr);
|
||||
ssize_t ret = -EIO;
|
||||
|
||||
if (reset_attr->store)
|
||||
ret = reset_attr->store(kobj, attr, buf, count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct sysfs_ops reset_sysfs_ops = {
|
||||
.show = attr_show,
|
||||
.store = attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type reset_ktype = {
|
||||
.sysfs_ops = &reset_sysfs_ops,
|
||||
};
|
||||
|
||||
static ssize_t show_emmc_dload(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
uint32_t read_val, show_val;
|
||||
|
||||
read_val = __raw_readl(dload_type_addr);
|
||||
if (read_val == EMMC_DLOAD_TYPE)
|
||||
show_val = 1;
|
||||
else
|
||||
show_val = 0;
|
||||
|
||||
return snprintf(buf, sizeof(show_val), "%u\n", show_val);
|
||||
}
|
||||
|
||||
static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint32_t enabled;
|
||||
int ret;
|
||||
|
||||
ret = kstrtouint(buf, 0, &enabled);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!((enabled == 0) || (enabled == 1)))
|
||||
return -EINVAL;
|
||||
|
||||
if (enabled == 1)
|
||||
__raw_writel(EMMC_DLOAD_TYPE, dload_type_addr);
|
||||
else
|
||||
__raw_writel(0, dload_type_addr);
|
||||
|
||||
return count;
|
||||
}
|
||||
RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);
|
||||
|
||||
static struct attribute *reset_attrs[] = {
|
||||
&reset_attr_emmc_dload.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group reset_attr_group = {
|
||||
.attrs = reset_attrs,
|
||||
};
|
||||
|
||||
static int msm_restart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -419,6 +511,33 @@ static int msm_restart_probe(struct platform_device *pdev)
|
|||
pr_err("unable to map imem EDLOAD mode offset\n");
|
||||
}
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL,
|
||||
"qcom,msm-imem-dload-type");
|
||||
if (!np) {
|
||||
pr_err("unable to find DT imem dload-type node\n");
|
||||
goto skip_sysfs_create;
|
||||
} else {
|
||||
dload_type_addr = of_iomap(np, 0);
|
||||
if (!dload_type_addr) {
|
||||
pr_err("unable to map imem dload-type offset\n");
|
||||
goto skip_sysfs_create;
|
||||
}
|
||||
}
|
||||
|
||||
ret = kobject_init_and_add(&dload_kobj, &reset_ktype,
|
||||
kernel_kobj, "%s", "dload");
|
||||
if (ret) {
|
||||
pr_err("%s:Error in creation kobject_add\n", __func__);
|
||||
kobject_put(&dload_kobj);
|
||||
goto skip_sysfs_create;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&dload_kobj, &reset_attr_group);
|
||||
if (ret) {
|
||||
pr_err("%s:Error in creation sysfs_create_group\n", __func__);
|
||||
kobject_del(&dload_kobj);
|
||||
}
|
||||
skip_sysfs_create:
|
||||
#endif
|
||||
np = of_find_compatible_node(NULL, NULL,
|
||||
"qcom,msm-imem-restart_reason");
|
||||
|
@ -454,6 +573,8 @@ static int msm_restart_probe(struct platform_device *pdev)
|
|||
|
||||
download_mode = scm_is_secure_device();
|
||||
set_dload_mode(download_mode);
|
||||
if (!download_mode)
|
||||
scm_disable_sdi();
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue