cregit-Linux how code gets into the kernel

Release 4.16 drivers/slimbus/qcom-ctrl.c

Directory: drivers/slimbus
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2011-2017, The Linux Foundation
 */

#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include "slimbus.h"

/* Manager registers */

#define	MGR_CFG		0x200

#define	MGR_STATUS	0x204

#define	MGR_INT_EN	0x210

#define	MGR_INT_STAT	0x214

#define	MGR_INT_CLR	0x218

#define	MGR_TX_MSG	0x230

#define	MGR_RX_MSG	0x270

#define	MGR_IE_STAT	0x2F0

#define	MGR_VE_STAT	0x300

#define	MGR_CFG_ENABLE	1

/* Framer registers */

#define	FRM_CFG		0x400

#define	FRM_STAT	0x404

#define	FRM_INT_EN	0x410

#define	FRM_INT_STAT	0x414

#define	FRM_INT_CLR	0x418

#define	FRM_WAKEUP	0x41C

#define	FRM_CLKCTL_DONE	0x420

#define	FRM_IE_STAT	0x430

#define	FRM_VE_STAT	0x440

/* Interface registers */

#define	INTF_CFG	0x600

#define	INTF_STAT	0x604

#define	INTF_INT_EN	0x610

#define	INTF_INT_STAT	0x614

#define	INTF_INT_CLR	0x618

#define	INTF_IE_STAT	0x630

#define	INTF_VE_STAT	0x640

/* Interrupt status bits */

#define	MGR_INT_TX_NACKED_2	BIT(25)

#define	MGR_INT_MSG_BUF_CONTE	BIT(26)

#define	MGR_INT_RX_MSG_RCVD	BIT(30)

#define	MGR_INT_TX_MSG_SENT	BIT(31)

/* Framer config register settings */

#define	FRM_ACTIVE	1

#define	CLK_GEAR	7

#define	ROOT_FREQ	11

#define	REF_CLK_GEAR	15

#define	INTR_WAKE	19


#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))


#define SLIM_ROOT_FREQ 24576000

#define QCOM_SLIM_AUTOSUSPEND 1000

/* MAX message size over control channel */

#define SLIM_MSGQ_BUF_LEN	40

#define QCOM_TX_MSGS 2

#define QCOM_RX_MSGS	8

#define QCOM_BUF_ALLOC_RETRIES	10


#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))

/* V2 Component registers */

#define CFG_PORT_V2(r) ((r ## _V2))

#define	COMP_CFG_V2		4

#define	COMP_TRUST_CFG_V2	0x3000

/* V1 Component registers */

#define CFG_PORT_V1(r) ((r ## _V1))

#define	COMP_CFG_V1		0

#define	COMP_TRUST_CFG_V1	0x14

/* Resource group info for manager, and non-ported generic device-components */

#define EE_MGR_RSC_GRP	(1 << 10)

#define EE_NGD_2	(2 << 6)

#define EE_NGD_1	0


struct slim_ctrl_buf {
	
void		*base;
	
spinlock_t	lock;
	
int		head;
	
int		tail;
	
int		sl_sz;
	
int		n;
};


struct qcom_slim_ctrl {
	
struct slim_controller  ctrl;
	
struct slim_framer	framer;
	
struct device		*dev;
	
void __iomem		*base;
	
void __iomem		*slew_reg;

	
struct slim_ctrl_buf	rx;
	
struct slim_ctrl_buf	tx;

	
struct completion	**wr_comp;
	
int			irq;
	
struct workqueue_struct *rxwq;
	
struct work_struct	wd;
	
struct clk		*rclk;
	
struct clk		*hclk;
};


static void qcom_slim_queue_tx(struct qcom_slim_ctrl *ctrl, void *buf, u8 len, u32 tx_reg) { int count = (len + 3) >> 2; __iowrite32_copy(ctrl->base + tx_reg, buf, count); /* Ensure Oder of subsequent writes */ mb(); }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia49100.00%1100.00%
Total49100.00%1100.00%


static void *slim_alloc_rxbuf(struct qcom_slim_ctrl *ctrl) { unsigned long flags; int idx; spin_lock_irqsave(&ctrl->rx.lock, flags); if ((ctrl->rx.tail + 1) % ctrl->rx.n == ctrl->rx.head) { spin_unlock_irqrestore(&ctrl->rx.lock, flags); dev_err(ctrl->dev, "RX QUEUE full!"); return NULL; } idx = ctrl->rx.tail; ctrl->rx.tail = (ctrl->rx.tail + 1) % ctrl->rx.n; spin_unlock_irqrestore(&ctrl->rx.lock, flags); return ctrl->rx.base + (idx * ctrl->rx.sl_sz); }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia140100.00%1100.00%
Total140100.00%1100.00%


static void slim_ack_txn(struct qcom_slim_ctrl *ctrl, int err) { struct completion *comp; unsigned long flags; int idx; spin_lock_irqsave(&ctrl->tx.lock, flags); idx = ctrl->tx.head; ctrl->tx.head = (ctrl->tx.head + 1) % ctrl->tx.n; spin_unlock_irqrestore(&ctrl->tx.lock, flags); comp = ctrl->wr_comp[idx]; ctrl->wr_comp[idx] = NULL; complete(comp); }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia10299.03%150.00%
Colin Ian King10.97%150.00%
Total103100.00%2100.00%


static irqreturn_t qcom_slim_handle_tx_irq(struct qcom_slim_ctrl *ctrl, u32 stat) { int err = 0; if (stat & MGR_INT_TX_MSG_SENT) writel_relaxed(MGR_INT_TX_MSG_SENT, ctrl->base + MGR_INT_CLR); if (stat & MGR_INT_TX_NACKED_2) { u32 mgr_stat = readl_relaxed(ctrl->base + MGR_STATUS); u32 mgr_ie_stat = readl_relaxed(ctrl->base + MGR_IE_STAT); u32 frm_stat = readl_relaxed(ctrl->base + FRM_STAT); u32 frm_cfg = readl_relaxed(ctrl->base + FRM_CFG); u32 frm_intr_stat = readl_relaxed(ctrl->base + FRM_INT_STAT); u32 frm_ie_stat = readl_relaxed(ctrl->base + FRM_IE_STAT); u32 intf_stat = readl_relaxed(ctrl->base + INTF_STAT); u32 intf_intr_stat = readl_relaxed(ctrl->base + INTF_INT_STAT); u32 intf_ie_stat = readl_relaxed(ctrl->base + INTF_IE_STAT); writel_relaxed(MGR_INT_TX_NACKED_2, ctrl->base + MGR_INT_CLR); dev_err(ctrl->dev, "TX Nack MGR:int:0x%x, stat:0x%x\n", stat, mgr_stat); dev_err(ctrl->dev, "TX Nack MGR:ie:0x%x\n", mgr_ie_stat); dev_err(ctrl->dev, "TX Nack FRM:int:0x%x, stat:0x%x\n", frm_intr_stat, frm_stat); dev_err(ctrl->dev, "TX Nack FRM:cfg:0x%x, ie:0x%x\n", frm_cfg, frm_ie_stat); dev_err(ctrl->dev, "TX Nack INTF:intr:0x%x, stat:0x%x\n", intf_intr_stat, intf_stat); dev_err(ctrl->dev, "TX Nack INTF:ie:0x%x\n", intf_ie_stat); err = -ENOTCONN; } slim_ack_txn(ctrl, err); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia252100.00%1100.00%
Total252100.00%1100.00%


static irqreturn_t qcom_slim_handle_rx_irq(struct qcom_slim_ctrl *ctrl, u32 stat) { u32 *rx_buf, pkt[10]; bool q_rx = false; u8 mc, mt, len; pkt[0] = readl_relaxed(ctrl->base + MGR_RX_MSG); mt = SLIM_HEADER_GET_MT(pkt[0]); len = SLIM_HEADER_GET_RL(pkt[0]); mc = SLIM_HEADER_GET_MC(pkt[0]>>8); /* * this message cannot be handled by ISR, so * let work-queue handle it */ if (mt == SLIM_MSG_MT_CORE && mc == SLIM_MSG_MC_REPORT_PRESENT) { rx_buf = (u32 *)slim_alloc_rxbuf(ctrl); if (!rx_buf) { dev_err(ctrl->dev, "dropping RX:0x%x due to RX full\n", pkt[0]); goto rx_ret_irq; } rx_buf[0] = pkt[0]; } else { rx_buf = pkt; } __ioread32_copy(rx_buf + 1, ctrl->base + MGR_RX_MSG + 4, DIV_ROUND_UP(len, 4)); switch (mc) { case SLIM_MSG_MC_REPORT_PRESENT: q_rx = true; break; case SLIM_MSG_MC_REPLY_INFORMATION: case SLIM_MSG_MC_REPLY_VALUE: slim_msg_response(&ctrl->ctrl, (u8 *)(rx_buf + 1), (u8)(*rx_buf >> 24), (len - 4)); break; default: dev_err(ctrl->dev, "unsupported MC,%x MT:%x\n", mc, mt); break; } rx_ret_irq: writel(MGR_INT_RX_MSG_RCVD, ctrl->base + MGR_INT_CLR); if (q_rx) queue_work(ctrl->rxwq, &ctrl->wd); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia270100.00%1100.00%
Total270100.00%1100.00%


static irqreturn_t qcom_slim_interrupt(int irq, void *d) { struct qcom_slim_ctrl *ctrl = d; u32 stat = readl_relaxed(ctrl->base + MGR_INT_STAT); int ret = IRQ_NONE; if (stat & MGR_INT_TX_MSG_SENT || stat & MGR_INT_TX_NACKED_2) ret = qcom_slim_handle_tx_irq(ctrl, stat); if (stat & MGR_INT_RX_MSG_RCVD) ret = qcom_slim_handle_rx_irq(ctrl, stat); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia74100.00%1100.00%
Total74100.00%1100.00%


static int qcom_clk_pause_wakeup(struct slim_controller *sctrl) { struct qcom_slim_ctrl *ctrl = dev_get_drvdata(sctrl->dev); clk_prepare_enable(ctrl->hclk); clk_prepare_enable(ctrl->rclk); enable_irq(ctrl->irq); writel_relaxed(1, ctrl->base + FRM_WAKEUP); /* Make sure framer wakeup write goes through before ISR fires */ mb(); /* * HW Workaround: Currently, slave is reporting lost-sync messages * after SLIMbus comes out of clock pause. * Transaction with slave fail before slave reports that message * Give some time for that report to come * SLIMbus wakes up in clock gear 10 at 24.576MHz. With each superframe * being 250 usecs, we wait for 5-10 superframes here to ensure * we get the message */ usleep_range(1250, 2500); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia70100.00%1100.00%
Total70100.00%1100.00%


static void *slim_alloc_txbuf(struct qcom_slim_ctrl *ctrl, struct slim_msg_txn *txn, struct completion *done) { unsigned long flags; int idx; spin_lock_irqsave(&ctrl->tx.lock, flags); if (((ctrl->tx.head + 1) % ctrl->tx.n) == ctrl->tx.tail) { spin_unlock_irqrestore(&ctrl->tx.lock, flags); dev_err(ctrl->dev, "controller TX buf unavailable"); return NULL; } idx = ctrl->tx.tail; ctrl->wr_comp[idx] = done; ctrl->tx.tail = (ctrl->tx.tail + 1) % ctrl->tx.n; spin_unlock_irqrestore(&ctrl->tx.lock, flags); return ctrl->tx.base + (idx * ctrl->tx.sl_sz); }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia16099.38%150.00%
Colin Ian King10.62%150.00%
Total161100.00%2100.00%


static int qcom_xfer_msg(struct slim_controller *sctrl, struct slim_msg_txn *txn) { struct qcom_slim_ctrl *ctrl = dev_get_drvdata(sctrl->dev); DECLARE_COMPLETION_ONSTACK(done); void *pbuf = slim_alloc_txbuf(ctrl, txn, &done); unsigned long ms = txn->rl + HZ; u8 *puc; int ret = 0, timeout, retries = QCOM_BUF_ALLOC_RETRIES; u8 la = txn->la; u32 *head; /* HW expects length field to be excluded */ txn->rl--; /* spin till buffer is made available */ if (!pbuf) { while (retries--) { usleep_range(10000, 15000); pbuf = slim_alloc_txbuf(ctrl, txn, &done); if (pbuf) break; } } if (retries < 0 && !pbuf) return -ENOMEM; puc = (u8 *)pbuf; head = (u32 *)pbuf; if (txn->dt == SLIM_MSG_DEST_LOGICALADDR) { *head = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0, la); puc += 3; } else { *head = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1, la); puc += 2; } if (slim_tid_txn(txn->mt, txn->mc)) *(puc++) = txn->tid; if (slim_ec_txn(txn->mt, txn->mc)) { *(puc++) = (txn->ec & 0xFF); *(puc++) = (txn->ec >> 8) & 0xFF; } if (txn->msg && txn->msg->wbuf) memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes); qcom_slim_queue_tx(ctrl, head, txn->rl, MGR_TX_MSG); timeout = wait_for_completion_timeout(&done, msecs_to_jiffies(ms)); if (!timeout) { dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc, txn->mt); ret = -ETIMEDOUT; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia37599.47%150.00%
Colin Ian King20.53%150.00%
Total377100.00%2100.00%


static int qcom_set_laddr(struct slim_controller *sctrl, struct slim_eaddr *ead, u8 laddr) { struct qcom_slim_ctrl *ctrl = dev_get_drvdata(sctrl->dev); struct { __be16 manf_id; __be16 prod_code; u8 dev_index; u8 instance; u8 laddr; } __packed p; struct slim_val_inf msg = {0}; DEFINE_SLIM_EDEST_TXN(txn, SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS, 10, laddr, &msg); int ret; p.manf_id = cpu_to_be16(ead->manf_id); p.prod_code = cpu_to_be16(ead->prod_code); p.dev_index = ead->dev_index; p.instance = ead->instance; p.laddr = laddr; msg.wbuf = (void *)&p; msg.num_bytes = 7; ret = slim_do_transfer(&ctrl->ctrl, &txn); if (ret) dev_err(ctrl->dev, "set LA:0x%x failed:ret:%d\n", laddr, ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia171100.00%1100.00%
Total171100.00%1100.00%


static int slim_get_current_rxbuf(struct qcom_slim_ctrl *ctrl, void *buf) { unsigned long flags; spin_lock_irqsave(&ctrl->rx.lock, flags); if (ctrl->rx.tail == ctrl->rx.head) { spin_unlock_irqrestore(&ctrl->rx.lock, flags); return -ENODATA; } memcpy(buf, ctrl->rx.base + (ctrl->rx.head * ctrl->rx.sl_sz), ctrl->rx.sl_sz); ctrl->rx.head = (ctrl->rx.head + 1) % ctrl->rx.n; spin_unlock_irqrestore(&ctrl->rx.lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia131100.00%1100.00%
Total131100.00%1100.00%


static void qcom_slim_rxwq(struct work_struct *work) { u8 buf[SLIM_MSGQ_BUF_LEN]; u8 mc, mt, len; int ret; struct qcom_slim_ctrl *ctrl = container_of(work, struct qcom_slim_ctrl, wd); while ((slim_get_current_rxbuf(ctrl, buf)) != -ENODATA) { len = SLIM_HEADER_GET_RL(buf[0]); mt = SLIM_HEADER_GET_MT(buf[0]); mc = SLIM_HEADER_GET_MC(buf[1]); if (mt == SLIM_MSG_MT_CORE && mc == SLIM_MSG_MC_REPORT_PRESENT) { struct slim_eaddr ea; u8 laddr; ea.manf_id = be16_to_cpup((__be16 *)&buf[2]); ea.prod_code = be16_to_cpup((__be16 *)&buf[4]); ea.dev_index = buf[6]; ea.instance = buf[7]; ret = slim_device_report_present(&ctrl->ctrl, &ea, &laddr); if (ret < 0) dev_err(ctrl->dev, "assign laddr failed:%d\n", ret); } else { dev_err(ctrl->dev, "unexpected message:mc:%x, mt:%x\n", mc, mt); } } }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia208100.00%1100.00%
Total208100.00%1100.00%


static void qcom_slim_prg_slew(struct platform_device *pdev, struct qcom_slim_ctrl *ctrl) { struct resource *slew_mem; if (!ctrl->slew_reg) { /* SLEW RATE register for this SLIMbus */ slew_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slew"); ctrl->slew_reg = devm_ioremap(&pdev->dev, slew_mem->start, resource_size(slew_mem)); if (!ctrl->slew_reg) return; } writel_relaxed(1, ctrl->slew_reg); /* Make sure SLIMbus-slew rate enabling goes through */ wmb(); }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia84100.00%1100.00%
Total84100.00%1100.00%


static int qcom_slim_probe(struct platform_device *pdev) { struct qcom_slim_ctrl *ctrl; struct slim_controller *sctrl; struct resource *slim_mem; int ret, ver; ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; ctrl->hclk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(ctrl->hclk)) return PTR_ERR(ctrl->hclk); ctrl->rclk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(ctrl->rclk)) return PTR_ERR(ctrl->rclk); ret = clk_set_rate(ctrl->rclk, SLIM_ROOT_FREQ); if (ret) { dev_err(&pdev->dev, "ref-clock set-rate failed:%d\n", ret); return ret; } ctrl->irq = platform_get_irq(pdev, 0); if (!ctrl->irq) { dev_err(&pdev->dev, "no slimbus IRQ\n"); return -ENODEV; } sctrl = &ctrl->ctrl; sctrl->dev = &pdev->dev; ctrl->dev = &pdev->dev; platform_set_drvdata(pdev, ctrl); dev_set_drvdata(ctrl->dev, ctrl); slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); ctrl->base = devm_ioremap_resource(ctrl->dev, slim_mem); if (IS_ERR(ctrl->base)) { dev_err(&pdev->dev, "IOremap failed\n"); return PTR_ERR(ctrl->base); } sctrl->set_laddr = qcom_set_laddr; sctrl->xfer_msg = qcom_xfer_msg; sctrl->wakeup = qcom_clk_pause_wakeup; ctrl->tx.n = QCOM_TX_MSGS; ctrl->tx.sl_sz = SLIM_MSGQ_BUF_LEN; ctrl->rx.n = QCOM_RX_MSGS; ctrl->rx.sl_sz = SLIM_MSGQ_BUF_LEN; ctrl->wr_comp = kzalloc(sizeof(struct completion *) * QCOM_TX_MSGS, GFP_KERNEL); if (!ctrl->wr_comp) return -ENOMEM; spin_lock_init(&ctrl->rx.lock); spin_lock_init(&ctrl->tx.lock); INIT_WORK(&ctrl->wd, qcom_slim_rxwq); ctrl->rxwq = create_singlethread_workqueue("qcom_slim_rx"); if (!ctrl->rxwq) { dev_err(ctrl->dev, "Failed to start Rx WQ\n"); return -ENOMEM; } ctrl->framer.rootfreq = SLIM_ROOT_FREQ / 8; ctrl->framer.superfreq = ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8; sctrl->a_framer = &ctrl->framer; sctrl->clkgear = SLIM_MAX_CLK_GEAR; qcom_slim_prg_slew(pdev, ctrl); ret = devm_request_irq(&pdev->dev, ctrl->irq, qcom_slim_interrupt, IRQF_TRIGGER_HIGH, "qcom_slim_irq", ctrl); if (ret) { dev_err(&pdev->dev, "request IRQ failed\n"); goto err_request_irq_failed; } ret = clk_prepare_enable(ctrl->hclk); if (ret) goto err_hclk_enable_failed; ret = clk_prepare_enable(ctrl->rclk); if (ret) goto err_rclk_enable_failed; ctrl->tx.base = devm_kcalloc(&pdev->dev, ctrl->tx.n, ctrl->tx.sl_sz, GFP_KERNEL); if (!ctrl->tx.base) { ret = -ENOMEM; goto err; } ctrl->rx.base = devm_kcalloc(&pdev->dev,ctrl->rx.n, ctrl->rx.sl_sz, GFP_KERNEL); if (!ctrl->rx.base) { ret = -ENOMEM; goto err; } /* Register with framework before enabling frame, clock */ ret = slim_register_controller(&ctrl->ctrl); if (ret) { dev_err(ctrl->dev, "error adding controller\n"); goto err; } ver = readl_relaxed(ctrl->base); /* Version info in 16 MSbits */ ver >>= 16; /* Component register initialization */ writel(1, ctrl->base + CFG_PORT(COMP_CFG, ver)); writel((EE_MGR_RSC_GRP | EE_NGD_2 | EE_NGD_1), ctrl->base + CFG_PORT(COMP_TRUST_CFG, ver)); writel((MGR_INT_TX_NACKED_2 | MGR_INT_MSG_BUF_CONTE | MGR_INT_RX_MSG_RCVD | MGR_INT_TX_MSG_SENT), ctrl->base + MGR_INT_EN); writel(1, ctrl->base + MGR_CFG); /* Framer register initialization */ writel((1 << INTR_WAKE) | (0xA << REF_CLK_GEAR) | (0xA << CLK_GEAR) | (1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1, ctrl->base + FRM_CFG); writel(MGR_CFG_ENABLE, ctrl->base + MGR_CFG); writel(1, ctrl->base + INTF_CFG); writel(1, ctrl->base + CFG_PORT(COMP_CFG, ver)); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, QCOM_SLIM_AUTOSUSPEND); pm_runtime_set_active(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_enable(&pdev->dev); dev_dbg(ctrl->dev, "QCOM SB controller is up:ver:0x%x!\n", ver); return 0; err: clk_disable_unprepare(ctrl->rclk); err_rclk_enable_failed: clk_disable_unprepare(ctrl->hclk); err_hclk_enable_failed: err_request_irq_failed: destroy_workqueue(ctrl->rxwq); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia90098.58%250.00%
Wei Yongjun90.99%125.00%
Arnd Bergmann40.44%125.00%
Total913100.00%4100.00%


static int qcom_slim_remove(struct platform_device *pdev) { struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); slim_unregister_controller(&ctrl->ctrl); destroy_workqueue(ctrl->rxwq); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia47100.00%2100.00%
Total47100.00%2100.00%

/* * If PM_RUNTIME is not defined, these 2 functions become helper * functions to be called from system suspend/resume. */ #ifdef CONFIG_PM
static int qcom_slim_runtime_suspend(struct device *device) { struct platform_device *pdev = to_platform_device(device); struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); int ret; dev_dbg(device, "pm_runtime: suspending...\n"); ret = slim_ctrl_clk_pause(&ctrl->ctrl, false, SLIM_CLK_UNSPECIFIED); if (ret) { dev_err(device, "clk pause not entered:%d", ret); } else { disable_irq(ctrl->irq); clk_disable_unprepare(ctrl->hclk); clk_disable_unprepare(ctrl->rclk); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia97100.00%2100.00%
Total97100.00%2100.00%


static int qcom_slim_runtime_resume(struct device *device) { struct platform_device *pdev = to_platform_device(device); struct qcom_slim_ctrl *ctrl = platform_get_drvdata(pdev); int ret = 0; dev_dbg(device, "pm_runtime: resuming...\n"); ret = slim_ctrl_clk_pause(&ctrl->ctrl, true, 0); if (ret) dev_err(device, "clk pause not exited:%d", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia73100.00%2100.00%
Total73100.00%2100.00%

#endif #ifdef CONFIG_PM_SLEEP
static int qcom_slim_suspend(struct device *dev) { int ret = 0; if (!pm_runtime_enabled(dev) || (!pm_runtime_suspended(dev))) { dev_dbg(dev, "system suspend"); ret = qcom_slim_runtime_suspend(dev); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia51100.00%1100.00%
Total51100.00%1100.00%


static int qcom_slim_resume(struct device *dev) { if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) { int ret; dev_dbg(dev, "system resume"); ret = qcom_slim_runtime_resume(dev); if (!ret) { pm_runtime_mark_last_busy(dev); pm_request_autosuspend(dev); } return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia67100.00%2100.00%
Total67100.00%2100.00%

#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops qcom_slim_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(qcom_slim_suspend, qcom_slim_resume) SET_RUNTIME_PM_OPS( qcom_slim_runtime_suspend, qcom_slim_runtime_resume, NULL ) }; static const struct of_device_id qcom_slim_dt_match[] = { { .compatible = "qcom,slim", }, { .compatible = "qcom,apq8064-slim", }, {} }; static struct platform_driver qcom_slim_driver = { .probe = qcom_slim_probe, .remove = qcom_slim_remove, .driver = { .name = "qcom_slim_ctrl", .of_match_table = qcom_slim_dt_match, .pm = &qcom_slim_dev_pm_ops, }, }; module_platform_driver(qcom_slim_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Qualcomm SLIMbus Controller");

Overall Contributors

PersonTokensPropCommitsCommitProp
Sagar Dharia380099.55%233.33%
Wei Yongjun90.24%116.67%
Arnd Bergmann40.10%116.67%
Colin Ian King40.10%233.33%
Total3817100.00%6100.00%
Directory: drivers/slimbus
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.