^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Mailbox: Common code for Mailbox controllers and users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013-2014 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Jassi Brar <jassisinghbrar@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mailbox_client.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mailbox_controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "mailbox.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static LIST_HEAD(mbox_cons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static DEFINE_MUTEX(con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) spin_lock_irqsave(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* See if there is any space left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) idx = chan->msg_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) chan->msg_data[idx] = mssg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) chan->msg_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (idx == MBOX_TX_QUEUE_LEN - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) chan->msg_free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) chan->msg_free++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void msg_submit(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned count, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) spin_lock_irqsave(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!chan->msg_count || chan->active_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) count = chan->msg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) idx = chan->msg_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (idx >= count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) idx -= count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) idx += MBOX_TX_QUEUE_LEN - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) data = chan->msg_data[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (chan->cl->tx_prepare)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) chan->cl->tx_prepare(chan->cl, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Try to submit a message to the MBOX controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) err = chan->mbox->ops->send_data(chan, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) chan->active_req = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) chan->msg_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* kick start the timer immediately to avoid delays */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* but only if not already active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!hrtimer_active(&chan->mbox->poll_hrt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void tx_tick(struct mbox_chan *chan, int r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void *mssg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) spin_lock_irqsave(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) mssg = chan->active_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) chan->active_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Submit next message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) msg_submit(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!mssg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Notify the client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (chan->cl->tx_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) chan->cl->tx_done(chan->cl, mssg, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (r != -ETIME && chan->cl->tx_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) complete(&chan->tx_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct mbox_controller *mbox =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) container_of(hrtimer, struct mbox_controller, poll_hrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool txdone, resched = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (i = 0; i < mbox->num_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct mbox_chan *chan = &mbox->chans[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (chan->active_req && chan->cl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) resched = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) txdone = chan->mbox->ops->last_tx_done(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (txdone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) tx_tick(chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (resched) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return HRTIMER_RESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * mbox_chan_received_data - A way for controller driver to push data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * received from remote to the upper layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @chan: Pointer to the mailbox channel on which RX happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @mssg: Client specific message typecasted as void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * After startup and before shutdown any data received on the chan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * is passed on to the API via atomic mbox_chan_received_data().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * The controller should ACK the RX only after this call returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* No buffering the received data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (chan->cl->rx_callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) chan->cl->rx_callback(chan->cl, mssg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) EXPORT_SYMBOL_GPL(mbox_chan_received_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * mbox_chan_txdone - A way for controller driver to notify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * framework that the last TX has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @chan: Pointer to the mailbox chan on which TX happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @r: Status of last TX - OK or ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * The controller that has IRQ for TX ACK calls this atomic API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * to tick the TX state machine. It works only if txdone_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * is set by the controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) void mbox_chan_txdone(struct mbox_chan *chan, int r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev_err(chan->mbox->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "Controller can't run the TX ticker\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) tx_tick(chan, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) EXPORT_SYMBOL_GPL(mbox_chan_txdone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * mbox_client_txdone - The way for a client to run the TX state machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @chan: Mailbox channel assigned to this client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @r: Success status of last transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * The client/protocol had received some 'ACK' packet and it notifies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * the API that the last packet was sent successfully. This only works
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * if the controller can't sense TX-Done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) void mbox_client_txdone(struct mbox_chan *chan, int r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dev_err(chan->mbox->dev, "Client can't run the TX ticker\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tx_tick(chan, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EXPORT_SYMBOL_GPL(mbox_client_txdone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * mbox_client_peek_data - A way for client driver to pull data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * received from remote by the controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * @chan: Mailbox channel assigned to this client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * A poke to controller driver for any received data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * The data is actually passed onto client via the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * mbox_chan_received_data()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * The call can be made from atomic context, so the controller's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * implementation of peek_data() must not sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * Return: True, if controller has, and is going to push after this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * some data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * False, if controller doesn't have any data to be read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bool mbox_client_peek_data(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (chan->mbox->ops->peek_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return chan->mbox->ops->peek_data(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) EXPORT_SYMBOL_GPL(mbox_client_peek_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * mbox_send_message - For client to submit a message to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * sent to the remote.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @chan: Mailbox channel assigned to this client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * @mssg: Client specific message typecasted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * For client to submit data to the controller destined for a remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * processor. If the client had set 'tx_block', the call will return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * either when the remote receives the data or when 'tx_tout' millisecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * run out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * In non-blocking mode, the requests are buffered by the API and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * non-negative token is returned for each queued request. If the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * is not queued, a negative token is returned. Upon failure or successful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * TX, the API calls 'tx_done' from atomic context, from which the client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * could submit yet another request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * The pointer to message should be preserved until it is sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * over the chan, i.e, tx_done() is made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * This function could be called from atomic context as it simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * queues the data and returns a token against the request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * Return: Non-negative integer for successful submission (non-blocking mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * or transmission over chan (blocking mode).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * Negative value denotes failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int mbox_send_message(struct mbox_chan *chan, void *mssg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (!chan || !chan->cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) t = add_to_rbuf(chan, mssg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (t < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_err(chan->mbox->dev, "Try increasing MBOX_TX_QUEUE_LEN\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) msg_submit(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (chan->cl->tx_block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned long wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!chan->cl->tx_tout) /* wait forever */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) wait = msecs_to_jiffies(3600000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) wait = msecs_to_jiffies(chan->cl->tx_tout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = wait_for_completion_timeout(&chan->tx_complete, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) t = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) tx_tick(chan, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) EXPORT_SYMBOL_GPL(mbox_send_message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * mbox_flush - flush a mailbox channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * @chan: mailbox channel to flush
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * @timeout: time, in milliseconds, to allow the flush operation to succeed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Mailbox controllers that need to work in atomic context can implement the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * ->flush() callback to busy loop until a transmission has been completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * The implementation must call mbox_chan_txdone() upon success. Clients can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * call the mbox_flush() function at any time after mbox_send_message() to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * flush the transmission. After the function returns success, the mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * transmission is guaranteed to have completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Returns: 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!chan->mbox->ops->flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ret = chan->mbox->ops->flush(chan, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) tx_tick(chan, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) EXPORT_SYMBOL_GPL(mbox_flush);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * mbox_request_channel - Request a mailbox channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * @cl: Identity of the client requesting the channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * @index: Index of mailbox specifier in 'mboxes' property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * The Client specifies its requirements and capabilities while asking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * a mailbox channel. It can't be called from atomic context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * The channel is exclusively allocated and can't be used by another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * client before the owner calls mbox_free_channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * After assignment, any packet received on this channel will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * handed over to the client via the 'rx_callback'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * The framework holds reference to the client, so the mbox_client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * structure shouldn't be modified until the mbox_free_channel returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Return: Pointer to the channel assigned to the client if successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * ERR_PTR for request failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct device *dev = cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct mbox_controller *mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct of_phandle_args spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct mbox_chan *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!dev || !dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) pr_debug("%s: No owner device node\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) mutex_lock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (of_parse_phandle_with_args(dev->of_node, "mboxes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) "#mbox-cells", index, &spec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) chan = ERR_PTR(-EPROBE_DEFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) list_for_each_entry(mbox, &mbox_cons, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (mbox->dev->of_node == spec.np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) chan = mbox->of_xlate(mbox, &spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!IS_ERR(chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) of_node_put(spec.np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (IS_ERR(chan)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dev_dbg(dev, "%s: mailbox not free\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return ERR_PTR(-EBUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) spin_lock_irqsave(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) chan->msg_free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) chan->msg_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) chan->active_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) chan->cl = cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) init_completion(&chan->tx_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) chan->txdone_method = TXDONE_BY_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (chan->mbox->ops->startup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret = chan->mbox->ops->startup(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_err(dev, "Unable to startup the chan (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mbox_free_channel(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) chan = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) EXPORT_SYMBOL_GPL(mbox_request_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct device_node *np = cl->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) const char *mbox_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) dev_err(cl->dev, "%s() currently only supports DT\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!of_get_property(np, "mbox-names", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dev_err(cl->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) "%s() requires an \"mbox-names\" property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) of_property_for_each_string(np, "mbox-names", prop, mbox_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!strncmp(name, mbox_name, strlen(name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return mbox_request_channel(cl, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dev_err(cl->dev, "%s() could not locate channel named \"%s\"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * mbox_free_channel - The client relinquishes control of a mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * channel by this call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * @chan: The mailbox channel to be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) void mbox_free_channel(struct mbox_chan *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!chan || !chan->cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (chan->mbox->ops->shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) chan->mbox->ops->shutdown(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* The queued TX requests are simply aborted, no callbacks are made */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) spin_lock_irqsave(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) chan->cl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) chan->active_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (chan->txdone_method == TXDONE_BY_ACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) chan->txdone_method = TXDONE_BY_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) module_put(chan->mbox->dev->driver->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) spin_unlock_irqrestore(&chan->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) EXPORT_SYMBOL_GPL(mbox_free_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static struct mbox_chan *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) of_mbox_index_xlate(struct mbox_controller *mbox,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) const struct of_phandle_args *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int ind = sp->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (ind >= mbox->num_chans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return &mbox->chans[ind];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * mbox_controller_register - Register the mailbox controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * @mbox: Pointer to the mailbox controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * The controller driver registers its communication channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int mbox_controller_register(struct mbox_controller *mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int i, txdone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (mbox->txdone_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) txdone = TXDONE_BY_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) else if (mbox->txdone_poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) txdone = TXDONE_BY_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) else /* It has to be ACK then */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) txdone = TXDONE_BY_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (txdone == TXDONE_BY_POLL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!mbox->ops->last_tx_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) dev_err(mbox->dev, "last_tx_done method is absent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mbox->poll_hrt.function = txdone_hrtimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) for (i = 0; i < mbox->num_chans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct mbox_chan *chan = &mbox->chans[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) chan->cl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) chan->mbox = mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) chan->txdone_method = txdone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spin_lock_init(&chan->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (!mbox->of_xlate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mbox->of_xlate = of_mbox_index_xlate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mutex_lock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) list_add_tail(&mbox->node, &mbox_cons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) EXPORT_SYMBOL_GPL(mbox_controller_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * mbox_controller_unregister - Unregister the mailbox controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * @mbox: Pointer to the mailbox controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) void mbox_controller_unregister(struct mbox_controller *mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (!mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) mutex_lock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) list_del(&mbox->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) for (i = 0; i < mbox->num_chans; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) mbox_free_channel(&mbox->chans[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (mbox->txdone_poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) hrtimer_cancel(&mbox->poll_hrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) mutex_unlock(&con_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) EXPORT_SYMBOL_GPL(mbox_controller_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static void __devm_mbox_controller_unregister(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct mbox_controller **mbox = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) mbox_controller_unregister(*mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int devm_mbox_controller_match(struct device *dev, void *res, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct mbox_controller **mbox = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (WARN_ON(!mbox || !*mbox))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return *mbox == data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * devm_mbox_controller_register() - managed mbox_controller_register()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * @dev: device owning the mailbox controller being registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * @mbox: mailbox controller being registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * This function adds a device-managed resource that will make sure that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * mailbox controller, which is registered using mbox_controller_register()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * as part of this function, will be unregistered along with the rest of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * device-managed resources upon driver probe failure or driver removal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * Returns 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int devm_mbox_controller_register(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct mbox_controller *mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct mbox_controller **ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ptr = devres_alloc(__devm_mbox_controller_unregister, sizeof(*ptr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) err = mbox_controller_register(mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) devres_free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) devres_add(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) *ptr = mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) EXPORT_SYMBOL_GPL(devm_mbox_controller_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * devm_mbox_controller_unregister() - managed mbox_controller_unregister()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * @dev: device owning the mailbox controller being unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * @mbox: mailbox controller being unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * This function unregisters the mailbox controller and removes the device-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * managed resource that was set up to automatically unregister the mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * controller on driver probe failure or driver removal. It's typically not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * necessary to call this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) void devm_mbox_controller_unregister(struct device *dev, struct mbox_controller *mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) WARN_ON(devres_release(dev, __devm_mbox_controller_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) devm_mbox_controller_match, mbox));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) EXPORT_SYMBOL_GPL(devm_mbox_controller_unregister);