Loading drivers/platform/msm/mhi/mhi.h +15 −4 Original line number Diff line number Diff line Loading @@ -405,9 +405,10 @@ struct mhi_flags { struct mhi_device_ctxt { struct mhi_pcie_dev_info *dev_info; struct pcie_core_info *dev_props; u64 channel_db_addr; u64 event_db_addr; u64 cmd_db_addr; void __iomem *mmio_addr; void __iomem *channel_db_addr; void __iomem *event_db_addr; void __iomem *cmd_db_addr; struct mhi_control_seg *mhi_ctrl_seg; struct mhi_meminfo *mhi_ctrl_seg_info; u64 nr_of_cc; Loading @@ -415,7 +416,6 @@ struct mhi_device_ctxt { u64 nr_of_cmdc; enum MHI_STATE mhi_state; enum MHI_EXEC_ENV dev_exec_env; void __iomem *mmio_addr; u64 mmio_len; struct mhi_ring mhi_local_chan_ctxt[MHI_MAX_CHANNELS]; struct mhi_ring mhi_local_event_ctxt[MHI_MAX_CHANNELS]; Loading Loading @@ -583,5 +583,16 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_set_bus_request(struct mhi_device_ctxt *mhi_dev_ctxt, int index); enum MHI_STATUS start_chan_sync(struct mhi_client_handle *client_handle); void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val); void mhi_reg_write_field(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift, u32 val); void mhi_reg_write(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val); u32 mhi_reg_read(void __iomem *io_addr, uintptr_t io_offset); u32 mhi_reg_read_field(void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift); #endif drivers/platform/msm/mhi/mhi_bhi.c +7 −7 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ static ssize_t bhi_write(struct file *file, /* Write the image size */ pcie_word_val = HIGH_WORD(bhi_ctxt->phy_image_loc); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_HIGH, 0xFFFFFFFF, 0, Loading @@ -100,22 +100,22 @@ static ssize_t bhi_write(struct file *file, pcie_word_val = LOW_WORD(bhi_ctxt->phy_image_loc); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_LOW, 0xFFFFFFFF, 0, pcie_word_val); pcie_word_val = bhi_ctxt->image_size; MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, BHI_IMGSIZE, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGSIZE, 0xFFFFFFFF, 0, pcie_word_val); MHI_REG_READ(bhi_ctxt->bhi_base, BHI_IMGTXDB, pcie_word_val); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, pcie_word_val = mhi_reg_read(bhi_ctxt->bhi_base, BHI_IMGTXDB); mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGTXDB, 0xFFFFFFFF, 0, ++pcie_word_val); for (i = 0; i < BHI_POLL_NR_RETRIES; ++i) { MHI_REG_READ(bhi_ctxt->bhi_base, BHI_STATUS, tx_db_val); tx_db_val = mhi_reg_read(bhi_ctxt->bhi_base, BHI_STATUS); if ((0x80000000 | tx_db_val) == pcie_word_val) break; else Loading Loading @@ -186,7 +186,7 @@ int bhi_probe(struct mhi_pcie_dev_info *mhi_pcie_device) } bhi_ctxt->bhi_base = mhi_pcie_device->core.bar0_base; MHI_REG_READ(bhi_ctxt->bhi_base, BHIOFF, pcie_word_val); pcie_word_val = mhi_reg_read(bhi_ctxt->bhi_base, BHIOFF); bhi_ctxt->bhi_base += pcie_word_val; mhi_log(MHI_MSG_INFO, Loading drivers/platform/msm/mhi/mhi_macros.h +6 −90 Original line number Diff line number Diff line Loading @@ -208,96 +208,6 @@ #define HIGH_WORD(_x) ((u32)((((u64)(_x)) >> 32) & 0xFFFFFFFF)) #define LOW_WORD(_x) ((u32)(((u64)(_x)) & 0xFFFFFFFF)) #define MHI_REG_WRITE(_base, _offset, _val) \ do { \ u32 addr; \ (addr) = (u32)(_base) + (u32)(_offset); \ *(u32 *)(addr) = (_val); \ wmb(); \ mhi_log(MHI_MSG_INFO, "d.s 0x%x %%LONG 0x%x\n", \ (u32)(_offset),\ (u32)(_val)); \ } while (0) #define MHI_REG_WRITE_FIELD(_base, _offset, _mask, _shift, _val) \ do { \ u32 reg_val; \ MHI_REG_READ(_base, _offset, reg_val); \ reg_val &= ~(_mask); \ reg_val = reg_val | ((u32)(_val) << ((u32)(_shift))); \ MHI_REG_WRITE(_base, _offset, reg_val); \ } while (0) #define MHI_REG_READ(_base, _offset, _dest) \ do { \ u32 addr; \ (addr) = (u32)(_base) + (u32)(_offset); \ (_dest) = *(u32 *)(addr); \ } while (0) #define MHI_REG_READ_FIELD(_base, _offset, _mask, _shift, _dest) \ do { \ MHI_REG_READ(_base, _offset, (_dest)); \ (_dest) &= (u32)(_mask); \ (_dest) >>= (u32)(_shift); \ } while (0) #define MHI_READ_FIELD(_val, _mask, _shift) \ do { \ _val &= (u32)(_mask); \ _val >>= (u32)(_shift); \ } while (0) #define MHI_WRITE_DB(_mhi_dev_ctxt, _addr, _index, _val) \ { \ u32 word; \ void *offset = (void *)(_index * sizeof(u64)); \ mhi_log(MHI_MSG_VERBOSE, \ "db.set addr: 0x%llX offset 0x%x val:0x%llX\n", \ (u64)_addr, (unsigned int)_index, (u64)_val); \ if (mhi_dev_ctxt->channel_db_addr == (_addr)) { \ (_mhi_dev_ctxt)->mhi_ctrl_seg->mhi_cc_list[_index]. \ mhi_trb_write_ptr = (_val); \ } else if (mhi_dev_ctxt->event_db_addr == (_addr)) { \ (_mhi_dev_ctxt)->mhi_ctrl_seg->mhi_ec_list[_index]. \ mhi_event_write_ptr = (_val); \ } \ if (_addr == mhi_dev_ctxt->channel_db_addr) { \ if (!(IS_HARDWARE_CHANNEL(_index) && \ mhi_dev_ctxt->uldl_enabled && \ !mhi_dev_ctxt->db_mode[_index])) { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } else if (_addr == mhi_dev_ctxt->event_db_addr) { \ if (IS_SOFTWARE_CHANNEL(_index) || \ !mhi_dev_ctxt->uldl_enabled) { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ wmb(); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } else { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ wmb(); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } #define EVENT_RING_MSI_VEC #define MHI_EVENT_RING_MSI_VEC__MASK (0xf) #define MHI_EVENT_RING_MSI_VEC__SHIFT (2) Loading Loading @@ -338,4 +248,10 @@ #define MHI_GET_EV_CTXT(_FIELD, _CTXT) \ (((_CTXT)->mhi_intmodt >> MHI_##_FIELD ## __SHIFT) & \ MHI_##_FIELD ## __MASK) #define MHI_READ_FIELD(_val, _mask, _shift) \ do { \ _val &= (u32)(_mask); \ _val >>= (u32)(_shift); \ } while (0) #endif drivers/platform/msm/mhi/mhi_main.c +104 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,32 @@ #include "mhi_hwio.h" #include "mhi_macros.h" static void mhi_write_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr_lower, uintptr_t chan, u64 val) { uintptr_t io_offset = chan * sizeof(u64); void __iomem *io_addr_upper = (void __iomem *)((uintptr_t)io_addr_lower + 4); mhi_reg_write(mhi_dev_ctxt, io_addr_upper, io_offset, val >> 32); mhi_reg_write(mhi_dev_ctxt, io_addr_lower, io_offset, (u32)val); } static void mhi_update_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, void *__iomem *io_addr, uintptr_t chan, u64 val) { wmb(); if (mhi_dev_ctxt->channel_db_addr == io_addr) { mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan]. mhi_trb_write_ptr = val; } else if (mhi_dev_ctxt->event_db_addr == io_addr) { mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[chan]. mhi_event_write_ptr = val; } } int mhi_init_pcie_device(struct mhi_pcie_dev_info *mhi_pcie_dev) { int ret_val = 0; Loading Loading @@ -374,7 +400,7 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) &mhi_dev_ctxt->mhi_local_event_ctxt[event_ring_index]; db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)event_ctxt->wp); MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, event_ring_index, db_value); } Loading Loading @@ -501,7 +527,7 @@ static enum MHI_STATUS mhi_notify_device( if ((mhi_dev_ctxt-> mhi_chan_cntr[chan].pkts_xferd % mhi_xfer_db_interval) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading @@ -509,13 +535,13 @@ static enum MHI_STATUS mhi_notify_device( if ((mhi_dev_ctxt-> mhi_chan_cntr[chan].pkts_xferd % MHI_XFER_DB_INTERVAL) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } } } else { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading Loading @@ -702,7 +728,7 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, if (MHI_STATE_M0 == mhi_dev_ctxt->mhi_state || MHI_STATE_M1 == mhi_dev_ctxt->mhi_state) { mhi_dev_ctxt->cmd_ring_order++; MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, 0, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, 0, db_value); } else { mhi_log(MHI_MSG_INFO, Loading Loading @@ -963,7 +989,7 @@ enum MHI_STATUS parse_xfer_event(struct mhi_device_ctxt *ctxt, if (chan_ctxt->wp != chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)chan_ctxt->wp); MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading Loading @@ -1032,7 +1058,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_cmd_mutex_list[PRIMARY_CMD_RING]; mutex_lock(cmd_mutex); mhi_dev_ctxt->cmd_ring_order = 1; MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, ring_index, db_value); mutex_unlock(cmd_mutex); break; Loading @@ -1046,7 +1072,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_dev_ctxt->mhi_ev_db_order[ring_index] = 1; if ((mhi_dev_ctxt->ev_counter[ring_index] % MHI_EV_DB_INTERVAL) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, ring_index, db_value); } Loading @@ -1061,7 +1087,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, &mhi_dev_ctxt->db_write_lock[ring_index], flags); mhi_dev_ctxt->mhi_chan_db_order[ring_index] = 1; MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, ring_index, db_value); spin_unlock_irqrestore( Loading Loading @@ -1366,3 +1392,72 @@ enum MHI_STATUS mhi_deregister_channel(struct mhi_client_handle return MHI_STATUS_SUCCESS; } EXPORT_SYMBOL(mhi_deregister_channel); void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t chan, u32 val) { mhi_log(MHI_MSG_VERBOSE, "db.set addr: %p io_offset 0x%lx val:0x%x\n", io_addr, chan, val); mhi_update_ctxt(mhi_dev_ctxt, io_addr, chan, val); /* Channel Doorbell and Polling Mode Disabled or Software Channel*/ if (io_addr == mhi_dev_ctxt->channel_db_addr) { if (!(IS_HARDWARE_CHANNEL(chan) && mhi_dev_ctxt->uldl_enabled && !mhi_dev_ctxt->db_mode[chan])) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } /* Event Doorbell and Polling mode Disabled */ } else if (io_addr == mhi_dev_ctxt->event_db_addr) { /* Only ring for software channel */ if (IS_SOFTWARE_CHANNEL(chan) || !mhi_dev_ctxt->uldl_enabled) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } } else { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } } void mhi_reg_write_field(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift, u32 val) { u32 reg_val; reg_val = mhi_reg_read(io_addr, io_offset); reg_val &= ~mask; reg_val = reg_val | (val << shift); mhi_reg_write(mhi_dev_ctxt, io_addr, io_offset, reg_val); } void mhi_reg_write(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val) { mhi_log(MHI_MSG_VERBOSE, "d.s 0x%p off: 0x%lx 0x%x\n", io_addr, io_offset, val); iowrite32(val, io_addr + io_offset); wmb(); msm_pcie_pm_control(MSM_PCIE_REQ_EXIT_L1, mhi_dev_ctxt->dev_info->pcie_device->bus->number, mhi_dev_ctxt->dev_info->pcie_device, NULL, 0); } u32 mhi_reg_read_field(void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift) { return (mhi_reg_read(io_addr, io_offset) & mask) >> shift; } u32 mhi_reg_read(void __iomem *io_addr, uintptr_t io_offset) { return ioread32(io_addr + io_offset); } drivers/platform/msm/mhi/mhi_mmio_ops.c +48 −36 Original line number Diff line number Diff line Loading @@ -20,8 +20,7 @@ enum MHI_STATUS mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_INFO, "Waiting for MMIO Ready bit to be set\n"); /* Read MMIO and poll for READY bit to be set */ pcie_word_val = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHISTATUS)); pcie_word_val = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHISTATUS); MHI_READ_FIELD(pcie_word_val, MHISTATUS_READY_MASK, MHISTATUS_READY_SHIFT); Loading @@ -34,8 +33,8 @@ enum MHI_STATUS mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_ERROR, "Device is not ready, sleeping and retrying.\n"); msleep(MHI_READY_STATUS_TIMEOUT_MS); pcie_word_val = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHISTATUS)); pcie_word_val = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHISTATUS); MHI_READ_FIELD(pcie_word_val, MHISTATUS_READY_MASK, MHISTATUS_READY_SHIFT); } Loading @@ -58,8 +57,8 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_INFO, "Bar 0 address is at: 0x%p\n", mhi_dev_ctxt->mmio_addr); mhi_dev_ctxt->mmio_len = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHIREGLEN)); mhi_dev_ctxt->mmio_len = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHIREGLEN); if (0 == mhi_dev_ctxt->mmio_len) { mhi_log(MHI_MSG_ERROR, "Received mmio length as zero\n"); Loading @@ -67,8 +66,8 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) } mhi_log(MHI_MSG_INFO, "Testing MHI Ver\n"); mhi_dev_ctxt->dev_props->mhi_ver = readl_relaxed( (void *)(mhi_dev_ctxt->mmio_addr + MHIVER)); mhi_dev_ctxt->dev_props->mhi_ver = mhi_reg_read( mhi_dev_ctxt->mmio_addr, MHIVER); if (MHI_VERSION != mhi_dev_ctxt->dev_props->mhi_ver) { mhi_log(MHI_MSG_CRITICAL, "Bad MMIO version, 0x%x\n", mhi_dev_ctxt->dev_props->mhi_ver); Loading @@ -91,29 +90,32 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) "Read back MMIO Ready bit successfully. Moving on..\n"); mhi_log(MHI_MSG_INFO, "Reading channel doorbell offset\n"); MHI_REG_READ_FIELD(mhi_dev_ctxt->mmio_addr, mhi_dev_ctxt->channel_db_addr = mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->event_db_addr = mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->channel_db_addr += mhi_reg_read_field( mhi_dev_ctxt->mmio_addr, CHDBOFF, CHDBOFF_CHDBOFF_MASK, CHDBOFF_CHDBOFF_SHIFT, mhi_dev_ctxt->channel_db_addr); CHDBOFF_CHDBOFF_SHIFT); mhi_log(MHI_MSG_INFO, "Reading event doorbell offset\n"); MHI_REG_READ_FIELD(mhi_dev_ctxt->mmio_addr, mhi_dev_ctxt->event_db_addr += mhi_reg_read_field( mhi_dev_ctxt->mmio_addr, ERDBOFF, ERDBOFF_ERDBOFF_MASK, ERDBOFF_ERDBOFF_SHIFT, mhi_dev_ctxt->event_db_addr); mhi_dev_ctxt->channel_db_addr += (uintptr_t)mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->event_db_addr += (uintptr_t)mhi_dev_ctxt->mmio_addr; ERDBOFF_ERDBOFF_SHIFT); mhi_log(MHI_MSG_INFO, "Setting all MMIO values.\n"); pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CCABAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CCABAP_HIGHER, CCABAP_HIGHER_CCABAP_HIGHER_MASK, CCABAP_HIGHER_CCABAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CCABAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CCABAP_LOWER, CCABAP_LOWER_CCABAP_LOWER_MASK, CCABAP_LOWER_CCABAP_LOWER_SHIFT, pcie_word_val); Loading @@ -122,12 +124,13 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, ECABAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, ECABAP_HIGHER, ECABAP_HIGHER_ECABAP_HIGHER_MASK, ECABAP_HIGHER_ECABAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, ECABAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, ECABAP_LOWER, ECABAP_LOWER_ECABAP_LOWER_MASK, ECABAP_LOWER_ECABAP_LOWER_SHIFT, pcie_word_val); Loading @@ -136,29 +139,32 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cmd_ctxt_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CRCBAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CRCBAP_HIGHER, CRCBAP_HIGHER_CRCBAP_HIGHER_MASK, CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CRCBAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CRCBAP_LOWER, CRCBAP_LOWER_CRCBAP_LOWER_MASK, CRCBAP_LOWER_CRCBAP_LOWER_SHIFT, pcie_word_val); mhi_dev_ctxt->cmd_db_addr = (uintptr_t)mhi_dev_ctxt->mmio_addr + CRDB_LOWER; mhi_dev_ctxt->cmd_db_addr = mhi_dev_ctxt->mmio_addr + CRDB_LOWER; /* Set the control segment in the MMIO */ pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLBASE_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLBASE_HIGHER, MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK, MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLBASE_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLBASE_LOWER, MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK, MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT, pcie_word_val); Loading @@ -168,12 +174,14 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_get_memregion_len(mhi_dev_ctxt->mhi_ctrl_seg_info) - 1; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_HIGHER, MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK, MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_LOWER, MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK, MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT, pcie_word_val); Loading @@ -181,13 +189,15 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) /* Set the data segment in the MMIO */ pcie_dword_val = MHI_DATA_SEG_WINDOW_START_ADDR; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATABASE_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATABASE_HIGHER, MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK, MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATABASE_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATABASE_LOWER, MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK, MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT, pcie_word_val); Loading @@ -195,15 +205,17 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = MHI_DATA_SEG_WINDOW_END_ADDR; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_HIGHER, MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK, MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT, (pcie_word_val)); pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_LOWER, MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK, MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT, (pcie_word_val)); pcie_word_val); mhi_log(MHI_MSG_INFO, "Done..\n"); return MHI_STATUS_SUCCESS; Loading Loading
drivers/platform/msm/mhi/mhi.h +15 −4 Original line number Diff line number Diff line Loading @@ -405,9 +405,10 @@ struct mhi_flags { struct mhi_device_ctxt { struct mhi_pcie_dev_info *dev_info; struct pcie_core_info *dev_props; u64 channel_db_addr; u64 event_db_addr; u64 cmd_db_addr; void __iomem *mmio_addr; void __iomem *channel_db_addr; void __iomem *event_db_addr; void __iomem *cmd_db_addr; struct mhi_control_seg *mhi_ctrl_seg; struct mhi_meminfo *mhi_ctrl_seg_info; u64 nr_of_cc; Loading @@ -415,7 +416,6 @@ struct mhi_device_ctxt { u64 nr_of_cmdc; enum MHI_STATE mhi_state; enum MHI_EXEC_ENV dev_exec_env; void __iomem *mmio_addr; u64 mmio_len; struct mhi_ring mhi_local_chan_ctxt[MHI_MAX_CHANNELS]; struct mhi_ring mhi_local_event_ctxt[MHI_MAX_CHANNELS]; Loading Loading @@ -583,5 +583,16 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_set_bus_request(struct mhi_device_ctxt *mhi_dev_ctxt, int index); enum MHI_STATUS start_chan_sync(struct mhi_client_handle *client_handle); void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val); void mhi_reg_write_field(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift, u32 val); void mhi_reg_write(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val); u32 mhi_reg_read(void __iomem *io_addr, uintptr_t io_offset); u32 mhi_reg_read_field(void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift); #endif
drivers/platform/msm/mhi/mhi_bhi.c +7 −7 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ static ssize_t bhi_write(struct file *file, /* Write the image size */ pcie_word_val = HIGH_WORD(bhi_ctxt->phy_image_loc); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_HIGH, 0xFFFFFFFF, 0, Loading @@ -100,22 +100,22 @@ static ssize_t bhi_write(struct file *file, pcie_word_val = LOW_WORD(bhi_ctxt->phy_image_loc); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_LOW, 0xFFFFFFFF, 0, pcie_word_val); pcie_word_val = bhi_ctxt->image_size; MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, BHI_IMGSIZE, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGSIZE, 0xFFFFFFFF, 0, pcie_word_val); MHI_REG_READ(bhi_ctxt->bhi_base, BHI_IMGTXDB, pcie_word_val); MHI_REG_WRITE_FIELD(bhi_ctxt->bhi_base, pcie_word_val = mhi_reg_read(bhi_ctxt->bhi_base, BHI_IMGTXDB); mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGTXDB, 0xFFFFFFFF, 0, ++pcie_word_val); for (i = 0; i < BHI_POLL_NR_RETRIES; ++i) { MHI_REG_READ(bhi_ctxt->bhi_base, BHI_STATUS, tx_db_val); tx_db_val = mhi_reg_read(bhi_ctxt->bhi_base, BHI_STATUS); if ((0x80000000 | tx_db_val) == pcie_word_val) break; else Loading Loading @@ -186,7 +186,7 @@ int bhi_probe(struct mhi_pcie_dev_info *mhi_pcie_device) } bhi_ctxt->bhi_base = mhi_pcie_device->core.bar0_base; MHI_REG_READ(bhi_ctxt->bhi_base, BHIOFF, pcie_word_val); pcie_word_val = mhi_reg_read(bhi_ctxt->bhi_base, BHIOFF); bhi_ctxt->bhi_base += pcie_word_val; mhi_log(MHI_MSG_INFO, Loading
drivers/platform/msm/mhi/mhi_macros.h +6 −90 Original line number Diff line number Diff line Loading @@ -208,96 +208,6 @@ #define HIGH_WORD(_x) ((u32)((((u64)(_x)) >> 32) & 0xFFFFFFFF)) #define LOW_WORD(_x) ((u32)(((u64)(_x)) & 0xFFFFFFFF)) #define MHI_REG_WRITE(_base, _offset, _val) \ do { \ u32 addr; \ (addr) = (u32)(_base) + (u32)(_offset); \ *(u32 *)(addr) = (_val); \ wmb(); \ mhi_log(MHI_MSG_INFO, "d.s 0x%x %%LONG 0x%x\n", \ (u32)(_offset),\ (u32)(_val)); \ } while (0) #define MHI_REG_WRITE_FIELD(_base, _offset, _mask, _shift, _val) \ do { \ u32 reg_val; \ MHI_REG_READ(_base, _offset, reg_val); \ reg_val &= ~(_mask); \ reg_val = reg_val | ((u32)(_val) << ((u32)(_shift))); \ MHI_REG_WRITE(_base, _offset, reg_val); \ } while (0) #define MHI_REG_READ(_base, _offset, _dest) \ do { \ u32 addr; \ (addr) = (u32)(_base) + (u32)(_offset); \ (_dest) = *(u32 *)(addr); \ } while (0) #define MHI_REG_READ_FIELD(_base, _offset, _mask, _shift, _dest) \ do { \ MHI_REG_READ(_base, _offset, (_dest)); \ (_dest) &= (u32)(_mask); \ (_dest) >>= (u32)(_shift); \ } while (0) #define MHI_READ_FIELD(_val, _mask, _shift) \ do { \ _val &= (u32)(_mask); \ _val >>= (u32)(_shift); \ } while (0) #define MHI_WRITE_DB(_mhi_dev_ctxt, _addr, _index, _val) \ { \ u32 word; \ void *offset = (void *)(_index * sizeof(u64)); \ mhi_log(MHI_MSG_VERBOSE, \ "db.set addr: 0x%llX offset 0x%x val:0x%llX\n", \ (u64)_addr, (unsigned int)_index, (u64)_val); \ if (mhi_dev_ctxt->channel_db_addr == (_addr)) { \ (_mhi_dev_ctxt)->mhi_ctrl_seg->mhi_cc_list[_index]. \ mhi_trb_write_ptr = (_val); \ } else if (mhi_dev_ctxt->event_db_addr == (_addr)) { \ (_mhi_dev_ctxt)->mhi_ctrl_seg->mhi_ec_list[_index]. \ mhi_event_write_ptr = (_val); \ } \ if (_addr == mhi_dev_ctxt->channel_db_addr) { \ if (!(IS_HARDWARE_CHANNEL(_index) && \ mhi_dev_ctxt->uldl_enabled && \ !mhi_dev_ctxt->db_mode[_index])) { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } else if (_addr == mhi_dev_ctxt->event_db_addr) { \ if (IS_SOFTWARE_CHANNEL(_index) || \ !mhi_dev_ctxt->uldl_enabled) { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ wmb(); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } else { \ wmb(); \ word = HIGH_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset + 4); \ wmb(); \ word = LOW_WORD((u64)(_val)); \ writel_relaxed(word, _addr + offset); \ wmb(); \ mhi_dev_ctxt->db_mode[_index] = 0; \ } \ } #define EVENT_RING_MSI_VEC #define MHI_EVENT_RING_MSI_VEC__MASK (0xf) #define MHI_EVENT_RING_MSI_VEC__SHIFT (2) Loading Loading @@ -338,4 +248,10 @@ #define MHI_GET_EV_CTXT(_FIELD, _CTXT) \ (((_CTXT)->mhi_intmodt >> MHI_##_FIELD ## __SHIFT) & \ MHI_##_FIELD ## __MASK) #define MHI_READ_FIELD(_val, _mask, _shift) \ do { \ _val &= (u32)(_mask); \ _val >>= (u32)(_shift); \ } while (0) #endif
drivers/platform/msm/mhi/mhi_main.c +104 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,32 @@ #include "mhi_hwio.h" #include "mhi_macros.h" static void mhi_write_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr_lower, uintptr_t chan, u64 val) { uintptr_t io_offset = chan * sizeof(u64); void __iomem *io_addr_upper = (void __iomem *)((uintptr_t)io_addr_lower + 4); mhi_reg_write(mhi_dev_ctxt, io_addr_upper, io_offset, val >> 32); mhi_reg_write(mhi_dev_ctxt, io_addr_lower, io_offset, (u32)val); } static void mhi_update_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, void *__iomem *io_addr, uintptr_t chan, u64 val) { wmb(); if (mhi_dev_ctxt->channel_db_addr == io_addr) { mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan]. mhi_trb_write_ptr = val; } else if (mhi_dev_ctxt->event_db_addr == io_addr) { mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[chan]. mhi_event_write_ptr = val; } } int mhi_init_pcie_device(struct mhi_pcie_dev_info *mhi_pcie_dev) { int ret_val = 0; Loading Loading @@ -374,7 +400,7 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) &mhi_dev_ctxt->mhi_local_event_ctxt[event_ring_index]; db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)event_ctxt->wp); MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, event_ring_index, db_value); } Loading Loading @@ -501,7 +527,7 @@ static enum MHI_STATUS mhi_notify_device( if ((mhi_dev_ctxt-> mhi_chan_cntr[chan].pkts_xferd % mhi_xfer_db_interval) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading @@ -509,13 +535,13 @@ static enum MHI_STATUS mhi_notify_device( if ((mhi_dev_ctxt-> mhi_chan_cntr[chan].pkts_xferd % MHI_XFER_DB_INTERVAL) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } } } else { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading Loading @@ -702,7 +728,7 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, if (MHI_STATE_M0 == mhi_dev_ctxt->mhi_state || MHI_STATE_M1 == mhi_dev_ctxt->mhi_state) { mhi_dev_ctxt->cmd_ring_order++; MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, 0, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, 0, db_value); } else { mhi_log(MHI_MSG_INFO, Loading Loading @@ -963,7 +989,7 @@ enum MHI_STATUS parse_xfer_event(struct mhi_device_ctxt *ctxt, if (chan_ctxt->wp != chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)chan_ctxt->wp); MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, chan, db_value); } Loading Loading @@ -1032,7 +1058,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_cmd_mutex_list[PRIMARY_CMD_RING]; mutex_lock(cmd_mutex); mhi_dev_ctxt->cmd_ring_order = 1; MHI_WRITE_DB(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, ring_index, db_value); mutex_unlock(cmd_mutex); break; Loading @@ -1046,7 +1072,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_dev_ctxt->mhi_ev_db_order[ring_index] = 1; if ((mhi_dev_ctxt->ev_counter[ring_index] % MHI_EV_DB_INTERVAL) == 0) { MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->event_db_addr, ring_index, db_value); } Loading @@ -1061,7 +1087,7 @@ enum MHI_STATUS recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, &mhi_dev_ctxt->db_write_lock[ring_index], flags); mhi_dev_ctxt->mhi_chan_db_order[ring_index] = 1; MHI_WRITE_DB(mhi_dev_ctxt, mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->channel_db_addr, ring_index, db_value); spin_unlock_irqrestore( Loading Loading @@ -1366,3 +1392,72 @@ enum MHI_STATUS mhi_deregister_channel(struct mhi_client_handle return MHI_STATUS_SUCCESS; } EXPORT_SYMBOL(mhi_deregister_channel); void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t chan, u32 val) { mhi_log(MHI_MSG_VERBOSE, "db.set addr: %p io_offset 0x%lx val:0x%x\n", io_addr, chan, val); mhi_update_ctxt(mhi_dev_ctxt, io_addr, chan, val); /* Channel Doorbell and Polling Mode Disabled or Software Channel*/ if (io_addr == mhi_dev_ctxt->channel_db_addr) { if (!(IS_HARDWARE_CHANNEL(chan) && mhi_dev_ctxt->uldl_enabled && !mhi_dev_ctxt->db_mode[chan])) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } /* Event Doorbell and Polling mode Disabled */ } else if (io_addr == mhi_dev_ctxt->event_db_addr) { /* Only ring for software channel */ if (IS_SOFTWARE_CHANNEL(chan) || !mhi_dev_ctxt->uldl_enabled) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } } else { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); mhi_dev_ctxt->db_mode[chan] = 0; } } void mhi_reg_write_field(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift, u32 val) { u32 reg_val; reg_val = mhi_reg_read(io_addr, io_offset); reg_val &= ~mask; reg_val = reg_val | (val << shift); mhi_reg_write(mhi_dev_ctxt, io_addr, io_offset, reg_val); } void mhi_reg_write(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t io_offset, u32 val) { mhi_log(MHI_MSG_VERBOSE, "d.s 0x%p off: 0x%lx 0x%x\n", io_addr, io_offset, val); iowrite32(val, io_addr + io_offset); wmb(); msm_pcie_pm_control(MSM_PCIE_REQ_EXIT_L1, mhi_dev_ctxt->dev_info->pcie_device->bus->number, mhi_dev_ctxt->dev_info->pcie_device, NULL, 0); } u32 mhi_reg_read_field(void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift) { return (mhi_reg_read(io_addr, io_offset) & mask) >> shift; } u32 mhi_reg_read(void __iomem *io_addr, uintptr_t io_offset) { return ioread32(io_addr + io_offset); }
drivers/platform/msm/mhi/mhi_mmio_ops.c +48 −36 Original line number Diff line number Diff line Loading @@ -20,8 +20,7 @@ enum MHI_STATUS mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_INFO, "Waiting for MMIO Ready bit to be set\n"); /* Read MMIO and poll for READY bit to be set */ pcie_word_val = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHISTATUS)); pcie_word_val = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHISTATUS); MHI_READ_FIELD(pcie_word_val, MHISTATUS_READY_MASK, MHISTATUS_READY_SHIFT); Loading @@ -34,8 +33,8 @@ enum MHI_STATUS mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_ERROR, "Device is not ready, sleeping and retrying.\n"); msleep(MHI_READY_STATUS_TIMEOUT_MS); pcie_word_val = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHISTATUS)); pcie_word_val = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHISTATUS); MHI_READ_FIELD(pcie_word_val, MHISTATUS_READY_MASK, MHISTATUS_READY_SHIFT); } Loading @@ -58,8 +57,8 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(MHI_MSG_INFO, "Bar 0 address is at: 0x%p\n", mhi_dev_ctxt->mmio_addr); mhi_dev_ctxt->mmio_len = readl_relaxed((void *)(mhi_dev_ctxt->mmio_addr + MHIREGLEN)); mhi_dev_ctxt->mmio_len = mhi_reg_read(mhi_dev_ctxt->mmio_addr, MHIREGLEN); if (0 == mhi_dev_ctxt->mmio_len) { mhi_log(MHI_MSG_ERROR, "Received mmio length as zero\n"); Loading @@ -67,8 +66,8 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) } mhi_log(MHI_MSG_INFO, "Testing MHI Ver\n"); mhi_dev_ctxt->dev_props->mhi_ver = readl_relaxed( (void *)(mhi_dev_ctxt->mmio_addr + MHIVER)); mhi_dev_ctxt->dev_props->mhi_ver = mhi_reg_read( mhi_dev_ctxt->mmio_addr, MHIVER); if (MHI_VERSION != mhi_dev_ctxt->dev_props->mhi_ver) { mhi_log(MHI_MSG_CRITICAL, "Bad MMIO version, 0x%x\n", mhi_dev_ctxt->dev_props->mhi_ver); Loading @@ -91,29 +90,32 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) "Read back MMIO Ready bit successfully. Moving on..\n"); mhi_log(MHI_MSG_INFO, "Reading channel doorbell offset\n"); MHI_REG_READ_FIELD(mhi_dev_ctxt->mmio_addr, mhi_dev_ctxt->channel_db_addr = mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->event_db_addr = mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->channel_db_addr += mhi_reg_read_field( mhi_dev_ctxt->mmio_addr, CHDBOFF, CHDBOFF_CHDBOFF_MASK, CHDBOFF_CHDBOFF_SHIFT, mhi_dev_ctxt->channel_db_addr); CHDBOFF_CHDBOFF_SHIFT); mhi_log(MHI_MSG_INFO, "Reading event doorbell offset\n"); MHI_REG_READ_FIELD(mhi_dev_ctxt->mmio_addr, mhi_dev_ctxt->event_db_addr += mhi_reg_read_field( mhi_dev_ctxt->mmio_addr, ERDBOFF, ERDBOFF_ERDBOFF_MASK, ERDBOFF_ERDBOFF_SHIFT, mhi_dev_ctxt->event_db_addr); mhi_dev_ctxt->channel_db_addr += (uintptr_t)mhi_dev_ctxt->mmio_addr; mhi_dev_ctxt->event_db_addr += (uintptr_t)mhi_dev_ctxt->mmio_addr; ERDBOFF_ERDBOFF_SHIFT); mhi_log(MHI_MSG_INFO, "Setting all MMIO values.\n"); pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CCABAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CCABAP_HIGHER, CCABAP_HIGHER_CCABAP_HIGHER_MASK, CCABAP_HIGHER_CCABAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CCABAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CCABAP_LOWER, CCABAP_LOWER_CCABAP_LOWER_MASK, CCABAP_LOWER_CCABAP_LOWER_SHIFT, pcie_word_val); Loading @@ -122,12 +124,13 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, ECABAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, ECABAP_HIGHER, ECABAP_HIGHER_ECABAP_HIGHER_MASK, ECABAP_HIGHER_ECABAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, ECABAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, ECABAP_LOWER, ECABAP_LOWER_ECABAP_LOWER_MASK, ECABAP_LOWER_ECABAP_LOWER_SHIFT, pcie_word_val); Loading @@ -136,29 +139,32 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cmd_ctxt_list); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CRCBAP_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CRCBAP_HIGHER, CRCBAP_HIGHER_CRCBAP_HIGHER_MASK, CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, CRCBAP_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, CRCBAP_LOWER, CRCBAP_LOWER_CRCBAP_LOWER_MASK, CRCBAP_LOWER_CRCBAP_LOWER_SHIFT, pcie_word_val); mhi_dev_ctxt->cmd_db_addr = (uintptr_t)mhi_dev_ctxt->mmio_addr + CRDB_LOWER; mhi_dev_ctxt->cmd_db_addr = mhi_dev_ctxt->mmio_addr + CRDB_LOWER; /* Set the control segment in the MMIO */ pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg); pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLBASE_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLBASE_HIGHER, MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK, MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLBASE_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLBASE_LOWER, MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK, MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT, pcie_word_val); Loading @@ -168,12 +174,14 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_get_memregion_len(mhi_dev_ctxt->mhi_ctrl_seg_info) - 1; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_HIGHER, MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK, MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICTRLLIMIT_LOWER, MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK, MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT, pcie_word_val); Loading @@ -181,13 +189,15 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) /* Set the data segment in the MMIO */ pcie_dword_val = MHI_DATA_SEG_WINDOW_START_ADDR; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATABASE_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATABASE_HIGHER, MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK, MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT, pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATABASE_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATABASE_LOWER, MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK, MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT, pcie_word_val); Loading @@ -195,15 +205,17 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) pcie_dword_val = MHI_DATA_SEG_WINDOW_END_ADDR; pcie_word_val = HIGH_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_HIGHER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_HIGHER, MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK, MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT, (pcie_word_val)); pcie_word_val); pcie_word_val = LOW_WORD(pcie_dword_val); MHI_REG_WRITE_FIELD(mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_LOWER, mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHIDATALIMIT_LOWER, MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK, MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT, (pcie_word_val)); pcie_word_val); mhi_log(MHI_MSG_INFO, "Done..\n"); return MHI_STATUS_SUCCESS; Loading