Lines Matching +full:data +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-only
18 #include <soc/tegra/bpmp-abi.h>
21 #include "bpmp-private.h"
34 channel_to_ops(struct tegra_bpmp_channel *channel) in channel_to_ops() argument
36 struct tegra_bpmp *bpmp = channel->bpmp; in channel_to_ops()
38 return bpmp->soc->ops; in channel_to_ops()
47 np = of_parse_phandle(dev->of_node, "nvidia,bpmp", 0); in tegra_bpmp_get()
49 return ERR_PTR(-ENOENT); in tegra_bpmp_get()
53 bpmp = ERR_PTR(-ENODEV); in tegra_bpmp_get()
59 bpmp = ERR_PTR(-EPROBE_DEFER); in tegra_bpmp_get()
60 put_device(&pdev->dev); in tegra_bpmp_get()
73 put_device(bpmp->dev); in tegra_bpmp_put()
78 tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel) in tegra_bpmp_channel_get_thread_index() argument
80 struct tegra_bpmp *bpmp = channel->bpmp; in tegra_bpmp_channel_get_thread_index()
84 count = bpmp->soc->channels.thread.count; in tegra_bpmp_channel_get_thread_index()
86 index = channel - channel->bpmp->threaded_channels; in tegra_bpmp_channel_get_thread_index()
88 return -EINVAL; in tegra_bpmp_channel_get_thread_index()
95 return (msg->tx.size <= MSG_DATA_MIN_SZ) && in tegra_bpmp_message_valid()
96 (msg->rx.size <= MSG_DATA_MIN_SZ) && in tegra_bpmp_message_valid()
97 (msg->tx.size == 0 || msg->tx.data) && in tegra_bpmp_message_valid()
98 (msg->rx.size == 0 || msg->rx.data); in tegra_bpmp_message_valid()
101 static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel) in tegra_bpmp_is_response_ready() argument
103 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_is_response_ready()
105 return ops->is_response_ready(channel); in tegra_bpmp_is_response_ready()
108 static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel) in tegra_bpmp_is_request_ready() argument
110 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_is_request_ready()
112 return ops->is_request_ready(channel); in tegra_bpmp_is_request_ready()
115 static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel) in tegra_bpmp_wait_response() argument
117 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; in tegra_bpmp_wait_response()
123 if (tegra_bpmp_is_response_ready(channel)) in tegra_bpmp_wait_response()
127 return -ETIMEDOUT; in tegra_bpmp_wait_response()
130 static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel) in tegra_bpmp_ack_response() argument
132 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_ack_response()
134 return ops->ack_response(channel); in tegra_bpmp_ack_response()
137 static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel) in tegra_bpmp_ack_request() argument
139 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_ack_request()
141 return ops->ack_request(channel); in tegra_bpmp_ack_request()
145 tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel) in tegra_bpmp_is_request_channel_free() argument
147 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_is_request_channel_free()
149 return ops->is_request_channel_free(channel); in tegra_bpmp_is_request_channel_free()
153 tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel) in tegra_bpmp_is_response_channel_free() argument
155 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_is_response_channel_free()
157 return ops->is_response_channel_free(channel); in tegra_bpmp_is_response_channel_free()
161 tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel) in tegra_bpmp_wait_request_channel_free() argument
163 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; in tegra_bpmp_wait_request_channel_free()
169 if (tegra_bpmp_is_request_channel_free(channel)) in tegra_bpmp_wait_request_channel_free()
175 return -ETIMEDOUT; in tegra_bpmp_wait_request_channel_free()
178 static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel) in tegra_bpmp_post_request() argument
180 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_post_request()
182 return ops->post_request(channel); in tegra_bpmp_post_request()
185 static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel) in tegra_bpmp_post_response() argument
187 const struct tegra_bpmp_ops *ops = channel_to_ops(channel); in tegra_bpmp_post_response()
189 return ops->post_response(channel); in tegra_bpmp_post_response()
194 return bpmp->soc->ops->ring_doorbell(bpmp); in tegra_bpmp_ring_doorbell()
197 static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, in __tegra_bpmp_channel_read() argument
198 void *data, size_t size, int *ret) in __tegra_bpmp_channel_read() argument
202 if (data && size > 0) in __tegra_bpmp_channel_read()
203 tegra_bpmp_mb_read(data, &channel->ib, size); in __tegra_bpmp_channel_read()
205 err = tegra_bpmp_ack_response(channel); in __tegra_bpmp_channel_read()
209 *ret = tegra_bpmp_mb_read_field(&channel->ib, code); in __tegra_bpmp_channel_read()
214 static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, in tegra_bpmp_channel_read() argument
215 void *data, size_t size, int *ret) in tegra_bpmp_channel_read() argument
217 struct tegra_bpmp *bpmp = channel->bpmp; in tegra_bpmp_channel_read()
222 index = tegra_bpmp_channel_get_thread_index(channel); in tegra_bpmp_channel_read()
228 spin_lock_irqsave(&bpmp->lock, flags); in tegra_bpmp_channel_read()
229 err = __tegra_bpmp_channel_read(channel, data, size, ret); in tegra_bpmp_channel_read()
230 clear_bit(index, bpmp->threaded.allocated); in tegra_bpmp_channel_read()
231 spin_unlock_irqrestore(&bpmp->lock, flags); in tegra_bpmp_channel_read()
234 up(&bpmp->threaded.lock); in tegra_bpmp_channel_read()
239 static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel, in __tegra_bpmp_channel_write() argument
241 const void *data, size_t size) in __tegra_bpmp_channel_write() argument
243 tegra_bpmp_mb_write_field(&channel->ob, code, mrq); in __tegra_bpmp_channel_write()
244 tegra_bpmp_mb_write_field(&channel->ob, flags, flags); in __tegra_bpmp_channel_write()
246 if (data && size > 0) in __tegra_bpmp_channel_write()
247 tegra_bpmp_mb_write(&channel->ob, data, size); in __tegra_bpmp_channel_write()
249 return tegra_bpmp_post_request(channel); in __tegra_bpmp_channel_write()
254 const void *data, size_t size) in tegra_bpmp_write_threaded() argument
256 unsigned long timeout = bpmp->soc->channels.thread.timeout; in tegra_bpmp_write_threaded()
257 unsigned int count = bpmp->soc->channels.thread.count; in tegra_bpmp_write_threaded()
258 struct tegra_bpmp_channel *channel; in tegra_bpmp_write_threaded() local
263 err = down_timeout(&bpmp->threaded.lock, usecs_to_jiffies(timeout)); in tegra_bpmp_write_threaded()
267 spin_lock_irqsave(&bpmp->lock, flags); in tegra_bpmp_write_threaded()
269 index = find_first_zero_bit(bpmp->threaded.allocated, count); in tegra_bpmp_write_threaded()
271 err = -EBUSY; in tegra_bpmp_write_threaded()
275 channel = &bpmp->threaded_channels[index]; in tegra_bpmp_write_threaded()
277 if (!tegra_bpmp_is_request_channel_free(channel)) { in tegra_bpmp_write_threaded()
278 err = -EBUSY; in tegra_bpmp_write_threaded()
282 set_bit(index, bpmp->threaded.allocated); in tegra_bpmp_write_threaded()
284 err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING, in tegra_bpmp_write_threaded()
285 data, size); in tegra_bpmp_write_threaded()
289 set_bit(index, bpmp->threaded.busy); in tegra_bpmp_write_threaded()
291 spin_unlock_irqrestore(&bpmp->lock, flags); in tegra_bpmp_write_threaded()
292 return channel; in tegra_bpmp_write_threaded()
295 clear_bit(index, bpmp->threaded.allocated); in tegra_bpmp_write_threaded()
297 spin_unlock_irqrestore(&bpmp->lock, flags); in tegra_bpmp_write_threaded()
298 up(&bpmp->threaded.lock); in tegra_bpmp_write_threaded()
303 static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel, in tegra_bpmp_channel_write() argument
305 const void *data, size_t size) in tegra_bpmp_channel_write() argument
309 err = tegra_bpmp_wait_request_channel_free(channel); in tegra_bpmp_channel_write()
313 return __tegra_bpmp_channel_write(channel, mrq, flags, data, size); in tegra_bpmp_channel_write()
321 struct tegra_bpmp_channel *channel; in tegra_bpmp_transfer_atomic() local
325 return -EPERM; in tegra_bpmp_transfer_atomic()
328 return -EINVAL; in tegra_bpmp_transfer_atomic()
330 if (bpmp->suspended) { in tegra_bpmp_transfer_atomic()
332 if (msg->flags & TEGRA_BPMP_MESSAGE_RESET) in tegra_bpmp_transfer_atomic()
333 tegra_bpmp_resume(bpmp->dev); in tegra_bpmp_transfer_atomic()
335 return -EAGAIN; in tegra_bpmp_transfer_atomic()
338 channel = bpmp->tx_channel; in tegra_bpmp_transfer_atomic()
340 spin_lock(&bpmp->atomic_tx_lock); in tegra_bpmp_transfer_atomic()
342 err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK, in tegra_bpmp_transfer_atomic()
343 msg->tx.data, msg->tx.size); in tegra_bpmp_transfer_atomic()
345 spin_unlock(&bpmp->atomic_tx_lock); in tegra_bpmp_transfer_atomic()
349 spin_unlock(&bpmp->atomic_tx_lock); in tegra_bpmp_transfer_atomic()
355 err = tegra_bpmp_wait_response(channel); in tegra_bpmp_transfer_atomic()
359 return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size, in tegra_bpmp_transfer_atomic()
360 &msg->rx.ret); in tegra_bpmp_transfer_atomic()
367 struct tegra_bpmp_channel *channel; in tegra_bpmp_transfer() local
372 return -EPERM; in tegra_bpmp_transfer()
375 return -EINVAL; in tegra_bpmp_transfer()
377 if (bpmp->suspended) { in tegra_bpmp_transfer()
379 if (msg->flags & TEGRA_BPMP_MESSAGE_RESET) in tegra_bpmp_transfer()
380 tegra_bpmp_resume(bpmp->dev); in tegra_bpmp_transfer()
382 return -EAGAIN; in tegra_bpmp_transfer()
385 channel = tegra_bpmp_write_threaded(bpmp, msg->mrq, msg->tx.data, in tegra_bpmp_transfer()
386 msg->tx.size); in tegra_bpmp_transfer()
387 if (IS_ERR(channel)) in tegra_bpmp_transfer()
388 return PTR_ERR(channel); in tegra_bpmp_transfer()
394 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout); in tegra_bpmp_transfer()
396 err = wait_for_completion_timeout(&channel->completion, timeout); in tegra_bpmp_transfer()
398 return -ETIMEDOUT; in tegra_bpmp_transfer()
400 return tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size, in tegra_bpmp_transfer()
401 &msg->rx.ret); in tegra_bpmp_transfer()
410 list_for_each_entry(entry, &bpmp->mrqs, list) in tegra_bpmp_find_mrq()
411 if (entry->mrq == mrq) in tegra_bpmp_find_mrq()
417 void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, in tegra_bpmp_mrq_return() argument
418 const void *data, size_t size) in tegra_bpmp_mrq_return() argument
420 unsigned long flags = tegra_bpmp_mb_read_field(&channel->ib, flags); in tegra_bpmp_mrq_return()
421 struct tegra_bpmp *bpmp = channel->bpmp; in tegra_bpmp_mrq_return()
427 err = tegra_bpmp_ack_request(channel); in tegra_bpmp_mrq_return()
434 if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel))) in tegra_bpmp_mrq_return()
437 tegra_bpmp_mb_write_field(&channel->ob, code, code); in tegra_bpmp_mrq_return()
439 if (data && size > 0) in tegra_bpmp_mrq_return()
440 tegra_bpmp_mb_write(&channel->ob, data, size); in tegra_bpmp_mrq_return()
442 err = tegra_bpmp_post_response(channel); in tegra_bpmp_mrq_return()
456 struct tegra_bpmp_channel *channel) in tegra_bpmp_handle_mrq() argument
461 spin_lock(&bpmp->lock); in tegra_bpmp_handle_mrq()
465 spin_unlock(&bpmp->lock); in tegra_bpmp_handle_mrq()
466 tegra_bpmp_mrq_return(channel, -EINVAL, &zero, sizeof(zero)); in tegra_bpmp_handle_mrq()
470 entry->handler(mrq, channel, entry->data); in tegra_bpmp_handle_mrq()
472 spin_unlock(&bpmp->lock); in tegra_bpmp_handle_mrq()
476 tegra_bpmp_mrq_handler_t handler, void *data) in tegra_bpmp_request_mrq() argument
482 return -EINVAL; in tegra_bpmp_request_mrq()
484 entry = devm_kzalloc(bpmp->dev, sizeof(*entry), GFP_KERNEL); in tegra_bpmp_request_mrq()
486 return -ENOMEM; in tegra_bpmp_request_mrq()
488 spin_lock_irqsave(&bpmp->lock, flags); in tegra_bpmp_request_mrq()
490 entry->mrq = mrq; in tegra_bpmp_request_mrq()
491 entry->handler = handler; in tegra_bpmp_request_mrq()
492 entry->data = data; in tegra_bpmp_request_mrq()
493 list_add(&entry->list, &bpmp->mrqs); in tegra_bpmp_request_mrq()
495 spin_unlock_irqrestore(&bpmp->lock, flags); in tegra_bpmp_request_mrq()
501 void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, void *data) in tegra_bpmp_free_mrq() argument
506 spin_lock_irqsave(&bpmp->lock, flags); in tegra_bpmp_free_mrq()
512 list_del(&entry->list); in tegra_bpmp_free_mrq()
513 devm_kfree(bpmp->dev, entry); in tegra_bpmp_free_mrq()
516 spin_unlock_irqrestore(&bpmp->lock, flags); in tegra_bpmp_free_mrq()
527 .data = &req, in tegra_bpmp_mrq_is_supported()
531 .data = &resp, in tegra_bpmp_mrq_is_supported()
546 struct tegra_bpmp_channel *channel, in tegra_bpmp_mrq_handle_ping() argument
547 void *data) in tegra_bpmp_mrq_handle_ping() argument
552 tegra_bpmp_mb_read(&request, &channel->ib, sizeof(request)); in tegra_bpmp_mrq_handle_ping()
557 tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response)); in tegra_bpmp_mrq_handle_ping()
576 msg.tx.data = &request; in tegra_bpmp_ping()
578 msg.rx.data = &response; in tegra_bpmp_ping()
588 dev_dbg(bpmp->dev, in tegra_bpmp_ping()
608 return -EINVAL; in tegra_bpmp_get_firmware_tag_old()
610 virt = dma_alloc_coherent(bpmp->dev, TAG_SZ, &phys, in tegra_bpmp_get_firmware_tag_old()
613 return -ENOMEM; in tegra_bpmp_get_firmware_tag_old()
620 msg.tx.data = &request; in tegra_bpmp_get_firmware_tag_old()
630 dma_free_coherent(bpmp->dev, TAG_SZ, virt, phys); in tegra_bpmp_get_firmware_tag_old()
643 .data = &resp, in tegra_bpmp_get_firmware_tag()
650 return -EINVAL; in tegra_bpmp_get_firmware_tag()
657 return -EINVAL; in tegra_bpmp_get_firmware_tag()
666 static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel) in tegra_bpmp_channel_signal() argument
668 unsigned long flags = tegra_bpmp_mb_read_field(&channel->ob, flags); in tegra_bpmp_channel_signal()
673 complete(&channel->completion); in tegra_bpmp_channel_signal()
678 struct tegra_bpmp_channel *channel; in tegra_bpmp_handle_rx() local
682 channel = bpmp->rx_channel; in tegra_bpmp_handle_rx()
683 count = bpmp->soc->channels.thread.count; in tegra_bpmp_handle_rx()
684 busy = bpmp->threaded.busy; in tegra_bpmp_handle_rx()
686 if (tegra_bpmp_is_request_ready(channel)) { in tegra_bpmp_handle_rx()
687 unsigned int mrq = tegra_bpmp_mb_read_field(&channel->ib, code); in tegra_bpmp_handle_rx()
689 tegra_bpmp_handle_mrq(bpmp, mrq, channel); in tegra_bpmp_handle_rx()
692 spin_lock(&bpmp->lock); in tegra_bpmp_handle_rx()
695 struct tegra_bpmp_channel *channel; in tegra_bpmp_handle_rx() local
697 channel = &bpmp->threaded_channels[i]; in tegra_bpmp_handle_rx()
699 if (tegra_bpmp_is_response_ready(channel)) { in tegra_bpmp_handle_rx()
700 tegra_bpmp_channel_signal(channel); in tegra_bpmp_handle_rx()
705 spin_unlock(&bpmp->lock); in tegra_bpmp_handle_rx()
715 bpmp = devm_kzalloc(&pdev->dev, sizeof(*bpmp), GFP_KERNEL); in tegra_bpmp_probe()
717 return -ENOMEM; in tegra_bpmp_probe()
719 bpmp->soc = of_device_get_match_data(&pdev->dev); in tegra_bpmp_probe()
720 bpmp->dev = &pdev->dev; in tegra_bpmp_probe()
722 INIT_LIST_HEAD(&bpmp->mrqs); in tegra_bpmp_probe()
723 spin_lock_init(&bpmp->lock); in tegra_bpmp_probe()
725 bpmp->threaded.count = bpmp->soc->channels.thread.count; in tegra_bpmp_probe()
726 sema_init(&bpmp->threaded.lock, bpmp->threaded.count); in tegra_bpmp_probe()
728 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long); in tegra_bpmp_probe()
730 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); in tegra_bpmp_probe()
731 if (!bpmp->threaded.allocated) in tegra_bpmp_probe()
732 return -ENOMEM; in tegra_bpmp_probe()
734 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); in tegra_bpmp_probe()
735 if (!bpmp->threaded.busy) in tegra_bpmp_probe()
736 return -ENOMEM; in tegra_bpmp_probe()
738 spin_lock_init(&bpmp->atomic_tx_lock); in tegra_bpmp_probe()
739 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel), in tegra_bpmp_probe()
741 if (!bpmp->tx_channel) in tegra_bpmp_probe()
742 return -ENOMEM; in tegra_bpmp_probe()
744 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel), in tegra_bpmp_probe()
746 if (!bpmp->rx_channel) in tegra_bpmp_probe()
747 return -ENOMEM; in tegra_bpmp_probe()
749 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count, in tegra_bpmp_probe()
750 sizeof(*bpmp->threaded_channels), in tegra_bpmp_probe()
752 if (!bpmp->threaded_channels) in tegra_bpmp_probe()
753 return -ENOMEM; in tegra_bpmp_probe()
757 err = bpmp->soc->ops->init(bpmp); in tegra_bpmp_probe()
768 dev_err(&pdev->dev, "failed to ping BPMP: %d\n", err); in tegra_bpmp_probe()
774 dev_err(&pdev->dev, "failed to get firmware tag: %d\n", err); in tegra_bpmp_probe()
778 dev_info(&pdev->dev, "firmware: %.*s\n", (int)sizeof(tag), tag); in tegra_bpmp_probe()
780 err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev); in tegra_bpmp_probe()
784 if (of_property_present(pdev->dev.of_node, "#clock-cells")) { in tegra_bpmp_probe()
790 if (of_property_present(pdev->dev.of_node, "#reset-cells")) { in tegra_bpmp_probe()
796 if (of_property_present(pdev->dev.of_node, "#power-domain-cells")) { in tegra_bpmp_probe()
804 dev_err(&pdev->dev, "debugfs initialization failed: %d\n", err); in tegra_bpmp_probe()
811 if (bpmp->soc->ops->deinit) in tegra_bpmp_probe()
812 bpmp->soc->ops->deinit(bpmp); in tegra_bpmp_probe()
821 bpmp->suspended = true; in tegra_bpmp_suspend()
830 bpmp->suspended = false; in tegra_bpmp_resume()
832 if (bpmp->soc->ops->resume) in tegra_bpmp_resume()
833 return bpmp->soc->ops->resume(bpmp); in tegra_bpmp_resume()
894 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
897 { .compatible = "nvidia,tegra210-bpmp", .data = &tegra210_soc },
904 .name = "tegra-bpmp",