diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index d324f0a0c9bc..97af7175a348 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -677,3 +677,10 @@ error_read: error_alloc_fw_table: release_firmware(firmware); } + +void mhi_perform_soc_reset(struct mhi_controller *mhi_cntrl) +{ + mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->regs, + MHI_SOC_RESET_REQ_OFFSET, + MHI_SOC_RESET_REQ); +} diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 259a801823db..41a18e224c94 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -525,6 +525,12 @@ static int mhi_init_debugfs_mhi_vote_open(struct inode *inode, struct file *fp) return single_open(fp, mhi_debugfs_mhi_vote_show, inode->i_private); } +static int mhi_init_debugfs_mhi_regdump_open(struct inode *inode, + struct file *fp) +{ + return single_open(fp, mhi_debugfs_mhi_regdump_show, inode->i_private); +} + static const struct file_operations debugfs_state_ops = { .open = mhi_init_debugfs_mhi_states_open, .release = single_release, @@ -549,9 +555,18 @@ static const struct file_operations debugfs_vote_ops = { .read = seq_read, }; +static const struct file_operations debugfs_regdump_ops = { + .open = mhi_init_debugfs_mhi_regdump_open, + .release = single_release, + .read = seq_read, +}; + DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_reset_fops, NULL, mhi_debugfs_trigger_reset, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_soc_reset_fops, NULL, + mhi_debugfs_trigger_soc_reset, "%llu\n"); + void mhi_init_debugfs(struct mhi_controller *mhi_cntrl) { struct dentry *dentry; @@ -578,6 +593,11 @@ void mhi_init_debugfs(struct mhi_controller *mhi_cntrl) &debugfs_vote_ops); debugfs_create_file_unsafe("reset", 0444, dentry, mhi_cntrl, &debugfs_trigger_reset_fops); + debugfs_create_file_unsafe("regdump", 0444, dentry, mhi_cntrl, + &debugfs_regdump_ops); + debugfs_create_file_unsafe("soc_reset", 0444, dentry, mhi_cntrl, + &debugfs_trigger_soc_reset_fops); + mhi_cntrl->dentry = dentry; } diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index d5148f96794e..7a4541f91553 100644 --- a/drivers/bus/mhi/core/mhi_internal.h +++ b/drivers/bus/mhi/core/mhi_internal.h @@ -755,11 +755,13 @@ extern struct mhi_bus mhi_bus; struct mhi_controller *find_mhi_controller_by_name(const char *name); /* debug fs related functions */ +int mhi_debugfs_mhi_regdump_show(struct seq_file *m, void *d); int mhi_debugfs_mhi_vote_show(struct seq_file *m, void *d); int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d); int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d); int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d); int mhi_debugfs_trigger_reset(void *data, u64 val); +int mhi_debugfs_trigger_soc_reset(void *data, u64 val); void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl); void mhi_init_debugfs(struct mhi_controller *mhi_cntrl); @@ -966,6 +968,7 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan); void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl); void mhi_force_reg_write(struct mhi_controller *mhi_cntrl); +void mhi_perform_soc_reset(struct mhi_controller *mhi_cntrl); /* isr handlers */ irqreturn_t mhi_msi_handlr(int irq_number, void *dev); diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index 5e780a028a99..6e492d24b3f6 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -2088,6 +2088,64 @@ error_invalid_state: mutex_unlock(&mhi_chan->mutex); } +int mhi_debugfs_mhi_regdump_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + enum mhi_dev_state state; + enum mhi_ee ee; + int i, ret; + u32 val; + void __iomem *mhi_base = mhi_cntrl->regs; + void __iomem *bhi_base = mhi_cntrl->bhi; + void __iomem *bhie_base = mhi_cntrl->bhie; + void __iomem *wake_db = mhi_cntrl->wake_db; + struct { + const char *name; + int offset; + void __iomem *base; + } debug_reg[] = { + { "MHI_CNTRL", MHICTRL, mhi_base}, + { "MHI_STATUS", MHISTATUS, mhi_base}, + { "MHI_WAKE_DB", 0, wake_db}, + { "BHI_EXECENV", BHI_EXECENV, bhi_base}, + { "BHI_STATUS", BHI_STATUS, bhi_base}, + { "BHI_ERRCODE", BHI_ERRCODE, bhi_base}, + { "BHI_ERRDBG1", BHI_ERRDBG1, bhi_base}, + { "BHI_ERRDBG2", BHI_ERRDBG2, bhi_base}, + { "BHI_ERRDBG3", BHI_ERRDBG3, bhi_base}, + { "BHIE_TXVEC_DB", BHIE_TXVECDB_OFFS, bhie_base}, + { "BHIE_TXVEC_STATUS", BHIE_TXVECSTATUS_OFFS, bhie_base}, + { "BHIE_RXVEC_DB", BHIE_RXVECDB_OFFS, bhie_base}, + { "BHIE_RXVEC_STATUS", BHIE_RXVECSTATUS_OFFS, bhie_base}, + { NULL }, + }; + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + return -EIO; + + seq_printf(m, "host pm_state:%s dev_state:%s ee:%s\n", + to_mhi_pm_state_str(mhi_cntrl->pm_state), + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + TO_MHI_EXEC_STR(mhi_cntrl->ee)); + + state = mhi_get_mhi_state(mhi_cntrl); + ee = mhi_get_exec_env(mhi_cntrl); + + seq_printf(m, "device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), + TO_MHI_STATE_STR(state)); + + for (i = 0; debug_reg[i].name; i++) { + if (!debug_reg[i].base) + continue; + ret = mhi_read_reg(mhi_cntrl, debug_reg[i].base, + debug_reg[i].offset, &val); + seq_printf(m, "reg:%s val:0x%x, ret:%d\n", debug_reg[i].name, + val, ret); + } + + return 0; +} + int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d) { struct mhi_controller *mhi_cntrl = m->private; diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index e8f945b9d799..4aac85254428 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -716,6 +716,17 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, mutex_unlock(&mhi_cntrl->pm_mutex); } +int mhi_debugfs_trigger_soc_reset(void *data, u64 val) +{ + struct mhi_controller *mhi_cntrl = data; + + MHI_LOG("Trigger MHI SOC Reset\n"); + + mhi_perform_soc_reset(mhi_cntrl); + + return 0; +} + int mhi_debugfs_trigger_reset(void *data, u64 val) { struct mhi_controller *mhi_cntrl = data;