blob: eb741ef9cab5c674f5d752936347139859a591b5 [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 Dhariacc1001e2012-11-06 13:56:42 -0700227 if (txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
Sagar Dharia24419e32013-01-14 17:56:32 -0700228 SLIM_MSG_MC_RECONFIGURE_NOW)) {
229 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
230 ret = sps_disconnect(dev->rx_msgq.sps);
231 dev->use_rx_msgqs = MSM_MSGQ_RESET;
232 }
233 if (!ret)
234 ret = msm_slim_qmi_power_request(dev, false);
235 else
236 pr_err("SPS pipe disconnect error:%d", ret);
237 return ret;
238 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700239 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
240 return 0;
241
Sagar Dharia71fcea52012-09-12 23:21:57 -0600242 if (txn->mt == SLIM_MSG_MT_CORE &&
243 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
244 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
245 return 0;
246 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600247 /* If txn is tried when controller is down, wait for ADSP to boot */
248 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
249 if (dev->state == MSM_CTRL_DOWN) {
250 u8 mc = (u8)txn->mc;
251 int timeout;
252 dev_err(dev->dev, "ADSP slimbus not up yet");
253 /*
254 * Messages related to data channel management can't
255 * wait since they are holding reconfiguration lock.
256 * clk_pause in resume (which can change state back to
257 * MSM_CTRL_AWAKE), will need that lock
258 */
259 if ((txn->mt == SLIM_MSG_MT_CORE) &&
260 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
261 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
262 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
263 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
264 return -EREMOTEIO;
265 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
266 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
267 mc <= SLIM_USR_MC_DISCONNECT_PORT)))
268 return -EREMOTEIO;
269 timeout = wait_for_completion_timeout(&dev->ctrl_up,
270 HZ);
271 if (!timeout)
272 return -ETIMEDOUT;
273 }
274 msm_slim_get_ctrl(dev);
275 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600276 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600277
Sagar Dharia71fcea52012-09-12 23:21:57 -0600278 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
Sagar Dharia33beca02012-10-22 16:21:46 -0600279 (dev->state != MSM_CTRL_AWAKE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600280 dev_err(dev->dev, "controller not ready");
281 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600282 msm_slim_put_ctrl(dev);
283 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600284 }
285 if (txn->mt == SLIM_MSG_MT_CORE &&
286 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
287 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
288 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
289 int i = 0;
290 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
291 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
292 txn->mc = SLIM_USR_MC_CONNECT_SRC;
293 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
294 txn->mc = SLIM_USR_MC_CONNECT_SINK;
295 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
296 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
297 if (txn->la == SLIM_LA_MGR)
298 txn->la = dev->pgdla;
299 wbuf[i++] = txn->la;
300 la = SLIM_LA_MGR;
301 wbuf[i++] = txn->wbuf[0];
302 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
303 wbuf[i++] = txn->wbuf[1];
304 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
305 if (ret) {
306 pr_err("TID for connect/disconnect fail:%d", ret);
307 goto ngd_xfer_err;
308 }
309 txn->len = i;
310 txn->wbuf = wbuf;
311 txn->rl = txn->len + 4;
312 }
313 txn->rl--;
314 pbuf = msm_get_msg_buf(dev, txn->rl);
315 if (!pbuf) {
316 dev_err(dev->dev, "Message buffer unavailable");
317 ret = -ENOMEM;
318 goto ngd_xfer_err;
319 }
320 dev->err = 0;
321
322 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
323 ret = -EPROTONOSUPPORT;
324 goto ngd_xfer_err;
325 }
326 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
327 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
328 la);
329 else
330 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
331 la);
332 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
333 puc = ((u8 *)pbuf) + 3;
334 else
335 puc = ((u8 *)pbuf) + 2;
336 if (txn->rbuf)
337 *(puc++) = txn->tid;
338 if ((txn->mt == SLIM_MSG_MT_CORE) &&
339 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
340 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
341 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
342 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
343 *(puc++) = (txn->ec & 0xFF);
344 *(puc++) = (txn->ec >> 8)&0xFF;
345 }
346 if (txn->wbuf)
347 memcpy(puc, txn->wbuf, txn->len);
348 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
349 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
350 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
351 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
352 wbuf[0] == dev->pgdla) {
353 if (txn->mc != SLIM_MSG_MC_DISCONNECT_PORT)
354 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
355 else {
356 struct msm_slim_endp *endpoint = &dev->pipes[wbuf[1]];
357 struct sps_register_event sps_event;
358 memset(&sps_event, 0, sizeof(sps_event));
359 sps_register_event(endpoint->sps, &sps_event);
360 sps_disconnect(endpoint->sps);
361 /*
362 * Remove channel disconnects master-side ports from
363 * channel. No need to send that again on the bus
364 */
365 dev->pipes[wbuf[1]].connected = false;
366 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700367 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600368 return 0;
369 }
370 if (dev->err) {
371 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
372 goto ngd_xfer_err;
373 }
374 }
375 dev->err = 0;
376 dev->wr_comp = &tx_sent;
377 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
378 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
379 if (!ret) {
380 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
381 if (!timeout)
382 ret = -ETIMEDOUT;
383 else
384 ret = dev->err;
385 }
386 dev->wr_comp = NULL;
387 if (ret) {
388 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
389 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
390 dev->ver);
391 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
392 txn->mc, txn->mt, ret, dev->ver);
393 conf = readl_relaxed(ngd);
394 stat = readl_relaxed(ngd + NGD_STATUS);
395 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
396 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
397 int_en = readl_relaxed(ngd + NGD_INT_EN);
398 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
399
400 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
401 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
402 int_en, int_clr);
403 } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
404 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
405 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
406 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
407 int timeout;
408 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700409 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600410 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600411 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600412 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600413 else
414 ret = txn->ec;
415 if (ret) {
416 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
417 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700418 mutex_lock(&ctrl->m_ctrl);
419 ctrl->txnt[txn->tid] = NULL;
420 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600421 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600422 return ret ? ret : dev->err;
423 }
424ngd_xfer_err:
425 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600426 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE)
427 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600428 return ret ? ret : dev->err;
429}
430
431static int ngd_xferandwait_ack(struct slim_controller *ctrl,
432 struct slim_msg_txn *txn)
433{
434 int ret = ngd_xfer_msg(ctrl, txn);
435 if (!ret) {
436 int timeout;
437 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600438 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600439 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600440 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600441 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600442 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600443 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600444 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
445 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600446 mutex_lock(&ctrl->m_ctrl);
447 ctrl->txnt[txn->tid] = NULL;
448 mutex_unlock(&ctrl->m_ctrl);
449 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600450
451 return ret;
452}
453
454static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
455{
456 int ret;
457 struct slim_pending_ch *pch;
458 struct slim_msg_txn txn;
459 struct slim_controller *ctrl = sb->ctrl;
460 DECLARE_COMPLETION_ONSTACK(done);
461 u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
462
463 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
464 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
465 txn.la = SLIM_LA_MGR;
466 txn.len = 0;
467 txn.ec = 0;
468 txn.wbuf = wbuf;
469 txn.rbuf = NULL;
470
471 list_for_each_entry(pch, &sb->mark_define, pending) {
472 struct slim_ich *slc;
473 slc = &ctrl->chans[pch->chan];
474 if (!slc) {
475 pr_err("no channel in define?");
476 return -ENXIO;
477 }
478 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600479 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600480 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600481 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600482 wbuf[txn.len] = slc->seglen;
483 if (slc->coeff == SLIM_COEFF_3)
484 wbuf[txn.len] |= 1 << 5;
485 wbuf[txn.len++] |= slc->prop.auxf << 6;
486 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
487 wbuf[txn.len++] = slc->prrate;
488 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
489 if (ret) {
490 pr_err("no tid for channel define?");
491 return -ENXIO;
492 }
493 }
494 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600495 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600496 }
497 if (txn.len) {
498 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
499 txn.rl = txn.len + 4;
500 ret = ngd_xferandwait_ack(ctrl, &txn);
501 if (ret)
502 return ret;
503
504 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
505 txn.len = 2;
506 wbuf[1] = sb->laddr;
507 txn.rl = txn.len + 4;
508 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
509 if (ret)
510 return ret;
511 ret = ngd_xferandwait_ack(ctrl, &txn);
512 if (ret)
513 return ret;
514 }
515 txn.len = 0;
516 list_for_each_entry(pch, &sb->mark_removal, pending) {
517 struct slim_ich *slc;
518 slc = &ctrl->chans[pch->chan];
519 if (!slc) {
520 pr_err("no channel in removal?");
521 return -ENXIO;
522 }
523 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600524 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600525 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600526 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600527 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
528 if (ret) {
529 pr_err("no tid for channel define?");
530 return -ENXIO;
531 }
532 }
533 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600534 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600535 }
536 if (txn.len) {
537 txn.mc = SLIM_USR_MC_CHAN_CTRL;
538 txn.rl = txn.len + 4;
539 ret = ngd_xferandwait_ack(ctrl, &txn);
540 if (ret)
541 return ret;
542
543 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
544 txn.len = 2;
545 wbuf[1] = sb->laddr;
546 txn.rl = txn.len + 4;
547 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
548 if (ret)
549 return ret;
550 ret = ngd_xferandwait_ack(ctrl, &txn);
551 if (ret)
552 return ret;
553 txn.len = 0;
554 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700555 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600556}
557
558static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
559 u8 elen, u8 laddr)
560{
561 return 0;
562}
563
564static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
565 u8 elen, u8 *laddr)
566{
567 int ret;
568 u8 wbuf[10];
569 struct slim_msg_txn txn;
570 DECLARE_COMPLETION_ONSTACK(done);
571 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
572 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
573 txn.la = SLIM_LA_MGR;
574 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600575 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
576 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600577 return ret;
578 }
579 memcpy(&wbuf[1], ea, elen);
580 txn.mc = SLIM_USR_MC_ADDR_QUERY;
581 txn.rl = 11;
582 txn.len = 7;
583 txn.wbuf = wbuf;
584 txn.rbuf = NULL;
585 ret = ngd_xferandwait_ack(ctrl, &txn);
586 if (!ret && txn.la == 0xFF)
587 ret = -ENXIO;
588 else if (!ret)
589 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600590 return ret;
591}
592
Sagar Dharia24419e32013-01-14 17:56:32 -0700593static void ngd_slim_setup_rx_path(struct msm_slim_ctrl *dev)
594{
595 int ret;
596 if (dev->state == MSM_CTRL_DOWN) {
597 msm_slim_sps_init(dev, dev->bam_mem,
598 NGD_BASE(dev->ctrl.nr,
599 dev->ver) + NGD_STATUS, true);
600 } else {
601 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
602 return;
603 ret = msm_slim_connect_endp(dev, &dev->rx_msgq,
604 &dev->rx_msgq_notify);
605 if (!ret)
606 dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
607 else
608 pr_err("RX msgq not being used:%d", ret);
609 }
610}
Sagar Dharia71fcea52012-09-12 23:21:57 -0600611static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
612{
613 u8 mc, mt, len;
614 int ret;
615 u32 msgq_en = 1;
616
617 len = buf[0] & 0x1F;
618 mt = (buf[0] >> 5) & 0x7;
619 mc = buf[1];
620 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
621 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
622 struct slim_msg_txn txn;
623 u8 wbuf[8];
624 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
625 txn.ec = 0;
626 txn.rbuf = NULL;
627 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
628 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
629 txn.la = SLIM_LA_MGR;
630 txn.rl = 8;
631 wbuf[0] = SAT_MAGIC_LSB;
632 wbuf[1] = SAT_MAGIC_MSB;
633 wbuf[2] = SAT_MSG_VER;
634 wbuf[3] = SAT_MSG_PROT;
635 txn.wbuf = wbuf;
636 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700637 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700638 if (dev->state >= MSM_CTRL_ASLEEP) {
639 ngd_slim_setup_rx_path(dev);
640 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600641 msgq_en |= NGD_CFG_RX_MSGQ_EN;
642 writel_relaxed(msgq_en, dev->base +
643 NGD_BASE(dev->ctrl.nr, dev->ver));
644 /* make sure NGD MSG-Q config goes through */
645 mb();
646 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600647
648 ret = ngd_xfer_msg(&dev->ctrl, &txn);
649 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600650 enum msm_ctrl_state prev_state = dev->state;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600651 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600652 if (prev_state >= MSM_CTRL_ASLEEP)
653 complete(&dev->reconf);
654 else
655 pr_err("SLIM: unexpected capability, state:%d",
656 prev_state);
657 /* ADSP SSR, send device_up notifications */
658 if (prev_state == MSM_CTRL_DOWN)
659 schedule_work(&dev->slave_notify);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600660 }
661 }
662 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
663 mc == SLIM_MSG_MC_REPLY_VALUE) {
664 u8 tid = buf[3];
665 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
666 slim_msg_response(&dev->ctrl, &buf[4], tid,
667 len - 4);
668 pm_runtime_mark_last_busy(dev->dev);
669 }
670 if (mc == SLIM_USR_MC_ADDR_REPLY &&
671 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700672 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600673 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700674 mutex_lock(&dev->ctrl.m_ctrl);
675 txn = dev->ctrl.txnt[buf[3]];
676 if (!txn) {
677 pr_err("LADDR response after timeout, tid:0x%x",
678 buf[3]);
679 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600680 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700681 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600682 if (memcmp(&buf[4], failed_ea, 6))
683 txn->la = buf[10];
684 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700685 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600686 complete(txn->comp);
687 }
688 if (mc == SLIM_USR_MC_GENERIC_ACK &&
689 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700690 struct slim_msg_txn *txn;
691 mutex_lock(&dev->ctrl.m_ctrl);
692 txn = dev->ctrl.txnt[buf[3]];
693 if (!txn) {
694 pr_err("ACK received after timeout, tid:0x%x",
695 buf[3]);
696 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600697 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700698 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600699 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
700 (int)buf[3], buf[4]);
701 if (!(buf[4] & MSM_SAT_SUCCSS)) {
702 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
703 buf[4]);
704 txn->ec = -EIO;
705 }
706 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700707 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600708 complete(txn->comp);
709 }
710}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700711
Sagar Dharia33beca02012-10-22 16:21:46 -0600712static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700713{
Sagar Dharia33beca02012-10-22 16:21:46 -0600714 void __iomem *ngd;
715 int timeout, ret;
716 enum msm_ctrl_state cur_state = dev->state;
717 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700718 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700719 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
720 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
721 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600722
723 if (cur_state == MSM_CTRL_DOWN) {
724 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
725 HZ);
726 if (!timeout)
727 pr_err("slimbus QMI init timed out");
728 }
729
730 ret = msm_slim_qmi_power_request(dev, true);
731 if (ret) {
732 pr_err("SLIM QMI power request failed:%d", ret);
733 return ret;
734 }
735 if (!dev->ver) {
736 dev->ver = readl_relaxed(dev->base);
737 /* Version info in 16 MSbits */
738 dev->ver >>= 16;
739 }
740 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
741 laddr = readl_relaxed(ngd + NGD_STATUS);
742 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700743 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600744 * ADSP power collapse case, where HW wasn't reset.
745 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700746 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700747 ngd_slim_setup_rx_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600748 return 0;
749 } else if (cur_state != MSM_CTRL_DOWN) {
750 pr_info("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
751 dev->state, laddr);
Sagar Dharia33beca02012-10-22 16:21:46 -0600752 }
753
754 /*
755 * ADSP power collapse case (OR SSR), where HW was reset
756 * BAM programming will happen when capability message is received
757 */
758 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700759 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600760 /*
761 * Enable NGD. Configure NGD in register acc. mode until master
762 * announcement is received
763 */
Sagar Dharia24419e32013-01-14 17:56:32 -0700764 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -0600765 /* make sure NGD enabling goes through */
766 mb();
767
768 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
769 if (!timeout) {
770 pr_err("failed to received master capability");
771 return -ETIMEDOUT;
772 }
773 if (cur_state == MSM_CTRL_DOWN)
774 complete(&dev->ctrl_up);
775 return 0;
776}
777
778static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
779{
780 int ret = 0;
781 if (enable) {
782 ret = msm_slim_qmi_init(dev, false);
783 /* controller state should be in sync with framework state */
784 if (!ret) {
785 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
786 SLIM_CLK_UNSPECIFIED);
787 complete(&dev->qmi.qmi_comp);
788 /*
789 * Power-up won't be called if clock pause failed.
790 * This can happen if ADSP SSR happened when audio
791 * session is in progress. Framework will think that
792 * clock pause failed so no need to wakeup controller.
793 * Call power-up explicitly in that case, since slimbus
794 * HW needs to be powered-on to be in sync with
795 * framework state
796 */
797 if (ret)
798 ngd_slim_power_up(dev);
799 if (!pm_runtime_enabled(dev->dev) ||
800 !pm_runtime_suspended(dev->dev))
801 ngd_slim_runtime_resume(dev->dev);
802 else
803 pm_runtime_resume(dev->dev);
804 pm_runtime_mark_last_busy(dev->dev);
805 pm_runtime_put(dev->dev);
806 } else
807 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
808 ret, dev->state);
809 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700810 msm_slim_qmi_exit(dev);
811 }
812
Sagar Dharia33beca02012-10-22 16:21:46 -0600813 return ret;
814}
815
816static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
817{
818 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
819 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700820}
821
Sagar Dharia71fcea52012-09-12 23:21:57 -0600822static int ngd_slim_rx_msgq_thread(void *data)
823{
824 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
825 struct completion *notify = &dev->rx_msgq_notify;
826 int ret = 0, index = 0;
827 u32 mc = 0;
828 u32 mt = 0;
829 u32 buffer[10];
830 u8 msg_len = 0;
831
832 while (!kthread_should_stop()) {
833 set_current_state(TASK_INTERRUPTIBLE);
834 ret = wait_for_completion_interruptible(notify);
835 if (ret) {
836 dev_err(dev->dev, "rx thread wait err:%d", ret);
837 continue;
838 }
839 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -0700840 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600841 msm_slim_rx_dequeue(dev, (u8 *)buffer);
842 ngd_slim_rx(dev, (u8 *)buffer);
843 continue;
844 }
845 ret = msm_slim_rx_msgq_get(dev, buffer, index);
846 if (ret) {
847 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
848 continue;
849 }
850
851 /* Wait for complete message */
852 if (index++ == 0) {
853 msg_len = *buffer & 0x1F;
854 mt = (buffer[0] >> 5) & 0x7;
855 mc = (buffer[0] >> 8) & 0xff;
856 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
857 }
858 if ((index * 4) >= msg_len) {
859 index = 0;
860 ngd_slim_rx(dev, (u8 *)buffer);
861 } else
862 continue;
863 }
864 return 0;
865}
866
Sagar Dharia33beca02012-10-22 16:21:46 -0600867static void ngd_laddr_lookup(struct work_struct *work)
868{
869 struct msm_slim_ctrl *dev =
870 container_of(work, struct msm_slim_ctrl, slave_notify);
871 struct slim_controller *ctrl = &dev->ctrl;
872 struct slim_device *sbdev;
873 int i;
874 mutex_lock(&ctrl->m_ctrl);
875 list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
876 int ret = 0;
877 mutex_unlock(&ctrl->m_ctrl);
878 for (i = 0; i < LADDR_RETRY; i++) {
879 ret = slim_get_logical_addr(sbdev, sbdev->e_addr,
880 6, &sbdev->laddr);
881 if (!ret)
882 break;
883 else /* time for ADSP to assign LA */
884 msleep(20);
885 }
886 mutex_lock(&ctrl->m_ctrl);
887 }
888 mutex_unlock(&ctrl->m_ctrl);
889}
890
891static void ngd_adsp_down(struct work_struct *work)
892{
893 struct msm_slim_qmi *qmi =
894 container_of(work, struct msm_slim_qmi, ssr_down);
895 struct msm_slim_ctrl *dev =
896 container_of(qmi, struct msm_slim_ctrl, qmi);
897 struct slim_controller *ctrl = &dev->ctrl;
898 struct slim_device *sbdev;
899 int i;
900
901 ngd_slim_enable(dev, false);
902 /* disconnect BAM pipes */
903 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -0600904 mutex_lock(&ctrl->m_ctrl);
905 /* device up should be called again after SSR */
906 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
907 sbdev->notified = false;
908 /* invalidate logical addresses */
909 for (i = 0; i < ctrl->num_dev; i++)
910 ctrl->addrt[i].valid = false;
911 mutex_unlock(&ctrl->m_ctrl);
912 pr_info("SLIM ADSP SSR (DOWN) done");
913}
914
915static void ngd_adsp_up(struct work_struct *work)
916{
917 struct msm_slim_qmi *qmi =
918 container_of(work, struct msm_slim_qmi, ssr_up);
919 struct msm_slim_ctrl *dev =
920 container_of(qmi, struct msm_slim_ctrl, qmi);
921 ngd_slim_enable(dev, true);
922}
923
Sagar Dharia71fcea52012-09-12 23:21:57 -0600924static int __devinit ngd_slim_probe(struct platform_device *pdev)
925{
926 struct msm_slim_ctrl *dev;
927 int ret;
928 struct resource *bam_mem;
929 struct resource *slim_mem;
930 struct resource *irq, *bam_irq;
931 enum apr_subsys_state q6_state;
Sagar Dharia24419e32013-01-14 17:56:32 -0700932 bool rxreg_access = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600933
934 q6_state = apr_get_q6_state();
935 if (q6_state == APR_SUBSYS_DOWN) {
936 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
937 q6_state);
938 return -EPROBE_DEFER;
939 } else
940 dev_dbg(&pdev->dev, "adsp is ready\n");
941
942 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
943 "slimbus_physical");
944 if (!slim_mem) {
945 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
946 return -ENODEV;
947 }
948 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
949 "slimbus_bam_physical");
950 if (!bam_mem) {
951 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
952 return -ENODEV;
953 }
954 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
955 "slimbus_irq");
956 if (!irq) {
957 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
958 return -ENODEV;
959 }
960 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
961 "slimbus_bam_irq");
962 if (!bam_irq) {
963 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
964 return -ENODEV;
965 }
966
967 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
968 if (IS_ERR(dev)) {
969 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
970 return PTR_ERR(dev);
971 }
972 dev->dev = &pdev->dev;
973 platform_set_drvdata(pdev, dev);
974 slim_set_ctrldata(&dev->ctrl, dev);
975 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
976 if (!dev->base) {
977 dev_err(&pdev->dev, "IOremap failed\n");
978 ret = -ENOMEM;
979 goto err_ioremap_failed;
980 }
981 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
982 if (!dev->bam.base) {
983 dev_err(&pdev->dev, "BAM IOremap failed\n");
984 ret = -ENOMEM;
985 goto err_ioremap_bam_failed;
986 }
987 if (pdev->dev.of_node) {
988
989 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
990 &dev->ctrl.nr);
991 if (ret) {
992 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
993 goto err_ctrl_failed;
994 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700995 rxreg_access = of_property_read_bool(pdev->dev.of_node,
996 "qcom,rxreg-access");
Sagar Dharia71fcea52012-09-12 23:21:57 -0600997 } else {
998 dev->ctrl.nr = pdev->id;
999 }
1000 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1001 dev->ctrl.nports = MSM_SLIM_NPORTS;
1002 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1003 dev->framer.superfreq =
1004 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1005 dev->ctrl.a_framer = &dev->framer;
1006 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1007 dev->ctrl.set_laddr = ngd_set_laddr;
1008 dev->ctrl.get_laddr = ngd_get_laddr;
1009 dev->ctrl.allocbw = ngd_allocbw;
1010 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001011 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001012 dev->ctrl.config_port = msm_config_port;
1013 dev->ctrl.port_xfer = msm_slim_port_xfer;
1014 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
1015 /* Reserve some messaging BW for satellite-apps driver communication */
1016 dev->ctrl.sched.pending_msgsl = 30;
1017 dev->bam_mem = bam_mem;
1018
1019 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001020 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001021 mutex_init(&dev->tx_lock);
1022 spin_lock_init(&dev->rx_lock);
1023 dev->ee = 1;
1024 dev->irq = irq->start;
1025 dev->bam.irq = bam_irq->start;
1026
Sagar Dharia24419e32013-01-14 17:56:32 -07001027 if (rxreg_access)
1028 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1029 else
1030 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001031 init_completion(&dev->rx_msgq_notify);
1032
1033 /* Register with framework */
1034 ret = slim_add_numbered_controller(&dev->ctrl);
1035 if (ret) {
1036 dev_err(dev->dev, "error adding controller\n");
1037 goto err_ctrl_failed;
1038 }
1039
1040 dev->ctrl.dev.parent = &pdev->dev;
1041 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001042 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001043
1044 ret = request_irq(dev->irq, ngd_slim_interrupt,
1045 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1046
1047 if (ret) {
1048 dev_err(&pdev->dev, "request IRQ failed\n");
1049 goto err_request_irq_failed;
1050 }
1051
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001052 init_completion(&dev->qmi.qmi_comp);
Sagar Dharia33beca02012-10-22 16:21:46 -06001053 pm_runtime_use_autosuspend(dev->dev);
1054 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1055 pm_runtime_set_suspended(dev->dev);
1056 pm_runtime_enable(dev->dev);
1057
1058 INIT_WORK(&dev->slave_notify, ngd_laddr_lookup);
1059 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1060 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001061 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001062 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001063 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
1064 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1065 if (ret) {
1066 pr_err("Slimbus QMI service registration failed:%d", ret);
1067 goto qmi_register_failed;
1068 }
1069
Sagar Dharia33beca02012-10-22 16:21:46 -06001070
Sagar Dharia71fcea52012-09-12 23:21:57 -06001071 /* Fire up the Rx message queue thread */
1072 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
1073 NGD_SLIM_NAME "_ngd_msgq_thread");
1074 if (IS_ERR(dev->rx_msgq_thread)) {
1075 ret = PTR_ERR(dev->rx_msgq_thread);
1076 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
1077 goto err_thread_create_failed;
1078 }
1079
Sagar Dharia71fcea52012-09-12 23:21:57 -06001080 if (pdev->dev.of_node)
1081 of_register_slim_devices(&dev->ctrl);
1082
1083 /* Add devices registered with board-info now that controller is up */
1084 slim_ctrl_add_boarddevs(&dev->ctrl);
1085
Sagar Dharia71fcea52012-09-12 23:21:57 -06001086 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1087 return 0;
1088
1089err_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001090 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1091 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1092qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001093 free_irq(dev->irq, dev);
1094err_request_irq_failed:
1095 slim_del_controller(&dev->ctrl);
1096err_ctrl_failed:
1097 iounmap(dev->bam.base);
1098err_ioremap_bam_failed:
1099 iounmap(dev->base);
1100err_ioremap_failed:
1101 kfree(dev);
1102 return ret;
1103}
1104
1105static int __devexit ngd_slim_remove(struct platform_device *pdev)
1106{
1107 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001108 ngd_slim_enable(dev, false);
1109 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
1110 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001111 pm_runtime_disable(&pdev->dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001112 free_irq(dev->irq, dev);
1113 slim_del_controller(&dev->ctrl);
1114 kthread_stop(dev->rx_msgq_thread);
1115 iounmap(dev->bam.base);
1116 iounmap(dev->base);
1117 kfree(dev);
1118 return 0;
1119}
1120
1121#ifdef CONFIG_PM_RUNTIME
1122static int ngd_slim_runtime_idle(struct device *device)
1123{
1124 dev_dbg(device, "pm_runtime: idle...\n");
1125 pm_request_autosuspend(device);
1126 return -EAGAIN;
1127}
1128#endif
1129
1130/*
1131 * If PM_RUNTIME is not defined, these 2 functions become helper
1132 * functions to be called from system suspend/resume. So they are not
1133 * inside ifdef CONFIG_PM_RUNTIME
1134 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001135static int ngd_slim_runtime_resume(struct device *device)
1136{
1137 struct platform_device *pdev = to_platform_device(device);
1138 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1139 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001140 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001141 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1142 if (ret) {
1143 dev_err(device, "clk pause not exited:%d", ret);
1144 dev->state = MSM_CTRL_ASLEEP;
1145 } else {
1146 dev->state = MSM_CTRL_AWAKE;
1147 }
1148 return ret;
1149}
1150
Sagar Dharia33beca02012-10-22 16:21:46 -06001151#ifdef CONFIG_PM_SLEEP
1152static int ngd_slim_runtime_suspend(struct device *device)
1153{
1154 struct platform_device *pdev = to_platform_device(device);
1155 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1156 int ret = 0;
1157 dev->state = MSM_CTRL_SLEEPING;
1158 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1159 if (ret) {
1160 if (ret != -EBUSY)
1161 dev_err(device, "clk pause not entered:%d", ret);
1162 dev->state = MSM_CTRL_AWAKE;
1163 } else {
1164 dev->state = MSM_CTRL_ASLEEP;
1165 }
1166 return ret;
1167}
1168
Sagar Dharia71fcea52012-09-12 23:21:57 -06001169static int ngd_slim_suspend(struct device *dev)
1170{
1171 int ret = -EBUSY;
1172 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
1173 dev_dbg(dev, "system suspend");
1174 ret = ngd_slim_runtime_suspend(dev);
1175 }
1176 if (ret == -EBUSY) {
1177 /*
1178 * There is a possibility that some audio stream is active
1179 * during suspend. We dont want to return suspend failure in
1180 * that case so that display and relevant components can still
1181 * go to suspend.
1182 * If there is some other error, then it should be passed-on
1183 * to system level suspend
1184 */
1185 ret = 0;
1186 }
1187 return ret;
1188}
1189
1190static int ngd_slim_resume(struct device *dev)
1191{
1192 /* If runtime_pm is enabled, this resume shouldn't do anything */
1193 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
1194 int ret;
1195 dev_dbg(dev, "system resume");
1196 ret = ngd_slim_runtime_resume(dev);
1197 if (!ret) {
1198 pm_runtime_mark_last_busy(dev);
1199 pm_request_autosuspend(dev);
1200 }
1201 return ret;
1202
1203 }
1204 return 0;
1205}
1206#endif /* CONFIG_PM_SLEEP */
1207
1208static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1209 SET_SYSTEM_SLEEP_PM_OPS(
1210 ngd_slim_suspend,
1211 ngd_slim_resume
1212 )
1213 SET_RUNTIME_PM_OPS(
1214 ngd_slim_runtime_suspend,
1215 ngd_slim_runtime_resume,
1216 ngd_slim_runtime_idle
1217 )
1218};
1219
1220static struct of_device_id ngd_slim_dt_match[] = {
1221 {
1222 .compatible = "qcom,slim-ngd",
1223 },
1224 {}
1225};
1226
1227static struct platform_driver ngd_slim_driver = {
1228 .probe = ngd_slim_probe,
1229 .remove = ngd_slim_remove,
1230 .driver = {
1231 .name = NGD_SLIM_NAME,
1232 .owner = THIS_MODULE,
1233 .pm = &ngd_slim_dev_pm_ops,
1234 .of_match_table = ngd_slim_dt_match,
1235 },
1236};
1237
1238static int ngd_slim_init(void)
1239{
1240 return platform_driver_register(&ngd_slim_driver);
1241}
1242late_initcall(ngd_slim_init);
1243
1244static void ngd_slim_exit(void)
1245{
1246 platform_driver_unregister(&ngd_slim_driver);
1247}
1248module_exit(ngd_slim_exit);
1249
1250MODULE_LICENSE("GPL v2");
1251MODULE_DESCRIPTION("MSM Slimbus controller");
1252MODULE_ALIAS("platform:msm-slim-ngd");