Lines Matching +full:wp +full:- +full:controller
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
9 #include <linux/dma-direction.h>
10 #include <linux/dma-mapping.h>
59 [MHI_PM_STATE_M3_ENTER] = "M?->M3",
61 [MHI_PM_STATE_M3_EXIT] = "M3->M0",
84 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; in serial_number_show()
87 mhi_cntrl->serial_number); in serial_number_show()
96 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; in oem_pk_hash_show()
99 for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) in oem_pk_hash_show()
100 cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, in oem_pk_hash_show()
102 mhi_cntrl->oem_pk_hash[i]); in oem_pk_hash_show()
120 ring->alloc_size = len + (len - 1); in mhi_alloc_aligned_ring()
121 ring->pre_aligned = mhi_alloc_coherent(mhi_cntrl, ring->alloc_size, in mhi_alloc_aligned_ring()
122 &ring->dma_handle, GFP_KERNEL); in mhi_alloc_aligned_ring()
123 if (!ring->pre_aligned) in mhi_alloc_aligned_ring()
124 return -ENOMEM; in mhi_alloc_aligned_ring()
126 ring->iommu_base = (ring->dma_handle + (len - 1)) & ~(len - 1); in mhi_alloc_aligned_ring()
127 ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); in mhi_alloc_aligned_ring()
135 struct mhi_event *mhi_event = mhi_cntrl->mhi_event; in mhi_deinit_free_irq()
137 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { in mhi_deinit_free_irq()
138 if (mhi_event->offload_ev) in mhi_deinit_free_irq()
141 free_irq(mhi_cntrl->irq[mhi_event->irq], mhi_event); in mhi_deinit_free_irq()
144 free_irq(mhi_cntrl->irq[0], mhi_cntrl); in mhi_deinit_free_irq()
149 struct mhi_event *mhi_event = mhi_cntrl->mhi_event; in mhi_init_irq_setup()
150 struct device *dev = &mhi_cntrl->mhi_dev->dev; in mhi_init_irq_setup()
154 ret = request_threaded_irq(mhi_cntrl->irq[0], mhi_intvec_handler, in mhi_init_irq_setup()
161 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { in mhi_init_irq_setup()
162 if (mhi_event->offload_ev) in mhi_init_irq_setup()
165 if (mhi_event->irq >= mhi_cntrl->nr_irqs) { in mhi_init_irq_setup()
167 mhi_event->irq); in mhi_init_irq_setup()
168 ret = -EINVAL; in mhi_init_irq_setup()
172 ret = request_irq(mhi_cntrl->irq[mhi_event->irq], in mhi_init_irq_setup()
178 mhi_cntrl->irq[mhi_event->irq], i); in mhi_init_irq_setup()
186 for (--i, --mhi_event; i >= 0; i--, mhi_event--) { in mhi_init_irq_setup()
187 if (mhi_event->offload_ev) in mhi_init_irq_setup()
190 free_irq(mhi_cntrl->irq[mhi_event->irq], mhi_event); in mhi_init_irq_setup()
192 free_irq(mhi_cntrl->irq[0], mhi_cntrl); in mhi_init_irq_setup()
200 struct mhi_ctxt *mhi_ctxt = mhi_cntrl->mhi_ctxt; in mhi_deinit_dev_ctxt()
205 mhi_cmd = mhi_cntrl->mhi_cmd; in mhi_deinit_dev_ctxt()
207 ring = &mhi_cmd->ring; in mhi_deinit_dev_ctxt()
208 mhi_free_coherent(mhi_cntrl, ring->alloc_size, in mhi_deinit_dev_ctxt()
209 ring->pre_aligned, ring->dma_handle); in mhi_deinit_dev_ctxt()
210 ring->base = NULL; in mhi_deinit_dev_ctxt()
211 ring->iommu_base = 0; in mhi_deinit_dev_ctxt()
215 sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS, in mhi_deinit_dev_ctxt()
216 mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr); in mhi_deinit_dev_ctxt()
218 mhi_event = mhi_cntrl->mhi_event; in mhi_deinit_dev_ctxt()
219 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { in mhi_deinit_dev_ctxt()
220 if (mhi_event->offload_ev) in mhi_deinit_dev_ctxt()
223 ring = &mhi_event->ring; in mhi_deinit_dev_ctxt()
224 mhi_free_coherent(mhi_cntrl, ring->alloc_size, in mhi_deinit_dev_ctxt()
225 ring->pre_aligned, ring->dma_handle); in mhi_deinit_dev_ctxt()
226 ring->base = NULL; in mhi_deinit_dev_ctxt()
227 ring->iommu_base = 0; in mhi_deinit_dev_ctxt()
230 mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) * in mhi_deinit_dev_ctxt()
231 mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt, in mhi_deinit_dev_ctxt()
232 mhi_ctxt->er_ctxt_addr); in mhi_deinit_dev_ctxt()
234 mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) * in mhi_deinit_dev_ctxt()
235 mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt, in mhi_deinit_dev_ctxt()
236 mhi_ctxt->chan_ctxt_addr); in mhi_deinit_dev_ctxt()
239 mhi_cntrl->mhi_ctxt = NULL; in mhi_deinit_dev_ctxt()
252 int ret = -ENOMEM, i; in mhi_init_dev_ctxt()
254 atomic_set(&mhi_cntrl->dev_wake, 0); in mhi_init_dev_ctxt()
255 atomic_set(&mhi_cntrl->pending_pkts, 0); in mhi_init_dev_ctxt()
259 return -ENOMEM; in mhi_init_dev_ctxt()
262 mhi_ctxt->chan_ctxt = mhi_alloc_coherent(mhi_cntrl, in mhi_init_dev_ctxt()
263 sizeof(*mhi_ctxt->chan_ctxt) * in mhi_init_dev_ctxt()
264 mhi_cntrl->max_chan, in mhi_init_dev_ctxt()
265 &mhi_ctxt->chan_ctxt_addr, in mhi_init_dev_ctxt()
267 if (!mhi_ctxt->chan_ctxt) in mhi_init_dev_ctxt()
270 mhi_chan = mhi_cntrl->mhi_chan; in mhi_init_dev_ctxt()
271 chan_ctxt = mhi_ctxt->chan_ctxt; in mhi_init_dev_ctxt()
272 for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { in mhi_init_dev_ctxt()
274 if (mhi_chan->offload_ch) in mhi_init_dev_ctxt()
277 tmp = chan_ctxt->chcfg; in mhi_init_dev_ctxt()
281 tmp |= (mhi_chan->db_cfg.brstmode << CHAN_CTX_BRSTMODE_SHIFT); in mhi_init_dev_ctxt()
283 tmp |= (mhi_chan->db_cfg.pollcfg << CHAN_CTX_POLLCFG_SHIFT); in mhi_init_dev_ctxt()
284 chan_ctxt->chcfg = tmp; in mhi_init_dev_ctxt()
286 chan_ctxt->chtype = mhi_chan->type; in mhi_init_dev_ctxt()
287 chan_ctxt->erindex = mhi_chan->er_index; in mhi_init_dev_ctxt()
289 mhi_chan->ch_state = MHI_CH_STATE_DISABLED; in mhi_init_dev_ctxt()
290 mhi_chan->tre_ring.db_addr = (void __iomem *)&chan_ctxt->wp; in mhi_init_dev_ctxt()
294 mhi_ctxt->er_ctxt = mhi_alloc_coherent(mhi_cntrl, in mhi_init_dev_ctxt()
295 sizeof(*mhi_ctxt->er_ctxt) * in mhi_init_dev_ctxt()
296 mhi_cntrl->total_ev_rings, in mhi_init_dev_ctxt()
297 &mhi_ctxt->er_ctxt_addr, in mhi_init_dev_ctxt()
299 if (!mhi_ctxt->er_ctxt) in mhi_init_dev_ctxt()
302 er_ctxt = mhi_ctxt->er_ctxt; in mhi_init_dev_ctxt()
303 mhi_event = mhi_cntrl->mhi_event; in mhi_init_dev_ctxt()
304 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, in mhi_init_dev_ctxt()
306 struct mhi_ring *ring = &mhi_event->ring; in mhi_init_dev_ctxt()
309 if (mhi_event->offload_ev) in mhi_init_dev_ctxt()
312 tmp = er_ctxt->intmod; in mhi_init_dev_ctxt()
315 tmp |= (mhi_event->intmod << EV_CTX_INTMODT_SHIFT); in mhi_init_dev_ctxt()
316 er_ctxt->intmod = tmp; in mhi_init_dev_ctxt()
318 er_ctxt->ertype = MHI_ER_TYPE_VALID; in mhi_init_dev_ctxt()
319 er_ctxt->msivec = mhi_event->irq; in mhi_init_dev_ctxt()
320 mhi_event->db_cfg.db_mode = true; in mhi_init_dev_ctxt()
322 ring->el_size = sizeof(struct mhi_tre); in mhi_init_dev_ctxt()
323 ring->len = ring->el_size * ring->elements; in mhi_init_dev_ctxt()
324 ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); in mhi_init_dev_ctxt()
332 ring->rp = ring->wp = ring->base; in mhi_init_dev_ctxt()
333 er_ctxt->rbase = ring->iommu_base; in mhi_init_dev_ctxt()
334 er_ctxt->rp = er_ctxt->wp = er_ctxt->rbase; in mhi_init_dev_ctxt()
335 er_ctxt->rlen = ring->len; in mhi_init_dev_ctxt()
336 ring->ctxt_wp = &er_ctxt->wp; in mhi_init_dev_ctxt()
340 ret = -ENOMEM; in mhi_init_dev_ctxt()
341 mhi_ctxt->cmd_ctxt = mhi_alloc_coherent(mhi_cntrl, in mhi_init_dev_ctxt()
342 sizeof(*mhi_ctxt->cmd_ctxt) * in mhi_init_dev_ctxt()
344 &mhi_ctxt->cmd_ctxt_addr, in mhi_init_dev_ctxt()
346 if (!mhi_ctxt->cmd_ctxt) in mhi_init_dev_ctxt()
349 mhi_cmd = mhi_cntrl->mhi_cmd; in mhi_init_dev_ctxt()
350 cmd_ctxt = mhi_ctxt->cmd_ctxt; in mhi_init_dev_ctxt()
352 struct mhi_ring *ring = &mhi_cmd->ring; in mhi_init_dev_ctxt()
354 ring->el_size = sizeof(struct mhi_tre); in mhi_init_dev_ctxt()
355 ring->elements = CMD_EL_PER_RING; in mhi_init_dev_ctxt()
356 ring->len = ring->el_size * ring->elements; in mhi_init_dev_ctxt()
357 ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); in mhi_init_dev_ctxt()
361 ring->rp = ring->wp = ring->base; in mhi_init_dev_ctxt()
362 cmd_ctxt->rbase = ring->iommu_base; in mhi_init_dev_ctxt()
363 cmd_ctxt->rp = cmd_ctxt->wp = cmd_ctxt->rbase; in mhi_init_dev_ctxt()
364 cmd_ctxt->rlen = ring->len; in mhi_init_dev_ctxt()
365 ring->ctxt_wp = &cmd_ctxt->wp; in mhi_init_dev_ctxt()
368 mhi_cntrl->mhi_ctxt = mhi_ctxt; in mhi_init_dev_ctxt()
373 for (--i, --mhi_cmd; i >= 0; i--, mhi_cmd--) { in mhi_init_dev_ctxt()
374 struct mhi_ring *ring = &mhi_cmd->ring; in mhi_init_dev_ctxt()
376 mhi_free_coherent(mhi_cntrl, ring->alloc_size, in mhi_init_dev_ctxt()
377 ring->pre_aligned, ring->dma_handle); in mhi_init_dev_ctxt()
380 sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS, in mhi_init_dev_ctxt()
381 mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr); in mhi_init_dev_ctxt()
382 i = mhi_cntrl->total_ev_rings; in mhi_init_dev_ctxt()
383 mhi_event = mhi_cntrl->mhi_event + i; in mhi_init_dev_ctxt()
386 for (--i, --mhi_event; i >= 0; i--, mhi_event--) { in mhi_init_dev_ctxt()
387 struct mhi_ring *ring = &mhi_event->ring; in mhi_init_dev_ctxt()
389 if (mhi_event->offload_ev) in mhi_init_dev_ctxt()
392 mhi_free_coherent(mhi_cntrl, ring->alloc_size, in mhi_init_dev_ctxt()
393 ring->pre_aligned, ring->dma_handle); in mhi_init_dev_ctxt()
395 mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) * in mhi_init_dev_ctxt()
396 mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt, in mhi_init_dev_ctxt()
397 mhi_ctxt->er_ctxt_addr); in mhi_init_dev_ctxt()
400 mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) * in mhi_init_dev_ctxt()
401 mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt, in mhi_init_dev_ctxt()
402 mhi_ctxt->chan_ctxt_addr); in mhi_init_dev_ctxt()
416 void __iomem *base = mhi_cntrl->regs; in mhi_init_mmio()
417 struct device *dev = &mhi_cntrl->mhi_dev->dev; in mhi_init_mmio()
426 upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), in mhi_init_mmio()
430 lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), in mhi_init_mmio()
434 upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), in mhi_init_mmio()
438 lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), in mhi_init_mmio()
442 upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), in mhi_init_mmio()
446 lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), in mhi_init_mmio()
450 mhi_cntrl->total_ev_rings, in mhi_init_mmio()
454 mhi_cntrl->hw_ev_rings, in mhi_init_mmio()
458 upper_32_bits(mhi_cntrl->iova_start), in mhi_init_mmio()
462 lower_32_bits(mhi_cntrl->iova_start), in mhi_init_mmio()
466 upper_32_bits(mhi_cntrl->iova_start), in mhi_init_mmio()
470 lower_32_bits(mhi_cntrl->iova_start), in mhi_init_mmio()
474 upper_32_bits(mhi_cntrl->iova_stop), in mhi_init_mmio()
478 lower_32_bits(mhi_cntrl->iova_stop), in mhi_init_mmio()
482 upper_32_bits(mhi_cntrl->iova_stop), in mhi_init_mmio()
486 lower_32_bits(mhi_cntrl->iova_stop), in mhi_init_mmio()
498 return -EIO; in mhi_init_mmio()
502 mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB); in mhi_init_mmio()
503 mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 4, 0); in mhi_init_mmio()
504 mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 0, 0); in mhi_init_mmio()
505 mhi_cntrl->wake_set = false; in mhi_init_mmio()
508 mhi_chan = mhi_cntrl->mhi_chan; in mhi_init_mmio()
509 for (i = 0; i < mhi_cntrl->max_chan; i++, val += 8, mhi_chan++) in mhi_init_mmio()
510 mhi_chan->tre_ring.db_addr = base + val; in mhi_init_mmio()
517 return -EIO; in mhi_init_mmio()
521 mhi_event = mhi_cntrl->mhi_event; in mhi_init_mmio()
522 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) { in mhi_init_mmio()
523 if (mhi_event->offload_ev) in mhi_init_mmio()
526 mhi_event->ring.db_addr = base + val; in mhi_init_mmio()
530 mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING].ring.db_addr = base + CRDB_LOWER; in mhi_init_mmio()
548 buf_ring = &mhi_chan->buf_ring; in mhi_deinit_chan_ctxt()
549 tre_ring = &mhi_chan->tre_ring; in mhi_deinit_chan_ctxt()
550 chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; in mhi_deinit_chan_ctxt()
552 mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size, in mhi_deinit_chan_ctxt()
553 tre_ring->pre_aligned, tre_ring->dma_handle); in mhi_deinit_chan_ctxt()
554 vfree(buf_ring->base); in mhi_deinit_chan_ctxt()
556 buf_ring->base = tre_ring->base = NULL; in mhi_deinit_chan_ctxt()
557 chan_ctxt->rbase = 0; in mhi_deinit_chan_ctxt()
569 buf_ring = &mhi_chan->buf_ring; in mhi_init_chan_ctxt()
570 tre_ring = &mhi_chan->tre_ring; in mhi_init_chan_ctxt()
571 tre_ring->el_size = sizeof(struct mhi_tre); in mhi_init_chan_ctxt()
572 tre_ring->len = tre_ring->el_size * tre_ring->elements; in mhi_init_chan_ctxt()
573 chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; in mhi_init_chan_ctxt()
574 ret = mhi_alloc_aligned_ring(mhi_cntrl, tre_ring, tre_ring->len); in mhi_init_chan_ctxt()
576 return -ENOMEM; in mhi_init_chan_ctxt()
578 buf_ring->el_size = sizeof(struct mhi_buf_info); in mhi_init_chan_ctxt()
579 buf_ring->len = buf_ring->el_size * buf_ring->elements; in mhi_init_chan_ctxt()
580 buf_ring->base = vzalloc(buf_ring->len); in mhi_init_chan_ctxt()
582 if (!buf_ring->base) { in mhi_init_chan_ctxt()
583 mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size, in mhi_init_chan_ctxt()
584 tre_ring->pre_aligned, tre_ring->dma_handle); in mhi_init_chan_ctxt()
585 return -ENOMEM; in mhi_init_chan_ctxt()
588 tmp = chan_ctxt->chcfg; in mhi_init_chan_ctxt()
591 chan_ctxt->chcfg = tmp; in mhi_init_chan_ctxt()
593 chan_ctxt->rbase = tre_ring->iommu_base; in mhi_init_chan_ctxt()
594 chan_ctxt->rp = chan_ctxt->wp = chan_ctxt->rbase; in mhi_init_chan_ctxt()
595 chan_ctxt->rlen = tre_ring->len; in mhi_init_chan_ctxt()
596 tre_ring->ctxt_wp = &chan_ctxt->wp; in mhi_init_chan_ctxt()
598 tre_ring->rp = tre_ring->wp = tre_ring->base; in mhi_init_chan_ctxt()
599 buf_ring->rp = buf_ring->wp = buf_ring->base; in mhi_init_chan_ctxt()
600 mhi_chan->db_cfg.db_mode = 1; in mhi_init_chan_ctxt()
613 struct device *dev = &mhi_cntrl->mhi_dev->dev; in parse_ev_cfg()
616 num = config->num_events; in parse_ev_cfg()
617 mhi_cntrl->total_ev_rings = num; in parse_ev_cfg()
618 mhi_cntrl->mhi_event = kcalloc(num, sizeof(*mhi_cntrl->mhi_event), in parse_ev_cfg()
620 if (!mhi_cntrl->mhi_event) in parse_ev_cfg()
621 return -ENOMEM; in parse_ev_cfg()
624 mhi_event = mhi_cntrl->mhi_event; in parse_ev_cfg()
626 event_cfg = &config->event_cfg[i]; in parse_ev_cfg()
628 mhi_event->er_index = i; in parse_ev_cfg()
629 mhi_event->ring.elements = event_cfg->num_elements; in parse_ev_cfg()
630 mhi_event->intmod = event_cfg->irq_moderation_ms; in parse_ev_cfg()
631 mhi_event->irq = event_cfg->irq; in parse_ev_cfg()
633 if (event_cfg->channel != U32_MAX) { in parse_ev_cfg()
635 mhi_event->chan = event_cfg->channel; in parse_ev_cfg()
636 if (mhi_event->chan >= mhi_cntrl->max_chan) { in parse_ev_cfg()
642 mhi_event->mhi_chan = in parse_ev_cfg()
643 &mhi_cntrl->mhi_chan[mhi_event->chan]; in parse_ev_cfg()
647 mhi_event->priority = 1; in parse_ev_cfg()
649 mhi_event->db_cfg.brstmode = event_cfg->mode; in parse_ev_cfg()
650 if (MHI_INVALID_BRSTMODE(mhi_event->db_cfg.brstmode)) in parse_ev_cfg()
653 if (mhi_event->db_cfg.brstmode == MHI_DB_BRST_ENABLE) in parse_ev_cfg()
654 mhi_event->db_cfg.process_db = mhi_db_brstmode; in parse_ev_cfg()
656 mhi_event->db_cfg.process_db = mhi_db_brstmode_disable; in parse_ev_cfg()
658 mhi_event->data_type = event_cfg->data_type; in parse_ev_cfg()
660 switch (mhi_event->data_type) { in parse_ev_cfg()
662 mhi_event->process_event = mhi_process_data_event_ring; in parse_ev_cfg()
665 mhi_event->process_event = mhi_process_ctrl_ev_ring; in parse_ev_cfg()
672 mhi_event->hw_ring = event_cfg->hardware_event; in parse_ev_cfg()
673 if (mhi_event->hw_ring) in parse_ev_cfg()
674 mhi_cntrl->hw_ev_rings++; in parse_ev_cfg()
676 mhi_cntrl->sw_ev_rings++; in parse_ev_cfg()
678 mhi_event->cl_manage = event_cfg->client_managed; in parse_ev_cfg()
679 mhi_event->offload_ev = event_cfg->offload_channel; in parse_ev_cfg()
687 kfree(mhi_cntrl->mhi_event); in parse_ev_cfg()
688 return -EINVAL; in parse_ev_cfg()
695 struct device *dev = &mhi_cntrl->mhi_dev->dev; in parse_ch_cfg()
699 mhi_cntrl->max_chan = config->max_channels; in parse_ch_cfg()
706 mhi_cntrl->mhi_chan = vzalloc(mhi_cntrl->max_chan * in parse_ch_cfg()
707 sizeof(*mhi_cntrl->mhi_chan)); in parse_ch_cfg()
708 if (!mhi_cntrl->mhi_chan) in parse_ch_cfg()
709 return -ENOMEM; in parse_ch_cfg()
711 INIT_LIST_HEAD(&mhi_cntrl->lpm_chans); in parse_ch_cfg()
714 for (i = 0; i < config->num_channels; i++) { in parse_ch_cfg()
717 ch_cfg = &config->ch_cfg[i]; in parse_ch_cfg()
719 chan = ch_cfg->num; in parse_ch_cfg()
720 if (chan >= mhi_cntrl->max_chan) { in parse_ch_cfg()
725 mhi_chan = &mhi_cntrl->mhi_chan[chan]; in parse_ch_cfg()
726 mhi_chan->name = ch_cfg->name; in parse_ch_cfg()
727 mhi_chan->chan = chan; in parse_ch_cfg()
729 mhi_chan->tre_ring.elements = ch_cfg->num_elements; in parse_ch_cfg()
730 if (!mhi_chan->tre_ring.elements) in parse_ch_cfg()
740 mhi_chan->buf_ring.elements = ch_cfg->local_elements; in parse_ch_cfg()
741 if (!mhi_chan->buf_ring.elements) in parse_ch_cfg()
742 mhi_chan->buf_ring.elements = mhi_chan->tre_ring.elements; in parse_ch_cfg()
743 mhi_chan->er_index = ch_cfg->event_ring; in parse_ch_cfg()
744 mhi_chan->dir = ch_cfg->dir; in parse_ch_cfg()
751 mhi_chan->type = ch_cfg->type; in parse_ch_cfg()
752 if (!mhi_chan->type) in parse_ch_cfg()
753 mhi_chan->type = (enum mhi_ch_type)mhi_chan->dir; in parse_ch_cfg()
755 mhi_chan->ee_mask = ch_cfg->ee_mask; in parse_ch_cfg()
756 mhi_chan->db_cfg.pollcfg = ch_cfg->pollcfg; in parse_ch_cfg()
757 mhi_chan->lpm_notify = ch_cfg->lpm_notify; in parse_ch_cfg()
758 mhi_chan->offload_ch = ch_cfg->offload_channel; in parse_ch_cfg()
759 mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch; in parse_ch_cfg()
760 mhi_chan->pre_alloc = ch_cfg->auto_queue; in parse_ch_cfg()
761 mhi_chan->auto_start = ch_cfg->auto_start; in parse_ch_cfg()
767 if (mhi_chan->pre_alloc && mhi_chan->dir != DMA_FROM_DEVICE) { in parse_ch_cfg()
773 * Bi-directional and direction less channel must be an in parse_ch_cfg()
776 if ((mhi_chan->dir == DMA_BIDIRECTIONAL || in parse_ch_cfg()
777 mhi_chan->dir == DMA_NONE) && !mhi_chan->offload_ch) { in parse_ch_cfg()
782 if (!mhi_chan->offload_ch) { in parse_ch_cfg()
783 mhi_chan->db_cfg.brstmode = ch_cfg->doorbell; in parse_ch_cfg()
784 if (MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode)) { in parse_ch_cfg()
790 if (mhi_chan->db_cfg.brstmode == MHI_DB_BRST_ENABLE) in parse_ch_cfg()
791 mhi_chan->db_cfg.process_db = mhi_db_brstmode; in parse_ch_cfg()
793 mhi_chan->db_cfg.process_db = mhi_db_brstmode_disable; in parse_ch_cfg()
795 mhi_chan->configured = true; in parse_ch_cfg()
797 if (mhi_chan->lpm_notify) in parse_ch_cfg()
798 list_add_tail(&mhi_chan->node, &mhi_cntrl->lpm_chans); in parse_ch_cfg()
804 vfree(mhi_cntrl->mhi_chan); in parse_ch_cfg()
806 return -EINVAL; in parse_ch_cfg()
824 mhi_cntrl->timeout_ms = config->timeout_ms; in parse_config()
825 if (!mhi_cntrl->timeout_ms) in parse_config()
826 mhi_cntrl->timeout_ms = MHI_TIMEOUT_MS; in parse_config()
828 mhi_cntrl->bounce_buf = config->use_bounce_buf; in parse_config()
829 mhi_cntrl->buffer_len = config->buf_len; in parse_config()
830 if (!mhi_cntrl->buffer_len) in parse_config()
831 mhi_cntrl->buffer_len = MHI_MAX_MTU; in parse_config()
834 mhi_cntrl->db_access = MHI_PM_M0 | MHI_PM_M2; in parse_config()
835 if (config->m2_no_db) in parse_config()
836 mhi_cntrl->db_access &= ~MHI_PM_M2; in parse_config()
841 vfree(mhi_cntrl->mhi_chan); in parse_config()
857 return -EINVAL; in mhi_register_controller()
859 if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put || in mhi_register_controller()
860 !mhi_cntrl->status_cb || !mhi_cntrl->read_reg || in mhi_register_controller()
861 !mhi_cntrl->write_reg) in mhi_register_controller()
862 return -EINVAL; in mhi_register_controller()
866 return -EINVAL; in mhi_register_controller()
868 mhi_cntrl->mhi_cmd = kcalloc(NR_OF_CMD_RINGS, in mhi_register_controller()
869 sizeof(*mhi_cntrl->mhi_cmd), GFP_KERNEL); in mhi_register_controller()
870 if (!mhi_cntrl->mhi_cmd) { in mhi_register_controller()
871 ret = -ENOMEM; in mhi_register_controller()
875 INIT_LIST_HEAD(&mhi_cntrl->transition_list); in mhi_register_controller()
876 mutex_init(&mhi_cntrl->pm_mutex); in mhi_register_controller()
877 rwlock_init(&mhi_cntrl->pm_lock); in mhi_register_controller()
878 spin_lock_init(&mhi_cntrl->transition_lock); in mhi_register_controller()
879 spin_lock_init(&mhi_cntrl->wlock); in mhi_register_controller()
880 INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); in mhi_register_controller()
881 init_waitqueue_head(&mhi_cntrl->state_event); in mhi_register_controller()
883 mhi_cmd = mhi_cntrl->mhi_cmd; in mhi_register_controller()
885 spin_lock_init(&mhi_cmd->lock); in mhi_register_controller()
887 mhi_event = mhi_cntrl->mhi_event; in mhi_register_controller()
888 for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { in mhi_register_controller()
890 if (mhi_event->offload_ev) in mhi_register_controller()
893 mhi_event->mhi_cntrl = mhi_cntrl; in mhi_register_controller()
894 spin_lock_init(&mhi_event->lock); in mhi_register_controller()
895 if (mhi_event->data_type == MHI_ER_CTRL) in mhi_register_controller()
896 tasklet_init(&mhi_event->task, mhi_ctrl_ev_task, in mhi_register_controller()
899 tasklet_init(&mhi_event->task, mhi_ev_task, in mhi_register_controller()
903 mhi_chan = mhi_cntrl->mhi_chan; in mhi_register_controller()
904 for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { in mhi_register_controller()
905 mutex_init(&mhi_chan->mutex); in mhi_register_controller()
906 init_completion(&mhi_chan->completion); in mhi_register_controller()
907 rwlock_init(&mhi_chan->lock); in mhi_register_controller()
910 mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index]; in mhi_register_controller()
911 mhi_chan->intmod = mhi_event->intmod; in mhi_register_controller()
914 if (mhi_cntrl->bounce_buf) { in mhi_register_controller()
915 mhi_cntrl->map_single = mhi_map_single_use_bb; in mhi_register_controller()
916 mhi_cntrl->unmap_single = mhi_unmap_single_use_bb; in mhi_register_controller()
918 mhi_cntrl->map_single = mhi_map_single_no_bb; in mhi_register_controller()
919 mhi_cntrl->unmap_single = mhi_unmap_single_no_bb; in mhi_register_controller()
923 ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, in mhi_register_controller()
928 mhi_cntrl->family_number = (soc_info & SOC_HW_VERSION_FAM_NUM_BMSK) >> in mhi_register_controller()
930 mhi_cntrl->device_number = (soc_info & SOC_HW_VERSION_DEV_NUM_BMSK) >> in mhi_register_controller()
932 mhi_cntrl->major_version = (soc_info & SOC_HW_VERSION_MAJOR_VER_BMSK) >> in mhi_register_controller()
934 mhi_cntrl->minor_version = (soc_info & SOC_HW_VERSION_MINOR_VER_BMSK) >> in mhi_register_controller()
937 /* Register controller with MHI bus */ in mhi_register_controller()
940 dev_err(mhi_cntrl->cntrl_dev, "Failed to allocate MHI device\n"); in mhi_register_controller()
945 mhi_dev->dev_type = MHI_DEVICE_CONTROLLER; in mhi_register_controller()
946 mhi_dev->mhi_cntrl = mhi_cntrl; in mhi_register_controller()
947 dev_set_name(&mhi_dev->dev, "%s", dev_name(mhi_cntrl->cntrl_dev)); in mhi_register_controller()
948 mhi_dev->name = dev_name(mhi_cntrl->cntrl_dev); in mhi_register_controller()
951 device_init_wakeup(&mhi_dev->dev, true); in mhi_register_controller()
953 ret = device_add(&mhi_dev->dev); in mhi_register_controller()
957 mhi_cntrl->mhi_dev = mhi_dev; in mhi_register_controller()
964 put_device(&mhi_dev->dev); in mhi_register_controller()
967 kfree(mhi_cntrl->mhi_cmd); in mhi_register_controller()
970 vfree(mhi_cntrl->mhi_chan); in mhi_register_controller()
971 kfree(mhi_cntrl->mhi_event); in mhi_register_controller()
979 struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; in mhi_unregister_controller()
980 struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan; in mhi_unregister_controller()
985 kfree(mhi_cntrl->mhi_cmd); in mhi_unregister_controller()
986 kfree(mhi_cntrl->mhi_event); in mhi_unregister_controller()
989 for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { in mhi_unregister_controller()
990 if (!mhi_chan->mhi_dev) in mhi_unregister_controller()
993 put_device(&mhi_chan->mhi_dev->dev); in mhi_unregister_controller()
995 vfree(mhi_cntrl->mhi_chan); in mhi_unregister_controller()
997 device_del(&mhi_dev->dev); in mhi_unregister_controller()
998 put_device(&mhi_dev->dev); in mhi_unregister_controller()
1020 struct device *dev = &mhi_cntrl->mhi_dev->dev; in mhi_prepare_for_power_up()
1024 mutex_lock(&mhi_cntrl->pm_mutex); in mhi_prepare_for_power_up()
1033 if (mhi_cntrl->rddm_size) { in mhi_prepare_for_power_up()
1034 mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, in mhi_prepare_for_power_up()
1035 mhi_cntrl->rddm_size); in mhi_prepare_for_power_up()
1038 * This controller supports RDDM, so we need to manually clear in mhi_prepare_for_power_up()
1041 ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, in mhi_prepare_for_power_up()
1048 mhi_cntrl->bhie = mhi_cntrl->regs + bhie_off; in mhi_prepare_for_power_up()
1049 memset_io(mhi_cntrl->bhie + BHIE_RXVECADDR_LOW_OFFS, in mhi_prepare_for_power_up()
1050 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + in mhi_prepare_for_power_up()
1053 if (mhi_cntrl->rddm_image) in mhi_prepare_for_power_up()
1054 mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); in mhi_prepare_for_power_up()
1057 mhi_cntrl->pre_init = true; in mhi_prepare_for_power_up()
1059 mutex_unlock(&mhi_cntrl->pm_mutex); in mhi_prepare_for_power_up()
1064 if (mhi_cntrl->rddm_image) { in mhi_prepare_for_power_up()
1065 mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); in mhi_prepare_for_power_up()
1066 mhi_cntrl->rddm_image = NULL; in mhi_prepare_for_power_up()
1070 mutex_unlock(&mhi_cntrl->pm_mutex); in mhi_prepare_for_power_up()
1078 if (mhi_cntrl->fbc_image) { in mhi_unprepare_after_power_down()
1079 mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); in mhi_unprepare_after_power_down()
1080 mhi_cntrl->fbc_image = NULL; in mhi_unprepare_after_power_down()
1083 if (mhi_cntrl->rddm_image) { in mhi_unprepare_after_power_down()
1084 mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); in mhi_unprepare_after_power_down()
1085 mhi_cntrl->rddm_image = NULL; in mhi_unprepare_after_power_down()
1089 mhi_cntrl->pre_init = false; in mhi_unprepare_after_power_down()
1098 * We need to set the mhi_chan->mhi_dev to NULL here since the MHI in mhi_release_device()
1101 * controller suspend and resume. in mhi_release_device()
1103 if (mhi_dev->ul_chan) in mhi_release_device()
1104 mhi_dev->ul_chan->mhi_dev = NULL; in mhi_release_device()
1106 if (mhi_dev->dl_chan) in mhi_release_device()
1107 mhi_dev->dl_chan->mhi_dev = NULL; in mhi_release_device()
1119 return ERR_PTR(-ENOMEM); in mhi_alloc_device()
1121 dev = &mhi_dev->dev; in mhi_alloc_device()
1123 dev->bus = &mhi_bus_type; in mhi_alloc_device()
1124 dev->release = mhi_release_device; in mhi_alloc_device()
1125 dev->parent = mhi_cntrl->cntrl_dev; in mhi_alloc_device()
1126 mhi_dev->mhi_cntrl = mhi_cntrl; in mhi_alloc_device()
1127 mhi_dev->dev_wake = 0; in mhi_alloc_device()
1135 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; in mhi_driver_probe()
1136 struct device_driver *drv = dev->driver; in mhi_driver_probe()
1139 struct mhi_chan *ul_chan = mhi_dev->ul_chan; in mhi_driver_probe()
1140 struct mhi_chan *dl_chan = mhi_dev->dl_chan; in mhi_driver_probe()
1148 ret = -EINVAL; in mhi_driver_probe()
1155 if (ul_chan->lpm_notify && !mhi_drv->status_cb) in mhi_driver_probe()
1158 /* For non-offload channels then xfer_cb should be provided */ in mhi_driver_probe()
1159 if (!ul_chan->offload_ch && !mhi_drv->ul_xfer_cb) in mhi_driver_probe()
1162 ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; in mhi_driver_probe()
1163 if (ul_chan->auto_start) { in mhi_driver_probe()
1170 ret = -EINVAL; in mhi_driver_probe()
1176 if (dl_chan->lpm_notify && !mhi_drv->status_cb) in mhi_driver_probe()
1179 /* For non-offload channels then xfer_cb should be provided */ in mhi_driver_probe()
1180 if (!dl_chan->offload_ch && !mhi_drv->dl_xfer_cb) in mhi_driver_probe()
1183 mhi_event = &mhi_cntrl->mhi_event[dl_chan->er_index]; in mhi_driver_probe()
1190 if (mhi_event->cl_manage && !mhi_drv->status_cb) in mhi_driver_probe()
1193 dl_chan->xfer_cb = mhi_drv->dl_xfer_cb; in mhi_driver_probe()
1197 ret = mhi_drv->probe(mhi_dev, mhi_dev->id); in mhi_driver_probe()
1201 if (dl_chan && dl_chan->auto_start) in mhi_driver_probe()
1219 struct mhi_driver *mhi_drv = to_mhi_driver(dev->driver); in mhi_driver_remove()
1220 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; in mhi_driver_remove()
1228 /* Skip if it is a controller device */ in mhi_driver_remove()
1229 if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER) in mhi_driver_remove()
1234 mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; in mhi_driver_remove()
1240 write_lock_irq(&mhi_chan->lock); in mhi_driver_remove()
1241 mhi_chan->ccs = MHI_EV_CC_INVALID; in mhi_driver_remove()
1242 complete_all(&mhi_chan->completion); in mhi_driver_remove()
1243 write_unlock_irq(&mhi_chan->lock); in mhi_driver_remove()
1246 mutex_lock(&mhi_chan->mutex); in mhi_driver_remove()
1247 write_lock_irq(&mhi_chan->lock); in mhi_driver_remove()
1248 ch_state[dir] = mhi_chan->ch_state; in mhi_driver_remove()
1249 mhi_chan->ch_state = MHI_CH_STATE_SUSPENDED; in mhi_driver_remove()
1250 write_unlock_irq(&mhi_chan->lock); in mhi_driver_remove()
1252 /* Reset the non-offload channel */ in mhi_driver_remove()
1253 if (!mhi_chan->offload_ch) in mhi_driver_remove()
1256 mutex_unlock(&mhi_chan->mutex); in mhi_driver_remove()
1259 mhi_drv->remove(mhi_dev); in mhi_driver_remove()
1261 /* De-init channel if it was enabled */ in mhi_driver_remove()
1263 mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; in mhi_driver_remove()
1268 mutex_lock(&mhi_chan->mutex); in mhi_driver_remove()
1271 !mhi_chan->offload_ch) in mhi_driver_remove()
1274 mhi_chan->ch_state = MHI_CH_STATE_DISABLED; in mhi_driver_remove()
1276 mutex_unlock(&mhi_chan->mutex); in mhi_driver_remove()
1279 read_lock_bh(&mhi_cntrl->pm_lock); in mhi_driver_remove()
1280 while (mhi_dev->dev_wake) in mhi_driver_remove()
1282 read_unlock_bh(&mhi_cntrl->pm_lock); in mhi_driver_remove()
1289 struct device_driver *driver = &mhi_drv->driver; in __mhi_driver_register()
1291 if (!mhi_drv->probe || !mhi_drv->remove) in __mhi_driver_register()
1292 return -EINVAL; in __mhi_driver_register()
1294 driver->bus = &mhi_bus_type; in __mhi_driver_register()
1295 driver->owner = owner; in __mhi_driver_register()
1296 driver->probe = mhi_driver_probe; in __mhi_driver_register()
1297 driver->remove = mhi_driver_remove; in __mhi_driver_register()
1305 driver_unregister(&mhi_drv->driver); in mhi_driver_unregister()
1314 mhi_dev->name); in mhi_uevent()
1324 * If the device is a controller type then there is no client driver in mhi_match()
1327 if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER) in mhi_match()
1330 for (id = mhi_drv->id_table; id->chan[0]; id++) in mhi_match()
1331 if (!strcmp(mhi_dev->name, id->chan)) { in mhi_match()
1332 mhi_dev->id = id; in mhi_match()