in mhi/core/init.c [427:554]
int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
{
u32 val;
int i, ret;
struct mhi_chan *mhi_chan;
struct mhi_event *mhi_event;
void __iomem *base = mhi_cntrl->regs;
struct device *dev = &mhi_cntrl->mhi_dev->dev;
struct {
u32 offset;
u32 mask;
u32 shift;
u32 val;
} reg_info[] = {
{
CCABAP_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
},
{
CCABAP_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
},
{
ECABAP_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
},
{
ECABAP_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
},
{
CRCBAP_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
},
{
CRCBAP_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
},
{
MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT,
mhi_cntrl->total_ev_rings,
},
{
MHICFG, MHICFG_NHWER_MASK, MHICFG_NHWER_SHIFT,
mhi_cntrl->hw_ev_rings,
},
{
MHICTRLBASE_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->iova_start),
},
{
MHICTRLBASE_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_start),
},
{
MHIDATABASE_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->iova_start),
},
{
MHIDATABASE_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_start),
},
{
MHICTRLLIMIT_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->iova_stop),
},
{
MHICTRLLIMIT_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_stop),
},
{
MHIDATALIMIT_HIGHER, U32_MAX, 0,
upper_32_bits(mhi_cntrl->iova_stop),
},
{
MHIDATALIMIT_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_stop),
},
{ 0, 0, 0 }
};
dev_dbg(dev, "Initializing MHI registers\n");
/* Read channel db offset */
ret = mhi_read_reg_field(mhi_cntrl, base, CHDBOFF, CHDBOFF_CHDBOFF_MASK,
CHDBOFF_CHDBOFF_SHIFT, &val);
if (ret) {
dev_err(dev, "Unable to read CHDBOFF register\n");
return -EIO;
}
/* Setup wake db */
mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB);
mhi_cntrl->wake_set = false;
/* Setup channel db address for each channel in tre_ring */
mhi_chan = mhi_cntrl->mhi_chan;
for (i = 0; i < mhi_cntrl->max_chan; i++, val += 8, mhi_chan++)
mhi_chan->tre_ring.db_addr = base + val;
/* Read event ring db offset */
ret = mhi_read_reg_field(mhi_cntrl, base, ERDBOFF, ERDBOFF_ERDBOFF_MASK,
ERDBOFF_ERDBOFF_SHIFT, &val);
if (ret) {
dev_err(dev, "Unable to read ERDBOFF register\n");
return -EIO;
}
/* Setup event db address for each ev_ring */
mhi_event = mhi_cntrl->mhi_event;
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) {
if (mhi_event->offload_ev)
continue;
mhi_event->ring.db_addr = base + val;
}
/* Setup DB register for primary CMD rings */
mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING].ring.db_addr = base + CRDB_LOWER;
/* Write to MMIO registers */
for (i = 0; reg_info[i].offset; i++)
mhi_write_reg_field(mhi_cntrl, base, reg_info[i].offset,
reg_info[i].mask, reg_info[i].shift,
reg_info[i].val);
return 0;
}