blob: 10c69c31c798db7ae8272194bb828e9629658e73 [file] [log] [blame]
Sagar Dharia33beca02012-10-22 16:21:46 -06001/* Copyright (c) 2011-2013, 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 */
12
13#include <linux/irq.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/io.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h>
20#include <linux/dma-mapping.h>
21#include <linux/slimbus/slimbus.h>
22#include <linux/delay.h>
23#include <linux/kthread.h>
24#include <linux/clk.h>
25#include <linux/pm_runtime.h>
26#include <linux/of.h>
27#include <linux/of_slimbus.h>
28#include <linux/timer.h>
29#include <mach/sps.h>
30#include "slim-msm.h"
31#include <mach/qdsp6v2/apr.h>
32
33#define NGD_SLIM_NAME "ngd_msm_ctrl"
34#define SLIM_LA_MGR 0xFF
35#define SLIM_ROOT_FREQ 24576000
Sagar Dharia33beca02012-10-22 16:21:46 -060036#define LADDR_RETRY 5
Sagar Dharia71fcea52012-09-12 23:21:57 -060037
38#define NGD_BASE_V1(r) (((r) % 2) ? 0x800 : 0xA00)
39#define NGD_BASE_V2(r) (((r) % 2) ? 0x1000 : 0x2000)
40#define NGD_BASE(r, v) ((v) ? NGD_BASE_V2(r) : NGD_BASE_V1(r))
41/* NGD (Non-ported Generic Device) registers */
42enum ngd_reg {
43 NGD_CFG = 0x0,
44 NGD_STATUS = 0x4,
45 NGD_RX_MSGQ_CFG = 0x8,
46 NGD_INT_EN = 0x10,
47 NGD_INT_STAT = 0x14,
48 NGD_INT_CLR = 0x18,
49 NGD_TX_MSG = 0x30,
50 NGD_RX_MSG = 0x70,
51 NGD_IE_STAT = 0xF0,
52 NGD_VE_STAT = 0x100,
53};
54
55enum ngd_msg_cfg {
56 NGD_CFG_ENABLE = 1,
57 NGD_CFG_RX_MSGQ_EN = 1 << 1,
58 NGD_CFG_TX_MSGQ_EN = 1 << 2,
59};
60
61enum ngd_intr {
62 NGD_INT_RECFG_DONE = 1 << 24,
63 NGD_INT_TX_NACKED_2 = 1 << 25,
64 NGD_INT_MSG_BUF_CONTE = 1 << 26,
65 NGD_INT_MSG_TX_INVAL = 1 << 27,
66 NGD_INT_IE_VE_CHG = 1 << 28,
67 NGD_INT_DEV_ERR = 1 << 29,
68 NGD_INT_RX_MSG_RCVD = 1 << 30,
69 NGD_INT_TX_MSG_SENT = 1 << 31,
70};
71
72enum ngd_offsets {
73 NGD_NACKED_MC = 0x7F00000,
74 NGD_ACKED_MC = 0xFE000,
75 NGD_ERROR = 0x1800,
76 NGD_MSGQ_SUPPORT = 0x400,
77 NGD_RX_MSGQ_TIME_OUT = 0x16,
78 NGD_ENUMERATED = 0x1,
79 NGD_TX_BUSY = 0x0,
80};
81
Sagar Dharia33beca02012-10-22 16:21:46 -060082enum ngd_status {
83 NGD_LADDR = 1 << 1,
84};
85
86static int ngd_slim_runtime_resume(struct device *device);
87
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);
93
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 }
151 return IRQ_HANDLED;
152}
153
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700154static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
155 void *_cmd)
156{
157 struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
Sagar Dharia33beca02012-10-22 16:21:46 -0600158 struct msm_slim_ctrl *dev =
159 container_of(qmi, struct msm_slim_ctrl, qmi);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700160 pr_info("Slimbus QMI NGD CB received event:%ld", code);
161 switch (code) {
162 case QMI_SERVER_ARRIVE:
Sagar Dharia33beca02012-10-22 16:21:46 -0600163 schedule_work(&qmi->ssr_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700164 break;
165 case QMI_SERVER_EXIT:
Sagar Dharia33beca02012-10-22 16:21:46 -0600166 dev->state = MSM_CTRL_DOWN;
167 /* make sure autosuspend is not called until ADSP comes up*/
168 pm_runtime_get_noresume(dev->dev);
169 /* Reset ctrl_up completion */
170 init_completion(&dev->ctrl_up);
171 schedule_work(&qmi->ssr_down);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700172 break;
173 default:
174 break;
175 }
176 return 0;
177}
178
Sagar Dharia71fcea52012-09-12 23:21:57 -0600179static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
180 u8 *tid, struct completion *done)
181{
182 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700183 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600184 if (ctrl->last_tid <= 255) {
185 ctrl->txnt = krealloc(ctrl->txnt,
186 (ctrl->last_tid + 1) *
187 sizeof(struct slim_msg_txn *),
188 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700189 if (!ctrl->txnt) {
190 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600191 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700192 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600193 dev->msg_cnt = ctrl->last_tid;
194 ctrl->last_tid++;
195 } else {
196 int i;
197 for (i = 0; i < 256; i++) {
198 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
199 if (ctrl->txnt[dev->msg_cnt] == NULL)
200 break;
201 }
202 if (i >= 256) {
203 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700204 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600205 return -ENOMEM;
206 }
207 }
208 ctrl->txnt[dev->msg_cnt] = txn;
209 txn->tid = dev->msg_cnt;
210 txn->comp = done;
211 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700212 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600213 return 0;
214}
215static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
216{
217 DECLARE_COMPLETION_ONSTACK(done);
218 DECLARE_COMPLETION_ONSTACK(tx_sent);
219
220 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
221 u32 *pbuf;
222 u8 *puc;
223 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600224 u8 la = txn->la;
225 u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
226
Sagar Dhariaa1398282013-01-22 13:26:20 -0700227 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
228 txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
229 /*
230 * Counter-part of system-suspend when runtime-pm is not enabled
231 * This way, resume can be left empty and device will be put in
232 * active mode only if client requests anything on the bus
233 * If the state was DOWN, SSR UP notification will take
234 * care of putting the device in active state.
235 */
236 ngd_slim_runtime_resume(dev->dev);
237 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700238 if (txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
Sagar Dharia24419e32013-01-14 17:56:32 -0700239 SLIM_MSG_MC_RECONFIGURE_NOW)) {
240 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
241 ret = sps_disconnect(dev->rx_msgq.sps);
242 dev->use_rx_msgqs = MSM_MSGQ_RESET;
243 }
244 if (!ret)
245 ret = msm_slim_qmi_power_request(dev, false);
246 else
247 pr_err("SPS pipe disconnect error:%d", ret);
248 return ret;
249 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700250 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
251 return 0;
252
Sagar Dharia71fcea52012-09-12 23:21:57 -0600253 if (txn->mt == SLIM_MSG_MT_CORE &&
254 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
255 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
256 return 0;
257 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600258 /* If txn is tried when controller is down, wait for ADSP to boot */
259 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
260 if (dev->state == MSM_CTRL_DOWN) {
261 u8 mc = (u8)txn->mc;
262 int timeout;
263 dev_err(dev->dev, "ADSP slimbus not up yet");
264 /*
265 * Messages related to data channel management can't
266 * wait since they are holding reconfiguration lock.
267 * clk_pause in resume (which can change state back to
268 * MSM_CTRL_AWAKE), will need that lock
269 */
270 if ((txn->mt == SLIM_MSG_MT_CORE) &&
271 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
272 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
273 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
274 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
275 return -EREMOTEIO;
276 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
277 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
278 mc <= SLIM_USR_MC_DISCONNECT_PORT)))
279 return -EREMOTEIO;
280 timeout = wait_for_completion_timeout(&dev->ctrl_up,
281 HZ);
282 if (!timeout)
283 return -ETIMEDOUT;
284 }
285 msm_slim_get_ctrl(dev);
286 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600287 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600288
Sagar Dharia71fcea52012-09-12 23:21:57 -0600289 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
Sagar Dharia33beca02012-10-22 16:21:46 -0600290 (dev->state != MSM_CTRL_AWAKE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600291 dev_err(dev->dev, "controller not ready");
292 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600293 msm_slim_put_ctrl(dev);
294 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600295 }
296 if (txn->mt == SLIM_MSG_MT_CORE &&
297 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
298 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
299 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
300 int i = 0;
301 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
302 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
303 txn->mc = SLIM_USR_MC_CONNECT_SRC;
304 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
305 txn->mc = SLIM_USR_MC_CONNECT_SINK;
306 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
307 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
308 if (txn->la == SLIM_LA_MGR)
309 txn->la = dev->pgdla;
310 wbuf[i++] = txn->la;
311 la = SLIM_LA_MGR;
312 wbuf[i++] = txn->wbuf[0];
313 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
314 wbuf[i++] = txn->wbuf[1];
315 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
316 if (ret) {
317 pr_err("TID for connect/disconnect fail:%d", ret);
318 goto ngd_xfer_err;
319 }
320 txn->len = i;
321 txn->wbuf = wbuf;
322 txn->rl = txn->len + 4;
323 }
324 txn->rl--;
325 pbuf = msm_get_msg_buf(dev, txn->rl);
326 if (!pbuf) {
327 dev_err(dev->dev, "Message buffer unavailable");
328 ret = -ENOMEM;
329 goto ngd_xfer_err;
330 }
331 dev->err = 0;
332
333 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
334 ret = -EPROTONOSUPPORT;
335 goto ngd_xfer_err;
336 }
337 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
338 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
339 la);
340 else
341 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
342 la);
343 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
344 puc = ((u8 *)pbuf) + 3;
345 else
346 puc = ((u8 *)pbuf) + 2;
347 if (txn->rbuf)
348 *(puc++) = txn->tid;
349 if ((txn->mt == SLIM_MSG_MT_CORE) &&
350 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
351 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
352 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
353 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
354 *(puc++) = (txn->ec & 0xFF);
355 *(puc++) = (txn->ec >> 8)&0xFF;
356 }
357 if (txn->wbuf)
358 memcpy(puc, txn->wbuf, txn->len);
359 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
360 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
361 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
362 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
363 wbuf[0] == dev->pgdla) {
364 if (txn->mc != SLIM_MSG_MC_DISCONNECT_PORT)
365 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
366 else {
367 struct msm_slim_endp *endpoint = &dev->pipes[wbuf[1]];
368 struct sps_register_event sps_event;
369 memset(&sps_event, 0, sizeof(sps_event));
370 sps_register_event(endpoint->sps, &sps_event);
371 sps_disconnect(endpoint->sps);
372 /*
373 * Remove channel disconnects master-side ports from
374 * channel. No need to send that again on the bus
375 */
376 dev->pipes[wbuf[1]].connected = false;
377 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700378 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600379 return 0;
380 }
381 if (dev->err) {
382 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
383 goto ngd_xfer_err;
384 }
385 }
386 dev->err = 0;
387 dev->wr_comp = &tx_sent;
388 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
389 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
390 if (!ret) {
391 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
392 if (!timeout)
393 ret = -ETIMEDOUT;
394 else
395 ret = dev->err;
396 }
397 dev->wr_comp = NULL;
398 if (ret) {
399 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
400 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
401 dev->ver);
402 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
403 txn->mc, txn->mt, ret, dev->ver);
404 conf = readl_relaxed(ngd);
405 stat = readl_relaxed(ngd + NGD_STATUS);
406 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
407 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
408 int_en = readl_relaxed(ngd + NGD_INT_EN);
409 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
410
411 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
412 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
413 int_en, int_clr);
414 } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
415 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
416 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
417 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
418 int timeout;
419 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700420 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600421 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600422 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600423 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600424 else
425 ret = txn->ec;
426 if (ret) {
427 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
428 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700429 mutex_lock(&ctrl->m_ctrl);
430 ctrl->txnt[txn->tid] = NULL;
431 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600432 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600433 return ret ? ret : dev->err;
434 }
435ngd_xfer_err:
436 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600437 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE)
438 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600439 return ret ? ret : dev->err;
440}
441
442static int ngd_xferandwait_ack(struct slim_controller *ctrl,
443 struct slim_msg_txn *txn)
444{
445 int ret = ngd_xfer_msg(ctrl, txn);
446 if (!ret) {
447 int timeout;
448 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600449 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600450 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600451 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600452 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600453 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600454 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600455 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
456 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600457 mutex_lock(&ctrl->m_ctrl);
458 ctrl->txnt[txn->tid] = NULL;
459 mutex_unlock(&ctrl->m_ctrl);
460 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600461
462 return ret;
463}
464
465static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
466{
467 int ret;
468 struct slim_pending_ch *pch;
469 struct slim_msg_txn txn;
470 struct slim_controller *ctrl = sb->ctrl;
471 DECLARE_COMPLETION_ONSTACK(done);
472 u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
473
474 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
475 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
476 txn.la = SLIM_LA_MGR;
477 txn.len = 0;
478 txn.ec = 0;
479 txn.wbuf = wbuf;
480 txn.rbuf = NULL;
481
482 list_for_each_entry(pch, &sb->mark_define, pending) {
483 struct slim_ich *slc;
484 slc = &ctrl->chans[pch->chan];
485 if (!slc) {
486 pr_err("no channel in define?");
487 return -ENXIO;
488 }
489 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600490 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600491 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600492 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600493 wbuf[txn.len] = slc->seglen;
494 if (slc->coeff == SLIM_COEFF_3)
495 wbuf[txn.len] |= 1 << 5;
496 wbuf[txn.len++] |= slc->prop.auxf << 6;
497 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
498 wbuf[txn.len++] = slc->prrate;
499 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
500 if (ret) {
501 pr_err("no tid for channel define?");
502 return -ENXIO;
503 }
504 }
505 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600506 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600507 }
508 if (txn.len) {
509 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
510 txn.rl = txn.len + 4;
511 ret = ngd_xferandwait_ack(ctrl, &txn);
512 if (ret)
513 return ret;
514
515 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
516 txn.len = 2;
517 wbuf[1] = sb->laddr;
518 txn.rl = txn.len + 4;
519 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
520 if (ret)
521 return ret;
522 ret = ngd_xferandwait_ack(ctrl, &txn);
523 if (ret)
524 return ret;
525 }
526 txn.len = 0;
527 list_for_each_entry(pch, &sb->mark_removal, pending) {
528 struct slim_ich *slc;
529 slc = &ctrl->chans[pch->chan];
530 if (!slc) {
531 pr_err("no channel in removal?");
532 return -ENXIO;
533 }
534 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600535 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600536 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600537 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600538 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
539 if (ret) {
540 pr_err("no tid for channel define?");
541 return -ENXIO;
542 }
543 }
544 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600545 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600546 }
547 if (txn.len) {
548 txn.mc = SLIM_USR_MC_CHAN_CTRL;
549 txn.rl = txn.len + 4;
550 ret = ngd_xferandwait_ack(ctrl, &txn);
551 if (ret)
552 return ret;
553
554 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
555 txn.len = 2;
556 wbuf[1] = sb->laddr;
557 txn.rl = txn.len + 4;
558 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
559 if (ret)
560 return ret;
561 ret = ngd_xferandwait_ack(ctrl, &txn);
562 if (ret)
563 return ret;
564 txn.len = 0;
565 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700566 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600567}
568
569static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
570 u8 elen, u8 laddr)
571{
572 return 0;
573}
574
575static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
576 u8 elen, u8 *laddr)
577{
578 int ret;
579 u8 wbuf[10];
580 struct slim_msg_txn txn;
581 DECLARE_COMPLETION_ONSTACK(done);
582 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
583 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
584 txn.la = SLIM_LA_MGR;
585 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600586 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
587 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600588 return ret;
589 }
590 memcpy(&wbuf[1], ea, elen);
591 txn.mc = SLIM_USR_MC_ADDR_QUERY;
592 txn.rl = 11;
593 txn.len = 7;
594 txn.wbuf = wbuf;
595 txn.rbuf = NULL;
596 ret = ngd_xferandwait_ack(ctrl, &txn);
597 if (!ret && txn.la == 0xFF)
598 ret = -ENXIO;
599 else if (!ret)
600 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600601 return ret;
602}
603
Sagar Dharia24419e32013-01-14 17:56:32 -0700604static void ngd_slim_setup_rx_path(struct msm_slim_ctrl *dev)
605{
606 int ret;
607 if (dev->state == MSM_CTRL_DOWN) {
608 msm_slim_sps_init(dev, dev->bam_mem,
609 NGD_BASE(dev->ctrl.nr,
610 dev->ver) + NGD_STATUS, true);
611 } else {
612 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
613 return;
614 ret = msm_slim_connect_endp(dev, &dev->rx_msgq,
615 &dev->rx_msgq_notify);
616 if (!ret)
617 dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
618 else
619 pr_err("RX msgq not being used:%d", ret);
620 }
621}
Sagar Dharia71fcea52012-09-12 23:21:57 -0600622static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
623{
624 u8 mc, mt, len;
625 int ret;
626 u32 msgq_en = 1;
627
628 len = buf[0] & 0x1F;
629 mt = (buf[0] >> 5) & 0x7;
630 mc = buf[1];
631 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
632 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
633 struct slim_msg_txn txn;
634 u8 wbuf[8];
635 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
636 txn.ec = 0;
637 txn.rbuf = NULL;
638 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
639 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
640 txn.la = SLIM_LA_MGR;
641 txn.rl = 8;
642 wbuf[0] = SAT_MAGIC_LSB;
643 wbuf[1] = SAT_MAGIC_MSB;
644 wbuf[2] = SAT_MSG_VER;
645 wbuf[3] = SAT_MSG_PROT;
646 txn.wbuf = wbuf;
647 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700648 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700649 if (dev->state >= MSM_CTRL_ASLEEP) {
650 ngd_slim_setup_rx_path(dev);
651 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600652 msgq_en |= NGD_CFG_RX_MSGQ_EN;
653 writel_relaxed(msgq_en, dev->base +
654 NGD_BASE(dev->ctrl.nr, dev->ver));
655 /* make sure NGD MSG-Q config goes through */
656 mb();
657 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600658
659 ret = ngd_xfer_msg(&dev->ctrl, &txn);
660 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600661 enum msm_ctrl_state prev_state = dev->state;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600662 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600663 if (prev_state >= MSM_CTRL_ASLEEP)
664 complete(&dev->reconf);
665 else
666 pr_err("SLIM: unexpected capability, state:%d",
667 prev_state);
668 /* ADSP SSR, send device_up notifications */
669 if (prev_state == MSM_CTRL_DOWN)
670 schedule_work(&dev->slave_notify);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600671 }
672 }
673 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
674 mc == SLIM_MSG_MC_REPLY_VALUE) {
675 u8 tid = buf[3];
676 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
677 slim_msg_response(&dev->ctrl, &buf[4], tid,
678 len - 4);
679 pm_runtime_mark_last_busy(dev->dev);
680 }
681 if (mc == SLIM_USR_MC_ADDR_REPLY &&
682 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700683 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600684 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700685 mutex_lock(&dev->ctrl.m_ctrl);
686 txn = dev->ctrl.txnt[buf[3]];
687 if (!txn) {
688 pr_err("LADDR response after timeout, tid:0x%x",
689 buf[3]);
690 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600691 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700692 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600693 if (memcmp(&buf[4], failed_ea, 6))
694 txn->la = buf[10];
695 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700696 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600697 complete(txn->comp);
698 }
699 if (mc == SLIM_USR_MC_GENERIC_ACK &&
700 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700701 struct slim_msg_txn *txn;
702 mutex_lock(&dev->ctrl.m_ctrl);
703 txn = dev->ctrl.txnt[buf[3]];
704 if (!txn) {
705 pr_err("ACK received after timeout, tid:0x%x",
706 buf[3]);
707 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600708 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700709 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600710 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
711 (int)buf[3], buf[4]);
712 if (!(buf[4] & MSM_SAT_SUCCSS)) {
713 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
714 buf[4]);
715 txn->ec = -EIO;
716 }
717 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700718 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600719 complete(txn->comp);
720 }
721}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700722
Sagar Dharia33beca02012-10-22 16:21:46 -0600723static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700724{
Sagar Dharia33beca02012-10-22 16:21:46 -0600725 void __iomem *ngd;
726 int timeout, ret;
727 enum msm_ctrl_state cur_state = dev->state;
728 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700729 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700730 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
731 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
732 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600733
734 if (cur_state == MSM_CTRL_DOWN) {
735 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
736 HZ);
737 if (!timeout)
738 pr_err("slimbus QMI init timed out");
739 }
740
741 ret = msm_slim_qmi_power_request(dev, true);
742 if (ret) {
743 pr_err("SLIM QMI power request failed:%d", ret);
744 return ret;
745 }
746 if (!dev->ver) {
747 dev->ver = readl_relaxed(dev->base);
748 /* Version info in 16 MSbits */
749 dev->ver >>= 16;
750 }
751 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
752 laddr = readl_relaxed(ngd + NGD_STATUS);
753 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700754 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600755 * ADSP power collapse case, where HW wasn't reset.
756 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700757 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700758 ngd_slim_setup_rx_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600759 return 0;
760 } else if (cur_state != MSM_CTRL_DOWN) {
761 pr_info("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
762 dev->state, laddr);
Sagar Dharia33beca02012-10-22 16:21:46 -0600763 }
764
765 /*
766 * ADSP power collapse case (OR SSR), where HW was reset
767 * BAM programming will happen when capability message is received
768 */
769 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700770 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600771 /*
772 * Enable NGD. Configure NGD in register acc. mode until master
773 * announcement is received
774 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700775 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600776 /* make sure NGD enabling goes through */
777 mb();
778
779 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
780 if (!timeout) {
781 pr_err("failed to received master capability");
782 return -ETIMEDOUT;
783 }
784 if (cur_state == MSM_CTRL_DOWN)
785 complete(&dev->ctrl_up);
786 return 0;
787}
788
789static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
790{
791 int ret = 0;
792 if (enable) {
793 ret = msm_slim_qmi_init(dev, false);
794 /* controller state should be in sync with framework state */
795 if (!ret) {
796 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
797 SLIM_CLK_UNSPECIFIED);
798 complete(&dev->qmi.qmi_comp);
799 /*
800 * Power-up won't be called if clock pause failed.
801 * This can happen if ADSP SSR happened when audio
802 * session is in progress. Framework will think that
803 * clock pause failed so no need to wakeup controller.
804 * Call power-up explicitly in that case, since slimbus
805 * HW needs to be powered-on to be in sync with
806 * framework state
807 */
808 if (ret)
809 ngd_slim_power_up(dev);
810 if (!pm_runtime_enabled(dev->dev) ||
811 !pm_runtime_suspended(dev->dev))
812 ngd_slim_runtime_resume(dev->dev);
813 else
814 pm_runtime_resume(dev->dev);
815 pm_runtime_mark_last_busy(dev->dev);
816 pm_runtime_put(dev->dev);
817 } else
818 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
819 ret, dev->state);
820 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700821 msm_slim_qmi_exit(dev);
822 }
823
Sagar Dharia33beca02012-10-22 16:21:46 -0600824 return ret;
825}
826
827static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
828{
829 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
830 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700831}
832
Sagar Dharia71fcea52012-09-12 23:21:57 -0600833static int ngd_slim_rx_msgq_thread(void *data)
834{
835 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
836 struct completion *notify = &dev->rx_msgq_notify;
837 int ret = 0, index = 0;
838 u32 mc = 0;
839 u32 mt = 0;
840 u32 buffer[10];
841 u8 msg_len = 0;
842
843 while (!kthread_should_stop()) {
844 set_current_state(TASK_INTERRUPTIBLE);
845 ret = wait_for_completion_interruptible(notify);
846 if (ret) {
847 dev_err(dev->dev, "rx thread wait err:%d", ret);
848 continue;
849 }
850 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -0700851 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600852 msm_slim_rx_dequeue(dev, (u8 *)buffer);
853 ngd_slim_rx(dev, (u8 *)buffer);
854 continue;
855 }
856 ret = msm_slim_rx_msgq_get(dev, buffer, index);
857 if (ret) {
858 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
859 continue;
860 }
861
862 /* Wait for complete message */
863 if (index++ == 0) {
864 msg_len = *buffer & 0x1F;
865 mt = (buffer[0] >> 5) & 0x7;
866 mc = (buffer[0] >> 8) & 0xff;
867 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
868 }
869 if ((index * 4) >= msg_len) {
870 index = 0;
871 ngd_slim_rx(dev, (u8 *)buffer);
872 } else
873 continue;
874 }
875 return 0;
876}
877
Sagar Dharia33beca02012-10-22 16:21:46 -0600878static void ngd_laddr_lookup(struct work_struct *work)
879{
880 struct msm_slim_ctrl *dev =
881 container_of(work, struct msm_slim_ctrl, slave_notify);
882 struct slim_controller *ctrl = &dev->ctrl;
883 struct slim_device *sbdev;
884 int i;
885 mutex_lock(&ctrl->m_ctrl);
886 list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
887 int ret = 0;
888 mutex_unlock(&ctrl->m_ctrl);
889 for (i = 0; i < LADDR_RETRY; i++) {
890 ret = slim_get_logical_addr(sbdev, sbdev->e_addr,
891 6, &sbdev->laddr);
892 if (!ret)
893 break;
894 else /* time for ADSP to assign LA */
895 msleep(20);
896 }
897 mutex_lock(&ctrl->m_ctrl);
898 }
899 mutex_unlock(&ctrl->m_ctrl);
900}
901
902static void ngd_adsp_down(struct work_struct *work)
903{
904 struct msm_slim_qmi *qmi =
905 container_of(work, struct msm_slim_qmi, ssr_down);
906 struct msm_slim_ctrl *dev =
907 container_of(qmi, struct msm_slim_ctrl, qmi);
908 struct slim_controller *ctrl = &dev->ctrl;
909 struct slim_device *sbdev;
910 int i;
911
912 ngd_slim_enable(dev, false);
913 /* disconnect BAM pipes */
914 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -0600915 mutex_lock(&ctrl->m_ctrl);
916 /* device up should be called again after SSR */
917 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
918 sbdev->notified = false;
919 /* invalidate logical addresses */
920 for (i = 0; i < ctrl->num_dev; i++)
921 ctrl->addrt[i].valid = false;
922 mutex_unlock(&ctrl->m_ctrl);
923 pr_info("SLIM ADSP SSR (DOWN) done");
924}
925
926static void ngd_adsp_up(struct work_struct *work)
927{
928 struct msm_slim_qmi *qmi =
929 container_of(work, struct msm_slim_qmi, ssr_up);
930 struct msm_slim_ctrl *dev =
931 container_of(qmi, struct msm_slim_ctrl, qmi);
932 ngd_slim_enable(dev, true);
933}
934
Sagar Dharia71fcea52012-09-12 23:21:57 -0600935static int __devinit ngd_slim_probe(struct platform_device *pdev)
936{
937 struct msm_slim_ctrl *dev;
938 int ret;
939 struct resource *bam_mem;
940 struct resource *slim_mem;
941 struct resource *irq, *bam_irq;
942 enum apr_subsys_state q6_state;
Sagar Dharia24419e32013-01-14 17:56:32 -0700943 bool rxreg_access = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600944
945 q6_state = apr_get_q6_state();
946 if (q6_state == APR_SUBSYS_DOWN) {
947 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
948 q6_state);
949 return -EPROBE_DEFER;
950 } else
951 dev_dbg(&pdev->dev, "adsp is ready\n");
952
953 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
954 "slimbus_physical");
955 if (!slim_mem) {
956 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
957 return -ENODEV;
958 }
959 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
960 "slimbus_bam_physical");
961 if (!bam_mem) {
962 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
963 return -ENODEV;
964 }
965 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
966 "slimbus_irq");
967 if (!irq) {
968 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
969 return -ENODEV;
970 }
971 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
972 "slimbus_bam_irq");
973 if (!bam_irq) {
974 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
975 return -ENODEV;
976 }
977
978 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
979 if (IS_ERR(dev)) {
980 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
981 return PTR_ERR(dev);
982 }
983 dev->dev = &pdev->dev;
984 platform_set_drvdata(pdev, dev);
985 slim_set_ctrldata(&dev->ctrl, dev);
986 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
987 if (!dev->base) {
988 dev_err(&pdev->dev, "IOremap failed\n");
989 ret = -ENOMEM;
990 goto err_ioremap_failed;
991 }
992 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
993 if (!dev->bam.base) {
994 dev_err(&pdev->dev, "BAM IOremap failed\n");
995 ret = -ENOMEM;
996 goto err_ioremap_bam_failed;
997 }
998 if (pdev->dev.of_node) {
999
1000 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1001 &dev->ctrl.nr);
1002 if (ret) {
1003 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1004 goto err_ctrl_failed;
1005 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001006 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1007 "qcom,rxreg-access");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001008 } else {
1009 dev->ctrl.nr = pdev->id;
1010 }
1011 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1012 dev->ctrl.nports = MSM_SLIM_NPORTS;
1013 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1014 dev->framer.superfreq =
1015 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1016 dev->ctrl.a_framer = &dev->framer;
1017 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1018 dev->ctrl.set_laddr = ngd_set_laddr;
1019 dev->ctrl.get_laddr = ngd_get_laddr;
1020 dev->ctrl.allocbw = ngd_allocbw;
1021 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001022 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001023 dev->ctrl.config_port = msm_config_port;
1024 dev->ctrl.port_xfer = msm_slim_port_xfer;
1025 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
1026 /* Reserve some messaging BW for satellite-apps driver communication */
1027 dev->ctrl.sched.pending_msgsl = 30;
1028 dev->bam_mem = bam_mem;
1029
1030 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001031 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001032 mutex_init(&dev->tx_lock);
1033 spin_lock_init(&dev->rx_lock);
1034 dev->ee = 1;
1035 dev->irq = irq->start;
1036 dev->bam.irq = bam_irq->start;
1037
Sagar Dharia24419e32013-01-14 17:56:32 -07001038 if (rxreg_access)
1039 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1040 else
1041 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001042 init_completion(&dev->rx_msgq_notify);
1043
1044 /* Register with framework */
1045 ret = slim_add_numbered_controller(&dev->ctrl);
1046 if (ret) {
1047 dev_err(dev->dev, "error adding controller\n");
1048 goto err_ctrl_failed;
1049 }
1050
1051 dev->ctrl.dev.parent = &pdev->dev;
1052 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001053 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001054
1055 ret = request_irq(dev->irq, ngd_slim_interrupt,
1056 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1057
1058 if (ret) {
1059 dev_err(&pdev->dev, "request IRQ failed\n");
1060 goto err_request_irq_failed;
1061 }
1062
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001063 init_completion(&dev->qmi.qmi_comp);
Sagar Dharia33beca02012-10-22 16:21:46 -06001064 pm_runtime_use_autosuspend(dev->dev);
1065 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1066 pm_runtime_set_suspended(dev->dev);
1067 pm_runtime_enable(dev->dev);
1068
1069 INIT_WORK(&dev->slave_notify, ngd_laddr_lookup);
1070 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1071 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001072 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001073 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001074 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
1075 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1076 if (ret) {
1077 pr_err("Slimbus QMI service registration failed:%d", ret);
1078 goto qmi_register_failed;
1079 }
1080
Sagar Dharia33beca02012-10-22 16:21:46 -06001081
Sagar Dharia71fcea52012-09-12 23:21:57 -06001082 /* Fire up the Rx message queue thread */
1083 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
1084 NGD_SLIM_NAME "_ngd_msgq_thread");
1085 if (IS_ERR(dev->rx_msgq_thread)) {
1086 ret = PTR_ERR(dev->rx_msgq_thread);
1087 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
1088 goto err_thread_create_failed;
1089 }
1090
Sagar Dharia71fcea52012-09-12 23:21:57 -06001091 if (pdev->dev.of_node)
1092 of_register_slim_devices(&dev->ctrl);
1093
1094 /* Add devices registered with board-info now that controller is up */
1095 slim_ctrl_add_boarddevs(&dev->ctrl);
1096
Sagar Dharia71fcea52012-09-12 23:21:57 -06001097 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1098 return 0;
1099
1100err_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001101 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1102 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1103qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001104 free_irq(dev->irq, dev);
1105err_request_irq_failed:
1106 slim_del_controller(&dev->ctrl);
1107err_ctrl_failed:
1108 iounmap(dev->bam.base);
1109err_ioremap_bam_failed:
1110 iounmap(dev->base);
1111err_ioremap_failed:
1112 kfree(dev);
1113 return ret;
1114}
1115
1116static int __devexit ngd_slim_remove(struct platform_device *pdev)
1117{
1118 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001119 ngd_slim_enable(dev, false);
1120 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1121 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001122 pm_runtime_disable(&pdev->dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001123 free_irq(dev->irq, dev);
1124 slim_del_controller(&dev->ctrl);
1125 kthread_stop(dev->rx_msgq_thread);
1126 iounmap(dev->bam.base);
1127 iounmap(dev->base);
1128 kfree(dev);
1129 return 0;
1130}
1131
1132#ifdef CONFIG_PM_RUNTIME
1133static int ngd_slim_runtime_idle(struct device *device)
1134{
1135 dev_dbg(device, "pm_runtime: idle...\n");
1136 pm_request_autosuspend(device);
1137 return -EAGAIN;
1138}
1139#endif
1140
1141/*
1142 * If PM_RUNTIME is not defined, these 2 functions become helper
1143 * functions to be called from system suspend/resume. So they are not
1144 * inside ifdef CONFIG_PM_RUNTIME
1145 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001146static int ngd_slim_runtime_resume(struct device *device)
1147{
1148 struct platform_device *pdev = to_platform_device(device);
1149 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1150 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001151 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001152 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1153 if (ret) {
1154 dev_err(device, "clk pause not exited:%d", ret);
1155 dev->state = MSM_CTRL_ASLEEP;
1156 } else {
1157 dev->state = MSM_CTRL_AWAKE;
1158 }
1159 return ret;
1160}
1161
Sagar Dharia33beca02012-10-22 16:21:46 -06001162#ifdef CONFIG_PM_SLEEP
1163static int ngd_slim_runtime_suspend(struct device *device)
1164{
1165 struct platform_device *pdev = to_platform_device(device);
1166 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1167 int ret = 0;
1168 dev->state = MSM_CTRL_SLEEPING;
1169 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1170 if (ret) {
1171 if (ret != -EBUSY)
1172 dev_err(device, "clk pause not entered:%d", ret);
1173 dev->state = MSM_CTRL_AWAKE;
1174 } else {
1175 dev->state = MSM_CTRL_ASLEEP;
1176 }
1177 return ret;
1178}
1179
Sagar Dharia71fcea52012-09-12 23:21:57 -06001180static int ngd_slim_suspend(struct device *dev)
1181{
1182 int ret = -EBUSY;
1183 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
1184 dev_dbg(dev, "system suspend");
1185 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001186 /*
1187 * If runtime-PM still thinks it's active, then make sure its
1188 * status is in sync with HW status.
1189 * Since this suspend calls QMI api, it results in holding a
1190 * wakelock. That results in failure of first suspend.
1191 * Subsequent suspend should not call low-power transition
1192 * again since the HW is already in suspended state.
1193 */
1194 if (!ret) {
1195 pm_runtime_disable(dev);
1196 pm_runtime_set_suspended(dev);
1197 pm_runtime_enable(dev);
1198 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001199 }
1200 if (ret == -EBUSY) {
1201 /*
1202 * There is a possibility that some audio stream is active
1203 * during suspend. We dont want to return suspend failure in
1204 * that case so that display and relevant components can still
1205 * go to suspend.
1206 * If there is some other error, then it should be passed-on
1207 * to system level suspend
1208 */
1209 ret = 0;
1210 }
1211 return ret;
1212}
1213
1214static int ngd_slim_resume(struct device *dev)
1215{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001216 /*
1217 * Rely on runtime-PM to call resume in case it is enabled.
1218 * Even if it's not enabled, rely on 1st client transaction to do
1219 * clock/power on
1220 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001221 return 0;
1222}
1223#endif /* CONFIG_PM_SLEEP */
1224
1225static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1226 SET_SYSTEM_SLEEP_PM_OPS(
1227 ngd_slim_suspend,
1228 ngd_slim_resume
1229 )
1230 SET_RUNTIME_PM_OPS(
1231 ngd_slim_runtime_suspend,
1232 ngd_slim_runtime_resume,
1233 ngd_slim_runtime_idle
1234 )
1235};
1236
1237static struct of_device_id ngd_slim_dt_match[] = {
1238 {
1239 .compatible = "qcom,slim-ngd",
1240 },
1241 {}
1242};
1243
1244static struct platform_driver ngd_slim_driver = {
1245 .probe = ngd_slim_probe,
1246 .remove = ngd_slim_remove,
1247 .driver = {
1248 .name = NGD_SLIM_NAME,
1249 .owner = THIS_MODULE,
1250 .pm = &ngd_slim_dev_pm_ops,
1251 .of_match_table = ngd_slim_dt_match,
1252 },
1253};
1254
1255static int ngd_slim_init(void)
1256{
1257 return platform_driver_register(&ngd_slim_driver);
1258}
1259late_initcall(ngd_slim_init);
1260
1261static void ngd_slim_exit(void)
1262{
1263 platform_driver_unregister(&ngd_slim_driver);
1264}
1265module_exit(ngd_slim_exit);
1266
1267MODULE_LICENSE("GPL v2");
1268MODULE_DESCRIPTION("MSM Slimbus controller");
1269MODULE_ALIAS("platform:msm-slim-ngd");