blob: 818d169cc029e86cb769e6b427461604503d07fa [file] [log] [blame]
Sagar Dharia32379162013-12-12 00:46:37 -07001/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
Sagar Dharia71fcea52012-09-12 23:21:57 -06002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Sagar Dharia71fcea52012-09-12 23:21:57 -060012#include <linux/irq.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/io.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
20#include <linux/slimbus/slimbus.h>
21#include <linux/delay.h>
22#include <linux/kthread.h>
23#include <linux/clk.h>
24#include <linux/pm_runtime.h>
25#include <linux/of.h>
26#include <linux/of_slimbus.h>
27#include <linux/timer.h>
28#include <mach/sps.h>
29#include "slim-msm.h"
30#include <mach/qdsp6v2/apr.h>
31
32#define NGD_SLIM_NAME "ngd_msm_ctrl"
33#define SLIM_LA_MGR 0xFF
34#define SLIM_ROOT_FREQ 24576000
Sagar Dharia33beca02012-10-22 16:21:46 -060035#define LADDR_RETRY 5
Sagar Dharia71fcea52012-09-12 23:21:57 -060036
37#define NGD_BASE_V1(r) (((r) % 2) ? 0x800 : 0xA00)
38#define NGD_BASE_V2(r) (((r) % 2) ? 0x1000 : 0x2000)
39#define NGD_BASE(r, v) ((v) ? NGD_BASE_V2(r) : NGD_BASE_V1(r))
40/* NGD (Non-ported Generic Device) registers */
41enum ngd_reg {
42 NGD_CFG = 0x0,
43 NGD_STATUS = 0x4,
44 NGD_RX_MSGQ_CFG = 0x8,
45 NGD_INT_EN = 0x10,
46 NGD_INT_STAT = 0x14,
47 NGD_INT_CLR = 0x18,
48 NGD_TX_MSG = 0x30,
49 NGD_RX_MSG = 0x70,
50 NGD_IE_STAT = 0xF0,
51 NGD_VE_STAT = 0x100,
52};
53
54enum ngd_msg_cfg {
55 NGD_CFG_ENABLE = 1,
56 NGD_CFG_RX_MSGQ_EN = 1 << 1,
57 NGD_CFG_TX_MSGQ_EN = 1 << 2,
58};
59
60enum ngd_intr {
61 NGD_INT_RECFG_DONE = 1 << 24,
62 NGD_INT_TX_NACKED_2 = 1 << 25,
63 NGD_INT_MSG_BUF_CONTE = 1 << 26,
64 NGD_INT_MSG_TX_INVAL = 1 << 27,
65 NGD_INT_IE_VE_CHG = 1 << 28,
66 NGD_INT_DEV_ERR = 1 << 29,
67 NGD_INT_RX_MSG_RCVD = 1 << 30,
68 NGD_INT_TX_MSG_SENT = 1 << 31,
69};
70
71enum ngd_offsets {
72 NGD_NACKED_MC = 0x7F00000,
73 NGD_ACKED_MC = 0xFE000,
74 NGD_ERROR = 0x1800,
75 NGD_MSGQ_SUPPORT = 0x400,
76 NGD_RX_MSGQ_TIME_OUT = 0x16,
77 NGD_ENUMERATED = 0x1,
78 NGD_TX_BUSY = 0x0,
79};
80
Sagar Dharia33beca02012-10-22 16:21:46 -060081enum ngd_status {
82 NGD_LADDR = 1 << 1,
83};
84
85static int ngd_slim_runtime_resume(struct device *device);
86
Sagar Dharia71fcea52012-09-12 23:21:57 -060087static irqreturn_t ngd_slim_interrupt(int irq, void *d)
88{
89 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)d;
90 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
91 u32 stat = readl_relaxed(ngd + NGD_INT_STAT);
Sagar Dharia2b8a4b52013-05-15 20:01:45 -060092 u32 pstat;
Sagar Dharia71fcea52012-09-12 23:21:57 -060093
94 if (stat & NGD_INT_TX_MSG_SENT) {
95 writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
96 /* Make sure interrupt is cleared */
97 mb();
98 if (dev->wr_comp)
99 complete(dev->wr_comp);
100 } else if ((stat & NGD_INT_MSG_BUF_CONTE) ||
101 (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
102 (stat & NGD_INT_TX_NACKED_2)) {
103 dev_err(dev->dev, "NGD interrupt error:0x%x", stat);
104 writel_relaxed(stat, ngd + NGD_INT_CLR);
105 /* Guarantee that error interrupts are cleared */
106 mb();
107 if (((stat & NGD_INT_TX_NACKED_2) ||
108 (stat & NGD_INT_MSG_TX_INVAL))) {
109 dev->err = -EIO;
110 if (dev->wr_comp)
111 complete(dev->wr_comp);
112 }
113 }
114 if (stat & NGD_INT_RX_MSG_RCVD) {
115 u32 rx_buf[10];
116 u8 len, i;
117 rx_buf[0] = readl_relaxed(ngd + NGD_RX_MSG);
118 len = rx_buf[0] & 0x1F;
119 for (i = 1; i < ((len + 3) >> 2); i++) {
120 rx_buf[i] = readl_relaxed(ngd + NGD_RX_MSG +
121 (4 * i));
122 dev_dbg(dev->dev, "REG-RX data: %x\n", rx_buf[i]);
123 }
124 msm_slim_rx_enqueue(dev, rx_buf, len);
125 writel_relaxed(NGD_INT_RX_MSG_RCVD,
126 ngd + NGD_INT_CLR);
127 /*
128 * Guarantee that CLR bit write goes through before
129 * queuing work
130 */
131 mb();
Sagar Dharia24419e32013-01-14 17:56:32 -0700132 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600133 dev_err(dev->dev,
134 "direct message received even with RX MSGQs");
135 else
136 complete(&dev->rx_msgq_notify);
137 }
138 if (stat & NGD_INT_RECFG_DONE) {
139 writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
140 /* Guarantee RECONFIG DONE interrupt is cleared */
141 mb();
142 /* In satellite mode, just log the reconfig done IRQ */
143 dev_dbg(dev->dev, "reconfig done IRQ for NGD");
144 }
145 if (stat & NGD_INT_IE_VE_CHG) {
146 writel_relaxed(NGD_INT_IE_VE_CHG, ngd + NGD_INT_CLR);
147 /* Guarantee IE VE change interrupt is cleared */
148 mb();
149 dev_err(dev->dev, "NGD IE VE change");
150 }
Sagar Dharia2b8a4b52013-05-15 20:01:45 -0600151
152 pstat = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_ST_EEn, dev->ver));
153 if (pstat != 0)
154 return msm_slim_port_irq_handler(dev, pstat);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600155 return IRQ_HANDLED;
156}
157
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700158static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
159 void *_cmd)
160{
161 struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
Sagar Dharia33beca02012-10-22 16:21:46 -0600162 struct msm_slim_ctrl *dev =
163 container_of(qmi, struct msm_slim_ctrl, qmi);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700164 pr_info("Slimbus QMI NGD CB received event:%ld", code);
165 switch (code) {
166 case QMI_SERVER_ARRIVE:
Sagar Dharia33beca02012-10-22 16:21:46 -0600167 schedule_work(&qmi->ssr_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700168 break;
169 case QMI_SERVER_EXIT:
Sagar Dharia33beca02012-10-22 16:21:46 -0600170 dev->state = MSM_CTRL_DOWN;
171 /* make sure autosuspend is not called until ADSP comes up*/
172 pm_runtime_get_noresume(dev->dev);
173 /* Reset ctrl_up completion */
174 init_completion(&dev->ctrl_up);
175 schedule_work(&qmi->ssr_down);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700176 break;
177 default:
178 break;
179 }
180 return 0;
181}
182
Sagar Dharia71fcea52012-09-12 23:21:57 -0600183static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
184 u8 *tid, struct completion *done)
185{
186 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700187 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600188 if (ctrl->last_tid <= 255) {
189 ctrl->txnt = krealloc(ctrl->txnt,
190 (ctrl->last_tid + 1) *
191 sizeof(struct slim_msg_txn *),
192 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700193 if (!ctrl->txnt) {
194 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600195 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700196 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600197 dev->msg_cnt = ctrl->last_tid;
198 ctrl->last_tid++;
199 } else {
200 int i;
201 for (i = 0; i < 256; i++) {
202 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
203 if (ctrl->txnt[dev->msg_cnt] == NULL)
204 break;
205 }
206 if (i >= 256) {
207 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700208 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600209 return -ENOMEM;
210 }
211 }
212 ctrl->txnt[dev->msg_cnt] = txn;
213 txn->tid = dev->msg_cnt;
214 txn->comp = done;
215 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700216 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600217 return 0;
218}
219static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
220{
221 DECLARE_COMPLETION_ONSTACK(done);
222 DECLARE_COMPLETION_ONSTACK(tx_sent);
223
224 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
225 u32 *pbuf;
226 u8 *puc;
227 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600228 u8 la = txn->la;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600229 u8 txn_mt;
230 u16 txn_mc = txn->mc;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600231 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600232
Sagar Dhariaa1398282013-01-22 13:26:20 -0700233 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
234 txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
235 /*
236 * Counter-part of system-suspend when runtime-pm is not enabled
237 * This way, resume can be left empty and device will be put in
238 * active mode only if client requests anything on the bus
239 * If the state was DOWN, SSR UP notification will take
240 * care of putting the device in active state.
241 */
242 ngd_slim_runtime_resume(dev->dev);
243 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600244 if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
245 SLIM_MSG_MC_RECONFIGURE_NOW)) &&
Sagar Dhariad1468b72013-07-16 12:56:22 -0600246 dev->state <= MSM_CTRL_IDLE) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600247 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
248 &dev->use_rx_msgqs);
249 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
250 &dev->use_tx_msgqs);
251 return msm_slim_qmi_power_request(dev, false);
Sagar Dharia24419e32013-01-14 17:56:32 -0700252 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700253 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
254 return 0;
255
Sagar Dharia71fcea52012-09-12 23:21:57 -0600256 if (txn->mt == SLIM_MSG_MT_CORE &&
257 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
258 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
259 return 0;
260 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600261 /* If txn is tried when controller is down, wait for ADSP to boot */
262 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
263 if (dev->state == MSM_CTRL_DOWN) {
264 u8 mc = (u8)txn->mc;
265 int timeout;
266 dev_err(dev->dev, "ADSP slimbus not up yet");
267 /*
268 * Messages related to data channel management can't
269 * wait since they are holding reconfiguration lock.
270 * clk_pause in resume (which can change state back to
Sagar Dharia32379162013-12-12 00:46:37 -0700271 * MSM_CTRL_AWAKE), will need that lock.
272 * Port disconnection, channel removal calls should pass
273 * through since there is no activity on the bus and
274 * those calls are triggered by clients due to
275 * device_down callback in that situation.
276 * Returning 0 on the disconnections and
277 * removals will ensure consistent state of channels,
278 * ports with the HW
Sagar Dharia55bced82014-01-20 16:00:44 -0700279 * Remote requests to remove channel/port will be
280 * returned from the path where they wait on
281 * acknowledgement from ADSP
Sagar Dharia33beca02012-10-22 16:21:46 -0600282 */
Sagar Dharia32379162013-12-12 00:46:37 -0700283 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
284 ((mc == SLIM_USR_MC_CHAN_CTRL ||
285 mc == SLIM_USR_MC_DISCONNECT_PORT ||
286 mc == SLIM_USR_MC_RECONFIG_NOW)))
Sagar Dharia55bced82014-01-20 16:00:44 -0700287 return -EREMOTEIO;
Sagar Dharia32379162013-12-12 00:46:37 -0700288 if ((txn->mt == SLIM_MSG_MT_CORE) &&
289 ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
290 mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
291 mc == SLIM_USR_MC_RECONFIG_NOW)))
292 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600293 if ((txn->mt == SLIM_MSG_MT_CORE) &&
294 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
295 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
296 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
297 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
298 return -EREMOTEIO;
299 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
300 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
Sagar Dharia32379162013-12-12 00:46:37 -0700301 mc < SLIM_USR_MC_DISCONNECT_PORT)))
Sagar Dharia33beca02012-10-22 16:21:46 -0600302 return -EREMOTEIO;
303 timeout = wait_for_completion_timeout(&dev->ctrl_up,
304 HZ);
Sagar Dharia4f240722014-01-15 13:50:58 -0700305 if (!timeout && dev->state == MSM_CTRL_DOWN)
Sagar Dharia33beca02012-10-22 16:21:46 -0600306 return -ETIMEDOUT;
307 }
Sagar Dharia129c7d82013-08-08 19:35:50 -0600308 ret = msm_slim_get_ctrl(dev);
309 /*
310 * Runtime-pm's callbacks are not called until runtime-pm's
311 * error status is cleared
312 * Setting runtime status to suspended clears the error
313 * It also makes HW status cosistent with what SW has it here
314 */
315 if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
316 pm_runtime_set_suspended(dev->dev);
317 msm_slim_put_ctrl(dev);
318 return -EREMOTEIO;
Sagar Dhariad1468b72013-07-16 12:56:22 -0600319 } else if (ret >= 0) {
320 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia129c7d82013-08-08 19:35:50 -0600321 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600322 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600323 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600324
Sagar Dharia71fcea52012-09-12 23:21:57 -0600325 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
Sagar Dharia33beca02012-10-22 16:21:46 -0600326 (dev->state != MSM_CTRL_AWAKE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600327 dev_err(dev->dev, "controller not ready");
328 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600329 msm_slim_put_ctrl(dev);
330 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600331 }
332 if (txn->mt == SLIM_MSG_MT_CORE &&
333 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
334 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
335 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
336 int i = 0;
337 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
338 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
339 txn->mc = SLIM_USR_MC_CONNECT_SRC;
340 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
341 txn->mc = SLIM_USR_MC_CONNECT_SINK;
342 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
343 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600344 if (txn->la == SLIM_LA_MGR) {
345 if (dev->pgdla == SLIM_LA_MGR) {
346 u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
347 QC_MFGID_LSB};
348 ea[2] = (u8)(dev->pdata.eapc & 0xFF);
349 ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
350 mutex_unlock(&dev->tx_lock);
351 ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
352 &dev->pgdla);
353 pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
354 ret);
355 if (ret) {
356 pr_err("Incorrect SLIM-PGD EAPC:0x%x",
357 dev->pdata.eapc);
358 return ret;
359 }
360 mutex_lock(&dev->tx_lock);
361 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600362 txn->la = dev->pgdla;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600363 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600364 wbuf[i++] = txn->la;
365 la = SLIM_LA_MGR;
366 wbuf[i++] = txn->wbuf[0];
367 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
368 wbuf[i++] = txn->wbuf[1];
369 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
370 if (ret) {
371 pr_err("TID for connect/disconnect fail:%d", ret);
372 goto ngd_xfer_err;
373 }
374 txn->len = i;
375 txn->wbuf = wbuf;
376 txn->rl = txn->len + 4;
377 }
378 txn->rl--;
379 pbuf = msm_get_msg_buf(dev, txn->rl);
380 if (!pbuf) {
381 dev_err(dev->dev, "Message buffer unavailable");
382 ret = -ENOMEM;
383 goto ngd_xfer_err;
384 }
385 dev->err = 0;
386
387 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
388 ret = -EPROTONOSUPPORT;
389 goto ngd_xfer_err;
390 }
391 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
392 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
393 la);
394 else
395 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
396 la);
397 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
398 puc = ((u8 *)pbuf) + 3;
399 else
400 puc = ((u8 *)pbuf) + 2;
401 if (txn->rbuf)
402 *(puc++) = txn->tid;
403 if ((txn->mt == SLIM_MSG_MT_CORE) &&
404 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
405 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
406 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
407 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
408 *(puc++) = (txn->ec & 0xFF);
409 *(puc++) = (txn->ec >> 8)&0xFF;
410 }
411 if (txn->wbuf)
412 memcpy(puc, txn->wbuf, txn->len);
413 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
414 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
415 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
416 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
417 wbuf[0] == dev->pgdla) {
Sagar Dharia2d74c142013-05-17 02:24:06 -0600418 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600419 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
420 else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600421 /*
422 * Remove channel disconnects master-side ports from
423 * channel. No need to send that again on the bus
Sagar Dharia2d74c142013-05-17 02:24:06 -0600424 * Only disable port
Sagar Dharia71fcea52012-09-12 23:21:57 -0600425 */
Sagar Dharia2d74c142013-05-17 02:24:06 -0600426 writel_relaxed(0, PGD_PORT(PGD_PORT_CFGn,
427 (wbuf[1] + dev->port_b), dev->ver));
Sagar Dharia71fcea52012-09-12 23:21:57 -0600428 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700429 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600430 return 0;
431 }
432 if (dev->err) {
433 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
434 goto ngd_xfer_err;
435 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600436 /* Add port-base to port number if this is manager side port */
437 puc[1] += dev->port_b;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600438 }
439 dev->err = 0;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600440 /*
441 * If it's a read txn, it may be freed if a response is received by
442 * received thread before reaching end of this function.
443 * mc, mt may have changed to convert standard slimbus code/type to
444 * satellite user-defined message. Reinitialize again
445 */
446 txn_mc = txn->mc;
447 txn_mt = txn->mt;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600448 dev->wr_comp = &tx_sent;
449 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
450 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
451 if (!ret) {
452 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600453 if (!timeout) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600454 ret = -ETIMEDOUT;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600455 /*
456 * disconnect/recoonect pipe so that subsequent
457 * transactions don't timeout due to unavailable
458 * descriptors
459 */
460 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
461 &dev->use_tx_msgqs);
462 msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
463 } else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600464 ret = dev->err;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600465 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600466 }
467 dev->wr_comp = NULL;
468 if (ret) {
469 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
470 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
471 dev->ver);
472 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600473 txn_mc, txn_mt, ret, dev->ver);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600474 conf = readl_relaxed(ngd);
475 stat = readl_relaxed(ngd + NGD_STATUS);
476 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
477 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
478 int_en = readl_relaxed(ngd + NGD_INT_EN);
479 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
480
481 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
482 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
483 int_en, int_clr);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600484 } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
485 (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
486 txn_mc == SLIM_USR_MC_CONNECT_SINK ||
487 txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600488 int timeout;
489 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700490 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600491 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600492 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600493 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600494 else
495 ret = txn->ec;
496 if (ret) {
497 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
498 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700499 mutex_lock(&ctrl->m_ctrl);
500 ctrl->txnt[txn->tid] = NULL;
501 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600502 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600503 return ret ? ret : dev->err;
504 }
505ngd_xfer_err:
506 mutex_unlock(&dev->tx_lock);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600507 if (txn_mc != SLIM_USR_MC_REPORT_SATELLITE)
Sagar Dharia33beca02012-10-22 16:21:46 -0600508 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600509 return ret ? ret : dev->err;
510}
511
512static int ngd_xferandwait_ack(struct slim_controller *ctrl,
513 struct slim_msg_txn *txn)
514{
515 int ret = ngd_xfer_msg(ctrl, txn);
516 if (!ret) {
517 int timeout;
518 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600519 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600520 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600521 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600522 ret = txn->ec;
Sagar Dharia55bced82014-01-20 16:00:44 -0700523 } else if (ret == -EREMOTEIO &&
524 (txn->mc == SLIM_USR_MC_CHAN_CTRL ||
525 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
526 /* HW restarting, channel/port removal should succeed */
527 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600528 }
Sagar Dharia55bced82014-01-20 16:00:44 -0700529
Sagar Dharia33beca02012-10-22 16:21:46 -0600530 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600531 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
532 txn->tid, ret);
Sagar Dharia4f240722014-01-15 13:50:58 -0700533 WARN(1, "timeout during xfer and wait");
Sagar Dharia33beca02012-10-22 16:21:46 -0600534 mutex_lock(&ctrl->m_ctrl);
535 ctrl->txnt[txn->tid] = NULL;
536 mutex_unlock(&ctrl->m_ctrl);
537 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600538
539 return ret;
540}
541
542static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
543{
544 int ret;
545 struct slim_pending_ch *pch;
546 struct slim_msg_txn txn;
547 struct slim_controller *ctrl = sb->ctrl;
548 DECLARE_COMPLETION_ONSTACK(done);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600549 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600550
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600551 *clkgear = ctrl->clkgear;
552 *subfrmc = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600553 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
554 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
555 txn.la = SLIM_LA_MGR;
556 txn.len = 0;
557 txn.ec = 0;
558 txn.wbuf = wbuf;
559 txn.rbuf = NULL;
560
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600561 if (ctrl->sched.msgsl != ctrl->sched.pending_msgsl) {
562 pr_debug("slim reserve BW for messaging: req: %d",
563 ctrl->sched.pending_msgsl);
564 txn.mc = SLIM_USR_MC_REQ_BW;
565 wbuf[txn.len++] = ((sb->laddr & 0x1f) |
566 ((u8)(ctrl->sched.pending_msgsl & 0x7) << 5));
567 wbuf[txn.len++] = (u8)(ctrl->sched.pending_msgsl >> 3);
568 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
569 if (ret)
570 return ret;
571 txn.rl = txn.len + 4;
572 ret = ngd_xferandwait_ack(ctrl, &txn);
573 if (ret)
574 return ret;
575
576 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
577 txn.len = 2;
578 wbuf[1] = sb->laddr;
579 txn.rl = txn.len + 4;
580 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
581 if (ret)
582 return ret;
583 ret = ngd_xferandwait_ack(ctrl, &txn);
584 if (ret)
585 return ret;
586
587 txn.len = 0;
588 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600589 list_for_each_entry(pch, &sb->mark_define, pending) {
590 struct slim_ich *slc;
591 slc = &ctrl->chans[pch->chan];
592 if (!slc) {
593 pr_err("no channel in define?");
594 return -ENXIO;
595 }
596 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600597 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600598 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600599 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600600 wbuf[txn.len] = slc->seglen;
601 if (slc->coeff == SLIM_COEFF_3)
602 wbuf[txn.len] |= 1 << 5;
603 wbuf[txn.len++] |= slc->prop.auxf << 6;
604 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
605 wbuf[txn.len++] = slc->prrate;
606 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
607 if (ret) {
608 pr_err("no tid for channel define?");
609 return -ENXIO;
610 }
611 }
612 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600613 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600614 }
615 if (txn.len) {
616 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
617 txn.rl = txn.len + 4;
618 ret = ngd_xferandwait_ack(ctrl, &txn);
619 if (ret)
620 return ret;
621
622 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
623 txn.len = 2;
624 wbuf[1] = sb->laddr;
625 txn.rl = txn.len + 4;
626 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
627 if (ret)
628 return ret;
629 ret = ngd_xferandwait_ack(ctrl, &txn);
630 if (ret)
631 return ret;
632 }
633 txn.len = 0;
634 list_for_each_entry(pch, &sb->mark_removal, pending) {
635 struct slim_ich *slc;
636 slc = &ctrl->chans[pch->chan];
637 if (!slc) {
638 pr_err("no channel in removal?");
639 return -ENXIO;
640 }
641 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600642 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600643 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600644 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600645 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
646 if (ret) {
647 pr_err("no tid for channel define?");
648 return -ENXIO;
649 }
650 }
651 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600652 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600653 }
654 if (txn.len) {
655 txn.mc = SLIM_USR_MC_CHAN_CTRL;
656 txn.rl = txn.len + 4;
657 ret = ngd_xferandwait_ack(ctrl, &txn);
658 if (ret)
659 return ret;
660
661 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
662 txn.len = 2;
663 wbuf[1] = sb->laddr;
664 txn.rl = txn.len + 4;
665 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
666 if (ret)
667 return ret;
668 ret = ngd_xferandwait_ack(ctrl, &txn);
669 if (ret)
670 return ret;
671 txn.len = 0;
672 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700673 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600674}
675
676static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
677 u8 elen, u8 laddr)
678{
679 return 0;
680}
681
682static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
683 u8 elen, u8 *laddr)
684{
685 int ret;
686 u8 wbuf[10];
687 struct slim_msg_txn txn;
688 DECLARE_COMPLETION_ONSTACK(done);
689 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
690 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
691 txn.la = SLIM_LA_MGR;
692 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600693 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
694 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600695 return ret;
696 }
697 memcpy(&wbuf[1], ea, elen);
698 txn.mc = SLIM_USR_MC_ADDR_QUERY;
699 txn.rl = 11;
700 txn.len = 7;
701 txn.wbuf = wbuf;
702 txn.rbuf = NULL;
703 ret = ngd_xferandwait_ack(ctrl, &txn);
704 if (!ret && txn.la == 0xFF)
705 ret = -ENXIO;
706 else if (!ret)
707 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600708 return ret;
709}
710
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600711static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
Sagar Dharia24419e32013-01-14 17:56:32 -0700712{
Sagar Dharia24419e32013-01-14 17:56:32 -0700713 if (dev->state == MSM_CTRL_DOWN) {
714 msm_slim_sps_init(dev, dev->bam_mem,
715 NGD_BASE(dev->ctrl.nr,
716 dev->ver) + NGD_STATUS, true);
717 } else {
718 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600719 goto setup_tx_msg_path;
720 msm_slim_connect_endp(dev, &dev->rx_msgq,
Sagar Dharia24419e32013-01-14 17:56:32 -0700721 &dev->rx_msgq_notify);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600722
723setup_tx_msg_path:
724 if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
725 return;
726 msm_slim_connect_endp(dev, &dev->tx_msgq,
727 NULL);
Sagar Dharia24419e32013-01-14 17:56:32 -0700728 }
729}
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600730
Sagar Dharia71fcea52012-09-12 23:21:57 -0600731static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
732{
733 u8 mc, mt, len;
734 int ret;
735 u32 msgq_en = 1;
736
737 len = buf[0] & 0x1F;
738 mt = (buf[0] >> 5) & 0x7;
739 mc = buf[1];
740 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
741 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
742 struct slim_msg_txn txn;
Sagar Dharia0a693332013-04-15 17:59:03 -0600743 int retries = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600744 u8 wbuf[8];
745 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
746 txn.ec = 0;
747 txn.rbuf = NULL;
748 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
749 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
750 txn.la = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600751 wbuf[0] = SAT_MAGIC_LSB;
752 wbuf[1] = SAT_MAGIC_MSB;
753 wbuf[2] = SAT_MSG_VER;
754 wbuf[3] = SAT_MSG_PROT;
755 txn.wbuf = wbuf;
756 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700757 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700758 if (dev->state >= MSM_CTRL_ASLEEP) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600759 ngd_slim_setup_msg_path(dev);
Sagar Dharia24419e32013-01-14 17:56:32 -0700760 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600761 msgq_en |= NGD_CFG_RX_MSGQ_EN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600762 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
763 msgq_en |= NGD_CFG_TX_MSGQ_EN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600764 writel_relaxed(msgq_en, dev->base +
765 NGD_BASE(dev->ctrl.nr, dev->ver));
766 /* make sure NGD MSG-Q config goes through */
767 mb();
768 }
Sagar Dharia0a693332013-04-15 17:59:03 -0600769capability_retry:
770 txn.rl = 8;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600771 ret = ngd_xfer_msg(&dev->ctrl, &txn);
772 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600773 enum msm_ctrl_state prev_state = dev->state;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600774 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600775 if (prev_state >= MSM_CTRL_ASLEEP)
776 complete(&dev->reconf);
777 else
778 pr_err("SLIM: unexpected capability, state:%d",
779 prev_state);
780 /* ADSP SSR, send device_up notifications */
781 if (prev_state == MSM_CTRL_DOWN)
782 schedule_work(&dev->slave_notify);
Sagar Dharia0a693332013-04-15 17:59:03 -0600783 } else if (ret == -EIO) {
784 pr_info("capability message NACKed, retrying");
785 if (retries < INIT_MX_RETRIES) {
786 msleep(DEF_RETRY_MS);
787 retries++;
788 goto capability_retry;
789 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600790 }
791 }
792 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
793 mc == SLIM_MSG_MC_REPLY_VALUE) {
794 u8 tid = buf[3];
795 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
796 slim_msg_response(&dev->ctrl, &buf[4], tid,
797 len - 4);
798 pm_runtime_mark_last_busy(dev->dev);
799 }
800 if (mc == SLIM_USR_MC_ADDR_REPLY &&
801 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700802 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600803 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700804 mutex_lock(&dev->ctrl.m_ctrl);
805 txn = dev->ctrl.txnt[buf[3]];
806 if (!txn) {
807 pr_err("LADDR response after timeout, tid:0x%x",
808 buf[3]);
809 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600810 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700811 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600812 if (memcmp(&buf[4], failed_ea, 6))
813 txn->la = buf[10];
814 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700815 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600816 complete(txn->comp);
817 }
818 if (mc == SLIM_USR_MC_GENERIC_ACK &&
819 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700820 struct slim_msg_txn *txn;
821 mutex_lock(&dev->ctrl.m_ctrl);
822 txn = dev->ctrl.txnt[buf[3]];
823 if (!txn) {
824 pr_err("ACK received after timeout, tid:0x%x",
825 buf[3]);
826 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600827 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700828 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600829 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
830 (int)buf[3], buf[4]);
831 if (!(buf[4] & MSM_SAT_SUCCSS)) {
832 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
833 buf[4]);
834 txn->ec = -EIO;
835 }
836 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700837 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600838 complete(txn->comp);
839 }
840}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700841
Sagar Dharia33beca02012-10-22 16:21:46 -0600842static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700843{
Sagar Dharia33beca02012-10-22 16:21:46 -0600844 void __iomem *ngd;
845 int timeout, ret;
846 enum msm_ctrl_state cur_state = dev->state;
847 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700848 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700849 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
850 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
851 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600852
853 if (cur_state == MSM_CTRL_DOWN) {
854 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
855 HZ);
856 if (!timeout)
857 pr_err("slimbus QMI init timed out");
858 }
859
860 ret = msm_slim_qmi_power_request(dev, true);
861 if (ret) {
862 pr_err("SLIM QMI power request failed:%d", ret);
863 return ret;
864 }
865 if (!dev->ver) {
866 dev->ver = readl_relaxed(dev->base);
867 /* Version info in 16 MSbits */
868 dev->ver >>= 16;
869 }
870 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
871 laddr = readl_relaxed(ngd + NGD_STATUS);
872 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700873 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600874 * ADSP power collapse case, where HW wasn't reset.
875 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700876 */
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600877 ngd_slim_setup_msg_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600878 return 0;
879 } else if (cur_state != MSM_CTRL_DOWN) {
880 pr_info("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
881 dev->state, laddr);
Sagar Dharia33beca02012-10-22 16:21:46 -0600882 }
Sagar Dhariada48bd62013-03-21 18:02:40 -0600883 /* ADSP SSR scenario, need to disconnect pipe before connecting */
884 if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
885 struct msm_slim_endp *endpoint = &dev->rx_msgq;
886 sps_disconnect(endpoint->sps);
887 sps_free_endpoint(endpoint->sps);
888 dev->use_rx_msgqs = MSM_MSGQ_RESET;
889 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600890 if (dev->use_tx_msgqs == MSM_MSGQ_DOWN) {
891 struct msm_slim_endp *endpoint = &dev->tx_msgq;
892 sps_disconnect(endpoint->sps);
893 sps_free_endpoint(endpoint->sps);
894 dev->use_tx_msgqs = MSM_MSGQ_RESET;
895 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600896 /*
897 * ADSP power collapse case (OR SSR), where HW was reset
898 * BAM programming will happen when capability message is received
899 */
900 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700901 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600902 /*
903 * Enable NGD. Configure NGD in register acc. mode until master
904 * announcement is received
905 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700906 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600907 /* make sure NGD enabling goes through */
908 mb();
909
910 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
911 if (!timeout) {
912 pr_err("failed to received master capability");
913 return -ETIMEDOUT;
914 }
915 if (cur_state == MSM_CTRL_DOWN)
916 complete(&dev->ctrl_up);
917 return 0;
918}
919
920static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
921{
922 int ret = 0;
923 if (enable) {
924 ret = msm_slim_qmi_init(dev, false);
925 /* controller state should be in sync with framework state */
926 if (!ret) {
927 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
928 SLIM_CLK_UNSPECIFIED);
929 complete(&dev->qmi.qmi_comp);
930 /*
931 * Power-up won't be called if clock pause failed.
932 * This can happen if ADSP SSR happened when audio
933 * session is in progress. Framework will think that
934 * clock pause failed so no need to wakeup controller.
935 * Call power-up explicitly in that case, since slimbus
936 * HW needs to be powered-on to be in sync with
937 * framework state
938 */
939 if (ret)
940 ngd_slim_power_up(dev);
941 if (!pm_runtime_enabled(dev->dev) ||
942 !pm_runtime_suspended(dev->dev))
943 ngd_slim_runtime_resume(dev->dev);
944 else
945 pm_runtime_resume(dev->dev);
946 pm_runtime_mark_last_busy(dev->dev);
947 pm_runtime_put(dev->dev);
948 } else
949 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
950 ret, dev->state);
951 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700952 msm_slim_qmi_exit(dev);
953 }
954
Sagar Dharia33beca02012-10-22 16:21:46 -0600955 return ret;
956}
957
958static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
959{
960 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
961 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700962}
963
Sagar Dharia71fcea52012-09-12 23:21:57 -0600964static int ngd_slim_rx_msgq_thread(void *data)
965{
966 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
967 struct completion *notify = &dev->rx_msgq_notify;
968 int ret = 0, index = 0;
969 u32 mc = 0;
970 u32 mt = 0;
971 u32 buffer[10];
972 u8 msg_len = 0;
973
974 while (!kthread_should_stop()) {
975 set_current_state(TASK_INTERRUPTIBLE);
976 ret = wait_for_completion_interruptible(notify);
977 if (ret) {
978 dev_err(dev->dev, "rx thread wait err:%d", ret);
979 continue;
980 }
981 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -0700982 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600983 msm_slim_rx_dequeue(dev, (u8 *)buffer);
984 ngd_slim_rx(dev, (u8 *)buffer);
985 continue;
986 }
987 ret = msm_slim_rx_msgq_get(dev, buffer, index);
988 if (ret) {
989 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
990 continue;
991 }
992
993 /* Wait for complete message */
994 if (index++ == 0) {
995 msg_len = *buffer & 0x1F;
996 mt = (buffer[0] >> 5) & 0x7;
997 mc = (buffer[0] >> 8) & 0xff;
998 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
999 }
1000 if ((index * 4) >= msg_len) {
1001 index = 0;
1002 ngd_slim_rx(dev, (u8 *)buffer);
1003 } else
1004 continue;
1005 }
1006 return 0;
1007}
1008
Sagar Dharia33beca02012-10-22 16:21:46 -06001009static void ngd_laddr_lookup(struct work_struct *work)
1010{
1011 struct msm_slim_ctrl *dev =
1012 container_of(work, struct msm_slim_ctrl, slave_notify);
1013 struct slim_controller *ctrl = &dev->ctrl;
1014 struct slim_device *sbdev;
1015 int i;
Sagar Dharia722f9e22013-12-11 23:59:22 -07001016 slim_framer_booted(ctrl);
Sagar Dharia33beca02012-10-22 16:21:46 -06001017 mutex_lock(&ctrl->m_ctrl);
1018 list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
1019 int ret = 0;
1020 mutex_unlock(&ctrl->m_ctrl);
1021 for (i = 0; i < LADDR_RETRY; i++) {
1022 ret = slim_get_logical_addr(sbdev, sbdev->e_addr,
1023 6, &sbdev->laddr);
1024 if (!ret)
1025 break;
1026 else /* time for ADSP to assign LA */
1027 msleep(20);
1028 }
1029 mutex_lock(&ctrl->m_ctrl);
1030 }
1031 mutex_unlock(&ctrl->m_ctrl);
1032}
1033
1034static void ngd_adsp_down(struct work_struct *work)
1035{
1036 struct msm_slim_qmi *qmi =
1037 container_of(work, struct msm_slim_qmi, ssr_down);
1038 struct msm_slim_ctrl *dev =
1039 container_of(qmi, struct msm_slim_ctrl, qmi);
1040 struct slim_controller *ctrl = &dev->ctrl;
1041 struct slim_device *sbdev;
Sagar Dharia33beca02012-10-22 16:21:46 -06001042
1043 ngd_slim_enable(dev, false);
1044 /* disconnect BAM pipes */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001045 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
1046 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001047 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
1048 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -06001049 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001050 /* device up should be called again after SSR */
1051 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
Sagar Dhariaf68d71f2013-07-31 17:43:46 -06001052 slim_report_absent(sbdev);
Sagar Dharia33beca02012-10-22 16:21:46 -06001053 pr_info("SLIM ADSP SSR (DOWN) done");
1054}
1055
1056static void ngd_adsp_up(struct work_struct *work)
1057{
1058 struct msm_slim_qmi *qmi =
1059 container_of(work, struct msm_slim_qmi, ssr_up);
1060 struct msm_slim_ctrl *dev =
1061 container_of(qmi, struct msm_slim_ctrl, qmi);
1062 ngd_slim_enable(dev, true);
1063}
1064
Sagar Dharia71fcea52012-09-12 23:21:57 -06001065static int __devinit ngd_slim_probe(struct platform_device *pdev)
1066{
1067 struct msm_slim_ctrl *dev;
1068 int ret;
1069 struct resource *bam_mem;
1070 struct resource *slim_mem;
1071 struct resource *irq, *bam_irq;
1072 enum apr_subsys_state q6_state;
Sagar Dharia24419e32013-01-14 17:56:32 -07001073 bool rxreg_access = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001074
1075 q6_state = apr_get_q6_state();
1076 if (q6_state == APR_SUBSYS_DOWN) {
1077 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
1078 q6_state);
1079 return -EPROBE_DEFER;
1080 } else
1081 dev_dbg(&pdev->dev, "adsp is ready\n");
1082
1083 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1084 "slimbus_physical");
1085 if (!slim_mem) {
1086 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
1087 return -ENODEV;
1088 }
1089 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1090 "slimbus_bam_physical");
1091 if (!bam_mem) {
1092 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
1093 return -ENODEV;
1094 }
1095 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1096 "slimbus_irq");
1097 if (!irq) {
1098 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
1099 return -ENODEV;
1100 }
1101 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1102 "slimbus_bam_irq");
1103 if (!bam_irq) {
1104 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
1105 return -ENODEV;
1106 }
1107
1108 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
Kiran Gunda318cac42013-10-21 17:00:15 +05301109 if (IS_ERR_OR_NULL(dev)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001110 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
1111 return PTR_ERR(dev);
1112 }
1113 dev->dev = &pdev->dev;
1114 platform_set_drvdata(pdev, dev);
1115 slim_set_ctrldata(&dev->ctrl, dev);
1116 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
1117 if (!dev->base) {
1118 dev_err(&pdev->dev, "IOremap failed\n");
1119 ret = -ENOMEM;
1120 goto err_ioremap_failed;
1121 }
1122 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
1123 if (!dev->bam.base) {
1124 dev_err(&pdev->dev, "BAM IOremap failed\n");
1125 ret = -ENOMEM;
1126 goto err_ioremap_bam_failed;
1127 }
1128 if (pdev->dev.of_node) {
1129
1130 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1131 &dev->ctrl.nr);
1132 if (ret) {
1133 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1134 goto err_ctrl_failed;
1135 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001136 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1137 "qcom,rxreg-access");
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001138 of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
1139 &dev->pdata.apps_pipes);
1140 of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
1141 &dev->pdata.eapc);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001142 } else {
1143 dev->ctrl.nr = pdev->id;
1144 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001145 /*
1146 * Keep PGD's logical address as manager's. Query it when first data
1147 * channel request comes in
1148 */
1149 dev->pgdla = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001150 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1151 dev->ctrl.nports = MSM_SLIM_NPORTS;
1152 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1153 dev->framer.superfreq =
1154 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1155 dev->ctrl.a_framer = &dev->framer;
1156 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1157 dev->ctrl.set_laddr = ngd_set_laddr;
1158 dev->ctrl.get_laddr = ngd_get_laddr;
1159 dev->ctrl.allocbw = ngd_allocbw;
1160 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001161 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia100e7212013-05-17 18:20:57 -06001162 dev->ctrl.alloc_port = msm_alloc_port;
1163 dev->ctrl.dealloc_port = msm_dealloc_port;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001164 dev->ctrl.port_xfer = msm_slim_port_xfer;
1165 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001166 dev->bam_mem = bam_mem;
1167
1168 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001169 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001170 mutex_init(&dev->tx_lock);
1171 spin_lock_init(&dev->rx_lock);
1172 dev->ee = 1;
1173 dev->irq = irq->start;
1174 dev->bam.irq = bam_irq->start;
1175
Sagar Dharia24419e32013-01-14 17:56:32 -07001176 if (rxreg_access)
1177 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1178 else
1179 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001180
1181 /* Enable TX message queues by default as recommended by HW */
1182 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1183
Sagar Dharia71fcea52012-09-12 23:21:57 -06001184 init_completion(&dev->rx_msgq_notify);
1185
1186 /* Register with framework */
1187 ret = slim_add_numbered_controller(&dev->ctrl);
1188 if (ret) {
1189 dev_err(dev->dev, "error adding controller\n");
1190 goto err_ctrl_failed;
1191 }
1192
1193 dev->ctrl.dev.parent = &pdev->dev;
1194 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001195 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001196
1197 ret = request_irq(dev->irq, ngd_slim_interrupt,
1198 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1199
1200 if (ret) {
1201 dev_err(&pdev->dev, "request IRQ failed\n");
1202 goto err_request_irq_failed;
1203 }
1204
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001205 init_completion(&dev->qmi.qmi_comp);
Sagar Dharia33beca02012-10-22 16:21:46 -06001206 pm_runtime_use_autosuspend(dev->dev);
1207 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1208 pm_runtime_set_suspended(dev->dev);
1209 pm_runtime_enable(dev->dev);
1210
1211 INIT_WORK(&dev->slave_notify, ngd_laddr_lookup);
1212 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1213 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001214 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001215 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001216 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
1217 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1218 if (ret) {
1219 pr_err("Slimbus QMI service registration failed:%d", ret);
1220 goto qmi_register_failed;
1221 }
1222
Sagar Dharia33beca02012-10-22 16:21:46 -06001223
Sagar Dharia71fcea52012-09-12 23:21:57 -06001224 /* Fire up the Rx message queue thread */
1225 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
1226 NGD_SLIM_NAME "_ngd_msgq_thread");
1227 if (IS_ERR(dev->rx_msgq_thread)) {
1228 ret = PTR_ERR(dev->rx_msgq_thread);
1229 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
1230 goto err_thread_create_failed;
1231 }
1232
Sagar Dharia71fcea52012-09-12 23:21:57 -06001233 if (pdev->dev.of_node)
1234 of_register_slim_devices(&dev->ctrl);
1235
1236 /* Add devices registered with board-info now that controller is up */
1237 slim_ctrl_add_boarddevs(&dev->ctrl);
1238
Sagar Dharia71fcea52012-09-12 23:21:57 -06001239 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1240 return 0;
1241
1242err_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001243 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1244 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1245qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001246 free_irq(dev->irq, dev);
1247err_request_irq_failed:
1248 slim_del_controller(&dev->ctrl);
1249err_ctrl_failed:
1250 iounmap(dev->bam.base);
1251err_ioremap_bam_failed:
1252 iounmap(dev->base);
1253err_ioremap_failed:
1254 kfree(dev);
1255 return ret;
1256}
1257
1258static int __devexit ngd_slim_remove(struct platform_device *pdev)
1259{
1260 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001261 ngd_slim_enable(dev, false);
1262 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1263 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001264 pm_runtime_disable(&pdev->dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001265 free_irq(dev->irq, dev);
1266 slim_del_controller(&dev->ctrl);
1267 kthread_stop(dev->rx_msgq_thread);
1268 iounmap(dev->bam.base);
1269 iounmap(dev->base);
1270 kfree(dev);
1271 return 0;
1272}
1273
1274#ifdef CONFIG_PM_RUNTIME
1275static int ngd_slim_runtime_idle(struct device *device)
1276{
Sagar Dhariad1468b72013-07-16 12:56:22 -06001277 struct platform_device *pdev = to_platform_device(device);
1278 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1279 if (dev->state == MSM_CTRL_AWAKE)
1280 dev->state = MSM_CTRL_IDLE;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001281 dev_dbg(device, "pm_runtime: idle...\n");
1282 pm_request_autosuspend(device);
1283 return -EAGAIN;
1284}
1285#endif
1286
1287/*
1288 * If PM_RUNTIME is not defined, these 2 functions become helper
1289 * functions to be called from system suspend/resume. So they are not
1290 * inside ifdef CONFIG_PM_RUNTIME
1291 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001292static int ngd_slim_runtime_resume(struct device *device)
1293{
1294 struct platform_device *pdev = to_platform_device(device);
1295 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1296 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001297 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001298 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1299 if (ret) {
Sagar Dharia129c7d82013-08-08 19:35:50 -06001300 /* Did SSR cause this clock pause failure */
1301 if (dev->state != MSM_CTRL_DOWN)
1302 dev->state = MSM_CTRL_ASLEEP;
1303 else
1304 dev_err(device, "HW wakeup attempt during SSR");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001305 } else {
1306 dev->state = MSM_CTRL_AWAKE;
1307 }
1308 return ret;
1309}
1310
Sagar Dharia33beca02012-10-22 16:21:46 -06001311#ifdef CONFIG_PM_SLEEP
1312static int ngd_slim_runtime_suspend(struct device *device)
1313{
1314 struct platform_device *pdev = to_platform_device(device);
1315 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1316 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001317 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1318 if (ret) {
1319 if (ret != -EBUSY)
1320 dev_err(device, "clk pause not entered:%d", ret);
1321 dev->state = MSM_CTRL_AWAKE;
1322 } else {
1323 dev->state = MSM_CTRL_ASLEEP;
1324 }
1325 return ret;
1326}
1327
Sagar Dharia71fcea52012-09-12 23:21:57 -06001328static int ngd_slim_suspend(struct device *dev)
1329{
1330 int ret = -EBUSY;
Sagar Dhariad1468b72013-07-16 12:56:22 -06001331 struct platform_device *pdev = to_platform_device(dev);
1332 struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
1333 if (!pm_runtime_enabled(dev) ||
1334 (!pm_runtime_suspended(dev) &&
1335 cdev->state == MSM_CTRL_IDLE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001336 dev_dbg(dev, "system suspend");
1337 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001338 /*
1339 * If runtime-PM still thinks it's active, then make sure its
1340 * status is in sync with HW status.
1341 * Since this suspend calls QMI api, it results in holding a
1342 * wakelock. That results in failure of first suspend.
1343 * Subsequent suspend should not call low-power transition
1344 * again since the HW is already in suspended state.
1345 */
1346 if (!ret) {
1347 pm_runtime_disable(dev);
1348 pm_runtime_set_suspended(dev);
1349 pm_runtime_enable(dev);
1350 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001351 }
1352 if (ret == -EBUSY) {
1353 /*
1354 * There is a possibility that some audio stream is active
1355 * during suspend. We dont want to return suspend failure in
1356 * that case so that display and relevant components can still
1357 * go to suspend.
1358 * If there is some other error, then it should be passed-on
1359 * to system level suspend
1360 */
1361 ret = 0;
1362 }
1363 return ret;
1364}
1365
1366static int ngd_slim_resume(struct device *dev)
1367{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001368 /*
1369 * Rely on runtime-PM to call resume in case it is enabled.
1370 * Even if it's not enabled, rely on 1st client transaction to do
1371 * clock/power on
1372 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001373 return 0;
1374}
1375#endif /* CONFIG_PM_SLEEP */
1376
1377static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1378 SET_SYSTEM_SLEEP_PM_OPS(
1379 ngd_slim_suspend,
1380 ngd_slim_resume
1381 )
1382 SET_RUNTIME_PM_OPS(
1383 ngd_slim_runtime_suspend,
1384 ngd_slim_runtime_resume,
1385 ngd_slim_runtime_idle
1386 )
1387};
1388
1389static struct of_device_id ngd_slim_dt_match[] = {
1390 {
1391 .compatible = "qcom,slim-ngd",
1392 },
1393 {}
1394};
1395
1396static struct platform_driver ngd_slim_driver = {
1397 .probe = ngd_slim_probe,
1398 .remove = ngd_slim_remove,
1399 .driver = {
1400 .name = NGD_SLIM_NAME,
1401 .owner = THIS_MODULE,
1402 .pm = &ngd_slim_dev_pm_ops,
1403 .of_match_table = ngd_slim_dt_match,
1404 },
1405};
1406
1407static int ngd_slim_init(void)
1408{
1409 return platform_driver_register(&ngd_slim_driver);
1410}
1411late_initcall(ngd_slim_init);
1412
1413static void ngd_slim_exit(void)
1414{
1415 platform_driver_unregister(&ngd_slim_driver);
1416}
1417module_exit(ngd_slim_exit);
1418
1419MODULE_LICENSE("GPL v2");
1420MODULE_DESCRIPTION("MSM Slimbus controller");
1421MODULE_ALIAS("platform:msm-slim-ngd");