Lines Matching +full:tx +full:- +full:mailbox +full:- +full:count
1 // SPDX-License-Identifier: GPL-2.0
8 * An MHUv2 mailbox controller can provide up to 124 channel windows (each 32
10 * protocol modes: data-transfer and doorbell, to be used on those channel
18 * The number of registered mailbox channels is dependent on both the underlying
19 * hardware - mainly the number of channel windows implemented by the platform,
25 * for each mailbox controller, a sender device and a receiver device.
31 #include <linux/mailbox/arm_mhuv2_message.h>
45 #define LSB_MASK(n) ((1 << (n * __CHAR_BIT__)) - 1)
46 #define MHUV2_PROTOCOL_PROP "arm,mhuv2-protocols"
94 u8 pad1[0x0C - 0x04];
99 u8 pad2[0x20 - 0x1C];
114 u8 pad[0xFC8 - 0xFB0];
124 u8 reserved0[0x10 - 0x0C];
128 u8 pad[0x20 - 0x1C];
135 u8 reserved0[0xF90 - 0xF84];
141 u8 reserved2[0xFC8 - 0xFB0];
160 * struct mhuv2 - MHUv2 mailbox controller data
162 * @mbox: Mailbox controller belonging to the MHU frame.
171 * @doorbell_pending_lock: spinlock required for correct operation of Tx
193 * struct mhuv2_protocol_ops - MHUv2 operations
203 * @last_tx_done: Report back if the last tx is completed or not.
218 * MHUv2 mailbox channel's private information
263 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_doorbell_rx_startup()
265 writel_relaxed(BIT(priv->doorbell), in mhuv2_doorbell_rx_startup()
266 &mhu->recv->ch_wn[priv->ch_wn_idx].mask_clear); in mhuv2_doorbell_rx_startup()
273 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_doorbell_rx_shutdown()
275 writel_relaxed(BIT(priv->doorbell), in mhuv2_doorbell_rx_shutdown()
276 &mhu->recv->ch_wn[priv->ch_wn_idx].mask_set); in mhuv2_doorbell_rx_shutdown()
281 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_doorbell_read_data()
283 writel_relaxed(BIT(priv->doorbell), in mhuv2_doorbell_read_data()
284 &mhu->recv->ch_wn[priv->ch_wn_idx].stat_clear); in mhuv2_doorbell_read_data()
291 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_doorbell_last_tx_done()
293 return !(readl_relaxed(&mhu->send->ch_wn[priv->ch_wn_idx].stat) & in mhuv2_doorbell_last_tx_done()
294 BIT(priv->doorbell)); in mhuv2_doorbell_last_tx_done()
300 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_doorbell_send_data()
303 spin_lock_irqsave(&mhu->doorbell_pending_lock, flags); in mhuv2_doorbell_send_data()
305 priv->pending = 1; in mhuv2_doorbell_send_data()
306 writel_relaxed(BIT(priv->doorbell), in mhuv2_doorbell_send_data()
307 &mhu->send->ch_wn[priv->ch_wn_idx].stat_set); in mhuv2_doorbell_send_data()
309 spin_unlock_irqrestore(&mhu->doorbell_pending_lock, flags); in mhuv2_doorbell_send_data()
321 #define IS_PROTOCOL_DOORBELL(_priv) (_priv->ops == &mhuv2_doorbell_ops)
328 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_rx_startup()
329 int i = priv->ch_wn_idx + priv->windows - 1; in mhuv2_data_transfer_rx_startup()
335 writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_clear); in mhuv2_data_transfer_rx_startup()
342 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_rx_shutdown()
343 int i = priv->ch_wn_idx + priv->windows - 1; in mhuv2_data_transfer_rx_shutdown()
345 writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_set); in mhuv2_data_transfer_rx_shutdown()
351 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_read_data()
352 const int windows = priv->windows; in mhuv2_data_transfer_read_data()
359 return ERR_PTR(-ENOMEM); in mhuv2_data_transfer_read_data()
361 data = msg->data = msg + 1; in mhuv2_data_transfer_read_data()
362 msg->len = windows * MHUV2_STAT_BYTES; in mhuv2_data_transfer_read_data()
374 * data-transfer protocol, the interrupt is de-asserted. in mhuv2_data_transfer_read_data()
377 idx = priv->ch_wn_idx + i; in mhuv2_data_transfer_read_data()
378 data[windows - 1 - i] = readl_relaxed(&mhu->recv->ch_wn[idx].stat); in mhuv2_data_transfer_read_data()
379 writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[idx].stat_clear); in mhuv2_data_transfer_read_data()
388 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_tx_startup()
389 int i = priv->ch_wn_idx + priv->windows - 1; in mhuv2_data_transfer_tx_startup()
392 if (mhu->minor) { in mhuv2_data_transfer_tx_startup()
393 writel_relaxed(0x1, &mhu->send->ch_wn[i].int_clr); in mhuv2_data_transfer_tx_startup()
394 writel_relaxed(0x1, &mhu->send->ch_wn[i].int_en); in mhuv2_data_transfer_tx_startup()
401 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_tx_shutdown()
402 int i = priv->ch_wn_idx + priv->windows - 1; in mhuv2_data_transfer_tx_shutdown()
404 if (mhu->minor) in mhuv2_data_transfer_tx_shutdown()
405 writel_relaxed(0x0, &mhu->send->ch_wn[i].int_en); in mhuv2_data_transfer_tx_shutdown()
411 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_last_tx_done()
412 int i = priv->ch_wn_idx + priv->windows - 1; in mhuv2_data_transfer_last_tx_done()
415 return !readl_relaxed(&mhu->send->ch_wn[i].stat); in mhuv2_data_transfer_last_tx_done()
422 * written. As an example, a 6-word message is to be written on a 4-channel MHU
431 * [ stat 3 ] <- [0x00000001] 4 <- triggers interrupt on receiver
432 * [ stat 2 ] <- [0x00000002] 3
433 * [ stat 1 ] <- [0x00000003] 2
434 * [ stat 0 ] <- [0x00000004] 1
440 * [ stat 3 ] <- [0x00000005] 2 <- triggers interrupt on receiver
441 * [ stat 2 ] <- [0x00000006] 1
442 * [ stat 1 ] <- [0x00000000]
443 * [ stat 0 ] <- [0x00000000]
449 int bytes_left = msg->len, bytes_to_send, bytes_in_round, i; in mhuv2_data_transfer_send_data()
450 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_data_transfer_send_data()
451 int windows = priv->windows; in mhuv2_data_transfer_send_data()
452 u32 *data = msg->data, word; in mhuv2_data_transfer_send_data()
456 …dev_err(mhu->mbox.dev, "Data aligned at first window can't be zero to guarantee interrupt generati… in mhuv2_data_transfer_send_data()
457 return -EINVAL; in mhuv2_data_transfer_send_data()
465 for (i = windows - 1; i >= 0; i--) { in mhuv2_data_transfer_send_data()
471 bytes_to_send = bytes_in_round & (MHUV2_STAT_BYTES - 1); in mhuv2_data_transfer_send_data()
477 writel_relaxed(word, &mhu->send->ch_wn[priv->ch_wn_idx + windows - 1 - i].stat_set); in mhuv2_data_transfer_send_data()
478 bytes_left -= bytes_to_send; in mhuv2_data_transfer_send_data()
479 bytes_in_round -= bytes_to_send; in mhuv2_data_transfer_send_data()
502 struct mbox_chan *chans = mhu->mbox.chans; in get_irq_chan_comb()
513 for (i = 0; i < mhu->length; i += 2) { in get_irq_chan_comb()
514 protocol = mhu->protocols[i]; in get_irq_chan_comb()
515 windows = mhu->protocols[i + 1]; in get_irq_chan_comb()
529 channel += MHUV2_STAT_BITS * (ch_wn - offset); in get_irq_chan_comb()
535 return ERR_PTR(-EIO); in get_irq_chan_comb()
541 struct device *dev = mhu->mbox.dev; in mhuv2_sender_interrupt()
548 chan = get_irq_chan_comb(mhu, mhu->send->chcomb_int_st); in mhuv2_sender_interrupt()
550 dev_warn(dev, "Failed to find channel for the Tx interrupt\n"); in mhuv2_sender_interrupt()
553 priv = chan->con_priv; in mhuv2_sender_interrupt()
556 for (i = 0; i < priv->windows; i++) in mhuv2_sender_interrupt()
557 writel_relaxed(1, &mhu->send->ch_wn[priv->ch_wn_idx + i].int_clr); in mhuv2_sender_interrupt()
559 if (chan->cl) { in mhuv2_sender_interrupt()
564 …dev_warn(dev, "Tx interrupt Received on channel (%u) not currently attached to a mailbox client\n", in mhuv2_sender_interrupt()
565 priv->ch_wn_idx); in mhuv2_sender_interrupt()
570 writel_relaxed(1, &mhu->send->ch_wn[priv->ch_wn_idx].int_clr); in mhuv2_sender_interrupt()
574 * interrupt handler is trying to find the finished doorbell tx in mhuv2_sender_interrupt()
578 spin_lock_irqsave(&mhu->doorbell_pending_lock, flags); in mhuv2_sender_interrupt()
584 stat = readl_relaxed(&mhu->send->ch_wn[priv->ch_wn_idx].stat); in mhuv2_sender_interrupt()
590 if (priv->pending ^ ((stat >> i) & 0x1)) { in mhuv2_sender_interrupt()
591 BUG_ON(!priv->pending); in mhuv2_sender_interrupt()
593 if (!chan->cl) { in mhuv2_sender_interrupt()
594 …dev_warn(dev, "Tx interrupt received on doorbell (%u : %u) channel not currently attached to a mai… in mhuv2_sender_interrupt()
595 priv->ch_wn_idx, i); in mhuv2_sender_interrupt()
600 priv->pending = 0; in mhuv2_sender_interrupt()
605 spin_unlock_irqrestore(&mhu->doorbell_pending_lock, flags); in mhuv2_sender_interrupt()
613 dev_dbg(dev, "Couldn't find the doorbell (%u) for the Tx interrupt interrupt\n", in mhuv2_sender_interrupt()
614 priv->ch_wn_idx); in mhuv2_sender_interrupt()
627 chan = get_irq_chan_comb(mhu, mhu->recv->chcomb_int_st); in get_irq_chan_comb_rx()
631 priv = chan->con_priv; in get_irq_chan_comb_rx()
639 stat = readl_relaxed(&mhu->recv->ch_wn[priv->ch_wn_idx].stat_masked); in get_irq_chan_comb_rx()
647 struct mbox_chan *chans = mhu->mbox.chans; in get_irq_chan_stat_rx()
652 while (i < mhu->mbox.num_chans) { in get_irq_chan_stat_rx()
654 stat = readl_relaxed(&mhu->recv->ch_wn[priv->ch_wn_idx].stat_masked); in get_irq_chan_stat_rx()
665 return ERR_PTR(-EIO); in get_irq_chan_stat_rx()
670 if (!mhu->minor) in get_irq_chan_rx()
680 struct device *dev = mhu->mbox.dev; in mhuv2_receiver_interrupt()
689 priv = chan->con_priv; in mhuv2_receiver_interrupt()
692 data = priv->ops->read_data(mhu, chan); in mhuv2_receiver_interrupt()
694 if (!chan->cl) { in mhuv2_receiver_interrupt()
695 dev_warn(dev, "Received data on channel (%u) not currently attached to a mailbox client\n", in mhuv2_receiver_interrupt()
696 priv->ch_wn_idx); in mhuv2_receiver_interrupt()
713 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_sender_last_tx_done()
714 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_sender_last_tx_done()
716 return priv->ops->last_tx_done(mhu, chan); in mhuv2_sender_last_tx_done()
721 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_sender_send_data()
722 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_sender_send_data()
724 if (!priv->ops->last_tx_done(mhu, chan)) in mhuv2_sender_send_data()
725 return -EBUSY; in mhuv2_sender_send_data()
727 return priv->ops->send_data(mhu, chan, data); in mhuv2_sender_send_data()
732 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_sender_startup()
733 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_sender_startup()
735 if (priv->ops->tx_startup) in mhuv2_sender_startup()
736 priv->ops->tx_startup(mhu, chan); in mhuv2_sender_startup()
742 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_sender_shutdown()
743 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_sender_shutdown()
745 if (priv->ops->tx_shutdown) in mhuv2_sender_shutdown()
746 priv->ops->tx_shutdown(mhu, chan); in mhuv2_sender_shutdown()
758 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_receiver_startup()
759 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_receiver_startup()
761 return priv->ops->rx_startup(mhu, chan); in mhuv2_receiver_startup()
766 struct mhuv2 *mhu = mhu_from_mbox(chan->mbox); in mhuv2_receiver_shutdown()
767 struct mhuv2_mbox_chan_priv *priv = chan->con_priv; in mhuv2_receiver_shutdown()
769 priv->ops->rx_shutdown(mhu, chan); in mhuv2_receiver_shutdown()
774 dev_err(chan->mbox->dev, in mhuv2_receiver_send_data()
776 return -EIO; in mhuv2_receiver_send_data()
781 dev_err(chan->mbox->dev, "Trying to Tx poll on a receiver MHU frame\n"); in mhuv2_receiver_last_tx_done()
796 struct mbox_chan *chans = mbox->chans; in mhuv2_mbox_of_xlate()
799 if (pa->args_count != 2) in mhuv2_mbox_of_xlate()
800 return ERR_PTR(-EINVAL); in mhuv2_mbox_of_xlate()
802 offset = pa->args[0]; in mhuv2_mbox_of_xlate()
803 doorbell = pa->args[1]; in mhuv2_mbox_of_xlate()
807 for (i = 0; i < mhu->length; i += 2) { in mhuv2_mbox_of_xlate()
808 protocol = mhu->protocols[i]; in mhuv2_mbox_of_xlate()
809 windows = mhu->protocols[i + 1]; in mhuv2_mbox_of_xlate()
816 offset -= windows; in mhuv2_mbox_of_xlate()
826 offset--; in mhuv2_mbox_of_xlate()
831 dev_err(mbox->dev, "Couldn't xlate to a valid channel (%d: %d)\n", in mhuv2_mbox_of_xlate()
832 pa->args[0], doorbell); in mhuv2_mbox_of_xlate()
833 return ERR_PTR(-ENODEV); in mhuv2_mbox_of_xlate()
838 struct device *dev = mhu->mbox.dev; in mhuv2_verify_protocol()
841 for (i = 0; i < mhu->length; i += 2) { in mhuv2_verify_protocol()
842 protocol = mhu->protocols[i]; in mhuv2_verify_protocol()
843 windows = mhu->protocols[i + 1]; in mhuv2_verify_protocol()
847 return -EINVAL; in mhuv2_verify_protocol()
858 return -EINVAL; in mhuv2_verify_protocol()
862 if (total_windows > mhu->windows) { in mhuv2_verify_protocol()
864 total_windows, mhu->windows); in mhuv2_verify_protocol()
865 return -EINVAL; in mhuv2_verify_protocol()
868 mhu->mbox.num_chans = channels; in mhuv2_verify_protocol()
874 struct mbox_controller *mbox = &mhu->mbox; in mhuv2_allocate_channels()
876 struct device *dev = mbox->dev; in mhuv2_allocate_channels()
880 chans = devm_kcalloc(dev, mbox->num_chans, sizeof(*chans), GFP_KERNEL); in mhuv2_allocate_channels()
882 return -ENOMEM; in mhuv2_allocate_channels()
884 mbox->chans = chans; in mhuv2_allocate_channels()
886 for (i = 0; i < mhu->length; i += 2) { in mhuv2_allocate_channels()
889 protocol = mhu->protocols[i]; in mhuv2_allocate_channels()
890 windows = mhu->protocols[i + 1]; in mhuv2_allocate_channels()
895 return -ENOMEM; in mhuv2_allocate_channels()
897 priv->ch_wn_idx = next_window; in mhuv2_allocate_channels()
898 priv->ops = &mhuv2_data_transfer_ops; in mhuv2_allocate_channels()
899 priv->windows = windows; in mhuv2_allocate_channels()
900 chans++->con_priv = priv; in mhuv2_allocate_channels()
908 return -ENOMEM; in mhuv2_allocate_channels()
910 priv->ch_wn_idx = next_window + j; in mhuv2_allocate_channels()
911 priv->ops = &mhuv2_doorbell_ops; in mhuv2_allocate_channels()
912 priv->doorbell = k; in mhuv2_allocate_channels()
913 chans++->con_priv = priv; in mhuv2_allocate_channels()
920 if (mhu->frame == SENDER_FRAME && mhu->minor) in mhuv2_allocate_channels()
921 writel_relaxed(0x1, &mhu->send->ch_wn[priv->ch_wn_idx].int_en); in mhuv2_allocate_channels()
926 BUG_ON(chans - mbox->chans != mbox->num_chans); in mhuv2_allocate_channels()
933 struct device *dev = mhu->mbox.dev; in mhuv2_parse_channels()
934 const struct device_node *np = dev->of_node; in mhuv2_parse_channels()
935 int ret, count; in mhuv2_parse_channels() local
938 count = of_property_count_u32_elems(np, MHUV2_PROTOCOL_PROP); in mhuv2_parse_channels()
939 if (count <= 0 || count % 2) { in mhuv2_parse_channels()
941 count); in mhuv2_parse_channels()
942 return -EINVAL; in mhuv2_parse_channels()
945 protocols = devm_kmalloc_array(dev, count, sizeof(*protocols), GFP_KERNEL); in mhuv2_parse_channels()
947 return -ENOMEM; in mhuv2_parse_channels()
949 ret = of_property_read_u32_array(np, MHUV2_PROTOCOL_PROP, protocols, count); in mhuv2_parse_channels()
956 mhu->protocols = protocols; in mhuv2_parse_channels()
957 mhu->length = count; in mhuv2_parse_channels()
969 struct device *dev = mhu->mbox.dev; in mhuv2_tx_init()
972 mhu->frame = SENDER_FRAME; in mhuv2_tx_init()
973 mhu->mbox.ops = &mhuv2_sender_ops; in mhuv2_tx_init()
974 mhu->send = reg; in mhuv2_tx_init()
976 mhu->windows = readl_relaxed_bitfield(&mhu->send->mhu_cfg, struct mhu_cfg_t, num_ch); in mhuv2_tx_init()
977 mhu->minor = readl_relaxed_bitfield(&mhu->send->aidr, struct aidr_t, arch_minor_rev); in mhuv2_tx_init()
979 spin_lock_init(&mhu->doorbell_pending_lock); in mhuv2_tx_init()
982 * For minor version 1 and forward, tx interrupt is provided by in mhuv2_tx_init()
985 if (mhu->minor && adev->irq[0]) { in mhuv2_tx_init()
986 ret = devm_request_threaded_irq(dev, adev->irq[0], NULL, in mhuv2_tx_init()
988 IRQF_ONESHOT, "mhuv2-tx", mhu); in mhuv2_tx_init()
990 dev_err(dev, "Failed to request tx IRQ, fallback to polling mode: %d\n", in mhuv2_tx_init()
993 mhu->mbox.txdone_irq = true; in mhuv2_tx_init()
994 mhu->mbox.txdone_poll = false; in mhuv2_tx_init()
995 mhu->irq = adev->irq[0]; in mhuv2_tx_init()
997 writel_relaxed_bitfield(1, &mhu->send->int_en, struct int_en_t, chcomb); in mhuv2_tx_init()
1000 for (i = 0; i < mhu->windows; i++) in mhuv2_tx_init()
1001 writel_relaxed(0x0, &mhu->send->ch_wn[i].int_en); in mhuv2_tx_init()
1007 mhu->mbox.txdone_irq = false; in mhuv2_tx_init()
1008 mhu->mbox.txdone_poll = true; in mhuv2_tx_init()
1009 mhu->mbox.txpoll_period = 1; in mhuv2_tx_init()
1013 writel_relaxed(0x1, &mhu->send->access_request); in mhuv2_tx_init()
1014 while (!readl_relaxed(&mhu->send->access_ready)) in mhuv2_tx_init()
1023 struct device *dev = mhu->mbox.dev; in mhuv2_rx_init()
1026 mhu->frame = RECEIVER_FRAME; in mhuv2_rx_init()
1027 mhu->mbox.ops = &mhuv2_receiver_ops; in mhuv2_rx_init()
1028 mhu->recv = reg; in mhuv2_rx_init()
1030 mhu->windows = readl_relaxed_bitfield(&mhu->recv->mhu_cfg, struct mhu_cfg_t, num_ch); in mhuv2_rx_init()
1031 mhu->minor = readl_relaxed_bitfield(&mhu->recv->aidr, struct aidr_t, arch_minor_rev); in mhuv2_rx_init()
1033 mhu->irq = adev->irq[0]; in mhuv2_rx_init()
1034 if (!mhu->irq) { in mhuv2_rx_init()
1036 return -EINVAL; in mhuv2_rx_init()
1039 ret = devm_request_threaded_irq(dev, mhu->irq, NULL, in mhuv2_rx_init()
1041 "mhuv2-rx", mhu); in mhuv2_rx_init()
1048 for (i = 0; i < mhu->windows; i++) in mhuv2_rx_init()
1049 writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_set); in mhuv2_rx_init()
1051 if (mhu->minor) in mhuv2_rx_init()
1052 writel_relaxed_bitfield(1, &mhu->recv->int_en, struct int_en_t, chcomb); in mhuv2_rx_init()
1059 struct device *dev = &adev->dev; in mhuv2_probe()
1060 const struct device_node *np = dev->of_node; in mhuv2_probe()
1063 int ret = -EINVAL; in mhuv2_probe()
1065 reg = devm_of_iomap(dev, dev->of_node, 0, NULL); in mhuv2_probe()
1071 return -ENOMEM; in mhuv2_probe()
1073 mhu->mbox.dev = dev; in mhuv2_probe()
1074 mhu->mbox.of_xlate = mhuv2_mbox_of_xlate; in mhuv2_probe()
1076 if (of_device_is_compatible(np, "arm,mhuv2-tx")) in mhuv2_probe()
1078 else if (of_device_is_compatible(np, "arm,mhuv2-rx")) in mhuv2_probe()
1087 BUG_ON(!mhu->windows); in mhuv2_probe()
1095 ret = devm_mbox_controller_register(dev, &mhu->mbox); in mhuv2_probe()
1106 if (mhu->frame == SENDER_FRAME) in mhuv2_remove()
1107 writel_relaxed(0x0, &mhu->send->access_request); in mhuv2_remove()
1127 .name = "arm-mhuv2",