qcom-ctrl.c (ad7fcbc308b050e3c27c545021663d2cd73f8b23) | qcom-ctrl.c (c088c335b49228ca1759dca5676f1534b0ac13a5) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2011-2017, The Linux Foundation 4 */ 5 6#include <linux/irq.h> 7#include <linux/kernel.h> 8#include <linux/init.h> 9#include <linux/slab.h> 10#include <linux/io.h> 11#include <linux/interrupt.h> 12#include <linux/platform_device.h> 13#include <linux/delay.h> 14#include <linux/clk.h> 15#include <linux/of.h> 16#include <linux/dma-mapping.h> | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2011-2017, The Linux Foundation 4 */ 5 6#include <linux/irq.h> 7#include <linux/kernel.h> 8#include <linux/init.h> 9#include <linux/slab.h> 10#include <linux/io.h> 11#include <linux/interrupt.h> 12#include <linux/platform_device.h> 13#include <linux/delay.h> 14#include <linux/clk.h> 15#include <linux/of.h> 16#include <linux/dma-mapping.h> |
17#include <linux/pm_runtime.h> |
|
17#include "slimbus.h" 18 19/* Manager registers */ 20#define MGR_CFG 0x200 21#define MGR_STATUS 0x204 22#define MGR_INT_EN 0x210 23#define MGR_INT_STAT 0x214 24#define MGR_INT_CLR 0x218 --- 35 unchanged lines hidden (view full) --- 60#define ROOT_FREQ 11 61#define REF_CLK_GEAR 15 62#define INTR_WAKE 19 63 64#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \ 65 ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16)) 66 67#define SLIM_ROOT_FREQ 24576000 | 18#include "slimbus.h" 19 20/* Manager registers */ 21#define MGR_CFG 0x200 22#define MGR_STATUS 0x204 23#define MGR_INT_EN 0x210 24#define MGR_INT_STAT 0x214 25#define MGR_INT_CLR 0x218 --- 35 unchanged lines hidden (view full) --- 61#define ROOT_FREQ 11 62#define REF_CLK_GEAR 15 63#define INTR_WAKE 19 64 65#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \ 66 ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16)) 67 68#define SLIM_ROOT_FREQ 24576000 |
69#define QCOM_SLIM_AUTOSUSPEND 1000 |
|
68 69/* MAX message size over control channel */ 70#define SLIM_MSGQ_BUF_LEN 40 71#define QCOM_TX_MSGS 2 72#define QCOM_RX_MSGS 8 73#define QCOM_BUF_ALLOC_RETRIES 10 74 75#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r)) --- 194 unchanged lines hidden (view full) --- 270 ret = qcom_slim_handle_tx_irq(ctrl, stat); 271 272 if (stat & MGR_INT_RX_MSG_RCVD) 273 ret = qcom_slim_handle_rx_irq(ctrl, stat); 274 275 return ret; 276} 277 | 70 71/* MAX message size over control channel */ 72#define SLIM_MSGQ_BUF_LEN 40 73#define QCOM_TX_MSGS 2 74#define QCOM_RX_MSGS 8 75#define QCOM_BUF_ALLOC_RETRIES 10 76 77#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r)) --- 194 unchanged lines hidden (view full) --- 272 ret = qcom_slim_handle_tx_irq(ctrl, stat); 273 274 if (stat & MGR_INT_RX_MSG_RCVD) 275 ret = qcom_slim_handle_rx_irq(ctrl, stat); 276 277 return ret; 278} 279 |
280static int qcom_clk_pause_wakeup(struct slim_controller *sctrl) 281{ 282 struct qcom_slim_ctrl *ctrl = dev_get_drvdata(sctrl->dev); 283 284 clk_prepare_enable(ctrl->hclk); 285 clk_prepare_enable(ctrl->rclk); 286 enable_irq(ctrl->irq); 287 288 writel_relaxed(1, ctrl->base + FRM_WAKEUP); 289 /* Make sure framer wakeup write goes through before ISR fires */ 290 mb(); 291 /* 292 * HW Workaround: Currently, slave is reporting lost-sync messages 293 * after SLIMbus comes out of clock pause. 294 * Transaction with slave fail before slave reports that message 295 * Give some time for that report to come 296 * SLIMbus wakes up in clock gear 10 at 24.576MHz. With each superframe 297 * being 250 usecs, we wait for 5-10 superframes here to ensure 298 * we get the message 299 */ 300 usleep_range(1250, 2500); 301 return 0; 302} 303 |
|
278void *slim_alloc_txbuf(struct qcom_slim_ctrl *ctrl, struct slim_msg_txn *txn, 279 struct completion *done) 280{ 281 unsigned long flags; 282 int idx; 283 284 spin_lock_irqsave(&ctrl->tx.lock, flags); 285 if (((ctrl->tx.head + 1) % ctrl->tx.n) == ctrl->tx.tail) { --- 220 unchanged lines hidden (view full) --- 506 ctrl->base = devm_ioremap_resource(ctrl->dev, slim_mem); 507 if (!ctrl->base) { 508 dev_err(&pdev->dev, "IOremap failed\n"); 509 return -ENOMEM; 510 } 511 512 sctrl->set_laddr = qcom_set_laddr; 513 sctrl->xfer_msg = qcom_xfer_msg; | 304void *slim_alloc_txbuf(struct qcom_slim_ctrl *ctrl, struct slim_msg_txn *txn, 305 struct completion *done) 306{ 307 unsigned long flags; 308 int idx; 309 310 spin_lock_irqsave(&ctrl->tx.lock, flags); 311 if (((ctrl->tx.head + 1) % ctrl->tx.n) == ctrl->tx.tail) { --- 220 unchanged lines hidden (view full) --- 532 ctrl->base = devm_ioremap_resource(ctrl->dev, slim_mem); 533 if (!ctrl->base) { 534 dev_err(&pdev->dev, "IOremap failed\n"); 535 return -ENOMEM; 536 } 537 538 sctrl->set_laddr = qcom_set_laddr; 539 sctrl->xfer_msg = qcom_xfer_msg; |
540 sctrl->wakeup = qcom_clk_pause_wakeup; |
|
514 ctrl->tx.n = QCOM_TX_MSGS; 515 ctrl->tx.sl_sz = SLIM_MSGQ_BUF_LEN; 516 ctrl->rx.n = QCOM_RX_MSGS; 517 ctrl->rx.sl_sz = SLIM_MSGQ_BUF_LEN; 518 ctrl->wr_comp = kzalloc(sizeof(struct completion *) * QCOM_TX_MSGS, 519 GFP_KERNEL); 520 if (!ctrl->wr_comp) 521 return -ENOMEM; --- 91 unchanged lines hidden (view full) --- 613 destroy_workqueue(ctrl->rxwq); 614 return ret; 615} 616 617static int qcom_slim_remove(struct platform_device *pdev) 618{ 619 struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); 620 | 541 ctrl->tx.n = QCOM_TX_MSGS; 542 ctrl->tx.sl_sz = SLIM_MSGQ_BUF_LEN; 543 ctrl->rx.n = QCOM_RX_MSGS; 544 ctrl->rx.sl_sz = SLIM_MSGQ_BUF_LEN; 545 ctrl->wr_comp = kzalloc(sizeof(struct completion *) * QCOM_TX_MSGS, 546 GFP_KERNEL); 547 if (!ctrl->wr_comp) 548 return -ENOMEM; --- 91 unchanged lines hidden (view full) --- 640 destroy_workqueue(ctrl->rxwq); 641 return ret; 642} 643 644static int qcom_slim_remove(struct platform_device *pdev) 645{ 646 struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); 647 |
621 disable_irq(ctrl->irq); 622 clk_disable_unprepare(ctrl->hclk); 623 clk_disable_unprepare(ctrl->rclk); | 648 pm_runtime_disable(&pdev->dev); |
624 slim_unregister_controller(&ctrl->ctrl); 625 destroy_workqueue(ctrl->rxwq); 626 return 0; 627} 628 | 649 slim_unregister_controller(&ctrl->ctrl); 650 destroy_workqueue(ctrl->rxwq); 651 return 0; 652} 653 |
654/* 655 * If PM_RUNTIME is not defined, these 2 functions become helper 656 * functions to be called from system suspend/resume. 657 */ 658#ifdef CONFIG_PM 659static int qcom_slim_runtime_suspend(struct device *device) 660{ 661 struct platform_device *pdev = to_platform_device(device); 662 struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); 663 int ret; 664 665 dev_dbg(device, "pm_runtime: suspending...\n"); 666 ret = slim_ctrl_clk_pause(&ctrl->ctrl, false, SLIM_CLK_UNSPECIFIED); 667 if (ret) { 668 dev_err(device, "clk pause not entered:%d", ret); 669 } else { 670 disable_irq(ctrl->irq); 671 clk_disable_unprepare(ctrl->hclk); 672 clk_disable_unprepare(ctrl->rclk); 673 } 674 return ret; 675} 676 677static int qcom_slim_runtime_resume(struct device *device) 678{ 679 struct platform_device *pdev = to_platform_device(device); 680 struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); 681 int ret = 0; 682 683 dev_dbg(device, "pm_runtime: resuming...\n"); 684 ret = slim_ctrl_clk_pause(&ctrl->ctrl, true, 0); 685 if (ret) 686 dev_err(device, "clk pause not exited:%d", ret); 687 return ret; 688} 689#endif 690 691#ifdef CONFIG_PM_SLEEP 692static int qcom_slim_suspend(struct device *dev) 693{ 694 int ret = 0; 695 696 if (!pm_runtime_enabled(dev) || 697 (!pm_runtime_suspended(dev))) { 698 dev_dbg(dev, "system suspend"); 699 ret = qcom_slim_runtime_suspend(dev); 700 } 701 702 return ret; 703} 704 705static int qcom_slim_resume(struct device *dev) 706{ 707 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) { 708 int ret; 709 710 dev_dbg(dev, "system resume"); 711 ret = qcom_slim_runtime_resume(dev); 712 if (!ret) { 713 pm_runtime_mark_last_busy(dev); 714 pm_request_autosuspend(dev); 715 } 716 return ret; 717 718 } 719 return 0; 720} 721#endif /* CONFIG_PM_SLEEP */ 722 |
|
629static const struct dev_pm_ops qcom_slim_dev_pm_ops = { 630 SET_SYSTEM_SLEEP_PM_OPS(qcom_slim_suspend, qcom_slim_resume) 631 SET_RUNTIME_PM_OPS( 632 qcom_slim_runtime_suspend, 633 qcom_slim_runtime_resume, 634 NULL 635 ) 636}; --- 5 unchanged lines hidden (view full) --- 642}; 643 644static struct platform_driver qcom_slim_driver = { 645 .probe = qcom_slim_probe, 646 .remove = qcom_slim_remove, 647 .driver = { 648 .name = "qcom_slim_ctrl", 649 .of_match_table = qcom_slim_dt_match, | 723static const struct dev_pm_ops qcom_slim_dev_pm_ops = { 724 SET_SYSTEM_SLEEP_PM_OPS(qcom_slim_suspend, qcom_slim_resume) 725 SET_RUNTIME_PM_OPS( 726 qcom_slim_runtime_suspend, 727 qcom_slim_runtime_resume, 728 NULL 729 ) 730}; --- 5 unchanged lines hidden (view full) --- 736}; 737 738static struct platform_driver qcom_slim_driver = { 739 .probe = qcom_slim_probe, 740 .remove = qcom_slim_remove, 741 .driver = { 742 .name = "qcom_slim_ctrl", 743 .of_match_table = qcom_slim_dt_match, |
744 .pm = &qcom_slim_dev_pm_ops, |
|
650 }, 651}; 652module_platform_driver(qcom_slim_driver); 653 654MODULE_LICENSE("GPL v2"); 655MODULE_DESCRIPTION("Qualcomm SLIMbus Controller"); | 745 }, 746}; 747module_platform_driver(qcom_slim_driver); 748 749MODULE_LICENSE("GPL v2"); 750MODULE_DESCRIPTION("Qualcomm SLIMbus Controller"); |