static void communication_driver_exit(void) { pr_info("Communication Driver exit\n"); cdev_del(&driver_cdev); unregister_chrdev_region(driver_dev, driver_count); device_destroy(cl, driver_dev); class_destroy(cl); mbox_free_channel(chan_sender); mbox_free_channel(chan_receiver); platform_driver_unregister(&mailbox_nios_pdrv); }
static int mbox_test_remove(struct platform_device *pdev) { struct mbox_test_device *tdev = platform_get_drvdata(pdev); debugfs_remove_recursive(root_debugfs_dir); if (tdev->tx_channel) mbox_free_channel(tdev->tx_channel); if (tdev->rx_channel) mbox_free_channel(tdev->rx_channel); return 0; }
static int tegra_tcu_remove(struct platform_device *pdev) { struct tegra_tcu *tcu = platform_get_drvdata(pdev); #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) unregister_console(&tcu->console); #endif uart_remove_one_port(&tcu->driver, &tcu->port); uart_unregister_driver(&tcu->driver); mbox_free_channel(tcu->rx); mbox_free_channel(tcu->tx); return 0; }
static int hb_voltage_change(unsigned int freq) { u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 1000000}; struct mbox_client cl; int ret = -ETIMEDOUT; struct mbox_chan *chan; cl.rx_callback = NULL; cl.tx_done = NULL; cl.tx_block = true; cl.tx_tout = 1000; /* 1 sec */ cl.link_data = NULL; cl.knows_txdone = false; cl.chan_name = "pl320:A9_to_M3"; chan = mbox_request_channel(&cl); if (IS_ERR(chan)) return PTR_ERR(chan); if (mbox_send_message(chan, (void *)msg)) ret = msg[1]; /* PL320 updates buffer with FIFO after ACK */ mbox_free_channel(chan); return ret; }
static int send_scpi_cmd(struct scpi_data_buf *scpi_buf, bool high_priority) { struct mbox_chan *chan; struct mbox_client cl = {0}; struct mhu_data_buf *data = scpi_buf->data; u32 status; cl.dev = the_scpi_device; cl.rx_callback = scpi_rx_callback; chan = mbox_request_channel(&cl, high_priority); if (IS_ERR(chan)) return PTR_ERR(chan); init_completion(&scpi_buf->complete); if (mbox_send_message(chan, (void *)data) < 0) { status = SCPI_ERR_TIMEOUT; goto free_channel; } wait_for_completion(&scpi_buf->complete); status = *(u32 *)(data->rx_buf); /* read first word */ free_channel: mbox_free_channel(chan); return scpi_to_linux_errno(status); }
void cmdq_mbox_destroy(struct cmdq_client *client) { if (client->timeout_ms != CMDQ_NO_TIMEOUT) { spin_lock(&client->lock); del_timer_sync(&client->timer); spin_unlock(&client->lock); } mbox_free_channel(client->chan); kfree(client); }
static void scpi_free_channels(struct device *dev, struct scpi_chan *pchan, int count) { int i; for (i = 0; i < count && pchan->chan; i++, pchan++) { mbox_free_channel(pchan->chan); devm_kfree(dev, pchan->xfers); devm_iounmap(dev, pchan->rx_payload); } }
static int wkup_m3_rproc_stop(struct rproc *rproc) { struct wkup_m3_rproc *m3_rproc = rproc->priv; struct platform_device *pdev = m3_rproc->pdev; struct device *dev = &pdev->dev; struct wkup_m3_platform_data *pdata = dev->platform_data; mbox_free_channel(m3_rproc_static->mbox); pdata->assert_reset(pdev, pdata->reset_name); return 0; }
/** * mbox_controller_unregister - Unregister the mailbox controller * @mbox: Pointer to the mailbox controller. */ void mbox_controller_unregister(struct mbox_controller *mbox) { int i; if (!mbox) return; mutex_lock(&con_mutex); list_del(&mbox->node); for (i = 0; i < mbox->num_chans; i++) mbox_free_channel(&mbox->chans[i]); if (mbox->txdone_poll) del_timer_sync(&mbox->poll); mutex_unlock(&con_mutex); }
static int tegra_tcu_probe(struct platform_device *pdev) { struct uart_port *port; struct tegra_tcu *tcu; int err; tcu = devm_kzalloc(&pdev->dev, sizeof(*tcu), GFP_KERNEL); if (!tcu) return -ENOMEM; tcu->tx_client.dev = &pdev->dev; tcu->rx_client.dev = &pdev->dev; tcu->rx_client.rx_callback = tegra_tcu_receive; tcu->tx = mbox_request_channel_byname(&tcu->tx_client, "tx"); if (IS_ERR(tcu->tx)) { err = PTR_ERR(tcu->tx); dev_err(&pdev->dev, "failed to get tx mailbox: %d\n", err); return err; } tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); if (IS_ERR(tcu->rx)) { err = PTR_ERR(tcu->rx); dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); goto free_tx; } #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) /* setup the console */ strcpy(tcu->console.name, "ttyTCU"); tcu->console.device = uart_console_device; tcu->console.flags = CON_PRINTBUFFER | CON_ANYTIME; tcu->console.index = -1; tcu->console.write = tegra_tcu_console_write; tcu->console.setup = tegra_tcu_console_setup; tcu->console.data = &tcu->driver; #endif /* setup the driver */ tcu->driver.owner = THIS_MODULE; tcu->driver.driver_name = "tegra-tcu"; tcu->driver.dev_name = "ttyTCU"; #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) tcu->driver.cons = &tcu->console; #endif tcu->driver.nr = 1; err = uart_register_driver(&tcu->driver); if (err) { dev_err(&pdev->dev, "failed to register UART driver: %d\n", err); goto free_rx; } /* setup the port */ port = &tcu->port; spin_lock_init(&port->lock); port->dev = &pdev->dev; port->type = PORT_TEGRA_TCU; port->ops = &tegra_tcu_uart_ops; port->fifosize = 1; port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; port->private_data = tcu; err = uart_add_one_port(&tcu->driver, port); if (err) { dev_err(&pdev->dev, "failed to add UART port: %d\n", err); goto unregister_uart; } platform_set_drvdata(pdev, tcu); #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) register_console(&tcu->console); #endif return 0; unregister_uart: uart_unregister_driver(&tcu->driver); free_rx: mbox_free_channel(tcu->rx); free_tx: mbox_free_channel(tcu->tx); return err; }
/** * mbox_request_channel - Request a mailbox channel. * @cl: Identity of the client requesting the channel. * @index: Index of mailbox specifier in 'mboxes' property. * * The Client specifies its requirements and capabilities while asking for * a mailbox channel. It can't be called from atomic context. * The channel is exclusively allocated and can't be used by another * client before the owner calls mbox_free_channel. * After assignment, any packet received on this channel will be * handed over to the client via the 'rx_callback'. * The framework holds reference to the client, so the mbox_client * structure shouldn't be modified until the mbox_free_channel returns. * * Return: Pointer to the channel assigned to the client if successful. * ERR_PTR for request failure. */ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) { struct device *dev = cl->dev; struct mbox_controller *mbox; struct of_phandle_args spec; struct mbox_chan *chan; unsigned long flags; int ret; if (!dev || !dev->of_node) { pr_debug("%s: No owner device node\n", __func__); return ERR_PTR(-ENODEV); } mutex_lock(&con_mutex); if (of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells", index, &spec)) { dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__); mutex_unlock(&con_mutex); return ERR_PTR(-ENODEV); } chan = ERR_PTR(-EPROBE_DEFER); list_for_each_entry(mbox, &mbox_cons, node) if (mbox->dev->of_node == spec.np) { chan = mbox->of_xlate(mbox, &spec); break; } of_node_put(spec.np); if (IS_ERR(chan)) { mutex_unlock(&con_mutex); return chan; } if (chan->cl || !try_module_get(mbox->dev->driver->owner)) { dev_dbg(dev, "%s: mailbox not free\n", __func__); mutex_unlock(&con_mutex); return ERR_PTR(-EBUSY); } spin_lock_irqsave(&chan->lock, flags); chan->msg_free = 0; chan->msg_count = 0; chan->active_req = NULL; chan->cl = cl; init_completion(&chan->tx_complete); if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) chan->txdone_method |= TXDONE_BY_ACK; spin_unlock_irqrestore(&chan->lock, flags); ret = chan->mbox->ops->startup(chan); if (ret) { dev_err(dev, "Unable to startup the chan (%d)\n", ret); mbox_free_channel(chan); chan = ERR_PTR(ret); } mutex_unlock(&con_mutex); return chan; }