Lines Matching +full:queue +full:- +full:rx
1 // SPDX-License-Identifier: GPL-2.0-only
15 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
18 #include <linux/mailbox/exynos-message.h>
30 #include "exynos-acpm.h"
31 #include "exynos-acpm-pmic.h"
42 * struct acpm_shmem - shared memory configuration information.
56 * struct acpm_chan_shmem - descriptor of a shared memory channel.
60 * @rx_rear: rear pointer of APM RX queue (TX for AP).
61 * @rx_front: front pointer of APM RX queue (TX for AP).
62 * @rx_base: base address of APM RX queue (TX for AP).
64 * @tx_rear: rear pointer of APM TX queue (RX for AP).
65 * @tx_front: front pointer of APM TX queue (RX for AP).
66 * @tx_base: base address of APM TX queue (RX for AP).
67 * @qlen: queue length. Applies to both TX/RX queues.
68 * @mlen: message length. Applies to both TX/RX queues.
89 * struct acpm_queue - exynos acpm queue.
91 * @rear: rear address of the queue.
92 * @front: front address of the queue.
93 * @base: base address of the queue.
102 * struct acpm_rx_data - RX queue data.
105 * @n_cmd: number of 32-bit commands.
106 * @response: true if the client expects the RX data.
117 * struct acpm_chan - driver internal representation of a channel.
121 * @tx: TX queue. The enqueue is done by the host.
122 * - front index is written by the host.
123 * - rear index is written by the firmware.
125 * @rx: RX queue. The enqueue is done by the firmware.
126 * - front index is written by the firmware.
127 * - rear index is written by the host.
128 * @tx_lock: protects TX queue.
129 * @rx_lock: protects RX queue.
130 * @qlen: queue length. Applies to both TX/RX queues.
131 * @mlen: message length. Applies to both TX/RX queues.
132 * @seqnum: sequence number of the last message enqueued on TX queue.
136 * @bitmap_seqnum: bitmap that tracks the messages on the TX/RX queues.
137 * @rx_data: internal buffer used to drain the RX queue.
144 struct acpm_queue rx; member
154 DECLARE_BITMAP(bitmap_seqnum, ACPM_SEQNUM_MAX - 1);
159 * struct acpm_info - driver's private data.
163 * @dev: pointer to the exynos-acpm device.
177 * struct acpm_match_data - of_device_id data.
188 * acpm_get_saved_rx() - get the response if it was already saved.
196 const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1]; in acpm_get_saved_rx()
199 if (!rx_data->response) in acpm_get_saved_rx()
202 rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]); in acpm_get_saved_rx()
205 memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen); in acpm_get_saved_rx()
206 clear_bit(rx_seqnum - 1, achan->bitmap_seqnum); in acpm_get_saved_rx()
211 * acpm_get_rx() - get response from RX queue.
215 * Return: 0 on success, -errno otherwise.
225 guard(mutex)(&achan->rx_lock); in acpm_get_rx()
227 rx_front = readl(achan->rx.front); in acpm_get_rx()
228 i = readl(achan->rx.rear); in acpm_get_rx()
230 tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]); in acpm_get_rx()
237 base = achan->rx.base; in acpm_get_rx()
238 mlen = achan->mlen; in acpm_get_rx()
240 /* Drain RX queue. */ in acpm_get_rx()
242 /* Read RX seqnum. */ in acpm_get_rx()
248 return -EIO; in acpm_get_rx()
253 seqnum = rx_seqnum - 1; in acpm_get_rx()
254 rx_data = &achan->rx_data[seqnum]; in acpm_get_rx()
256 if (rx_data->response) { in acpm_get_rx()
258 __ioread32_copy(xfer->rxd, addr, in acpm_get_rx()
259 xfer->rxlen / 4); in acpm_get_rx()
261 clear_bit(seqnum, achan->bitmap_seqnum); in acpm_get_rx()
264 * The RX data corresponds to another request. in acpm_get_rx()
265 * Save the data to drain the queue, but don't in acpm_get_rx()
269 __ioread32_copy(rx_data->cmd, addr, in acpm_get_rx()
270 xfer->rxlen / 4); in acpm_get_rx()
273 clear_bit(seqnum, achan->bitmap_seqnum); in acpm_get_rx()
276 i = (i + 1) % achan->qlen; in acpm_get_rx()
279 /* We saved all responses, mark RX empty. */ in acpm_get_rx()
280 writel(rx_front, achan->rx.rear); in acpm_get_rx()
283 * If the response was not in this iteration of the queue, check if the in acpm_get_rx()
284 * RX data was previously saved. in acpm_get_rx()
293 * acpm_dequeue_by_polling() - RX dequeue by polling.
297 * Return: 0 on success, -errno otherwise.
302 struct device *dev = achan->acpm->dev; in acpm_dequeue_by_polling()
307 seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]); in acpm_dequeue_by_polling()
314 if (!test_bit(seqnum - 1, achan->bitmap_seqnum)) in acpm_dequeue_by_polling()
323 achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us); in acpm_dequeue_by_polling()
325 return -ETIME; in acpm_dequeue_by_polling()
329 * acpm_wait_for_queue_slots() - wait for queue slots.
332 * @next_tx_front: next front index of the TX queue.
334 * Return: 0 on success, -errno otherwise.
341 * Wait for RX front to keep up with TX front. Make sure there's at in acpm_wait_for_queue_slots()
344 ret = readl_poll_timeout(achan->rx.front, val, next_tx_front != val, 0, in acpm_wait_for_queue_slots()
347 dev_err(achan->acpm->dev, "RX front can not keep up with TX front.\n"); in acpm_wait_for_queue_slots()
351 ret = readl_poll_timeout(achan->tx.rear, val, next_tx_front != val, 0, in acpm_wait_for_queue_slots()
354 dev_err(achan->acpm->dev, "TX queue is full.\n"); in acpm_wait_for_queue_slots()
360 * acpm_prepare_xfer() - prepare a transfer before writing the message to the
361 * TX queue.
369 u32 *txd = (u32 *)xfer->txd; in acpm_prepare_xfer()
371 /* Prevent chan->seqnum from being re-used */ in acpm_prepare_xfer()
373 if (++achan->seqnum == ACPM_SEQNUM_MAX) in acpm_prepare_xfer()
374 achan->seqnum = 1; in acpm_prepare_xfer()
375 } while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum)); in acpm_prepare_xfer()
377 txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum); in acpm_prepare_xfer()
380 rx_data = &achan->rx_data[achan->seqnum - 1]; in acpm_prepare_xfer()
381 memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd); in acpm_prepare_xfer()
382 if (xfer->rxd) in acpm_prepare_xfer()
383 rx_data->response = true; in acpm_prepare_xfer()
386 set_bit(achan->seqnum - 1, achan->bitmap_seqnum); in acpm_prepare_xfer()
390 * acpm_wait_for_message_response - an helper to group all possible ways of
396 * Return: 0 on success, -errno otherwise.
406 * acpm_do_xfer() - do one transfer.
410 * Return: 0 on success, -errno otherwise.
420 if (xfer->acpm_chan_id >= acpm->num_chans) in acpm_do_xfer()
421 return -EINVAL; in acpm_do_xfer()
423 achan = &acpm->chans[xfer->acpm_chan_id]; in acpm_do_xfer()
425 if (!xfer->txd || xfer->txlen > achan->mlen || xfer->rxlen > achan->mlen) in acpm_do_xfer()
426 return -EINVAL; in acpm_do_xfer()
428 if (!achan->poll_completion) { in acpm_do_xfer()
429 dev_err(achan->acpm->dev, "Interrupt mode not supported\n"); in acpm_do_xfer()
430 return -EOPNOTSUPP; in acpm_do_xfer()
433 scoped_guard(mutex, &achan->tx_lock) { in acpm_do_xfer()
434 tx_front = readl(achan->tx.front); in acpm_do_xfer()
435 idx = (tx_front + 1) % achan->qlen; in acpm_do_xfer()
444 __iowrite32_copy(achan->tx.base + achan->mlen * tx_front, in acpm_do_xfer()
445 xfer->txd, xfer->txlen / 4); in acpm_do_xfer()
448 writel(idx, achan->tx.front); in acpm_do_xfer()
451 msg.chan_id = xfer->acpm_chan_id; in acpm_do_xfer()
453 ret = mbox_send_message(achan->chan, (void *)&msg); in acpm_do_xfer()
465 mbox_client_txdone(achan->chan, ret); in acpm_do_xfer()
471 * acpm_chan_shmem_get_params() - get channel parameters and addresses of the
472 * TX/RX queues.
479 void __iomem *base = achan->acpm->sram_base; in acpm_chan_shmem_get_params()
480 struct acpm_queue *rx = &achan->rx; in acpm_chan_shmem_get_params() local
481 struct acpm_queue *tx = &achan->tx; in acpm_chan_shmem_get_params()
483 achan->mlen = readl(&chan_shmem->mlen); in acpm_chan_shmem_get_params()
484 achan->poll_completion = readl(&chan_shmem->poll_completion); in acpm_chan_shmem_get_params()
485 achan->id = readl(&chan_shmem->id); in acpm_chan_shmem_get_params()
486 achan->qlen = readl(&chan_shmem->qlen); in acpm_chan_shmem_get_params()
488 tx->base = base + readl(&chan_shmem->rx_base); in acpm_chan_shmem_get_params()
489 tx->rear = base + readl(&chan_shmem->rx_rear); in acpm_chan_shmem_get_params()
490 tx->front = base + readl(&chan_shmem->rx_front); in acpm_chan_shmem_get_params()
492 rx->base = base + readl(&chan_shmem->tx_base); in acpm_chan_shmem_get_params()
493 rx->rear = base + readl(&chan_shmem->tx_rear); in acpm_chan_shmem_get_params()
494 rx->front = base + readl(&chan_shmem->tx_front); in acpm_chan_shmem_get_params()
496 dev_vdbg(achan->acpm->dev, "ID = %d poll = %d, mlen = %d, qlen = %d\n", in acpm_chan_shmem_get_params()
497 achan->id, achan->poll_completion, achan->mlen, achan->qlen); in acpm_chan_shmem_get_params()
501 * acpm_achan_alloc_cmds() - allocate buffers for retrieving data from the ACPM
505 * Return: 0 on success, -errno otherwise.
509 struct device *dev = achan->acpm->dev; in acpm_achan_alloc_cmds()
514 if (achan->mlen == 0) in acpm_achan_alloc_cmds()
517 cmd_size = sizeof(*(achan->rx_data[0].cmd)); in acpm_achan_alloc_cmds()
518 n_cmd = DIV_ROUND_UP_ULL(achan->mlen, cmd_size); in acpm_achan_alloc_cmds()
521 rx_data = &achan->rx_data[i]; in acpm_achan_alloc_cmds()
522 rx_data->n_cmd = n_cmd; in acpm_achan_alloc_cmds()
523 rx_data->cmd = devm_kcalloc(dev, n_cmd, cmd_size, GFP_KERNEL); in acpm_achan_alloc_cmds()
524 if (!rx_data->cmd) in acpm_achan_alloc_cmds()
525 return -ENOMEM; in acpm_achan_alloc_cmds()
532 * acpm_free_mbox_chans() - free mailbox channels.
539 for (i = 0; i < acpm->num_chans; i++) in acpm_free_mbox_chans()
540 if (!IS_ERR_OR_NULL(acpm->chans[i].chan)) in acpm_free_mbox_chans()
541 mbox_free_channel(acpm->chans[i].chan); in acpm_free_mbox_chans()
545 * acpm_channels_init() - initialize channels based on the configuration data in
549 * Return: 0 on success, -errno otherwise.
553 struct acpm_shmem __iomem *shmem = acpm->shmem; in acpm_channels_init()
555 struct device *dev = acpm->dev; in acpm_channels_init()
558 acpm->num_chans = readl(&shmem->num_chans); in acpm_channels_init()
559 acpm->chans = devm_kcalloc(dev, acpm->num_chans, sizeof(*acpm->chans), in acpm_channels_init()
561 if (!acpm->chans) in acpm_channels_init()
562 return -ENOMEM; in acpm_channels_init()
564 chans_shmem = acpm->sram_base + readl(&shmem->chans); in acpm_channels_init()
566 for (i = 0; i < acpm->num_chans; i++) { in acpm_channels_init()
568 struct acpm_chan *achan = &acpm->chans[i]; in acpm_channels_init()
569 struct mbox_client *cl = &achan->cl; in acpm_channels_init()
571 achan->acpm = acpm; in acpm_channels_init()
579 mutex_init(&achan->rx_lock); in acpm_channels_init()
580 mutex_init(&achan->tx_lock); in acpm_channels_init()
582 cl->dev = dev; in acpm_channels_init()
584 achan->chan = mbox_request_channel(cl, 0); in acpm_channels_init()
585 if (IS_ERR(achan->chan)) { in acpm_channels_init()
587 return PTR_ERR(achan->chan); in acpm_channels_init()
595 * acpm_setup_ops() - setup the operations structures.
600 struct acpm_pmic_ops *pmic_ops = &acpm->handle.ops.pmic_ops; in acpm_setup_ops()
602 pmic_ops->read_reg = acpm_pmic_read_reg; in acpm_setup_ops()
603 pmic_ops->bulk_read = acpm_pmic_bulk_read; in acpm_setup_ops()
604 pmic_ops->write_reg = acpm_pmic_write_reg; in acpm_setup_ops()
605 pmic_ops->bulk_write = acpm_pmic_bulk_write; in acpm_setup_ops()
606 pmic_ops->update_reg = acpm_pmic_update_reg; in acpm_setup_ops()
612 struct device *dev = &pdev->dev; in acpm_probe()
621 return -ENOMEM; in acpm_probe()
623 shmem = of_parse_phandle(dev->of_node, "shmem", 0); in acpm_probe()
631 acpm->sram_base = devm_ioremap(dev, res.start, size); in acpm_probe()
632 if (!acpm->sram_base) in acpm_probe()
633 return dev_err_probe(dev, -ENOMEM, in acpm_probe()
638 return dev_err_probe(dev, -EINVAL, in acpm_probe()
641 acpm->shmem = acpm->sram_base + match_data->initdata_base; in acpm_probe()
642 acpm->dev = dev; in acpm_probe()
656 * acpm_handle_put() - release the handle acquired by acpm_get_by_phandle.
662 struct device *dev = acpm->dev; in acpm_handle_put()
664 module_put(dev->driver->owner); in acpm_handle_put()
670 * devm_acpm_release() - devres release method.
680 * acpm_get_by_phandle() - get the ACPM handle using DT phandle.
684 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
694 acpm_np = of_parse_phandle(dev->of_node, property, 0); in acpm_get_by_phandle()
696 return ERR_PTR(-ENODEV); in acpm_get_by_phandle()
700 dev_err(dev, "Cannot find device node %s\n", acpm_np->name); in acpm_get_by_phandle()
702 return ERR_PTR(-EPROBE_DEFER); in acpm_get_by_phandle()
710 dev_name(&pdev->dev)); in acpm_get_by_phandle()
712 return ERR_PTR(-EPROBE_DEFER); in acpm_get_by_phandle()
715 if (!try_module_get(pdev->dev.driver->owner)) { in acpm_get_by_phandle()
718 return ERR_PTR(-EPROBE_DEFER); in acpm_get_by_phandle()
721 link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER); in acpm_get_by_phandle()
723 dev_err(&pdev->dev, in acpm_get_by_phandle()
727 module_put(pdev->dev.driver->owner); in acpm_get_by_phandle()
728 return ERR_PTR(-EINVAL); in acpm_get_by_phandle()
731 return &acpm->handle; in acpm_get_by_phandle()
735 * devm_acpm_get_by_phandle() - managed get handle using phandle.
739 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
748 return ERR_PTR(-ENOMEM); in devm_acpm_get_by_phandle()
767 .compatible = "google,gs101-acpm-ipc",
777 .name = "exynos-acpm-protocol",