blob: 0b8c9317c560558abf09fc26c806a6645b47b5e8 [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);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -060086static int ngd_slim_power_up(struct msm_slim_ctrl *dev);
Sagar Dharia33beca02012-10-22 16:21:46 -060087
Sagar Dharia71fcea52012-09-12 23:21:57 -060088static irqreturn_t ngd_slim_interrupt(int irq, void *d)
89{
90 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)d;
91 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
92 u32 stat = readl_relaxed(ngd + NGD_INT_STAT);
Sagar Dharia2b8a4b52013-05-15 20:01:45 -060093 u32 pstat;
Sagar Dharia71fcea52012-09-12 23:21:57 -060094
95 if (stat & NGD_INT_TX_MSG_SENT) {
96 writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
97 /* Make sure interrupt is cleared */
98 mb();
99 if (dev->wr_comp)
100 complete(dev->wr_comp);
101 } else if ((stat & NGD_INT_MSG_BUF_CONTE) ||
102 (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
103 (stat & NGD_INT_TX_NACKED_2)) {
104 dev_err(dev->dev, "NGD interrupt error:0x%x", stat);
105 writel_relaxed(stat, ngd + NGD_INT_CLR);
106 /* Guarantee that error interrupts are cleared */
107 mb();
108 if (((stat & NGD_INT_TX_NACKED_2) ||
109 (stat & NGD_INT_MSG_TX_INVAL))) {
110 dev->err = -EIO;
111 if (dev->wr_comp)
112 complete(dev->wr_comp);
113 }
114 }
115 if (stat & NGD_INT_RX_MSG_RCVD) {
116 u32 rx_buf[10];
117 u8 len, i;
118 rx_buf[0] = readl_relaxed(ngd + NGD_RX_MSG);
119 len = rx_buf[0] & 0x1F;
120 for (i = 1; i < ((len + 3) >> 2); i++) {
121 rx_buf[i] = readl_relaxed(ngd + NGD_RX_MSG +
122 (4 * i));
123 dev_dbg(dev->dev, "REG-RX data: %x\n", rx_buf[i]);
124 }
125 msm_slim_rx_enqueue(dev, rx_buf, len);
126 writel_relaxed(NGD_INT_RX_MSG_RCVD,
127 ngd + NGD_INT_CLR);
128 /*
129 * Guarantee that CLR bit write goes through before
130 * queuing work
131 */
132 mb();
Sagar Dharia24419e32013-01-14 17:56:32 -0700133 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600134 dev_err(dev->dev,
135 "direct message received even with RX MSGQs");
136 else
137 complete(&dev->rx_msgq_notify);
138 }
139 if (stat & NGD_INT_RECFG_DONE) {
140 writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
141 /* Guarantee RECONFIG DONE interrupt is cleared */
142 mb();
143 /* In satellite mode, just log the reconfig done IRQ */
144 dev_dbg(dev->dev, "reconfig done IRQ for NGD");
145 }
146 if (stat & NGD_INT_IE_VE_CHG) {
147 writel_relaxed(NGD_INT_IE_VE_CHG, ngd + NGD_INT_CLR);
148 /* Guarantee IE VE change interrupt is cleared */
149 mb();
150 dev_err(dev->dev, "NGD IE VE change");
151 }
Sagar Dharia2b8a4b52013-05-15 20:01:45 -0600152
153 pstat = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_ST_EEn, dev->ver));
154 if (pstat != 0)
155 return msm_slim_port_irq_handler(dev, pstat);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600156 return IRQ_HANDLED;
157}
158
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700159static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
160 void *_cmd)
161{
162 struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
Sagar Dharia33beca02012-10-22 16:21:46 -0600163 struct msm_slim_ctrl *dev =
164 container_of(qmi, struct msm_slim_ctrl, qmi);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700165 pr_info("Slimbus QMI NGD CB received event:%ld", code);
166 switch (code) {
167 case QMI_SERVER_ARRIVE:
Sagar Dharia33beca02012-10-22 16:21:46 -0600168 schedule_work(&qmi->ssr_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700169 break;
170 case QMI_SERVER_EXIT:
Sagar Dharia33beca02012-10-22 16:21:46 -0600171 dev->state = MSM_CTRL_DOWN;
172 /* make sure autosuspend is not called until ADSP comes up*/
173 pm_runtime_get_noresume(dev->dev);
174 /* Reset ctrl_up completion */
175 init_completion(&dev->ctrl_up);
176 schedule_work(&qmi->ssr_down);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700177 break;
178 default:
179 break;
180 }
181 return 0;
182}
183
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600184static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
185 void *_cmd)
186{
187 struct msm_slim_mdm *mdm = container_of(n, struct msm_slim_mdm, nb);
188 struct msm_slim_ctrl *dev = container_of(mdm, struct msm_slim_ctrl,
189 mdm);
190 int ret;
191
192 switch (code) {
193 case SUBSYS_BEFORE_SHUTDOWN:
194 /* make sure runtime-pm doesn't suspend during modem SSR */
195 pm_runtime_get_noresume(dev->dev);
196 break;
197 case SUBSYS_AFTER_POWERUP:
198 ret = msm_slim_qmi_check_framer_request(dev);
199 dev_err(dev->dev,
200 "%s:SLIM %lu external_modem SSR notify cb, ret %d",
201 __func__, code, ret);
202 /*
203 * Next codec transaction will reinit the HW
204 * if it was suspended
205 */
206 if (pm_runtime_suspended(dev->dev) ||
207 dev->state >= MSM_CTRL_ASLEEP) {
208 break;
209 } else {
210 ngd_slim_power_up(dev);
211 msm_slim_put_ctrl(dev);
212 }
213 default:
214 break;
215 }
216 return NOTIFY_DONE;
217}
218
Sagar Dharia71fcea52012-09-12 23:21:57 -0600219static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
220 u8 *tid, struct completion *done)
221{
222 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700223 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600224 if (ctrl->last_tid <= 255) {
225 ctrl->txnt = krealloc(ctrl->txnt,
226 (ctrl->last_tid + 1) *
227 sizeof(struct slim_msg_txn *),
228 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700229 if (!ctrl->txnt) {
230 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600231 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700232 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600233 dev->msg_cnt = ctrl->last_tid;
234 ctrl->last_tid++;
235 } else {
236 int i;
237 for (i = 0; i < 256; i++) {
238 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
239 if (ctrl->txnt[dev->msg_cnt] == NULL)
240 break;
241 }
242 if (i >= 256) {
243 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700244 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600245 return -ENOMEM;
246 }
247 }
248 ctrl->txnt[dev->msg_cnt] = txn;
249 txn->tid = dev->msg_cnt;
250 txn->comp = done;
251 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700252 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600253 return 0;
254}
255static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
256{
257 DECLARE_COMPLETION_ONSTACK(done);
258 DECLARE_COMPLETION_ONSTACK(tx_sent);
259
260 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
261 u32 *pbuf;
262 u8 *puc;
263 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600264 u8 la = txn->la;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600265 u8 txn_mt;
266 u16 txn_mc = txn->mc;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600267 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600268
Sagar Dhariaa1398282013-01-22 13:26:20 -0700269 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
270 txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
271 /*
272 * Counter-part of system-suspend when runtime-pm is not enabled
273 * This way, resume can be left empty and device will be put in
274 * active mode only if client requests anything on the bus
275 * If the state was DOWN, SSR UP notification will take
276 * care of putting the device in active state.
277 */
278 ngd_slim_runtime_resume(dev->dev);
279 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600280 if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
281 SLIM_MSG_MC_RECONFIGURE_NOW)) &&
Sagar Dhariad1468b72013-07-16 12:56:22 -0600282 dev->state <= MSM_CTRL_IDLE) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600283 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
284 &dev->use_rx_msgqs);
285 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
286 &dev->use_tx_msgqs);
287 return msm_slim_qmi_power_request(dev, false);
Sagar Dharia24419e32013-01-14 17:56:32 -0700288 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700289 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
290 return 0;
291
Sagar Dharia71fcea52012-09-12 23:21:57 -0600292 if (txn->mt == SLIM_MSG_MT_CORE &&
293 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
294 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
295 return 0;
296 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600297 /* If txn is tried when controller is down, wait for ADSP to boot */
298 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
299 if (dev->state == MSM_CTRL_DOWN) {
300 u8 mc = (u8)txn->mc;
301 int timeout;
302 dev_err(dev->dev, "ADSP slimbus not up yet");
303 /*
304 * Messages related to data channel management can't
305 * wait since they are holding reconfiguration lock.
306 * clk_pause in resume (which can change state back to
Sagar Dharia32379162013-12-12 00:46:37 -0700307 * MSM_CTRL_AWAKE), will need that lock.
308 * Port disconnection, channel removal calls should pass
309 * through since there is no activity on the bus and
310 * those calls are triggered by clients due to
311 * device_down callback in that situation.
312 * Returning 0 on the disconnections and
313 * removals will ensure consistent state of channels,
314 * ports with the HW
Sagar Dharia55bced82014-01-20 16:00:44 -0700315 * Remote requests to remove channel/port will be
316 * returned from the path where they wait on
317 * acknowledgement from ADSP
Sagar Dharia33beca02012-10-22 16:21:46 -0600318 */
Sagar Dharia32379162013-12-12 00:46:37 -0700319 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
320 ((mc == SLIM_USR_MC_CHAN_CTRL ||
321 mc == SLIM_USR_MC_DISCONNECT_PORT ||
322 mc == SLIM_USR_MC_RECONFIG_NOW)))
Sagar Dharia55bced82014-01-20 16:00:44 -0700323 return -EREMOTEIO;
Sagar Dharia32379162013-12-12 00:46:37 -0700324 if ((txn->mt == SLIM_MSG_MT_CORE) &&
325 ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
326 mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
327 mc == SLIM_USR_MC_RECONFIG_NOW)))
328 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600329 if ((txn->mt == SLIM_MSG_MT_CORE) &&
330 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
331 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
332 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
333 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
334 return -EREMOTEIO;
335 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
336 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
Sagar Dharia32379162013-12-12 00:46:37 -0700337 mc < SLIM_USR_MC_DISCONNECT_PORT)))
Sagar Dharia33beca02012-10-22 16:21:46 -0600338 return -EREMOTEIO;
339 timeout = wait_for_completion_timeout(&dev->ctrl_up,
340 HZ);
Sagar Dharia4f240722014-01-15 13:50:58 -0700341 if (!timeout && dev->state == MSM_CTRL_DOWN)
Sagar Dharia33beca02012-10-22 16:21:46 -0600342 return -ETIMEDOUT;
343 }
Sagar Dharia129c7d82013-08-08 19:35:50 -0600344 ret = msm_slim_get_ctrl(dev);
345 /*
346 * Runtime-pm's callbacks are not called until runtime-pm's
347 * error status is cleared
348 * Setting runtime status to suspended clears the error
349 * It also makes HW status cosistent with what SW has it here
350 */
351 if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
352 pm_runtime_set_suspended(dev->dev);
353 msm_slim_put_ctrl(dev);
354 return -EREMOTEIO;
Sagar Dhariad1468b72013-07-16 12:56:22 -0600355 } else if (ret >= 0) {
356 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia129c7d82013-08-08 19:35:50 -0600357 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600358 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600359 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600360
Sagar Dharia71fcea52012-09-12 23:21:57 -0600361 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
Sagar Dharia33beca02012-10-22 16:21:46 -0600362 (dev->state != MSM_CTRL_AWAKE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600363 dev_err(dev->dev, "controller not ready");
364 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600365 msm_slim_put_ctrl(dev);
366 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600367 }
368 if (txn->mt == SLIM_MSG_MT_CORE &&
369 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
370 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
371 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
372 int i = 0;
373 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
374 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
375 txn->mc = SLIM_USR_MC_CONNECT_SRC;
376 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
377 txn->mc = SLIM_USR_MC_CONNECT_SINK;
378 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
379 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600380 if (txn->la == SLIM_LA_MGR) {
381 if (dev->pgdla == SLIM_LA_MGR) {
382 u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
383 QC_MFGID_LSB};
384 ea[2] = (u8)(dev->pdata.eapc & 0xFF);
385 ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
386 mutex_unlock(&dev->tx_lock);
387 ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
388 &dev->pgdla);
389 pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
390 ret);
391 if (ret) {
392 pr_err("Incorrect SLIM-PGD EAPC:0x%x",
393 dev->pdata.eapc);
394 return ret;
395 }
396 mutex_lock(&dev->tx_lock);
397 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600398 txn->la = dev->pgdla;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600399 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600400 wbuf[i++] = txn->la;
401 la = SLIM_LA_MGR;
402 wbuf[i++] = txn->wbuf[0];
403 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
404 wbuf[i++] = txn->wbuf[1];
405 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
406 if (ret) {
407 pr_err("TID for connect/disconnect fail:%d", ret);
408 goto ngd_xfer_err;
409 }
410 txn->len = i;
411 txn->wbuf = wbuf;
412 txn->rl = txn->len + 4;
413 }
414 txn->rl--;
415 pbuf = msm_get_msg_buf(dev, txn->rl);
416 if (!pbuf) {
417 dev_err(dev->dev, "Message buffer unavailable");
418 ret = -ENOMEM;
419 goto ngd_xfer_err;
420 }
421 dev->err = 0;
422
423 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
424 ret = -EPROTONOSUPPORT;
425 goto ngd_xfer_err;
426 }
427 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
428 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
429 la);
430 else
431 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
432 la);
433 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
434 puc = ((u8 *)pbuf) + 3;
435 else
436 puc = ((u8 *)pbuf) + 2;
437 if (txn->rbuf)
438 *(puc++) = txn->tid;
439 if ((txn->mt == SLIM_MSG_MT_CORE) &&
440 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
441 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
442 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
443 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
444 *(puc++) = (txn->ec & 0xFF);
445 *(puc++) = (txn->ec >> 8)&0xFF;
446 }
447 if (txn->wbuf)
448 memcpy(puc, txn->wbuf, txn->len);
449 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
450 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
451 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
452 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
453 wbuf[0] == dev->pgdla) {
Sagar Dharia2d74c142013-05-17 02:24:06 -0600454 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600455 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
456 else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600457 /*
458 * Remove channel disconnects master-side ports from
459 * channel. No need to send that again on the bus
Sagar Dharia2d74c142013-05-17 02:24:06 -0600460 * Only disable port
Sagar Dharia71fcea52012-09-12 23:21:57 -0600461 */
Sagar Dharia2d74c142013-05-17 02:24:06 -0600462 writel_relaxed(0, PGD_PORT(PGD_PORT_CFGn,
463 (wbuf[1] + dev->port_b), dev->ver));
Sagar Dharia71fcea52012-09-12 23:21:57 -0600464 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700465 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600466 return 0;
467 }
468 if (dev->err) {
469 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
470 goto ngd_xfer_err;
471 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600472 /* Add port-base to port number if this is manager side port */
473 puc[1] += dev->port_b;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600474 }
475 dev->err = 0;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600476 /*
477 * If it's a read txn, it may be freed if a response is received by
478 * received thread before reaching end of this function.
479 * mc, mt may have changed to convert standard slimbus code/type to
480 * satellite user-defined message. Reinitialize again
481 */
482 txn_mc = txn->mc;
483 txn_mt = txn->mt;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600484 dev->wr_comp = &tx_sent;
485 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
486 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
487 if (!ret) {
488 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600489 if (!timeout) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600490 ret = -ETIMEDOUT;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600491 /*
492 * disconnect/recoonect pipe so that subsequent
493 * transactions don't timeout due to unavailable
494 * descriptors
495 */
496 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
497 &dev->use_tx_msgqs);
498 msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
499 } else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600500 ret = dev->err;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600501 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600502 }
503 dev->wr_comp = NULL;
504 if (ret) {
505 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
506 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
507 dev->ver);
508 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600509 txn_mc, txn_mt, ret, dev->ver);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600510 conf = readl_relaxed(ngd);
511 stat = readl_relaxed(ngd + NGD_STATUS);
512 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
513 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
514 int_en = readl_relaxed(ngd + NGD_INT_EN);
515 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
516
517 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
518 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
519 int_en, int_clr);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600520 } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
521 (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
522 txn_mc == SLIM_USR_MC_CONNECT_SINK ||
523 txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600524 int timeout;
525 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700526 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600527 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600528 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600529 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600530 else
531 ret = txn->ec;
532 if (ret) {
533 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
534 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700535 mutex_lock(&ctrl->m_ctrl);
536 ctrl->txnt[txn->tid] = NULL;
537 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600538 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600539 return ret ? ret : dev->err;
540 }
541ngd_xfer_err:
542 mutex_unlock(&dev->tx_lock);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600543 if (txn_mc != SLIM_USR_MC_REPORT_SATELLITE)
Sagar Dharia33beca02012-10-22 16:21:46 -0600544 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600545 return ret ? ret : dev->err;
546}
547
548static int ngd_xferandwait_ack(struct slim_controller *ctrl,
549 struct slim_msg_txn *txn)
550{
551 int ret = ngd_xfer_msg(ctrl, txn);
552 if (!ret) {
553 int timeout;
554 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600555 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600556 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600557 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600558 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600559 }
Sagar Dharia55bced82014-01-20 16:00:44 -0700560
Sagar Dharia33beca02012-10-22 16:21:46 -0600561 if (ret) {
Sagar Dharia21f88552014-02-07 00:10:37 -0700562 if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL)
563 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
Sagar Dharia71fcea52012-09-12 23:21:57 -0600564 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600565 mutex_lock(&ctrl->m_ctrl);
566 ctrl->txnt[txn->tid] = NULL;
567 mutex_unlock(&ctrl->m_ctrl);
568 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600569
570 return ret;
571}
572
573static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
574{
575 int ret;
576 struct slim_pending_ch *pch;
577 struct slim_msg_txn txn;
578 struct slim_controller *ctrl = sb->ctrl;
579 DECLARE_COMPLETION_ONSTACK(done);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600580 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600581
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600582 *clkgear = ctrl->clkgear;
583 *subfrmc = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600584 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
585 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
586 txn.la = SLIM_LA_MGR;
587 txn.len = 0;
588 txn.ec = 0;
589 txn.wbuf = wbuf;
590 txn.rbuf = NULL;
591
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600592 if (ctrl->sched.msgsl != ctrl->sched.pending_msgsl) {
593 pr_debug("slim reserve BW for messaging: req: %d",
594 ctrl->sched.pending_msgsl);
595 txn.mc = SLIM_USR_MC_REQ_BW;
596 wbuf[txn.len++] = ((sb->laddr & 0x1f) |
597 ((u8)(ctrl->sched.pending_msgsl & 0x7) << 5));
598 wbuf[txn.len++] = (u8)(ctrl->sched.pending_msgsl >> 3);
599 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
600 if (ret)
601 return ret;
602 txn.rl = txn.len + 4;
603 ret = ngd_xferandwait_ack(ctrl, &txn);
604 if (ret)
605 return ret;
606
607 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
608 txn.len = 2;
609 wbuf[1] = sb->laddr;
610 txn.rl = txn.len + 4;
611 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
612 if (ret)
613 return ret;
614 ret = ngd_xferandwait_ack(ctrl, &txn);
615 if (ret)
616 return ret;
617
618 txn.len = 0;
619 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600620 list_for_each_entry(pch, &sb->mark_define, pending) {
621 struct slim_ich *slc;
622 slc = &ctrl->chans[pch->chan];
623 if (!slc) {
624 pr_err("no channel in define?");
625 return -ENXIO;
626 }
627 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600628 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600629 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600630 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600631 wbuf[txn.len] = slc->seglen;
632 if (slc->coeff == SLIM_COEFF_3)
633 wbuf[txn.len] |= 1 << 5;
634 wbuf[txn.len++] |= slc->prop.auxf << 6;
635 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
636 wbuf[txn.len++] = slc->prrate;
637 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
638 if (ret) {
639 pr_err("no tid for channel define?");
640 return -ENXIO;
641 }
642 }
643 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600644 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600645 }
646 if (txn.len) {
647 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
648 txn.rl = txn.len + 4;
649 ret = ngd_xferandwait_ack(ctrl, &txn);
650 if (ret)
651 return ret;
652
653 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
654 txn.len = 2;
655 wbuf[1] = sb->laddr;
656 txn.rl = txn.len + 4;
657 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
658 if (ret)
659 return ret;
660 ret = ngd_xferandwait_ack(ctrl, &txn);
661 if (ret)
662 return ret;
663 }
664 txn.len = 0;
665 list_for_each_entry(pch, &sb->mark_removal, pending) {
666 struct slim_ich *slc;
667 slc = &ctrl->chans[pch->chan];
668 if (!slc) {
669 pr_err("no channel in removal?");
670 return -ENXIO;
671 }
672 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600673 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600674 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600675 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600676 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
677 if (ret) {
678 pr_err("no tid for channel define?");
679 return -ENXIO;
680 }
681 }
682 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600683 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600684 }
685 if (txn.len) {
686 txn.mc = SLIM_USR_MC_CHAN_CTRL;
687 txn.rl = txn.len + 4;
688 ret = ngd_xferandwait_ack(ctrl, &txn);
Sagar Dharia21f88552014-02-07 00:10:37 -0700689 /* HW restarting, channel removal should succeed */
690 if (ret == -EREMOTEIO)
691 return 0;
692 else if (ret)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600693 return ret;
694
695 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
696 txn.len = 2;
697 wbuf[1] = sb->laddr;
698 txn.rl = txn.len + 4;
699 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
700 if (ret)
701 return ret;
702 ret = ngd_xferandwait_ack(ctrl, &txn);
703 if (ret)
704 return ret;
705 txn.len = 0;
706 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700707 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600708}
709
710static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
711 u8 elen, u8 laddr)
712{
713 return 0;
714}
715
716static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
717 u8 elen, u8 *laddr)
718{
719 int ret;
720 u8 wbuf[10];
721 struct slim_msg_txn txn;
722 DECLARE_COMPLETION_ONSTACK(done);
723 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
724 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
725 txn.la = SLIM_LA_MGR;
726 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600727 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
728 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600729 return ret;
730 }
731 memcpy(&wbuf[1], ea, elen);
732 txn.mc = SLIM_USR_MC_ADDR_QUERY;
733 txn.rl = 11;
734 txn.len = 7;
735 txn.wbuf = wbuf;
736 txn.rbuf = NULL;
737 ret = ngd_xferandwait_ack(ctrl, &txn);
738 if (!ret && txn.la == 0xFF)
739 ret = -ENXIO;
740 else if (!ret)
741 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600742 return ret;
743}
744
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600745static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
Sagar Dharia24419e32013-01-14 17:56:32 -0700746{
Sagar Dharia24419e32013-01-14 17:56:32 -0700747 if (dev->state == MSM_CTRL_DOWN) {
748 msm_slim_sps_init(dev, dev->bam_mem,
749 NGD_BASE(dev->ctrl.nr,
750 dev->ver) + NGD_STATUS, true);
751 } else {
752 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600753 goto setup_tx_msg_path;
754 msm_slim_connect_endp(dev, &dev->rx_msgq,
Sagar Dharia24419e32013-01-14 17:56:32 -0700755 &dev->rx_msgq_notify);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600756
757setup_tx_msg_path:
758 if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
759 return;
760 msm_slim_connect_endp(dev, &dev->tx_msgq,
761 NULL);
Sagar Dharia24419e32013-01-14 17:56:32 -0700762 }
763}
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600764
Sagar Dharia71fcea52012-09-12 23:21:57 -0600765static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
766{
767 u8 mc, mt, len;
768 int ret;
769 u32 msgq_en = 1;
770
771 len = buf[0] & 0x1F;
772 mt = (buf[0] >> 5) & 0x7;
773 mc = buf[1];
774 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
775 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
776 struct slim_msg_txn txn;
Sagar Dharia0a693332013-04-15 17:59:03 -0600777 int retries = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600778 u8 wbuf[8];
779 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
780 txn.ec = 0;
781 txn.rbuf = NULL;
782 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
783 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
784 txn.la = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600785 wbuf[0] = SAT_MAGIC_LSB;
786 wbuf[1] = SAT_MAGIC_MSB;
787 wbuf[2] = SAT_MSG_VER;
788 wbuf[3] = SAT_MSG_PROT;
789 txn.wbuf = wbuf;
790 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700791 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700792 if (dev->state >= MSM_CTRL_ASLEEP) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600793 ngd_slim_setup_msg_path(dev);
Sagar Dharia24419e32013-01-14 17:56:32 -0700794 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600795 msgq_en |= NGD_CFG_RX_MSGQ_EN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600796 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
797 msgq_en |= NGD_CFG_TX_MSGQ_EN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600798 writel_relaxed(msgq_en, dev->base +
799 NGD_BASE(dev->ctrl.nr, dev->ver));
800 /* make sure NGD MSG-Q config goes through */
801 mb();
802 }
Sagar Dharia0a693332013-04-15 17:59:03 -0600803capability_retry:
804 txn.rl = 8;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600805 ret = ngd_xfer_msg(&dev->ctrl, &txn);
806 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600807 enum msm_ctrl_state prev_state = dev->state;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600808 pr_info("SLIM SAT: capability exchange successful");
Sagar Dharia71fcea52012-09-12 23:21:57 -0600809 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600810 if (prev_state >= MSM_CTRL_ASLEEP)
811 complete(&dev->reconf);
812 else
813 pr_err("SLIM: unexpected capability, state:%d",
814 prev_state);
815 /* ADSP SSR, send device_up notifications */
816 if (prev_state == MSM_CTRL_DOWN)
817 schedule_work(&dev->slave_notify);
Sagar Dharia0a693332013-04-15 17:59:03 -0600818 } else if (ret == -EIO) {
819 pr_info("capability message NACKed, retrying");
820 if (retries < INIT_MX_RETRIES) {
821 msleep(DEF_RETRY_MS);
822 retries++;
823 goto capability_retry;
824 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600825 }
826 }
827 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
828 mc == SLIM_MSG_MC_REPLY_VALUE) {
829 u8 tid = buf[3];
830 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
831 slim_msg_response(&dev->ctrl, &buf[4], tid,
832 len - 4);
833 pm_runtime_mark_last_busy(dev->dev);
834 }
835 if (mc == SLIM_USR_MC_ADDR_REPLY &&
836 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700837 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600838 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700839 mutex_lock(&dev->ctrl.m_ctrl);
840 txn = dev->ctrl.txnt[buf[3]];
841 if (!txn) {
842 pr_err("LADDR response after timeout, tid:0x%x",
843 buf[3]);
844 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600845 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700846 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600847 if (memcmp(&buf[4], failed_ea, 6))
848 txn->la = buf[10];
849 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700850 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600851 complete(txn->comp);
852 }
853 if (mc == SLIM_USR_MC_GENERIC_ACK &&
854 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700855 struct slim_msg_txn *txn;
856 mutex_lock(&dev->ctrl.m_ctrl);
857 txn = dev->ctrl.txnt[buf[3]];
858 if (!txn) {
859 pr_err("ACK received after timeout, tid:0x%x",
860 buf[3]);
861 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600862 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700863 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600864 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
865 (int)buf[3], buf[4]);
866 if (!(buf[4] & MSM_SAT_SUCCSS)) {
867 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
868 buf[4]);
869 txn->ec = -EIO;
870 }
871 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700872 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600873 complete(txn->comp);
874 }
875}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700876
Sagar Dharia33beca02012-10-22 16:21:46 -0600877static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700878{
Sagar Dharia33beca02012-10-22 16:21:46 -0600879 void __iomem *ngd;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600880 int timeout, ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600881 enum msm_ctrl_state cur_state = dev->state;
882 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700883 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700884 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
885 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
886 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600887
888 if (cur_state == MSM_CTRL_DOWN) {
889 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
890 HZ);
891 if (!timeout)
892 pr_err("slimbus QMI init timed out");
893 }
894
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600895 /* No need to vote if contorller is not in low power mode */
896 if (cur_state == MSM_CTRL_DOWN || cur_state == MSM_CTRL_ASLEEP) {
897 ret = msm_slim_qmi_power_request(dev, true);
898 if (ret) {
899 pr_err("SLIM QMI power request failed:%d", ret);
900 return ret;
901 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600902 }
903 if (!dev->ver) {
904 dev->ver = readl_relaxed(dev->base);
905 /* Version info in 16 MSbits */
906 dev->ver >>= 16;
907 }
908 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
909 laddr = readl_relaxed(ngd + NGD_STATUS);
910 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700911 /*
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600912 * external MDM restart case where ADSP itself was active framer
913 * For example, modem restarted when playback was active
914 */
915 if (cur_state == MSM_CTRL_AWAKE) {
916 pr_err("SLIM MDM restart: ADSP active framer:NO OP");
917 return 0;
918 }
919 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600920 * ADSP power collapse case, where HW wasn't reset.
921 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700922 */
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600923 ngd_slim_setup_msg_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600924 return 0;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600925 } else if (cur_state == MSM_CTRL_ASLEEP) {
926 pr_debug("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
Sagar Dharia33beca02012-10-22 16:21:46 -0600927 dev->state, laddr);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600928 } else if (cur_state == MSM_CTRL_IDLE || cur_state == MSM_CTRL_AWAKE) {
929 /*
930 * external MDM SSR when only voice call is in progress.
931 * ADSP will reset slimbus HW. disconnect BAM pipes so that
932 * they can be connected after capability message is received.
933 * Set device state to ASLEEP to be synchronous with the HW
934 */
935 pr_err("SLIM MDM restart: MDM active framer: reinit HW");
936 dev->state = MSM_CTRL_ASLEEP;
937 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
938 &dev->use_rx_msgqs);
939 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
940 &dev->use_tx_msgqs);
Sagar Dharia33beca02012-10-22 16:21:46 -0600941 }
Sagar Dhariada48bd62013-03-21 18:02:40 -0600942 /* ADSP SSR scenario, need to disconnect pipe before connecting */
943 if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
944 struct msm_slim_endp *endpoint = &dev->rx_msgq;
945 sps_disconnect(endpoint->sps);
946 sps_free_endpoint(endpoint->sps);
947 dev->use_rx_msgqs = MSM_MSGQ_RESET;
948 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600949 if (dev->use_tx_msgqs == MSM_MSGQ_DOWN) {
950 struct msm_slim_endp *endpoint = &dev->tx_msgq;
951 sps_disconnect(endpoint->sps);
952 sps_free_endpoint(endpoint->sps);
953 dev->use_tx_msgqs = MSM_MSGQ_RESET;
954 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600955 /*
956 * ADSP power collapse case (OR SSR), where HW was reset
957 * BAM programming will happen when capability message is received
958 */
959 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700960 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600961 /*
962 * Enable NGD. Configure NGD in register acc. mode until master
963 * announcement is received
964 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700965 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600966 /* make sure NGD enabling goes through */
967 mb();
968
969 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
970 if (!timeout) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600971 pr_err("Failed to receive master capability");
Sagar Dharia33beca02012-10-22 16:21:46 -0600972 return -ETIMEDOUT;
973 }
974 if (cur_state == MSM_CTRL_DOWN)
975 complete(&dev->ctrl_up);
976 return 0;
977}
978
979static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
980{
981 int ret = 0;
982 if (enable) {
983 ret = msm_slim_qmi_init(dev, false);
984 /* controller state should be in sync with framework state */
985 if (!ret) {
986 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
987 SLIM_CLK_UNSPECIFIED);
988 complete(&dev->qmi.qmi_comp);
989 /*
990 * Power-up won't be called if clock pause failed.
991 * This can happen if ADSP SSR happened when audio
992 * session is in progress. Framework will think that
993 * clock pause failed so no need to wakeup controller.
994 * Call power-up explicitly in that case, since slimbus
995 * HW needs to be powered-on to be in sync with
996 * framework state
997 */
998 if (ret)
999 ngd_slim_power_up(dev);
1000 if (!pm_runtime_enabled(dev->dev) ||
1001 !pm_runtime_suspended(dev->dev))
1002 ngd_slim_runtime_resume(dev->dev);
1003 else
1004 pm_runtime_resume(dev->dev);
1005 pm_runtime_mark_last_busy(dev->dev);
1006 pm_runtime_put(dev->dev);
1007 } else
1008 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
1009 ret, dev->state);
1010 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001011 msm_slim_qmi_exit(dev);
1012 }
1013
Sagar Dharia33beca02012-10-22 16:21:46 -06001014 return ret;
1015}
1016
1017static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
1018{
1019 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
1020 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001021}
1022
Sagar Dharia71fcea52012-09-12 23:21:57 -06001023static int ngd_slim_rx_msgq_thread(void *data)
1024{
1025 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
1026 struct completion *notify = &dev->rx_msgq_notify;
1027 int ret = 0, index = 0;
1028 u32 mc = 0;
1029 u32 mt = 0;
1030 u32 buffer[10];
1031 u8 msg_len = 0;
1032
1033 while (!kthread_should_stop()) {
1034 set_current_state(TASK_INTERRUPTIBLE);
1035 ret = wait_for_completion_interruptible(notify);
1036 if (ret) {
1037 dev_err(dev->dev, "rx thread wait err:%d", ret);
1038 continue;
1039 }
1040 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -07001041 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001042 msm_slim_rx_dequeue(dev, (u8 *)buffer);
1043 ngd_slim_rx(dev, (u8 *)buffer);
1044 continue;
1045 }
1046 ret = msm_slim_rx_msgq_get(dev, buffer, index);
1047 if (ret) {
1048 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
1049 continue;
1050 }
1051
1052 /* Wait for complete message */
1053 if (index++ == 0) {
1054 msg_len = *buffer & 0x1F;
1055 mt = (buffer[0] >> 5) & 0x7;
1056 mc = (buffer[0] >> 8) & 0xff;
1057 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
1058 }
1059 if ((index * 4) >= msg_len) {
1060 index = 0;
1061 ngd_slim_rx(dev, (u8 *)buffer);
1062 } else
1063 continue;
1064 }
1065 return 0;
1066}
1067
Sagar Dharia33beca02012-10-22 16:21:46 -06001068static void ngd_laddr_lookup(struct work_struct *work)
1069{
1070 struct msm_slim_ctrl *dev =
1071 container_of(work, struct msm_slim_ctrl, slave_notify);
1072 struct slim_controller *ctrl = &dev->ctrl;
1073 struct slim_device *sbdev;
Sagar Dharia21f88552014-02-07 00:10:37 -07001074 struct list_head *pos, *next;
Sagar Dharia33beca02012-10-22 16:21:46 -06001075 int i;
Sagar Dharia722f9e22013-12-11 23:59:22 -07001076 slim_framer_booted(ctrl);
Sagar Dharia33beca02012-10-22 16:21:46 -06001077 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia21f88552014-02-07 00:10:37 -07001078 list_for_each_safe(pos, next, &ctrl->devs) {
Sagar Dharia33beca02012-10-22 16:21:46 -06001079 int ret = 0;
Sagar Dharia21f88552014-02-07 00:10:37 -07001080 sbdev = list_entry(pos, struct slim_device, dev_list);
Sagar Dharia33beca02012-10-22 16:21:46 -06001081 mutex_unlock(&ctrl->m_ctrl);
1082 for (i = 0; i < LADDR_RETRY; i++) {
1083 ret = slim_get_logical_addr(sbdev, sbdev->e_addr,
1084 6, &sbdev->laddr);
1085 if (!ret)
1086 break;
1087 else /* time for ADSP to assign LA */
1088 msleep(20);
1089 }
1090 mutex_lock(&ctrl->m_ctrl);
1091 }
1092 mutex_unlock(&ctrl->m_ctrl);
1093}
1094
1095static void ngd_adsp_down(struct work_struct *work)
1096{
1097 struct msm_slim_qmi *qmi =
1098 container_of(work, struct msm_slim_qmi, ssr_down);
1099 struct msm_slim_ctrl *dev =
1100 container_of(qmi, struct msm_slim_ctrl, qmi);
1101 struct slim_controller *ctrl = &dev->ctrl;
1102 struct slim_device *sbdev;
Sagar Dharia33beca02012-10-22 16:21:46 -06001103
1104 ngd_slim_enable(dev, false);
1105 /* disconnect BAM pipes */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001106 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
1107 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001108 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
1109 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -06001110 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001111 /* device up should be called again after SSR */
1112 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
Sagar Dhariaf68d71f2013-07-31 17:43:46 -06001113 slim_report_absent(sbdev);
Sagar Dharia33beca02012-10-22 16:21:46 -06001114 pr_info("SLIM ADSP SSR (DOWN) done");
1115}
1116
1117static void ngd_adsp_up(struct work_struct *work)
1118{
1119 struct msm_slim_qmi *qmi =
1120 container_of(work, struct msm_slim_qmi, ssr_up);
1121 struct msm_slim_ctrl *dev =
1122 container_of(qmi, struct msm_slim_ctrl, qmi);
1123 ngd_slim_enable(dev, true);
1124}
1125
Sagar Dharia71fcea52012-09-12 23:21:57 -06001126static int __devinit ngd_slim_probe(struct platform_device *pdev)
1127{
1128 struct msm_slim_ctrl *dev;
1129 int ret;
1130 struct resource *bam_mem;
1131 struct resource *slim_mem;
1132 struct resource *irq, *bam_irq;
1133 enum apr_subsys_state q6_state;
Sagar Dharia24419e32013-01-14 17:56:32 -07001134 bool rxreg_access = false;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001135 bool slim_mdm = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001136
1137 q6_state = apr_get_q6_state();
1138 if (q6_state == APR_SUBSYS_DOWN) {
1139 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
1140 q6_state);
1141 return -EPROBE_DEFER;
1142 } else
1143 dev_dbg(&pdev->dev, "adsp is ready\n");
1144
1145 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1146 "slimbus_physical");
1147 if (!slim_mem) {
1148 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
1149 return -ENODEV;
1150 }
1151 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1152 "slimbus_bam_physical");
1153 if (!bam_mem) {
1154 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
1155 return -ENODEV;
1156 }
1157 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1158 "slimbus_irq");
1159 if (!irq) {
1160 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
1161 return -ENODEV;
1162 }
1163 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1164 "slimbus_bam_irq");
1165 if (!bam_irq) {
1166 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
1167 return -ENODEV;
1168 }
1169
1170 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
Kiran Gunda318cac42013-10-21 17:00:15 +05301171 if (IS_ERR_OR_NULL(dev)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001172 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
1173 return PTR_ERR(dev);
1174 }
1175 dev->dev = &pdev->dev;
1176 platform_set_drvdata(pdev, dev);
1177 slim_set_ctrldata(&dev->ctrl, dev);
1178 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
1179 if (!dev->base) {
1180 dev_err(&pdev->dev, "IOremap failed\n");
1181 ret = -ENOMEM;
1182 goto err_ioremap_failed;
1183 }
1184 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
1185 if (!dev->bam.base) {
1186 dev_err(&pdev->dev, "BAM IOremap failed\n");
1187 ret = -ENOMEM;
1188 goto err_ioremap_bam_failed;
1189 }
1190 if (pdev->dev.of_node) {
1191
1192 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1193 &dev->ctrl.nr);
1194 if (ret) {
1195 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1196 goto err_ctrl_failed;
1197 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001198 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1199 "qcom,rxreg-access");
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001200 of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
1201 &dev->pdata.apps_pipes);
1202 of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
1203 &dev->pdata.eapc);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001204 slim_mdm = of_property_read_bool(pdev->dev.of_node,
1205 "qcom,slim-mdm");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001206 } else {
1207 dev->ctrl.nr = pdev->id;
1208 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001209 /*
1210 * Keep PGD's logical address as manager's. Query it when first data
1211 * channel request comes in
1212 */
1213 dev->pgdla = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001214 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1215 dev->ctrl.nports = MSM_SLIM_NPORTS;
1216 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1217 dev->framer.superfreq =
1218 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1219 dev->ctrl.a_framer = &dev->framer;
1220 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1221 dev->ctrl.set_laddr = ngd_set_laddr;
1222 dev->ctrl.get_laddr = ngd_get_laddr;
1223 dev->ctrl.allocbw = ngd_allocbw;
1224 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001225 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia100e7212013-05-17 18:20:57 -06001226 dev->ctrl.alloc_port = msm_alloc_port;
1227 dev->ctrl.dealloc_port = msm_dealloc_port;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001228 dev->ctrl.port_xfer = msm_slim_port_xfer;
1229 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001230 dev->bam_mem = bam_mem;
1231
1232 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001233 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001234 mutex_init(&dev->tx_lock);
1235 spin_lock_init(&dev->rx_lock);
1236 dev->ee = 1;
1237 dev->irq = irq->start;
1238 dev->bam.irq = bam_irq->start;
1239
Sagar Dharia24419e32013-01-14 17:56:32 -07001240 if (rxreg_access)
1241 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1242 else
1243 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001244
1245 /* Enable TX message queues by default as recommended by HW */
1246 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1247
Sagar Dharia71fcea52012-09-12 23:21:57 -06001248 init_completion(&dev->rx_msgq_notify);
1249
1250 /* Register with framework */
1251 ret = slim_add_numbered_controller(&dev->ctrl);
1252 if (ret) {
1253 dev_err(dev->dev, "error adding controller\n");
1254 goto err_ctrl_failed;
1255 }
1256
1257 dev->ctrl.dev.parent = &pdev->dev;
1258 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001259 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001260
1261 ret = request_irq(dev->irq, ngd_slim_interrupt,
1262 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1263
1264 if (ret) {
1265 dev_err(&pdev->dev, "request IRQ failed\n");
1266 goto err_request_irq_failed;
1267 }
1268
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001269 init_completion(&dev->qmi.qmi_comp);
Sagar Dharia33beca02012-10-22 16:21:46 -06001270 pm_runtime_use_autosuspend(dev->dev);
1271 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1272 pm_runtime_set_suspended(dev->dev);
1273 pm_runtime_enable(dev->dev);
1274
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001275 if (slim_mdm) {
1276 dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
1277 dev->mdm.ssr = subsys_notif_register_notifier("external_modem",
1278 &dev->mdm.nb);
1279 if (IS_ERR_OR_NULL(dev->mdm.ssr))
1280 dev_err(dev->dev,
1281 "subsys_notif_register_notifier failed %p",
1282 dev->mdm.ssr);
1283 }
1284
Sagar Dharia33beca02012-10-22 16:21:46 -06001285 INIT_WORK(&dev->slave_notify, ngd_laddr_lookup);
1286 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1287 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001288 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001289 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001290 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001291 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001292 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1293 if (ret) {
1294 pr_err("Slimbus QMI service registration failed:%d", ret);
1295 goto qmi_register_failed;
1296 }
1297
Sagar Dharia33beca02012-10-22 16:21:46 -06001298
Sagar Dharia71fcea52012-09-12 23:21:57 -06001299 /* Fire up the Rx message queue thread */
1300 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
1301 NGD_SLIM_NAME "_ngd_msgq_thread");
1302 if (IS_ERR(dev->rx_msgq_thread)) {
1303 ret = PTR_ERR(dev->rx_msgq_thread);
1304 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
1305 goto err_thread_create_failed;
1306 }
1307
Sagar Dharia71fcea52012-09-12 23:21:57 -06001308 if (pdev->dev.of_node)
1309 of_register_slim_devices(&dev->ctrl);
1310
1311 /* Add devices registered with board-info now that controller is up */
1312 slim_ctrl_add_boarddevs(&dev->ctrl);
1313
Sagar Dharia71fcea52012-09-12 23:21:57 -06001314 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1315 return 0;
1316
1317err_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001318 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001319 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001320 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1321qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001322 free_irq(dev->irq, dev);
1323err_request_irq_failed:
1324 slim_del_controller(&dev->ctrl);
1325err_ctrl_failed:
1326 iounmap(dev->bam.base);
1327err_ioremap_bam_failed:
1328 iounmap(dev->base);
1329err_ioremap_failed:
1330 kfree(dev);
1331 return ret;
1332}
1333
1334static int __devexit ngd_slim_remove(struct platform_device *pdev)
1335{
1336 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001337 ngd_slim_enable(dev, false);
1338 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001339 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001340 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001341 pm_runtime_disable(&pdev->dev);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001342 if (!IS_ERR_OR_NULL(dev->mdm.ssr))
1343 subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001344 free_irq(dev->irq, dev);
1345 slim_del_controller(&dev->ctrl);
1346 kthread_stop(dev->rx_msgq_thread);
1347 iounmap(dev->bam.base);
1348 iounmap(dev->base);
1349 kfree(dev);
1350 return 0;
1351}
1352
1353#ifdef CONFIG_PM_RUNTIME
1354static int ngd_slim_runtime_idle(struct device *device)
1355{
Sagar Dhariad1468b72013-07-16 12:56:22 -06001356 struct platform_device *pdev = to_platform_device(device);
1357 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1358 if (dev->state == MSM_CTRL_AWAKE)
1359 dev->state = MSM_CTRL_IDLE;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001360 dev_dbg(device, "pm_runtime: idle...\n");
1361 pm_request_autosuspend(device);
1362 return -EAGAIN;
1363}
1364#endif
1365
1366/*
1367 * If PM_RUNTIME is not defined, these 2 functions become helper
1368 * functions to be called from system suspend/resume. So they are not
1369 * inside ifdef CONFIG_PM_RUNTIME
1370 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001371static int ngd_slim_runtime_resume(struct device *device)
1372{
1373 struct platform_device *pdev = to_platform_device(device);
1374 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1375 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001376 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001377 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1378 if (ret) {
Sagar Dharia129c7d82013-08-08 19:35:50 -06001379 /* Did SSR cause this clock pause failure */
1380 if (dev->state != MSM_CTRL_DOWN)
1381 dev->state = MSM_CTRL_ASLEEP;
1382 else
1383 dev_err(device, "HW wakeup attempt during SSR");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001384 } else {
1385 dev->state = MSM_CTRL_AWAKE;
1386 }
1387 return ret;
1388}
1389
Sagar Dharia33beca02012-10-22 16:21:46 -06001390#ifdef CONFIG_PM_SLEEP
1391static int ngd_slim_runtime_suspend(struct device *device)
1392{
1393 struct platform_device *pdev = to_platform_device(device);
1394 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1395 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001396 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1397 if (ret) {
1398 if (ret != -EBUSY)
1399 dev_err(device, "clk pause not entered:%d", ret);
1400 dev->state = MSM_CTRL_AWAKE;
1401 } else {
1402 dev->state = MSM_CTRL_ASLEEP;
1403 }
1404 return ret;
1405}
1406
Sagar Dharia71fcea52012-09-12 23:21:57 -06001407static int ngd_slim_suspend(struct device *dev)
1408{
1409 int ret = -EBUSY;
Sagar Dhariad1468b72013-07-16 12:56:22 -06001410 struct platform_device *pdev = to_platform_device(dev);
1411 struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
1412 if (!pm_runtime_enabled(dev) ||
1413 (!pm_runtime_suspended(dev) &&
1414 cdev->state == MSM_CTRL_IDLE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001415 dev_dbg(dev, "system suspend");
1416 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001417 /*
1418 * If runtime-PM still thinks it's active, then make sure its
1419 * status is in sync with HW status.
1420 * Since this suspend calls QMI api, it results in holding a
1421 * wakelock. That results in failure of first suspend.
1422 * Subsequent suspend should not call low-power transition
1423 * again since the HW is already in suspended state.
1424 */
1425 if (!ret) {
1426 pm_runtime_disable(dev);
1427 pm_runtime_set_suspended(dev);
1428 pm_runtime_enable(dev);
1429 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001430 }
1431 if (ret == -EBUSY) {
1432 /*
1433 * There is a possibility that some audio stream is active
1434 * during suspend. We dont want to return suspend failure in
1435 * that case so that display and relevant components can still
1436 * go to suspend.
1437 * If there is some other error, then it should be passed-on
1438 * to system level suspend
1439 */
1440 ret = 0;
1441 }
1442 return ret;
1443}
1444
1445static int ngd_slim_resume(struct device *dev)
1446{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001447 /*
1448 * Rely on runtime-PM to call resume in case it is enabled.
1449 * Even if it's not enabled, rely on 1st client transaction to do
1450 * clock/power on
1451 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001452 return 0;
1453}
1454#endif /* CONFIG_PM_SLEEP */
1455
1456static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1457 SET_SYSTEM_SLEEP_PM_OPS(
1458 ngd_slim_suspend,
1459 ngd_slim_resume
1460 )
1461 SET_RUNTIME_PM_OPS(
1462 ngd_slim_runtime_suspend,
1463 ngd_slim_runtime_resume,
1464 ngd_slim_runtime_idle
1465 )
1466};
1467
1468static struct of_device_id ngd_slim_dt_match[] = {
1469 {
1470 .compatible = "qcom,slim-ngd",
1471 },
1472 {}
1473};
1474
1475static struct platform_driver ngd_slim_driver = {
1476 .probe = ngd_slim_probe,
1477 .remove = ngd_slim_remove,
1478 .driver = {
1479 .name = NGD_SLIM_NAME,
1480 .owner = THIS_MODULE,
1481 .pm = &ngd_slim_dev_pm_ops,
1482 .of_match_table = ngd_slim_dt_match,
1483 },
1484};
1485
1486static int ngd_slim_init(void)
1487{
1488 return platform_driver_register(&ngd_slim_driver);
1489}
1490late_initcall(ngd_slim_init);
1491
1492static void ngd_slim_exit(void)
1493{
1494 platform_driver_unregister(&ngd_slim_driver);
1495}
1496module_exit(ngd_slim_exit);
1497
1498MODULE_LICENSE("GPL v2");
1499MODULE_DESCRIPTION("MSM Slimbus controller");
1500MODULE_ALIAS("platform:msm-slim-ngd");