Loading drivers/bus/mhi/core/mhi_boot.c +25 −86 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ #include "mhi_internal.h" /* setup rddm vector table for rddm transfer */ static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, /* setup rddm vector table for rddm transfer and program rxvec */ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info) { struct mhi_buf *mhi_buf = img_info->mhi_buf; struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; void __iomem *base = mhi_cntrl->bhie; u32 sequence_id; int i = 0; for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { Loading @@ -32,17 +34,35 @@ static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, bhi_vec->dma_addr = mhi_buf->dma_addr; bhi_vec->size = mhi_buf->len; } MHI_LOG("BHIe programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; if (unlikely(!sequence_id)) sequence_id = 1; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); MHI_LOG("address:%pad len:0x%lx sequence:%u\n", &mhi_buf->dma_addr, mhi_buf->len, sequence_id); } /* collect rddm during kernel panic */ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) { int ret; struct mhi_buf *mhi_buf; u32 sequence_id; u32 rx_status; enum mhi_ee ee; struct image_info *rddm_image = mhi_cntrl->rddm_image; const u32 delayus = 5000; u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; const u32 rddm_timeout_us = 200000; Loading @@ -68,29 +88,6 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) /* update should take the effect immediately */ smp_wmb(); /* setup the RX vector table */ mhi_rddm_prepare(mhi_cntrl, rddm_image); mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; MHI_LOG("Starting BHIe programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; if (unlikely(!sequence_id)) sequence_id = 1; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); /* * Make sure device is not already in RDDM. * In case device asserts and a kernel panic follows, device will Loading Loading @@ -157,70 +154,15 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) { void __iomem *base = mhi_cntrl->bhie; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; struct image_info *rddm_image = mhi_cntrl->rddm_image; struct mhi_buf *mhi_buf; int ret; u32 rx_status; u32 sequence_id; if (!rddm_image) return -ENOMEM; if (in_panic) return __mhi_download_rddm_in_panic(mhi_cntrl); MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee)); ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->ee == MHI_EE_RDDM || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); return -EIO; } mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); /* vector table is the last entry */ mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; read_lock_bh(pm_lock); if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { read_unlock_bh(pm_lock); return -EIO; } MHI_LOG("Starting BHIe Programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); read_unlock_bh(pm_lock); MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n", upper_32_bits(mhi_buf->dma_addr), lower_32_bits(mhi_buf->dma_addr), mhi_buf->len, sequence_id); MHI_LOG("Waiting for image download completion\n"); /* waiting for image download completion */ wait_event_timeout(mhi_cntrl->state_event, MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, Loading @@ -228,9 +170,6 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) &rx_status) || rx_status, msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) return -EIO; return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; } EXPORT_SYMBOL(mhi_download_rddm_img); Loading drivers/bus/mhi/core/mhi_init.c +3 −0 Original line number Diff line number Diff line Loading @@ -1417,6 +1417,9 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) memset_io(mhi_cntrl->bhie + BHIE_RXVECADDR_LOW_OFFS, 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + 4); if (mhi_cntrl->rddm_image) mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); } mhi_cntrl->pre_init = true; Loading drivers/bus/mhi/core/mhi_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -822,6 +822,8 @@ void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl); int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl); void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl); int mhi_dtr_init(void); void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info); /* isr handlers */ irqreturn_t mhi_msi_handlr(int irq_number, void *dev); Loading drivers/bus/mhi/core/mhi_main.c +17 −3 Original line number Diff line number Diff line Loading @@ -1458,15 +1458,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) struct mhi_controller *mhi_cntrl = dev; enum mhi_dev_state state = MHI_STATE_MAX; enum MHI_PM_STATE pm_state = 0; enum mhi_ee ee; enum mhi_ee ee = 0; MHI_VERB("Enter\n"); write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { state = mhi_get_mhi_state(mhi_cntrl); ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), ee = mhi_cntrl->ee; mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_STATE_STR(state)); } Loading @@ -1476,6 +1478,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) MHI_PM_SYS_ERR_DETECT); } write_unlock_irq(&mhi_cntrl->pm_lock); /* if device in rddm don't bother processing sys error */ if (mhi_cntrl->ee == MHI_EE_RDDM) { if (mhi_cntrl->ee != ee) { mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_EE_RDDM); wake_up_all(&mhi_cntrl->state_event); } goto exit_intvec; } if (pm_state == MHI_PM_SYS_ERR_DETECT) { wake_up_all(&mhi_cntrl->state_event); Loading @@ -1487,6 +1500,7 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) schedule_work(&mhi_cntrl->syserr_worker); } exit_intvec: MHI_VERB("Exit\n"); return IRQ_HANDLED; Loading drivers/bus/mhi/core/mhi_pm.c +16 −1 Original line number Diff line number Diff line Loading @@ -522,9 +522,20 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, to_mhi_pm_state_str(transition_state)); /* We must notify MHI control driver so it can clean up first */ if (transition_state == MHI_PM_SYS_ERR_PROCESS) if (transition_state == MHI_PM_SYS_ERR_PROCESS) { /* * if controller support rddm, we do not process * sys error state, instead we will jump directly * to rddm state */ if (mhi_cntrl->rddm_image) { MHI_LOG( "Controller Support RDDM, skipping SYS_ERR_PROCESS\n"); return; } mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_SYS_ERROR); } mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); Loading Loading @@ -1394,6 +1405,10 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); /* device already in rddm */ if (mhi_cntrl->ee == MHI_EE_RDDM) return 0; MHI_LOG("Triggering SYS_ERR to force rddm state\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); Loading Loading
drivers/bus/mhi/core/mhi_boot.c +25 −86 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ #include "mhi_internal.h" /* setup rddm vector table for rddm transfer */ static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, /* setup rddm vector table for rddm transfer and program rxvec */ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info) { struct mhi_buf *mhi_buf = img_info->mhi_buf; struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; void __iomem *base = mhi_cntrl->bhie; u32 sequence_id; int i = 0; for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { Loading @@ -32,17 +34,35 @@ static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, bhi_vec->dma_addr = mhi_buf->dma_addr; bhi_vec->size = mhi_buf->len; } MHI_LOG("BHIe programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; if (unlikely(!sequence_id)) sequence_id = 1; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); MHI_LOG("address:%pad len:0x%lx sequence:%u\n", &mhi_buf->dma_addr, mhi_buf->len, sequence_id); } /* collect rddm during kernel panic */ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) { int ret; struct mhi_buf *mhi_buf; u32 sequence_id; u32 rx_status; enum mhi_ee ee; struct image_info *rddm_image = mhi_cntrl->rddm_image; const u32 delayus = 5000; u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; const u32 rddm_timeout_us = 200000; Loading @@ -68,29 +88,6 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) /* update should take the effect immediately */ smp_wmb(); /* setup the RX vector table */ mhi_rddm_prepare(mhi_cntrl, rddm_image); mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; MHI_LOG("Starting BHIe programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; if (unlikely(!sequence_id)) sequence_id = 1; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); /* * Make sure device is not already in RDDM. * In case device asserts and a kernel panic follows, device will Loading Loading @@ -157,70 +154,15 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) { void __iomem *base = mhi_cntrl->bhie; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; struct image_info *rddm_image = mhi_cntrl->rddm_image; struct mhi_buf *mhi_buf; int ret; u32 rx_status; u32 sequence_id; if (!rddm_image) return -ENOMEM; if (in_panic) return __mhi_download_rddm_in_panic(mhi_cntrl); MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee)); ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->ee == MHI_EE_RDDM || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); return -EIO; } mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); /* vector table is the last entry */ mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; read_lock_bh(pm_lock); if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { read_unlock_bh(pm_lock); return -EIO; } MHI_LOG("Starting BHIe Programming for RDDM\n"); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, upper_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, lower_32_bits(mhi_buf->dma_addr)); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, sequence_id); read_unlock_bh(pm_lock); MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n", upper_32_bits(mhi_buf->dma_addr), lower_32_bits(mhi_buf->dma_addr), mhi_buf->len, sequence_id); MHI_LOG("Waiting for image download completion\n"); /* waiting for image download completion */ wait_event_timeout(mhi_cntrl->state_event, MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, Loading @@ -228,9 +170,6 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) &rx_status) || rx_status, msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) return -EIO; return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; } EXPORT_SYMBOL(mhi_download_rddm_img); Loading
drivers/bus/mhi/core/mhi_init.c +3 −0 Original line number Diff line number Diff line Loading @@ -1417,6 +1417,9 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) memset_io(mhi_cntrl->bhie + BHIE_RXVECADDR_LOW_OFFS, 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + 4); if (mhi_cntrl->rddm_image) mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); } mhi_cntrl->pre_init = true; Loading
drivers/bus/mhi/core/mhi_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -822,6 +822,8 @@ void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl); int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl); void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl); int mhi_dtr_init(void); void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info); /* isr handlers */ irqreturn_t mhi_msi_handlr(int irq_number, void *dev); Loading
drivers/bus/mhi/core/mhi_main.c +17 −3 Original line number Diff line number Diff line Loading @@ -1458,15 +1458,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) struct mhi_controller *mhi_cntrl = dev; enum mhi_dev_state state = MHI_STATE_MAX; enum MHI_PM_STATE pm_state = 0; enum mhi_ee ee; enum mhi_ee ee = 0; MHI_VERB("Enter\n"); write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { state = mhi_get_mhi_state(mhi_cntrl); ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), ee = mhi_cntrl->ee; mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_STATE_STR(state)); } Loading @@ -1476,6 +1478,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) MHI_PM_SYS_ERR_DETECT); } write_unlock_irq(&mhi_cntrl->pm_lock); /* if device in rddm don't bother processing sys error */ if (mhi_cntrl->ee == MHI_EE_RDDM) { if (mhi_cntrl->ee != ee) { mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_EE_RDDM); wake_up_all(&mhi_cntrl->state_event); } goto exit_intvec; } if (pm_state == MHI_PM_SYS_ERR_DETECT) { wake_up_all(&mhi_cntrl->state_event); Loading @@ -1487,6 +1500,7 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) schedule_work(&mhi_cntrl->syserr_worker); } exit_intvec: MHI_VERB("Exit\n"); return IRQ_HANDLED; Loading
drivers/bus/mhi/core/mhi_pm.c +16 −1 Original line number Diff line number Diff line Loading @@ -522,9 +522,20 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, to_mhi_pm_state_str(transition_state)); /* We must notify MHI control driver so it can clean up first */ if (transition_state == MHI_PM_SYS_ERR_PROCESS) if (transition_state == MHI_PM_SYS_ERR_PROCESS) { /* * if controller support rddm, we do not process * sys error state, instead we will jump directly * to rddm state */ if (mhi_cntrl->rddm_image) { MHI_LOG( "Controller Support RDDM, skipping SYS_ERR_PROCESS\n"); return; } mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_SYS_ERROR); } mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); Loading Loading @@ -1394,6 +1405,10 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); /* device already in rddm */ if (mhi_cntrl->ee == MHI_EE_RDDM) return 0; MHI_LOG("Triggering SYS_ERR to force rddm state\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); Loading