Lines Matching +full:secure +full:- +full:reg +full:- +full:access
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/
21 #include <linux/soc/ti/ti-msgmgr.h>
23 #define Q_DATA_OFFSET(proxy, queue, reg) \ argument
24 ((0x10000 * (proxy)) + (0x80 * (queue)) + ((reg) * 4))
29 #define SPROXY_THREAD_DATA_OFFSET(tid, reg) \ argument
30 (SPROXY_THREAD_OFFSET(tid) + ((reg) * 0x4) + 0x4)
40 * struct ti_msgmgr_valid_queue_desc - SoC valid queues meant for this processor
52 * struct ti_msgmgr_desc - Description of message manager integration
62 * @valid_queues: List of Valid queues that the processor can access
67 * @is_sproxy: Is this an Secure Proxy instance?
91 * struct ti_queue_inst - Description of a queue instance
119 * struct ti_msgmgr_inst - Description of a Message Manager Instance
145 * ti_msgmgr_queue_get_num_messages() - Get the number of pending messages
156 u32 status_cnt_mask = d->status_cnt_mask; in ti_msgmgr_queue_get_num_messages()
159 * We cannot use relaxed operation here - update may happen in ti_msgmgr_queue_get_num_messages()
160 * real-time. in ti_msgmgr_queue_get_num_messages()
162 val = readl(qinst->queue_state) & status_cnt_mask; in ti_msgmgr_queue_get_num_messages()
169 * ti_msgmgr_queue_is_error() - Check to see if there is queue error
181 if (!d->is_sproxy) in ti_msgmgr_queue_is_error()
185 * We cannot use relaxed operation here - update may happen in ti_msgmgr_queue_is_error()
186 * real-time. in ti_msgmgr_queue_is_error()
188 val = readl(qinst->queue_state) & d->status_err_mask; in ti_msgmgr_queue_is_error()
194 * ti_msgmgr_queue_rx_interrupt() - Interrupt handler for receive Queue
198 * Return: -EINVAL if there is no instance
205 struct device *dev = chan->mbox->dev; in ti_msgmgr_queue_rx_interrupt()
207 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_queue_rx_interrupt()
216 return -EINVAL; in ti_msgmgr_queue_rx_interrupt()
220 if (qinst->is_tx) { in ti_msgmgr_queue_rx_interrupt()
222 qinst->name); in ti_msgmgr_queue_rx_interrupt()
226 desc = inst->desc; in ti_msgmgr_queue_rx_interrupt()
228 dev_err(dev, "Error on Rx channel %s\n", qinst->name); in ti_msgmgr_queue_rx_interrupt()
236 dev_dbg(dev, "Spurious event - 0 pending data!\n"); in ti_msgmgr_queue_rx_interrupt()
242 * remote producer - 0 could be valid data, so I wont make a judgement in ti_msgmgr_queue_rx_interrupt()
246 message.len = desc->max_message_size; in ti_msgmgr_queue_rx_interrupt()
247 message.buf = (u8 *)qinst->rx_buff; in ti_msgmgr_queue_rx_interrupt()
250 * NOTE about register access involved here: in ti_msgmgr_queue_rx_interrupt()
251 * the hardware block is implemented with 32bit access operations and no in ti_msgmgr_queue_rx_interrupt()
253 * with sub 32bit access - For example: if the last register read is in ti_msgmgr_queue_rx_interrupt()
254 * split into byte wise access, it can result in the queue getting in ti_msgmgr_queue_rx_interrupt()
263 for (data_reg = qinst->queue_buff_start, word_data = qinst->rx_buff, in ti_msgmgr_queue_rx_interrupt()
264 num_words = (desc->max_message_size / sizeof(u32)); in ti_msgmgr_queue_rx_interrupt()
265 num_words; num_words--, data_reg += sizeof(u32), word_data++) in ti_msgmgr_queue_rx_interrupt()
270 * is pending - so send the data up the stack.. in ti_msgmgr_queue_rx_interrupt()
280 * ti_msgmgr_queue_peek_data() - Peek to see if there are any rx messages.
287 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_queue_peek_data()
288 struct device *dev = chan->mbox->dev; in ti_msgmgr_queue_peek_data()
290 const struct ti_msgmgr_desc *desc = inst->desc; in ti_msgmgr_queue_peek_data()
293 if (qinst->is_tx) in ti_msgmgr_queue_peek_data()
297 dev_err(dev, "Error on channel %s\n", qinst->name); in ti_msgmgr_queue_peek_data()
307 * ti_msgmgr_last_tx_done() - See if all the tx messages are sent
314 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_last_tx_done()
315 struct device *dev = chan->mbox->dev; in ti_msgmgr_last_tx_done()
317 const struct ti_msgmgr_desc *desc = inst->desc; in ti_msgmgr_last_tx_done()
320 if (!qinst->is_tx) in ti_msgmgr_last_tx_done()
324 dev_err(dev, "Error on channel %s\n", qinst->name); in ti_msgmgr_last_tx_done()
330 if (desc->is_sproxy) { in ti_msgmgr_last_tx_done()
331 /* In secure proxy, msg_count indicates how many we can send */ in ti_msgmgr_last_tx_done()
340 * ti_msgmgr_send_data() - Send data
348 struct device *dev = chan->mbox->dev; in ti_msgmgr_send_data()
351 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_send_data()
359 return -EINVAL; in ti_msgmgr_send_data()
361 desc = inst->desc; in ti_msgmgr_send_data()
364 dev_err(dev, "Error on channel %s\n", qinst->name); in ti_msgmgr_send_data()
368 if (desc->max_message_size < message->len) { in ti_msgmgr_send_data()
370 qinst->name, message->len, desc->max_message_size); in ti_msgmgr_send_data()
371 return -EINVAL; in ti_msgmgr_send_data()
375 for (data_reg = qinst->queue_buff_start, in ti_msgmgr_send_data()
376 num_words = message->len / sizeof(u32), in ti_msgmgr_send_data()
377 word_data = (u32 *)message->buf; in ti_msgmgr_send_data()
378 num_words; num_words--, data_reg += sizeof(u32), word_data++) in ti_msgmgr_send_data()
381 trail_bytes = message->len % sizeof(u32); in ti_msgmgr_send_data()
386 data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); in ti_msgmgr_send_data()
392 * write on tx complete reg(last reg), we must do so for transmit in ti_msgmgr_send_data()
394 if (data_reg <= qinst->queue_buff_end) in ti_msgmgr_send_data()
395 writel(0, qinst->queue_buff_end); in ti_msgmgr_send_data()
401 * ti_msgmgr_queue_rx_irq_req() - RX IRQ request
417 "rx_%03d", d->is_sproxy ? qinst->proxy_id : qinst->queue_id); in ti_msgmgr_queue_rx_irq_req()
420 if (qinst->irq < 0) { in ti_msgmgr_queue_rx_irq_req()
421 np = of_node_get(dev->of_node); in ti_msgmgr_queue_rx_irq_req()
423 return -ENODATA; in ti_msgmgr_queue_rx_irq_req()
424 qinst->irq = of_irq_get_byname(np, of_rx_irq_name); in ti_msgmgr_queue_rx_irq_req()
427 if (qinst->irq < 0) { in ti_msgmgr_queue_rx_irq_req()
430 qinst->queue_id, qinst->proxy_id, in ti_msgmgr_queue_rx_irq_req()
431 of_rx_irq_name, qinst->irq); in ti_msgmgr_queue_rx_irq_req()
432 return qinst->irq; in ti_msgmgr_queue_rx_irq_req()
437 ret = request_irq(qinst->irq, ti_msgmgr_queue_rx_interrupt, in ti_msgmgr_queue_rx_irq_req()
438 IRQF_SHARED, qinst->name, chan); in ti_msgmgr_queue_rx_irq_req()
441 qinst->irq, qinst->name, ret); in ti_msgmgr_queue_rx_irq_req()
448 * ti_msgmgr_queue_startup() - Startup queue
455 struct device *dev = chan->mbox->dev; in ti_msgmgr_queue_startup()
457 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_queue_startup()
458 const struct ti_msgmgr_desc *d = inst->desc; in ti_msgmgr_queue_startup()
466 if (d->is_sproxy) { in ti_msgmgr_queue_startup()
467 qinst->is_tx = (readl(qinst->queue_ctrl) & in ti_msgmgr_queue_startup()
472 if (!msg_count && qinst->is_tx) { in ti_msgmgr_queue_startup()
474 qinst->name); in ti_msgmgr_queue_startup()
475 return -EINVAL; in ti_msgmgr_queue_startup()
479 if (!qinst->is_tx) { in ti_msgmgr_queue_startup()
481 qinst->rx_buff = kzalloc(d->max_message_size, GFP_KERNEL); in ti_msgmgr_queue_startup()
482 if (!qinst->rx_buff) in ti_msgmgr_queue_startup()
483 return -ENOMEM; in ti_msgmgr_queue_startup()
487 kfree(qinst->rx_buff); in ti_msgmgr_queue_startup()
496 * ti_msgmgr_queue_shutdown() - Shutdown the queue
501 struct ti_queue_inst *qinst = chan->con_priv; in ti_msgmgr_queue_shutdown()
503 if (!qinst->is_tx) { in ti_msgmgr_queue_shutdown()
504 free_irq(qinst->irq, chan); in ti_msgmgr_queue_shutdown()
505 kfree(qinst->rx_buff); in ti_msgmgr_queue_shutdown()
510 * ti_msgmgr_of_xlate() - Translation of phandle to queue
528 return ERR_PTR(-EINVAL); in ti_msgmgr_of_xlate()
530 d = inst->desc; in ti_msgmgr_of_xlate()
532 if (d->is_sproxy) in ti_msgmgr_of_xlate()
536 if (p->args_count != ncells) { in ti_msgmgr_of_xlate()
537 dev_err(inst->dev, "Invalid arguments in dt[%d]. Must be %d\n", in ti_msgmgr_of_xlate()
538 p->args_count, ncells); in ti_msgmgr_of_xlate()
539 return ERR_PTR(-EINVAL); in ti_msgmgr_of_xlate()
543 req_pid = p->args[0]; in ti_msgmgr_of_xlate()
545 req_qid = p->args[0]; in ti_msgmgr_of_xlate()
546 req_pid = p->args[1]; in ti_msgmgr_of_xlate()
549 if (d->is_sproxy) { in ti_msgmgr_of_xlate()
550 if (req_pid >= d->num_valid_queues) in ti_msgmgr_of_xlate()
552 qinst = &inst->qinsts[req_pid]; in ti_msgmgr_of_xlate()
553 return qinst->chan; in ti_msgmgr_of_xlate()
556 for (qinst = inst->qinsts, i = 0; i < inst->num_valid_queues; in ti_msgmgr_of_xlate()
558 if (req_qid == qinst->queue_id && req_pid == qinst->proxy_id) in ti_msgmgr_of_xlate()
559 return qinst->chan; in ti_msgmgr_of_xlate()
563 dev_err(inst->dev, "Queue ID %d, Proxy ID %d is wrong on %pOFn\n", in ti_msgmgr_of_xlate()
564 req_qid, req_pid, p->np); in ti_msgmgr_of_xlate()
565 return ERR_PTR(-ENOENT); in ti_msgmgr_of_xlate()
569 * ti_msgmgr_queue_setup() - Setup data structures for each queue instance
591 qinst->proxy_id = qd->proxy_id; in ti_msgmgr_queue_setup()
592 qinst->queue_id = qd->queue_id; in ti_msgmgr_queue_setup()
594 if (qinst->queue_id > d->queue_count) { in ti_msgmgr_queue_setup()
596 idx, qinst->queue_id, d->queue_count); in ti_msgmgr_queue_setup()
597 return -ERANGE; in ti_msgmgr_queue_setup()
600 if (d->is_sproxy) { in ti_msgmgr_queue_setup()
601 qinst->queue_buff_start = inst->queue_proxy_region + in ti_msgmgr_queue_setup()
602 SPROXY_THREAD_DATA_OFFSET(qinst->proxy_id, in ti_msgmgr_queue_setup()
603 d->data_first_reg); in ti_msgmgr_queue_setup()
604 qinst->queue_buff_end = inst->queue_proxy_region + in ti_msgmgr_queue_setup()
605 SPROXY_THREAD_DATA_OFFSET(qinst->proxy_id, in ti_msgmgr_queue_setup()
606 d->data_last_reg); in ti_msgmgr_queue_setup()
607 qinst->queue_state = inst->queue_state_debug_region + in ti_msgmgr_queue_setup()
608 SPROXY_THREAD_STATUS_OFFSET(qinst->proxy_id); in ti_msgmgr_queue_setup()
609 qinst->queue_ctrl = inst->queue_ctrl_region + in ti_msgmgr_queue_setup()
610 SPROXY_THREAD_CTRL_OFFSET(qinst->proxy_id); in ti_msgmgr_queue_setup()
614 snprintf(qinst->name, sizeof(qinst->name), "%s %s_%03d", in ti_msgmgr_queue_setup()
615 dev_name(dev), dir, qinst->proxy_id); in ti_msgmgr_queue_setup()
617 qinst->queue_buff_start = inst->queue_proxy_region + in ti_msgmgr_queue_setup()
618 Q_DATA_OFFSET(qinst->proxy_id, qinst->queue_id, in ti_msgmgr_queue_setup()
619 d->data_first_reg); in ti_msgmgr_queue_setup()
620 qinst->queue_buff_end = inst->queue_proxy_region + in ti_msgmgr_queue_setup()
621 Q_DATA_OFFSET(qinst->proxy_id, qinst->queue_id, in ti_msgmgr_queue_setup()
622 d->data_last_reg); in ti_msgmgr_queue_setup()
623 qinst->queue_state = in ti_msgmgr_queue_setup()
624 inst->queue_state_debug_region + in ti_msgmgr_queue_setup()
625 Q_STATE_OFFSET(qinst->queue_id); in ti_msgmgr_queue_setup()
626 qinst->is_tx = qd->is_tx; in ti_msgmgr_queue_setup()
627 dir = qinst->is_tx ? "tx" : "rx"; in ti_msgmgr_queue_setup()
628 snprintf(qinst->name, sizeof(qinst->name), "%s %s_%03d_%03d", in ti_msgmgr_queue_setup()
629 dev_name(dev), dir, qinst->queue_id, qinst->proxy_id); in ti_msgmgr_queue_setup()
632 qinst->chan = chan; in ti_msgmgr_queue_setup()
634 /* Setup an error value for IRQ - Lazy allocation */ in ti_msgmgr_queue_setup()
635 qinst->irq = -EINVAL; in ti_msgmgr_queue_setup()
637 chan->con_priv = qinst; in ti_msgmgr_queue_setup()
640 idx, qinst->queue_id, qinst->proxy_id, qinst->irq, in ti_msgmgr_queue_setup()
641 qinst->queue_buff_start, qinst->queue_buff_end); in ti_msgmgr_queue_setup()
699 {.compatible = "ti,k2g-message-manager", .data = &k2g_desc},
700 {.compatible = "ti,am654-secure-proxy", .data = &am654_desc},
708 struct device *dev = &pdev->dev; in ti_msgmgr_probe()
719 int ret = -EINVAL; in ti_msgmgr_probe()
722 if (!dev->of_node) { in ti_msgmgr_probe()
724 return -EINVAL; in ti_msgmgr_probe()
726 np = dev->of_node; in ti_msgmgr_probe()
731 return -EINVAL; in ti_msgmgr_probe()
733 desc = of_id->data; in ti_msgmgr_probe()
737 return -ENOMEM; in ti_msgmgr_probe()
739 inst->dev = dev; in ti_msgmgr_probe()
740 inst->desc = desc; in ti_msgmgr_probe()
743 desc->data_region_name); in ti_msgmgr_probe()
744 inst->queue_proxy_region = devm_ioremap_resource(dev, res); in ti_msgmgr_probe()
745 if (IS_ERR(inst->queue_proxy_region)) in ti_msgmgr_probe()
746 return PTR_ERR(inst->queue_proxy_region); in ti_msgmgr_probe()
749 desc->status_region_name); in ti_msgmgr_probe()
750 inst->queue_state_debug_region = devm_ioremap_resource(dev, res); in ti_msgmgr_probe()
751 if (IS_ERR(inst->queue_state_debug_region)) in ti_msgmgr_probe()
752 return PTR_ERR(inst->queue_state_debug_region); in ti_msgmgr_probe()
754 if (desc->is_sproxy) { in ti_msgmgr_probe()
756 desc->ctrl_region_name); in ti_msgmgr_probe()
757 inst->queue_ctrl_region = devm_ioremap_resource(dev, res); in ti_msgmgr_probe()
758 if (IS_ERR(inst->queue_ctrl_region)) in ti_msgmgr_probe()
759 return PTR_ERR(inst->queue_ctrl_region); in ti_msgmgr_probe()
763 inst->queue_proxy_region, inst->queue_state_debug_region); in ti_msgmgr_probe()
765 queue_count = desc->num_valid_queues; in ti_msgmgr_probe()
766 if (!queue_count || queue_count > desc->queue_count) { in ti_msgmgr_probe()
768 queue_count, desc->queue_count); in ti_msgmgr_probe()
769 return -ERANGE; in ti_msgmgr_probe()
771 inst->num_valid_queues = queue_count; in ti_msgmgr_probe()
775 return -ENOMEM; in ti_msgmgr_probe()
776 inst->qinsts = qinst; in ti_msgmgr_probe()
780 return -ENOMEM; in ti_msgmgr_probe()
781 inst->chans = chans; in ti_msgmgr_probe()
783 if (desc->is_sproxy) { in ti_msgmgr_probe()
786 /* All proxies may be valid in Secure Proxy instance */ in ti_msgmgr_probe()
798 for (i = 0, queue_desc = desc->valid_queues; in ti_msgmgr_probe()
808 mbox = &inst->mbox; in ti_msgmgr_probe()
809 mbox->dev = dev; in ti_msgmgr_probe()
810 mbox->ops = &ti_msgmgr_chan_ops; in ti_msgmgr_probe()
811 mbox->chans = inst->chans; in ti_msgmgr_probe()
812 mbox->num_chans = inst->num_valid_queues; in ti_msgmgr_probe()
813 mbox->txdone_irq = false; in ti_msgmgr_probe()
814 mbox->txdone_poll = desc->tx_polled; in ti_msgmgr_probe()
815 if (desc->tx_polled) in ti_msgmgr_probe()
816 mbox->txpoll_period = desc->tx_poll_timeout_ms; in ti_msgmgr_probe()
817 mbox->of_xlate = ti_msgmgr_of_xlate; in ti_msgmgr_probe()
830 .name = "ti-msgmgr",
839 MODULE_ALIAS("platform:ti-msgmgr");