ti-msgmgr.c (cb62b8f7346338eeefa6d46160200879dc345246) | ti-msgmgr.c (df227dc8a68d81b7fe3416eca16d1f21d0b537f0) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Texas Instruments' Message Manager Driver 4 * | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Texas Instruments' Message Manager Driver 4 * |
5 * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/ | 5 * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/ |
6 * Nishanth Menon 7 */ 8 9#define pr_fmt(fmt) "%s: " fmt, __func__ 10 11#include <linux/device.h> 12#include <linux/interrupt.h> 13#include <linux/io.h> | 6 * Nishanth Menon 7 */ 8 9#define pr_fmt(fmt) "%s: " fmt, __func__ 10 11#include <linux/device.h> 12#include <linux/interrupt.h> 13#include <linux/io.h> |
14#include <linux/iopoll.h> |
|
14#include <linux/kernel.h> 15#include <linux/mailbox_controller.h> 16#include <linux/module.h> 17#include <linux/of_device.h> 18#include <linux/of.h> 19#include <linux/of_irq.h> 20#include <linux/platform_device.h> 21#include <linux/soc/ti/ti-msgmgr.h> --- 73 unchanged lines hidden (view full) --- 95 * @irq: IRQ for Rx Queue 96 * @is_tx: 'true' if transmit queue, else, 'false' 97 * @queue_buff_start: First register of Data Buffer 98 * @queue_buff_end: Last (or confirmation) register of Data buffer 99 * @queue_state: Queue status register 100 * @queue_ctrl: Queue Control register 101 * @chan: Mailbox channel 102 * @rx_buff: Receive buffer pointer allocated at probe, max_message_size | 15#include <linux/kernel.h> 16#include <linux/mailbox_controller.h> 17#include <linux/module.h> 18#include <linux/of_device.h> 19#include <linux/of.h> 20#include <linux/of_irq.h> 21#include <linux/platform_device.h> 22#include <linux/soc/ti/ti-msgmgr.h> --- 73 unchanged lines hidden (view full) --- 96 * @irq: IRQ for Rx Queue 97 * @is_tx: 'true' if transmit queue, else, 'false' 98 * @queue_buff_start: First register of Data Buffer 99 * @queue_buff_end: Last (or confirmation) register of Data buffer 100 * @queue_state: Queue status register 101 * @queue_ctrl: Queue Control register 102 * @chan: Mailbox channel 103 * @rx_buff: Receive buffer pointer allocated at probe, max_message_size |
104 * @polled_rx_mode: Use polling for rx instead of interrupts |
|
103 */ 104struct ti_queue_inst { 105 char name[30]; 106 u8 queue_id; 107 u8 proxy_id; 108 int irq; 109 bool is_tx; 110 void __iomem *queue_buff_start; 111 void __iomem *queue_buff_end; 112 void __iomem *queue_state; 113 void __iomem *queue_ctrl; 114 struct mbox_chan *chan; 115 u32 *rx_buff; | 105 */ 106struct ti_queue_inst { 107 char name[30]; 108 u8 queue_id; 109 u8 proxy_id; 110 int irq; 111 bool is_tx; 112 void __iomem *queue_buff_start; 113 void __iomem *queue_buff_end; 114 void __iomem *queue_state; 115 void __iomem *queue_ctrl; 116 struct mbox_chan *chan; 117 u32 *rx_buff; |
118 bool polled_rx_mode; |
|
116}; 117 118/** 119 * struct ti_msgmgr_inst - Description of a Message Manager Instance 120 * @dev: device pointer corresponding to the Message Manager instance 121 * @desc: Description of the SoC integration 122 * @queue_proxy_region: Queue proxy region where queue buffers are located 123 * @queue_state_debug_region: Queue status register regions --- 108 unchanged lines hidden (view full) --- 232 * NOTE: Client is expected to be as optimal as possible, since 233 * we invoke the handler in IRQ context. 234 */ 235 mbox_chan_received_data(chan, (void *)&message); 236 237 return 0; 238} 239 | 119}; 120 121/** 122 * struct ti_msgmgr_inst - Description of a Message Manager Instance 123 * @dev: device pointer corresponding to the Message Manager instance 124 * @desc: Description of the SoC integration 125 * @queue_proxy_region: Queue proxy region where queue buffers are located 126 * @queue_state_debug_region: Queue status register regions --- 108 unchanged lines hidden (view full) --- 235 * NOTE: Client is expected to be as optimal as possible, since 236 * we invoke the handler in IRQ context. 237 */ 238 mbox_chan_received_data(chan, (void *)&message); 239 240 return 0; 241} 242 |
243static int ti_msgmgr_queue_rx_poll_timeout(struct mbox_chan *chan, int timeout_us) 244{ 245 struct device *dev = chan->mbox->dev; 246 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev); 247 struct ti_queue_inst *qinst = chan->con_priv; 248 const struct ti_msgmgr_desc *desc = inst->desc; 249 int msg_count; 250 int ret; 251 252 ret = readl_poll_timeout_atomic(qinst->queue_state, msg_count, 253 (msg_count & desc->status_cnt_mask), 254 10, timeout_us); 255 if (ret != 0) 256 return ret; 257 258 ti_msgmgr_queue_rx_data(chan, qinst, desc); 259 260 return 0; 261} 262 |
|
240/** 241 * ti_msgmgr_queue_rx_interrupt() - Interrupt handler for receive Queue 242 * @irq: Interrupt number 243 * @p: Channel Pointer 244 * 245 * Return: -EINVAL if there is no instance 246 * IRQ_NONE if the interrupt is not ours. 247 * IRQ_HANDLED if the rx interrupt was successfully handled. --- 93 unchanged lines hidden (view full) --- 341 /* In secure proxy, msg_count indicates how many we can send */ 342 return msg_count ? true : false; 343 } 344 345 /* if we have any messages pending.. */ 346 return msg_count ? false : true; 347} 348 | 263/** 264 * ti_msgmgr_queue_rx_interrupt() - Interrupt handler for receive Queue 265 * @irq: Interrupt number 266 * @p: Channel Pointer 267 * 268 * Return: -EINVAL if there is no instance 269 * IRQ_NONE if the interrupt is not ours. 270 * IRQ_HANDLED if the rx interrupt was successfully handled. --- 93 unchanged lines hidden (view full) --- 364 /* In secure proxy, msg_count indicates how many we can send */ 365 return msg_count ? true : false; 366 } 367 368 /* if we have any messages pending.. */ 369 return msg_count ? false : true; 370} 371 |
372static bool ti_msgmgr_chan_has_polled_queue_rx(struct mbox_chan *chan) 373{ 374 struct ti_queue_inst *qinst; 375 376 if (!chan) 377 return false; 378 379 qinst = chan->con_priv; 380 return qinst->polled_rx_mode; 381} 382 |
|
349/** 350 * ti_msgmgr_send_data() - Send data 351 * @chan: Channel Pointer 352 * @data: ti_msgmgr_message * Message Pointer 353 * 354 * Return: 0 if all goes good, else appropriate error messages. 355 */ 356static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data) 357{ 358 struct device *dev = chan->mbox->dev; 359 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev); 360 const struct ti_msgmgr_desc *desc; 361 struct ti_queue_inst *qinst = chan->con_priv; 362 int num_words, trail_bytes; 363 struct ti_msgmgr_message *message = data; 364 void __iomem *data_reg; 365 u32 *word_data; | 383/** 384 * ti_msgmgr_send_data() - Send data 385 * @chan: Channel Pointer 386 * @data: ti_msgmgr_message * Message Pointer 387 * 388 * Return: 0 if all goes good, else appropriate error messages. 389 */ 390static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data) 391{ 392 struct device *dev = chan->mbox->dev; 393 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev); 394 const struct ti_msgmgr_desc *desc; 395 struct ti_queue_inst *qinst = chan->con_priv; 396 int num_words, trail_bytes; 397 struct ti_msgmgr_message *message = data; 398 void __iomem *data_reg; 399 u32 *word_data; |
400 int ret = 0; |
|
366 367 if (WARN_ON(!inst)) { 368 dev_err(dev, "no platform drv data??\n"); 369 return -EINVAL; 370 } 371 desc = inst->desc; 372 373 if (ti_msgmgr_queue_is_error(desc, qinst)) { --- 25 unchanged lines hidden (view full) --- 399 } 400 /* 401 * 'data_reg' indicates next register to write. If we did not already 402 * write on tx complete reg(last reg), we must do so for transmit 403 */ 404 if (data_reg <= qinst->queue_buff_end) 405 writel(0, qinst->queue_buff_end); 406 | 401 402 if (WARN_ON(!inst)) { 403 dev_err(dev, "no platform drv data??\n"); 404 return -EINVAL; 405 } 406 desc = inst->desc; 407 408 if (ti_msgmgr_queue_is_error(desc, qinst)) { --- 25 unchanged lines hidden (view full) --- 434 } 435 /* 436 * 'data_reg' indicates next register to write. If we did not already 437 * write on tx complete reg(last reg), we must do so for transmit 438 */ 439 if (data_reg <= qinst->queue_buff_end) 440 writel(0, qinst->queue_buff_end); 441 |
407 return 0; | 442 /* If we are in polled mode, wait for a response before proceeding */ 443 if (ti_msgmgr_chan_has_polled_queue_rx(message->chan_rx)) 444 ret = ti_msgmgr_queue_rx_poll_timeout(message->chan_rx, 445 message->timeout_rx_ms * 1000); 446 447 return ret; |
408} 409 410/** 411 * ti_msgmgr_queue_rx_irq_req() - RX IRQ request 412 * @dev: device pointer 413 * @d: descriptor for ti_msgmgr 414 * @qinst: Queue instance 415 * @chan: Channel pointer --- 231 unchanged lines hidden (view full) --- 647 chan->con_priv = qinst; 648 649 dev_dbg(dev, "[%d] qidx=%d pidx=%d irq=%d q_s=%p q_e = %p\n", 650 idx, qinst->queue_id, qinst->proxy_id, qinst->irq, 651 qinst->queue_buff_start, qinst->queue_buff_end); 652 return 0; 653} 654 | 448} 449 450/** 451 * ti_msgmgr_queue_rx_irq_req() - RX IRQ request 452 * @dev: device pointer 453 * @d: descriptor for ti_msgmgr 454 * @qinst: Queue instance 455 * @chan: Channel pointer --- 231 unchanged lines hidden (view full) --- 687 chan->con_priv = qinst; 688 689 dev_dbg(dev, "[%d] qidx=%d pidx=%d irq=%d q_s=%p q_e = %p\n", 690 idx, qinst->queue_id, qinst->proxy_id, qinst->irq, 691 qinst->queue_buff_start, qinst->queue_buff_end); 692 return 0; 693} 694 |
695static int ti_msgmgr_queue_rx_set_polled_mode(struct ti_queue_inst *qinst, bool enable) 696{ 697 if (enable) { 698 disable_irq(qinst->irq); 699 qinst->polled_rx_mode = true; 700 } else { 701 enable_irq(qinst->irq); 702 qinst->polled_rx_mode = false; 703 } 704 705 return 0; 706} 707 708static int ti_msgmgr_suspend(struct device *dev) 709{ 710 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev); 711 struct ti_queue_inst *qinst; 712 int i; 713 714 /* 715 * We must switch operation to polled mode now as drivers and the genpd 716 * layer may make late TI SCI calls to change clock and device states 717 * from the noirq phase of suspend. 718 */ 719 for (qinst = inst->qinsts, i = 0; i < inst->num_valid_queues; qinst++, i++) { 720 if (!qinst->is_tx) 721 ti_msgmgr_queue_rx_set_polled_mode(qinst, true); 722 } 723 724 return 0; 725} 726 727static int ti_msgmgr_resume(struct device *dev) 728{ 729 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev); 730 struct ti_queue_inst *qinst; 731 int i; 732 733 for (qinst = inst->qinsts, i = 0; i < inst->num_valid_queues; qinst++, i++) { 734 if (!qinst->is_tx) 735 ti_msgmgr_queue_rx_set_polled_mode(qinst, false); 736 } 737 738 return 0; 739} 740 741static DEFINE_SIMPLE_DEV_PM_OPS(ti_msgmgr_pm_ops, ti_msgmgr_suspend, ti_msgmgr_resume); 742 |
|
655/* Queue operations */ 656static const struct mbox_chan_ops ti_msgmgr_chan_ops = { 657 .startup = ti_msgmgr_queue_startup, 658 .shutdown = ti_msgmgr_queue_shutdown, 659 .peek_data = ti_msgmgr_queue_peek_data, 660 .last_tx_done = ti_msgmgr_last_tx_done, 661 .send_data = ti_msgmgr_send_data, 662}; --- 171 unchanged lines hidden (view full) --- 834 return ret; 835} 836 837static struct platform_driver ti_msgmgr_driver = { 838 .probe = ti_msgmgr_probe, 839 .driver = { 840 .name = "ti-msgmgr", 841 .of_match_table = of_match_ptr(ti_msgmgr_of_match), | 743/* Queue operations */ 744static const struct mbox_chan_ops ti_msgmgr_chan_ops = { 745 .startup = ti_msgmgr_queue_startup, 746 .shutdown = ti_msgmgr_queue_shutdown, 747 .peek_data = ti_msgmgr_queue_peek_data, 748 .last_tx_done = ti_msgmgr_last_tx_done, 749 .send_data = ti_msgmgr_send_data, 750}; --- 171 unchanged lines hidden (view full) --- 922 return ret; 923} 924 925static struct platform_driver ti_msgmgr_driver = { 926 .probe = ti_msgmgr_probe, 927 .driver = { 928 .name = "ti-msgmgr", 929 .of_match_table = of_match_ptr(ti_msgmgr_of_match), |
930 .pm = &ti_msgmgr_pm_ops, |
|
842 }, 843}; 844module_platform_driver(ti_msgmgr_driver); 845 846MODULE_LICENSE("GPL v2"); 847MODULE_DESCRIPTION("TI message manager driver"); 848MODULE_AUTHOR("Nishanth Menon"); 849MODULE_ALIAS("platform:ti-msgmgr"); | 931 }, 932}; 933module_platform_driver(ti_msgmgr_driver); 934 935MODULE_LICENSE("GPL v2"); 936MODULE_DESCRIPTION("TI message manager driver"); 937MODULE_AUTHOR("Nishanth Menon"); 938MODULE_ALIAS("platform:ti-msgmgr"); |