blob: 28471ca63eff5857ab746eeacc74bde08e956ee4 [file] [log] [blame]
Sagar Dhariab47c8962012-10-30 13:44:08 -06001/* Copyright (c) 2011-2012, 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
36
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
81static irqreturn_t ngd_slim_interrupt(int irq, void *d)
82{
83 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)d;
84 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
85 u32 stat = readl_relaxed(ngd + NGD_INT_STAT);
86
87 if (stat & NGD_INT_TX_MSG_SENT) {
88 writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
89 /* Make sure interrupt is cleared */
90 mb();
91 if (dev->wr_comp)
92 complete(dev->wr_comp);
93 } else if ((stat & NGD_INT_MSG_BUF_CONTE) ||
94 (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
95 (stat & NGD_INT_TX_NACKED_2)) {
96 dev_err(dev->dev, "NGD interrupt error:0x%x", stat);
97 writel_relaxed(stat, ngd + NGD_INT_CLR);
98 /* Guarantee that error interrupts are cleared */
99 mb();
100 if (((stat & NGD_INT_TX_NACKED_2) ||
101 (stat & NGD_INT_MSG_TX_INVAL))) {
102 dev->err = -EIO;
103 if (dev->wr_comp)
104 complete(dev->wr_comp);
105 }
106 }
107 if (stat & NGD_INT_RX_MSG_RCVD) {
108 u32 rx_buf[10];
109 u8 len, i;
110 rx_buf[0] = readl_relaxed(ngd + NGD_RX_MSG);
111 len = rx_buf[0] & 0x1F;
112 for (i = 1; i < ((len + 3) >> 2); i++) {
113 rx_buf[i] = readl_relaxed(ngd + NGD_RX_MSG +
114 (4 * i));
115 dev_dbg(dev->dev, "REG-RX data: %x\n", rx_buf[i]);
116 }
117 msm_slim_rx_enqueue(dev, rx_buf, len);
118 writel_relaxed(NGD_INT_RX_MSG_RCVD,
119 ngd + NGD_INT_CLR);
120 /*
121 * Guarantee that CLR bit write goes through before
122 * queuing work
123 */
124 mb();
125 if (dev->use_rx_msgqs)
126 dev_err(dev->dev,
127 "direct message received even with RX MSGQs");
128 else
129 complete(&dev->rx_msgq_notify);
130 }
131 if (stat & NGD_INT_RECFG_DONE) {
132 writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
133 /* Guarantee RECONFIG DONE interrupt is cleared */
134 mb();
135 /* In satellite mode, just log the reconfig done IRQ */
136 dev_dbg(dev->dev, "reconfig done IRQ for NGD");
137 }
138 if (stat & NGD_INT_IE_VE_CHG) {
139 writel_relaxed(NGD_INT_IE_VE_CHG, ngd + NGD_INT_CLR);
140 /* Guarantee IE VE change interrupt is cleared */
141 mb();
142 dev_err(dev->dev, "NGD IE VE change");
143 }
144 return IRQ_HANDLED;
145}
146
147static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
148 u8 *tid, struct completion *done)
149{
150 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
151 if (ctrl->last_tid <= 255) {
152 ctrl->txnt = krealloc(ctrl->txnt,
153 (ctrl->last_tid + 1) *
154 sizeof(struct slim_msg_txn *),
155 GFP_KERNEL);
156 if (!ctrl->txnt)
157 return -ENOMEM;
158 dev->msg_cnt = ctrl->last_tid;
159 ctrl->last_tid++;
160 } else {
161 int i;
162 for (i = 0; i < 256; i++) {
163 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
164 if (ctrl->txnt[dev->msg_cnt] == NULL)
165 break;
166 }
167 if (i >= 256) {
168 dev_err(&ctrl->dev, "out of TID");
169 return -ENOMEM;
170 }
171 }
172 ctrl->txnt[dev->msg_cnt] = txn;
173 txn->tid = dev->msg_cnt;
174 txn->comp = done;
175 *tid = dev->msg_cnt;
176 return 0;
177}
178static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
179{
180 DECLARE_COMPLETION_ONSTACK(done);
181 DECLARE_COMPLETION_ONSTACK(tx_sent);
182
183 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
184 u32 *pbuf;
185 u8 *puc;
186 int ret = 0;
187 int msgv = -1;
188 u8 la = txn->la;
189 u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
190
191 if (txn->mt == SLIM_MSG_MT_CORE &&
192 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
193 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
194 return 0;
195 }
196 msgv = msm_slim_get_ctrl(dev);
197 mutex_lock(&dev->tx_lock);
198 if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
199 (dev->state == MSM_CTRL_ASLEEP ||
200 dev->state == MSM_CTRL_SLEEPING)) {
201 int timeout;
202 dev_err(dev->dev, "controller not ready");
203 mutex_unlock(&dev->tx_lock);
204 /* Reconf is signalled when master responds */
205 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
206 if (timeout) {
207 mutex_lock(&dev->tx_lock);
208 } else {
209 if (msgv >= 0)
210 msm_slim_put_ctrl(dev);
211 return -EBUSY;
212 }
213 }
214 if (txn->mt == SLIM_MSG_MT_CORE &&
215 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
216 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
217 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
218 int i = 0;
219 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
220 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
221 txn->mc = SLIM_USR_MC_CONNECT_SRC;
222 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
223 txn->mc = SLIM_USR_MC_CONNECT_SINK;
224 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
225 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
226 if (txn->la == SLIM_LA_MGR)
227 txn->la = dev->pgdla;
228 wbuf[i++] = txn->la;
229 la = SLIM_LA_MGR;
230 wbuf[i++] = txn->wbuf[0];
231 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
232 wbuf[i++] = txn->wbuf[1];
233 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
234 if (ret) {
235 pr_err("TID for connect/disconnect fail:%d", ret);
236 goto ngd_xfer_err;
237 }
238 txn->len = i;
239 txn->wbuf = wbuf;
240 txn->rl = txn->len + 4;
241 }
242 txn->rl--;
243 pbuf = msm_get_msg_buf(dev, txn->rl);
244 if (!pbuf) {
245 dev_err(dev->dev, "Message buffer unavailable");
246 ret = -ENOMEM;
247 goto ngd_xfer_err;
248 }
249 dev->err = 0;
250
251 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
252 ret = -EPROTONOSUPPORT;
253 goto ngd_xfer_err;
254 }
255 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
256 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
257 la);
258 else
259 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
260 la);
261 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
262 puc = ((u8 *)pbuf) + 3;
263 else
264 puc = ((u8 *)pbuf) + 2;
265 if (txn->rbuf)
266 *(puc++) = txn->tid;
267 if ((txn->mt == SLIM_MSG_MT_CORE) &&
268 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
269 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
270 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
271 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
272 *(puc++) = (txn->ec & 0xFF);
273 *(puc++) = (txn->ec >> 8)&0xFF;
274 }
275 if (txn->wbuf)
276 memcpy(puc, txn->wbuf, txn->len);
277 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
278 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
279 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
280 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
281 wbuf[0] == dev->pgdla) {
282 if (txn->mc != SLIM_MSG_MC_DISCONNECT_PORT)
283 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
284 else {
285 struct msm_slim_endp *endpoint = &dev->pipes[wbuf[1]];
286 struct sps_register_event sps_event;
287 memset(&sps_event, 0, sizeof(sps_event));
288 sps_register_event(endpoint->sps, &sps_event);
289 sps_disconnect(endpoint->sps);
290 /*
291 * Remove channel disconnects master-side ports from
292 * channel. No need to send that again on the bus
293 */
294 dev->pipes[wbuf[1]].connected = false;
295 mutex_unlock(&dev->tx_lock);
296 if (msgv >= 0)
297 msm_slim_put_ctrl(dev);
298 return 0;
299 }
300 if (dev->err) {
301 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
302 goto ngd_xfer_err;
303 }
304 }
305 dev->err = 0;
306 dev->wr_comp = &tx_sent;
307 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
308 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
309 if (!ret) {
310 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
311 if (!timeout)
312 ret = -ETIMEDOUT;
313 else
314 ret = dev->err;
315 }
316 dev->wr_comp = NULL;
317 if (ret) {
318 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
319 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
320 dev->ver);
321 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
322 txn->mc, txn->mt, ret, dev->ver);
323 conf = readl_relaxed(ngd);
324 stat = readl_relaxed(ngd + NGD_STATUS);
325 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
326 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
327 int_en = readl_relaxed(ngd + NGD_INT_EN);
328 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
329
330 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
331 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
332 int_en, int_clr);
333 } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
334 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
335 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
336 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
337 int timeout;
338 mutex_unlock(&dev->tx_lock);
339 if (msgv >= 0)
340 msm_slim_put_ctrl(dev);
341 timeout = wait_for_completion_timeout(txn->comp, HZ);
342 if (!timeout) {
343 pr_err("connect/disc :0x%x, tid:%d timed out", txn->mc,
344 txn->tid);
345 ret = -ETIMEDOUT;
346 } else {
347 ret = txn->ec;
348 }
349 if (ret)
350 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
351 txn->tid, ret);
352 return ret ? ret : dev->err;
353 }
354ngd_xfer_err:
355 mutex_unlock(&dev->tx_lock);
356 if (msgv >= 0)
357 msm_slim_put_ctrl(dev);
358 return ret ? ret : dev->err;
359}
360
361static int ngd_xferandwait_ack(struct slim_controller *ctrl,
362 struct slim_msg_txn *txn)
363{
364 int ret = ngd_xfer_msg(ctrl, txn);
365 if (!ret) {
366 int timeout;
367 timeout = wait_for_completion_timeout(txn->comp, HZ);
368 if (!timeout) {
369 pr_err("master req:0x%x, tid:%d timed out", txn->mc,
370 txn->tid);
371 ret = -ETIMEDOUT;
372 } else {
373 ret = txn->ec;
374 }
375 }
376 if (ret)
377 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
378 txn->tid, ret);
379
380 return ret;
381}
382
383static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
384{
385 int ret;
386 struct slim_pending_ch *pch;
387 struct slim_msg_txn txn;
388 struct slim_controller *ctrl = sb->ctrl;
389 DECLARE_COMPLETION_ONSTACK(done);
390 u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
391
392 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
393 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
394 txn.la = SLIM_LA_MGR;
395 txn.len = 0;
396 txn.ec = 0;
397 txn.wbuf = wbuf;
398 txn.rbuf = NULL;
399
400 list_for_each_entry(pch, &sb->mark_define, pending) {
401 struct slim_ich *slc;
402 slc = &ctrl->chans[pch->chan];
403 if (!slc) {
404 pr_err("no channel in define?");
405 return -ENXIO;
406 }
407 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600408 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600409 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600410 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600411 wbuf[txn.len] = slc->seglen;
412 if (slc->coeff == SLIM_COEFF_3)
413 wbuf[txn.len] |= 1 << 5;
414 wbuf[txn.len++] |= slc->prop.auxf << 6;
415 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
416 wbuf[txn.len++] = slc->prrate;
417 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
418 if (ret) {
419 pr_err("no tid for channel define?");
420 return -ENXIO;
421 }
422 }
423 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600424 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600425 }
426 if (txn.len) {
427 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
428 txn.rl = txn.len + 4;
429 ret = ngd_xferandwait_ack(ctrl, &txn);
430 if (ret)
431 return ret;
432
433 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
434 txn.len = 2;
435 wbuf[1] = sb->laddr;
436 txn.rl = txn.len + 4;
437 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
438 if (ret)
439 return ret;
440 ret = ngd_xferandwait_ack(ctrl, &txn);
441 if (ret)
442 return ret;
443 }
444 txn.len = 0;
445 list_for_each_entry(pch, &sb->mark_removal, pending) {
446 struct slim_ich *slc;
447 slc = &ctrl->chans[pch->chan];
448 if (!slc) {
449 pr_err("no channel in removal?");
450 return -ENXIO;
451 }
452 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600453 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600454 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600455 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600456 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
457 if (ret) {
458 pr_err("no tid for channel define?");
459 return -ENXIO;
460 }
461 }
462 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600463 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600464 }
465 if (txn.len) {
466 txn.mc = SLIM_USR_MC_CHAN_CTRL;
467 txn.rl = txn.len + 4;
468 ret = ngd_xferandwait_ack(ctrl, &txn);
469 if (ret)
470 return ret;
471
472 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
473 txn.len = 2;
474 wbuf[1] = sb->laddr;
475 txn.rl = txn.len + 4;
476 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
477 if (ret)
478 return ret;
479 ret = ngd_xferandwait_ack(ctrl, &txn);
480 if (ret)
481 return ret;
482 txn.len = 0;
483 }
484 return ret;
485}
486
487static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
488 u8 elen, u8 laddr)
489{
490 return 0;
491}
492
493static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
494 u8 elen, u8 *laddr)
495{
496 int ret;
497 u8 wbuf[10];
498 struct slim_msg_txn txn;
499 DECLARE_COMPLETION_ONSTACK(done);
500 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
501 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
502 txn.la = SLIM_LA_MGR;
503 txn.ec = 0;
504 mutex_lock(&ctrl->m_ctrl);
505 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
506 if (ret) {
507 mutex_unlock(&ctrl->m_ctrl);
508 return ret;
509 }
510 memcpy(&wbuf[1], ea, elen);
511 txn.mc = SLIM_USR_MC_ADDR_QUERY;
512 txn.rl = 11;
513 txn.len = 7;
514 txn.wbuf = wbuf;
515 txn.rbuf = NULL;
516 ret = ngd_xferandwait_ack(ctrl, &txn);
517 if (!ret && txn.la == 0xFF)
518 ret = -ENXIO;
519 else if (!ret)
520 *laddr = txn.la;
521 mutex_unlock(&ctrl->m_ctrl);
522 return ret;
523}
524
525static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
526{
527 u8 mc, mt, len;
528 int ret;
529 u32 msgq_en = 1;
530
531 len = buf[0] & 0x1F;
532 mt = (buf[0] >> 5) & 0x7;
533 mc = buf[1];
534 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
535 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
536 struct slim_msg_txn txn;
537 u8 wbuf[8];
538 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
539 txn.ec = 0;
540 txn.rbuf = NULL;
541 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
542 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
543 txn.la = SLIM_LA_MGR;
544 txn.rl = 8;
545 wbuf[0] = SAT_MAGIC_LSB;
546 wbuf[1] = SAT_MAGIC_MSB;
547 wbuf[2] = SAT_MSG_VER;
548 wbuf[3] = SAT_MSG_PROT;
549 txn.wbuf = wbuf;
550 txn.len = 4;
551 dev->use_rx_msgqs = 1;
552 msm_slim_sps_init(dev, dev->bam_mem,
553 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_STATUS, true);
554 if (dev->use_rx_msgqs)
555 msgq_en |= NGD_CFG_RX_MSGQ_EN;
556 writel_relaxed(msgq_en, dev->base +
557 NGD_BASE(dev->ctrl.nr, dev->ver));
558 /* make sure NGD MSG-Q config goes through */
559 mb();
560
561 ret = ngd_xfer_msg(&dev->ctrl, &txn);
562 if (!ret) {
563 dev->state = MSM_CTRL_AWAKE;
564 complete(&dev->reconf);
565 }
566 }
567 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
568 mc == SLIM_MSG_MC_REPLY_VALUE) {
569 u8 tid = buf[3];
570 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
571 slim_msg_response(&dev->ctrl, &buf[4], tid,
572 len - 4);
573 pm_runtime_mark_last_busy(dev->dev);
574 }
575 if (mc == SLIM_USR_MC_ADDR_REPLY &&
576 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
577 struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
578 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
579 if (!txn)
580 return;
581 if (memcmp(&buf[4], failed_ea, 6))
582 txn->la = buf[10];
583 dev->ctrl.txnt[buf[3]] = NULL;
584 complete(txn->comp);
585 }
586 if (mc == SLIM_USR_MC_GENERIC_ACK &&
587 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
588 struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
589 if (!txn)
590 return;
591 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
592 (int)buf[3], buf[4]);
593 if (!(buf[4] & MSM_SAT_SUCCSS)) {
594 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
595 buf[4]);
596 txn->ec = -EIO;
597 }
598 dev->ctrl.txnt[buf[3]] = NULL;
599 complete(txn->comp);
600 }
601}
602static int ngd_slim_rx_msgq_thread(void *data)
603{
604 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
605 struct completion *notify = &dev->rx_msgq_notify;
606 int ret = 0, index = 0;
607 u32 mc = 0;
608 u32 mt = 0;
609 u32 buffer[10];
610 u8 msg_len = 0;
611
612 while (!kthread_should_stop()) {
613 set_current_state(TASK_INTERRUPTIBLE);
614 ret = wait_for_completion_interruptible(notify);
615 if (ret) {
616 dev_err(dev->dev, "rx thread wait err:%d", ret);
617 continue;
618 }
619 /* 1 irq notification per message */
620 if (!dev->use_rx_msgqs) {
621 msm_slim_rx_dequeue(dev, (u8 *)buffer);
622 ngd_slim_rx(dev, (u8 *)buffer);
623 continue;
624 }
625 ret = msm_slim_rx_msgq_get(dev, buffer, index);
626 if (ret) {
627 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
628 continue;
629 }
630
631 /* Wait for complete message */
632 if (index++ == 0) {
633 msg_len = *buffer & 0x1F;
634 mt = (buffer[0] >> 5) & 0x7;
635 mc = (buffer[0] >> 8) & 0xff;
636 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
637 }
638 if ((index * 4) >= msg_len) {
639 index = 0;
640 ngd_slim_rx(dev, (u8 *)buffer);
641 } else
642 continue;
643 }
644 return 0;
645}
646
647static int __devinit ngd_slim_probe(struct platform_device *pdev)
648{
649 struct msm_slim_ctrl *dev;
650 int ret;
651 struct resource *bam_mem;
652 struct resource *slim_mem;
653 struct resource *irq, *bam_irq;
654 enum apr_subsys_state q6_state;
655 u32 ngd_int;
656
657 q6_state = apr_get_q6_state();
658 if (q6_state == APR_SUBSYS_DOWN) {
659 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
660 q6_state);
661 return -EPROBE_DEFER;
662 } else
663 dev_dbg(&pdev->dev, "adsp is ready\n");
664
665 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
666 "slimbus_physical");
667 if (!slim_mem) {
668 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
669 return -ENODEV;
670 }
671 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
672 "slimbus_bam_physical");
673 if (!bam_mem) {
674 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
675 return -ENODEV;
676 }
677 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
678 "slimbus_irq");
679 if (!irq) {
680 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
681 return -ENODEV;
682 }
683 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
684 "slimbus_bam_irq");
685 if (!bam_irq) {
686 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
687 return -ENODEV;
688 }
689
690 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
691 if (IS_ERR(dev)) {
692 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
693 return PTR_ERR(dev);
694 }
695 dev->dev = &pdev->dev;
696 platform_set_drvdata(pdev, dev);
697 slim_set_ctrldata(&dev->ctrl, dev);
698 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
699 if (!dev->base) {
700 dev_err(&pdev->dev, "IOremap failed\n");
701 ret = -ENOMEM;
702 goto err_ioremap_failed;
703 }
704 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
705 if (!dev->bam.base) {
706 dev_err(&pdev->dev, "BAM IOremap failed\n");
707 ret = -ENOMEM;
708 goto err_ioremap_bam_failed;
709 }
710 if (pdev->dev.of_node) {
711
712 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
713 &dev->ctrl.nr);
714 if (ret) {
715 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
716 goto err_ctrl_failed;
717 }
718 } else {
719 dev->ctrl.nr = pdev->id;
720 }
721 dev->ctrl.nchans = MSM_SLIM_NCHANS;
722 dev->ctrl.nports = MSM_SLIM_NPORTS;
723 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
724 dev->framer.superfreq =
725 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
726 dev->ctrl.a_framer = &dev->framer;
727 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
728 dev->ctrl.set_laddr = ngd_set_laddr;
729 dev->ctrl.get_laddr = ngd_get_laddr;
730 dev->ctrl.allocbw = ngd_allocbw;
731 dev->ctrl.xfer_msg = ngd_xfer_msg;
732 dev->ctrl.wakeup = NULL;
733 dev->ctrl.config_port = msm_config_port;
734 dev->ctrl.port_xfer = msm_slim_port_xfer;
735 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
736 /* Reserve some messaging BW for satellite-apps driver communication */
737 dev->ctrl.sched.pending_msgsl = 30;
738 dev->bam_mem = bam_mem;
739
740 init_completion(&dev->reconf);
741 mutex_init(&dev->tx_lock);
742 spin_lock_init(&dev->rx_lock);
743 dev->ee = 1;
744 dev->irq = irq->start;
745 dev->bam.irq = bam_irq->start;
746
747 dev->ver = readl_relaxed(dev->base);
748 /* Version info in 16 MSbits */
749 dev->ver >>= 16;
750 ngd_int = (NGD_INT_RECFG_DONE | NGD_INT_TX_NACKED_2 |
751 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
752 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
753 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
754 init_completion(&dev->rx_msgq_notify);
755
756 /* Register with framework */
757 ret = slim_add_numbered_controller(&dev->ctrl);
758 if (ret) {
759 dev_err(dev->dev, "error adding controller\n");
760 goto err_ctrl_failed;
761 }
762
763 dev->ctrl.dev.parent = &pdev->dev;
764 dev->ctrl.dev.of_node = pdev->dev.of_node;
765 dev->state = MSM_CTRL_ASLEEP;
766
767 ret = request_irq(dev->irq, ngd_slim_interrupt,
768 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
769
770 if (ret) {
771 dev_err(&pdev->dev, "request IRQ failed\n");
772 goto err_request_irq_failed;
773 }
774
775 /* Fire up the Rx message queue thread */
776 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
777 NGD_SLIM_NAME "_ngd_msgq_thread");
778 if (IS_ERR(dev->rx_msgq_thread)) {
779 ret = PTR_ERR(dev->rx_msgq_thread);
780 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
781 goto err_thread_create_failed;
782 }
783
784 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
785 NGD_BASE(dev->ctrl.nr, dev->ver));
786 /*
787 * Enable NGD. Configure NGD in register access mode until master
788 * announcement is received
789 */
790 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
791 /* make sure NGD enabling goes through */
792 mb();
793
794 if (pdev->dev.of_node)
795 of_register_slim_devices(&dev->ctrl);
796
797 /* Add devices registered with board-info now that controller is up */
798 slim_ctrl_add_boarddevs(&dev->ctrl);
799
800 pm_runtime_use_autosuspend(&pdev->dev);
801 pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
802 pm_runtime_set_active(&pdev->dev);
803
804 dev_dbg(dev->dev, "NGD SB controller is up!\n");
805 return 0;
806
807err_thread_create_failed:
808 free_irq(dev->irq, dev);
809err_request_irq_failed:
810 slim_del_controller(&dev->ctrl);
811err_ctrl_failed:
812 iounmap(dev->bam.base);
813err_ioremap_bam_failed:
814 iounmap(dev->base);
815err_ioremap_failed:
816 kfree(dev);
817 return ret;
818}
819
820static int __devexit ngd_slim_remove(struct platform_device *pdev)
821{
822 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
823 pm_runtime_disable(&pdev->dev);
824 pm_runtime_set_suspended(&pdev->dev);
825 free_irq(dev->irq, dev);
826 slim_del_controller(&dev->ctrl);
827 kthread_stop(dev->rx_msgq_thread);
828 iounmap(dev->bam.base);
829 iounmap(dev->base);
830 kfree(dev);
831 return 0;
832}
833
834#ifdef CONFIG_PM_RUNTIME
835static int ngd_slim_runtime_idle(struct device *device)
836{
837 dev_dbg(device, "pm_runtime: idle...\n");
838 pm_request_autosuspend(device);
839 return -EAGAIN;
840}
841#endif
842
843/*
844 * If PM_RUNTIME is not defined, these 2 functions become helper
845 * functions to be called from system suspend/resume. So they are not
846 * inside ifdef CONFIG_PM_RUNTIME
847 */
848#ifdef CONFIG_PM_SLEEP
849static int ngd_slim_runtime_suspend(struct device *device)
850{
851 struct platform_device *pdev = to_platform_device(device);
852 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
853 int ret;
854 dev_dbg(device, "pm_runtime: suspending...\n");
855 dev->state = MSM_CTRL_SLEEPING;
856 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
857 if (ret) {
858 dev_err(device, "clk pause not entered:%d", ret);
859 dev->state = MSM_CTRL_AWAKE;
860 } else {
861 dev->state = MSM_CTRL_ASLEEP;
862 }
863 return ret;
864}
865
866static int ngd_slim_runtime_resume(struct device *device)
867{
868 struct platform_device *pdev = to_platform_device(device);
869 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
870 int ret = 0;
871 dev_dbg(device, "pm_runtime: resuming...\n");
872 if (dev->state == MSM_CTRL_ASLEEP)
873 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
874 if (ret) {
875 dev_err(device, "clk pause not exited:%d", ret);
876 dev->state = MSM_CTRL_ASLEEP;
877 } else {
878 dev->state = MSM_CTRL_AWAKE;
879 }
880 return ret;
881}
882
883static int ngd_slim_suspend(struct device *dev)
884{
885 int ret = -EBUSY;
886 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
887 dev_dbg(dev, "system suspend");
888 ret = ngd_slim_runtime_suspend(dev);
889 }
890 if (ret == -EBUSY) {
891 /*
892 * There is a possibility that some audio stream is active
893 * during suspend. We dont want to return suspend failure in
894 * that case so that display and relevant components can still
895 * go to suspend.
896 * If there is some other error, then it should be passed-on
897 * to system level suspend
898 */
899 ret = 0;
900 }
901 return ret;
902}
903
904static int ngd_slim_resume(struct device *dev)
905{
906 /* If runtime_pm is enabled, this resume shouldn't do anything */
907 if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
908 int ret;
909 dev_dbg(dev, "system resume");
910 ret = ngd_slim_runtime_resume(dev);
911 if (!ret) {
912 pm_runtime_mark_last_busy(dev);
913 pm_request_autosuspend(dev);
914 }
915 return ret;
916
917 }
918 return 0;
919}
920#endif /* CONFIG_PM_SLEEP */
921
922static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
923 SET_SYSTEM_SLEEP_PM_OPS(
924 ngd_slim_suspend,
925 ngd_slim_resume
926 )
927 SET_RUNTIME_PM_OPS(
928 ngd_slim_runtime_suspend,
929 ngd_slim_runtime_resume,
930 ngd_slim_runtime_idle
931 )
932};
933
934static struct of_device_id ngd_slim_dt_match[] = {
935 {
936 .compatible = "qcom,slim-ngd",
937 },
938 {}
939};
940
941static struct platform_driver ngd_slim_driver = {
942 .probe = ngd_slim_probe,
943 .remove = ngd_slim_remove,
944 .driver = {
945 .name = NGD_SLIM_NAME,
946 .owner = THIS_MODULE,
947 .pm = &ngd_slim_dev_pm_ops,
948 .of_match_table = ngd_slim_dt_match,
949 },
950};
951
952static int ngd_slim_init(void)
953{
954 return platform_driver_register(&ngd_slim_driver);
955}
956late_initcall(ngd_slim_init);
957
958static void ngd_slim_exit(void)
959{
960 platform_driver_unregister(&ngd_slim_driver);
961}
962module_exit(ngd_slim_exit);
963
964MODULE_LICENSE("GPL v2");
965MODULE_DESCRIPTION("MSM Slimbus controller");
966MODULE_ALIAS("platform:msm-slim-ngd");