Lines Matching +full:mhuv2 +full:- +full:tx
1 // SPDX-License-Identifier: GPL-2.0
7 * Based on ARM MHUv2 driver.
84 #define fcgi_spt BIT(10) // MBX-only
129 /*-- MBX-only registers --*/
134 /*-- End of MBX-only ---- */
137 /*-- MBX-only registers --*/
143 /*-- End of MBX-only ---- */
252 * struct mhuv3_protocol_ops - MHUv3 operations
256 * @read_data: Read available Sender in-band LE data (if any).
257 * @rx_complete: Acknowledge data reception to the Sender. Any out-of-band data
279 * struct mhuv3_mbox_chan_priv - MHUv3 channel private information
295 * struct mhuv3_extension - MHUv3 extension descriptor
307 * @pending_db: Array of per-channel pending doorbells.
326 * struct mhuv3 - MHUv3 mailbox controller data
372 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_tx_startup()
375 writel_relaxed_bitmask(0x1, &mhu->pbx->dbcw[priv->ch_idx].int_en, tfr_ack); in mhuv3_doorbell_tx_startup()
380 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_tx_shutdown()
381 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_doorbell_tx_shutdown()
385 writel_relaxed_bitmask(0x0, &mhu->pbx->dbcw[priv->ch_idx].int_en, tfr_ack); in mhuv3_doorbell_tx_shutdown()
388 writel_relaxed_bitmask(0x1, &mhu->pbx->dbcw[priv->ch_idx].int_clr, tfr_ack); in mhuv3_doorbell_tx_shutdown()
389 spin_lock_irqsave(&e->pending_lock, flags); in mhuv3_doorbell_tx_shutdown()
390 e->pending_db[priv->ch_idx] = 0; in mhuv3_doorbell_tx_shutdown()
391 spin_unlock_irqrestore(&e->pending_lock, flags); in mhuv3_doorbell_tx_shutdown()
396 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_rx_startup()
399 writel_relaxed(BIT(priv->doorbell), &mhu->mbx->dbcw[priv->ch_idx].msk_clr); in mhuv3_doorbell_rx_startup()
407 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_rx_shutdown()
410 writel_relaxed(BIT(priv->doorbell), &mhu->mbx->dbcw[priv->ch_idx].msk_set); in mhuv3_doorbell_rx_shutdown()
415 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_rx_complete()
418 writel_relaxed(BIT(priv->doorbell), &mhu->mbx->dbcw[priv->ch_idx].clr); in mhuv3_doorbell_rx_complete()
424 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_last_tx_done()
427 done = !(readl_relaxed(&mhu->pbx->dbcw[priv->ch_idx].st) & in mhuv3_doorbell_last_tx_done()
428 BIT(priv->doorbell)); in mhuv3_doorbell_last_tx_done()
430 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_doorbell_last_tx_done()
434 spin_lock_irqsave(&e->pending_lock, flags); in mhuv3_doorbell_last_tx_done()
435 e->pending_db[priv->ch_idx] &= ~BIT(priv->doorbell); in mhuv3_doorbell_last_tx_done()
436 spin_unlock_irqrestore(&e->pending_lock, flags); in mhuv3_doorbell_last_tx_done()
445 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_doorbell_send_data()
446 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_doorbell_send_data()
448 scoped_guard(spinlock_irqsave, &e->pending_lock) { in mhuv3_doorbell_send_data()
449 /* Only one in-flight Transfer is allowed per-doorbell */ in mhuv3_doorbell_send_data()
450 if (e->pending_db[priv->ch_idx] & BIT(priv->doorbell)) in mhuv3_doorbell_send_data()
451 return -EBUSY; in mhuv3_doorbell_send_data()
453 e->pending_db[priv->ch_idx] |= BIT(priv->doorbell); in mhuv3_doorbell_send_data()
456 writel_relaxed(BIT(priv->doorbell), &mhu->pbx->dbcw[priv->ch_idx].set); in mhuv3_doorbell_send_data()
474 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_sender_last_tx_done()
475 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_sender_last_tx_done()
477 return priv->ops->last_tx_done(mhu, chan); in mhuv3_sender_last_tx_done()
482 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_sender_send_data()
483 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_sender_send_data()
485 if (!priv->ops->last_tx_done(mhu, chan)) in mhuv3_sender_send_data()
486 return -EBUSY; in mhuv3_sender_send_data()
488 return priv->ops->send_data(mhu, chan, data); in mhuv3_sender_send_data()
493 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_sender_startup()
494 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_sender_startup()
496 if (priv->ops->tx_startup) in mhuv3_sender_startup()
497 priv->ops->tx_startup(mhu, chan); in mhuv3_sender_startup()
504 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_sender_shutdown()
505 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_sender_shutdown()
507 if (priv->ops->tx_shutdown) in mhuv3_sender_shutdown()
508 priv->ops->tx_shutdown(mhu, chan); in mhuv3_sender_shutdown()
520 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_receiver_startup()
521 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_receiver_startup()
523 return priv->ops->rx_startup(mhu, chan); in mhuv3_receiver_startup()
528 struct mhuv3_mbox_chan_priv *priv = chan->con_priv; in mhuv3_receiver_shutdown()
529 struct mhuv3 *mhu = mhu_from_mbox(chan->mbox); in mhuv3_receiver_shutdown()
531 priv->ops->rx_shutdown(mhu, chan); in mhuv3_receiver_shutdown()
536 dev_err(chan->mbox->dev, in mhuv3_receiver_send_data()
538 return -EIO; in mhuv3_receiver_send_data()
543 dev_err(chan->mbox->dev, "Trying to Tx poll on a MBX MHUv3 frame\n"); in mhuv3_receiver_last_tx_done()
558 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_dbe_mbox_of_xlate()
559 struct mbox_controller *mbox = &mhu->mbox; in mhuv3_dbe_mbox_of_xlate()
560 struct mbox_chan *chans = mbox->chans; in mhuv3_dbe_mbox_of_xlate()
562 if (channel >= e->num_chans || doorbell >= MHUV3_FLAG_BITS) { in mhuv3_dbe_mbox_of_xlate()
563 dev_err(mbox->dev, "Couldn't xlate to a valid channel (%d: %d)\n", in mhuv3_dbe_mbox_of_xlate()
565 return ERR_PTR(-ENODEV); in mhuv3_dbe_mbox_of_xlate()
568 return &chans[e->base_ch_idx + channel * MHUV3_FLAG_BITS + doorbell]; in mhuv3_dbe_mbox_of_xlate()
573 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_dbe_combined_irq_setup()
576 if (mhu->frame == PBX_FRAME) { in mhuv3_dbe_combined_irq_setup()
577 struct pdbcw_page __iomem *dbcw = mhu->pbx->dbcw; in mhuv3_dbe_combined_irq_setup()
579 for (i = 0; i < e->num_chans; i++) { in mhuv3_dbe_combined_irq_setup()
585 struct mdbcw_page __iomem *dbcw = mhu->mbx->dbcw; in mhuv3_dbe_combined_irq_setup()
587 for (i = 0; i < e->num_chans; i++) { in mhuv3_dbe_combined_irq_setup()
597 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_dbe_channels_init()
598 struct mbox_controller *mbox = &mhu->mbox; in mhuv3_dbe_channels_init()
602 chans = mbox->chans + mbox->num_chans; in mhuv3_dbe_channels_init()
603 e->base_ch_idx = mbox->num_chans; in mhuv3_dbe_channels_init()
604 for (i = 0; i < e->num_chans; i++) { in mhuv3_dbe_channels_init()
609 priv = devm_kmalloc(mbox->dev, sizeof(*priv), GFP_KERNEL); in mhuv3_dbe_channels_init()
611 return -ENOMEM; in mhuv3_dbe_channels_init()
613 priv->ch_idx = i; in mhuv3_dbe_channels_init()
614 priv->ops = &mhuv3_doorbell_ops; in mhuv3_dbe_channels_init()
615 priv->doorbell = k; in mhuv3_dbe_channels_init()
616 chans++->con_priv = priv; in mhuv3_dbe_channels_init()
617 mbox->num_chans++; in mhuv3_dbe_channels_init()
621 spin_lock_init(&e->pending_lock); in mhuv3_dbe_channels_init()
629 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_dbe_doorbell_lookup()
630 struct device *dev = mhu->mbox.dev; in mhuv3_dbe_doorbell_lookup()
633 if (mhu->frame == PBX_FRAME) { in mhuv3_dbe_doorbell_lookup()
636 st = readl_relaxed_bitmask(&mhu->pbx->dbcw[channel].int_st, in mhuv3_dbe_doorbell_lookup()
641 active_dbs = readl_relaxed(&mhu->pbx->dbcw[channel].st); in mhuv3_dbe_doorbell_lookup()
642 scoped_guard(spinlock_irqsave, &e->pending_lock) { in mhuv3_dbe_doorbell_lookup()
643 fired_dbs = e->pending_db[channel] & ~active_dbs; in mhuv3_dbe_doorbell_lookup()
648 e->pending_db[channel] &= ~BIT(*db); in mhuv3_dbe_doorbell_lookup()
654 &mhu->pbx->dbcw[channel].int_clr, in mhuv3_dbe_doorbell_lookup()
657 st = readl_relaxed(&mhu->mbx->dbcw[channel].st_msk); in mhuv3_dbe_doorbell_lookup()
668 mhuv3_str[mhu->frame], channel); in mhuv3_dbe_doorbell_lookup()
675 struct mhuv3_extension *e = mhu->ext[DBE_EXT]; in mhuv3_dbe_chan_from_comb_irq_get()
676 struct device *dev = mhu->mbox.dev; in mhuv3_dbe_chan_from_comb_irq_get()
683 cmb_st = readl_relaxed(&mhu->ctrl->dbch_int_st[i]); in mhuv3_dbe_chan_from_comb_irq_get()
688 if (channel >= e->num_chans) { in mhuv3_dbe_chan_from_comb_irq_get()
690 mhuv3_str[mhu->frame], channel); in mhuv3_dbe_chan_from_comb_irq_get()
691 return ERR_PTR(-EIO); in mhuv3_dbe_chan_from_comb_irq_get()
698 mhuv3_str[mhu->frame], channel, db); in mhuv3_dbe_chan_from_comb_irq_get()
700 return &mhu->mbox.chans[channel * MHUV3_FLAG_BITS + db]; in mhuv3_dbe_chan_from_comb_irq_get()
703 return ERR_PTR(-EIO); in mhuv3_dbe_chan_from_comb_irq_get()
708 struct device *dev = mhu->mbox.dev; in mhuv3_dbe_init()
711 if (!readl_relaxed_bitmask(&mhu->ctrl->feat_spt0, dbe_spt)) in mhuv3_dbe_init()
714 dev_dbg(dev, "%s: Initializing DBE Extension.\n", mhuv3_str[mhu->frame]); in mhuv3_dbe_init()
718 return -ENOMEM; in mhuv3_dbe_init()
720 e->type = DBE_EXT; in mhuv3_dbe_init()
722 e->num_chans = in mhuv3_dbe_init()
723 readl_relaxed_bitmask(&mhu->ctrl->dbch_cfg0, num_dbch) + 1; in mhuv3_dbe_init()
724 e->mbox_of_xlate = mhuv3_dbe_mbox_of_xlate; in mhuv3_dbe_init()
725 e->combined_irq_setup = mhuv3_dbe_combined_irq_setup; in mhuv3_dbe_init()
726 e->channels_init = mhuv3_dbe_channels_init; in mhuv3_dbe_init()
727 e->chan_from_comb_irq_get = mhuv3_dbe_chan_from_comb_irq_get; in mhuv3_dbe_init()
729 mhu->num_chans += e->num_chans * MHUV3_FLAG_BITS; in mhuv3_dbe_init()
730 mhu->ext[DBE_EXT] = e; in mhuv3_dbe_init()
733 mhuv3_str[mhu->frame], e->num_chans); in mhuv3_dbe_init()
740 struct device *dev = mhu->mbox.dev; in mhuv3_fce_init()
742 if (!readl_relaxed_bitmask(&mhu->ctrl->feat_spt0, fce_spt)) in mhuv3_fce_init()
746 mhuv3_str[mhu->frame]); in mhuv3_fce_init()
753 struct device *dev = mhu->mbox.dev; in mhuv3_fe_init()
755 if (!readl_relaxed_bitmask(&mhu->ctrl->feat_spt0, fe_spt)) in mhuv3_fe_init()
759 mhuv3_str[mhu->frame]); in mhuv3_fe_init()
772 struct mbox_controller *mbox = &mhu->mbox; in mhuv3_initialize_channels()
775 mbox->chans = devm_kcalloc(dev, mhu->num_chans, in mhuv3_initialize_channels()
776 sizeof(*mbox->chans), GFP_KERNEL); in mhuv3_initialize_channels()
777 if (!mbox->chans) in mhuv3_initialize_channels()
778 return dev_err_probe(dev, -ENOMEM, in mhuv3_initialize_channels()
782 if (mhu->ext[i]) in mhuv3_initialize_channels()
783 ret = mhu->ext[i]->channels_init(mhu); in mhuv3_initialize_channels()
794 if (pa->args_count != MHUV3_MBOX_CELLS) in mhuv3_mbox_of_xlate()
795 return ERR_PTR(-EINVAL); in mhuv3_mbox_of_xlate()
797 type = pa->args[MHUV3_MBOX_CELL_TYPE]; in mhuv3_mbox_of_xlate()
799 return ERR_PTR(-EINVAL); in mhuv3_mbox_of_xlate()
801 channel = pa->args[MHUV3_MBOX_CELL_CHWN]; in mhuv3_mbox_of_xlate()
802 param = pa->args[MHUV3_MBOX_CELL_PARAM]; in mhuv3_mbox_of_xlate()
804 return mhu->ext[type]->mbox_of_xlate(mhu, channel, param); in mhuv3_mbox_of_xlate()
811 writel_relaxed_bitmask(0x0, &mhu->ctrl->x_ctrl, op_req); in mhu_frame_cleanup_actions()
816 struct device *dev = mhu->mbox.dev; in mhuv3_frame_init()
819 mhu->ctrl = regs; in mhuv3_frame_init()
820 mhu->frame = readl_relaxed_bitmask(&mhu->ctrl->blk_id, id); in mhuv3_frame_init()
821 if (mhu->frame > MBX_FRAME) in mhuv3_frame_init()
822 return dev_err_probe(dev, -EINVAL, in mhuv3_frame_init()
823 "Invalid Frame type- %d\n", mhu->frame); in mhuv3_frame_init()
825 mhu->major = readl_relaxed_bitmask(&mhu->ctrl->aidr, arch_major_rev); in mhuv3_frame_init()
826 mhu->minor = readl_relaxed_bitmask(&mhu->ctrl->aidr, arch_minor_rev); in mhuv3_frame_init()
827 mhu->implem = readl_relaxed_bitmask(&mhu->ctrl->iidr, implementer); in mhuv3_frame_init()
828 mhu->rev = readl_relaxed_bitmask(&mhu->ctrl->iidr, revision); in mhuv3_frame_init()
829 mhu->var = readl_relaxed_bitmask(&mhu->ctrl->iidr, variant); in mhuv3_frame_init()
830 mhu->prod_id = readl_relaxed_bitmask(&mhu->ctrl->iidr, product_id); in mhuv3_frame_init()
831 if (mhu->major != MHUV3_MAJOR_VERSION) in mhuv3_frame_init()
832 return dev_err_probe(dev, -EINVAL, in mhuv3_frame_init()
833 "Unsupported MHU %s block - major:%d minor:%d\n", in mhuv3_frame_init()
834 mhuv3_str[mhu->frame], mhu->major, in mhuv3_frame_init()
835 mhu->minor); in mhuv3_frame_init()
837 mhu->auto_op_full = in mhuv3_frame_init()
838 !!readl_relaxed_bitmask(&mhu->ctrl->feat_spt1, auto_op_spt); in mhuv3_frame_init()
840 if (mhu->auto_op_full) { in mhuv3_frame_init()
841 writel_relaxed_bitmask(0x1, &mhu->ctrl->x_ctrl, op_req); in mhuv3_frame_init()
846 "Found MHU %s block - major:%d minor:%d\n implem:0x%X rev:0x%X var:0x%X prod_id:0x%X", in mhuv3_frame_init()
847 mhuv3_str[mhu->frame], mhu->major, mhu->minor, in mhuv3_frame_init()
848 mhu->implem, mhu->rev, mhu->var, mhu->prod_id); in mhuv3_frame_init()
850 if (mhu->frame == PBX_FRAME) in mhuv3_frame_init()
851 mhu->pbx = regs; in mhuv3_frame_init()
853 mhu->mbx = regs; in mhuv3_frame_init()
867 mhuv3_str[mhu->frame], in mhuv3_frame_init()
882 dev = mhu->mbox.dev; in mhuv3_pbx_comb_interrupt()
887 if (i == FCE_EXT || !mhu->ext[i]) in mhuv3_pbx_comb_interrupt()
890 chan = mhu->ext[i]->chan_from_comb_irq_get(mhu); in mhuv3_pbx_comb_interrupt()
895 priv = chan->con_priv; in mhuv3_pbx_comb_interrupt()
896 if (!chan->cl) { in mhuv3_pbx_comb_interrupt()
897 dev_warn(dev, "TX Ack on UNBOUND channel (%u)\n", in mhuv3_pbx_comb_interrupt()
898 priv->ch_idx); in mhuv3_pbx_comb_interrupt()
907 dev_warn_once(dev, "Failed to find channel for the TX interrupt\n"); in mhuv3_pbx_comb_interrupt()
920 dev = mhu->mbox.dev; in mhuv3_mbx_comb_interrupt()
925 if (!mhu->ext[i]) in mhuv3_mbx_comb_interrupt()
929 chan = mhu->ext[i]->chan_from_comb_irq_get(mhu); in mhuv3_mbx_comb_interrupt()
935 priv = chan->con_priv; in mhuv3_mbx_comb_interrupt()
936 if (!chan->cl) { in mhuv3_mbx_comb_interrupt()
938 priv->ch_idx); in mhuv3_mbx_comb_interrupt()
942 /* Read optional in-band LE data first. */ in mhuv3_mbx_comb_interrupt()
943 if (priv->ops->read_data) { in mhuv3_mbx_comb_interrupt()
944 data = priv->ops->read_data(mhu, chan); in mhuv3_mbx_comb_interrupt()
947 "Failed to read in-band data. err:%ld\n", in mhuv3_mbx_comb_interrupt()
958 * out-of-band data has also been retrieved via in mhuv3_mbx_comb_interrupt()
962 if (priv->ops->rx_complete) in mhuv3_mbx_comb_interrupt()
963 priv->ops->rx_complete(mhu, chan); in mhuv3_mbx_comb_interrupt()
974 struct device *dev = mhu->mbox.dev; in mhuv3_setup_pbx()
976 mhu->mbox.ops = &mhuv3_sender_ops; in mhuv3_setup_pbx()
978 if (mhu->cmb_irq > 0) { in mhuv3_setup_pbx()
981 ret = devm_request_threaded_irq(dev, mhu->cmb_irq, NULL, in mhuv3_setup_pbx()
983 IRQF_ONESHOT, "mhuv3-pbx", mhu); in mhuv3_setup_pbx()
988 mhu->mbox.txdone_irq = true; in mhuv3_setup_pbx()
989 mhu->mbox.txdone_poll = false; in mhuv3_setup_pbx()
992 if (mhu->ext[i]) in mhuv3_setup_pbx()
993 mhu->ext[i]->combined_irq_setup(mhu); in mhuv3_setup_pbx()
1000 dev_info(dev, "Using PBX in Tx polling mode.\n"); in mhuv3_setup_pbx()
1001 mhu->mbox.txdone_irq = false; in mhuv3_setup_pbx()
1002 mhu->mbox.txdone_poll = true; in mhuv3_setup_pbx()
1003 mhu->mbox.txpoll_period = 1; in mhuv3_setup_pbx()
1010 struct device *dev = mhu->mbox.dev; in mhuv3_setup_mbx()
1013 mhu->mbox.ops = &mhuv3_receiver_ops; in mhuv3_setup_mbx()
1015 if (mhu->cmb_irq <= 0) in mhuv3_setup_mbx()
1016 return dev_err_probe(dev, -EINVAL, in mhuv3_setup_mbx()
1019 ret = devm_request_threaded_irq(dev, mhu->cmb_irq, NULL, in mhuv3_setup_mbx()
1021 "mhuv3-mbx", mhu); in mhuv3_setup_mbx()
1026 if (mhu->ext[i]) in mhuv3_setup_mbx()
1027 mhu->ext[i]->combined_irq_setup(mhu); in mhuv3_setup_mbx()
1036 dev_dbg(mhu->mbox.dev, "Initializing %s block.\n", in mhuv3_irqs_init()
1037 mhuv3_str[mhu->frame]); in mhuv3_irqs_init()
1039 if (mhu->frame == PBX_FRAME) { in mhuv3_irqs_init()
1040 mhu->cmb_irq = in mhuv3_irqs_init()
1045 mhu->cmb_irq = platform_get_irq_byname(pdev, "combined"); in mhuv3_irqs_init()
1051 struct device *dev = &pdev->dev; in mhuv3_probe()
1058 return -ENOMEM; in mhuv3_probe()
1064 mhu->mbox.dev = dev; in mhuv3_probe()
1073 mhu->mbox.of_xlate = mhuv3_mbox_of_xlate; in mhuv3_probe()
1078 ret = devm_mbox_controller_register(dev, &mhu->mbox); in mhuv3_probe()
1094 .name = "arm-mhuv3-mailbox",