blob: 0f8f1dd3cd27bbf9ccf4c7b77a45aadff5b2e3cc [file] [log] [blame]
Sagar Dharia32379162013-12-12 00:46:37 -07001/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
Sagar Dharia71fcea52012-09-12 23:21:57 -06002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Sagar Dharia71fcea52012-09-12 23:21:57 -060012#include <linux/irq.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/io.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
20#include <linux/slimbus/slimbus.h>
21#include <linux/delay.h>
22#include <linux/kthread.h>
23#include <linux/clk.h>
24#include <linux/pm_runtime.h>
25#include <linux/of.h>
26#include <linux/of_slimbus.h>
27#include <linux/timer.h>
28#include <mach/sps.h>
29#include "slim-msm.h"
30#include <mach/qdsp6v2/apr.h>
31
32#define NGD_SLIM_NAME "ngd_msm_ctrl"
33#define SLIM_LA_MGR 0xFF
34#define SLIM_ROOT_FREQ 24576000
Sagar Dharia33beca02012-10-22 16:21:46 -060035#define LADDR_RETRY 5
Sagar Dharia71fcea52012-09-12 23:21:57 -060036
37#define NGD_BASE_V1(r) (((r) % 2) ? 0x800 : 0xA00)
38#define NGD_BASE_V2(r) (((r) % 2) ? 0x1000 : 0x2000)
39#define NGD_BASE(r, v) ((v) ? NGD_BASE_V2(r) : NGD_BASE_V1(r))
40/* NGD (Non-ported Generic Device) registers */
41enum ngd_reg {
42 NGD_CFG = 0x0,
43 NGD_STATUS = 0x4,
44 NGD_RX_MSGQ_CFG = 0x8,
45 NGD_INT_EN = 0x10,
46 NGD_INT_STAT = 0x14,
47 NGD_INT_CLR = 0x18,
48 NGD_TX_MSG = 0x30,
49 NGD_RX_MSG = 0x70,
50 NGD_IE_STAT = 0xF0,
51 NGD_VE_STAT = 0x100,
52};
53
54enum ngd_msg_cfg {
55 NGD_CFG_ENABLE = 1,
56 NGD_CFG_RX_MSGQ_EN = 1 << 1,
57 NGD_CFG_TX_MSGQ_EN = 1 << 2,
58};
59
60enum ngd_intr {
61 NGD_INT_RECFG_DONE = 1 << 24,
62 NGD_INT_TX_NACKED_2 = 1 << 25,
63 NGD_INT_MSG_BUF_CONTE = 1 << 26,
64 NGD_INT_MSG_TX_INVAL = 1 << 27,
65 NGD_INT_IE_VE_CHG = 1 << 28,
66 NGD_INT_DEV_ERR = 1 << 29,
67 NGD_INT_RX_MSG_RCVD = 1 << 30,
68 NGD_INT_TX_MSG_SENT = 1 << 31,
69};
70
71enum ngd_offsets {
72 NGD_NACKED_MC = 0x7F00000,
73 NGD_ACKED_MC = 0xFE000,
74 NGD_ERROR = 0x1800,
75 NGD_MSGQ_SUPPORT = 0x400,
76 NGD_RX_MSGQ_TIME_OUT = 0x16,
77 NGD_ENUMERATED = 0x1,
78 NGD_TX_BUSY = 0x0,
79};
80
Sagar Dharia33beca02012-10-22 16:21:46 -060081enum ngd_status {
82 NGD_LADDR = 1 << 1,
83};
84
85static int ngd_slim_runtime_resume(struct device *device);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -060086static int ngd_slim_power_up(struct msm_slim_ctrl *dev);
Sagar Dharia33beca02012-10-22 16:21:46 -060087
Sagar Dharia71fcea52012-09-12 23:21:57 -060088static irqreturn_t ngd_slim_interrupt(int irq, void *d)
89{
90 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)d;
91 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
92 u32 stat = readl_relaxed(ngd + NGD_INT_STAT);
Sagar Dharia2b8a4b52013-05-15 20:01:45 -060093 u32 pstat;
Sagar Dharia71fcea52012-09-12 23:21:57 -060094
Sagar Dhariafc690502014-02-03 12:17:04 -070095 if ((stat & NGD_INT_MSG_BUF_CONTE) ||
96 (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
97 (stat & NGD_INT_TX_NACKED_2)) {
98 writel_relaxed(stat, ngd + NGD_INT_CLR);
99 dev->err = -EIO;
100
101 dev_err(dev->dev, "NGD interrupt error:0x%x, err:%d", stat,
102 dev->err);
103 /* Guarantee that error interrupts are cleared */
104 mb();
105 if (dev->wr_comp)
106 complete(dev->wr_comp);
107
108 } else if (stat & NGD_INT_TX_MSG_SENT) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600109 writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
110 /* Make sure interrupt is cleared */
111 mb();
112 if (dev->wr_comp)
113 complete(dev->wr_comp);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600114 }
115 if (stat & NGD_INT_RX_MSG_RCVD) {
116 u32 rx_buf[10];
117 u8 len, i;
118 rx_buf[0] = readl_relaxed(ngd + NGD_RX_MSG);
119 len = rx_buf[0] & 0x1F;
120 for (i = 1; i < ((len + 3) >> 2); i++) {
121 rx_buf[i] = readl_relaxed(ngd + NGD_RX_MSG +
122 (4 * i));
123 dev_dbg(dev->dev, "REG-RX data: %x\n", rx_buf[i]);
124 }
125 msm_slim_rx_enqueue(dev, rx_buf, len);
126 writel_relaxed(NGD_INT_RX_MSG_RCVD,
127 ngd + NGD_INT_CLR);
128 /*
129 * Guarantee that CLR bit write goes through before
130 * queuing work
131 */
132 mb();
Sagar Dharia24419e32013-01-14 17:56:32 -0700133 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600134 dev_err(dev->dev,
135 "direct message received even with RX MSGQs");
136 else
137 complete(&dev->rx_msgq_notify);
138 }
139 if (stat & NGD_INT_RECFG_DONE) {
140 writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
141 /* Guarantee RECONFIG DONE interrupt is cleared */
142 mb();
143 /* In satellite mode, just log the reconfig done IRQ */
144 dev_dbg(dev->dev, "reconfig done IRQ for NGD");
145 }
146 if (stat & NGD_INT_IE_VE_CHG) {
147 writel_relaxed(NGD_INT_IE_VE_CHG, ngd + NGD_INT_CLR);
148 /* Guarantee IE VE change interrupt is cleared */
149 mb();
150 dev_err(dev->dev, "NGD IE VE change");
151 }
Sagar Dharia2b8a4b52013-05-15 20:01:45 -0600152
153 pstat = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_ST_EEn, dev->ver));
154 if (pstat != 0)
155 return msm_slim_port_irq_handler(dev, pstat);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600156 return IRQ_HANDLED;
157}
158
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700159static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
160 void *_cmd)
161{
162 struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
Sagar Dharia33beca02012-10-22 16:21:46 -0600163 struct msm_slim_ctrl *dev =
164 container_of(qmi, struct msm_slim_ctrl, qmi);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700165 pr_info("Slimbus QMI NGD CB received event:%ld", code);
166 switch (code) {
167 case QMI_SERVER_ARRIVE:
Sagar Dharia33beca02012-10-22 16:21:46 -0600168 schedule_work(&qmi->ssr_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700169 break;
170 case QMI_SERVER_EXIT:
Sagar Dharia33beca02012-10-22 16:21:46 -0600171 dev->state = MSM_CTRL_DOWN;
172 /* make sure autosuspend is not called until ADSP comes up*/
173 pm_runtime_get_noresume(dev->dev);
174 /* Reset ctrl_up completion */
175 init_completion(&dev->ctrl_up);
176 schedule_work(&qmi->ssr_down);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700177 break;
178 default:
179 break;
180 }
181 return 0;
182}
183
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600184static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
185 void *_cmd)
186{
187 struct msm_slim_mdm *mdm = container_of(n, struct msm_slim_mdm, nb);
188 struct msm_slim_ctrl *dev = container_of(mdm, struct msm_slim_ctrl,
189 mdm);
190 int ret;
191
192 switch (code) {
193 case SUBSYS_BEFORE_SHUTDOWN:
194 /* make sure runtime-pm doesn't suspend during modem SSR */
195 pm_runtime_get_noresume(dev->dev);
196 break;
197 case SUBSYS_AFTER_POWERUP:
198 ret = msm_slim_qmi_check_framer_request(dev);
199 dev_err(dev->dev,
200 "%s:SLIM %lu external_modem SSR notify cb, ret %d",
201 __func__, code, ret);
202 /*
203 * Next codec transaction will reinit the HW
204 * if it was suspended
205 */
206 if (pm_runtime_suspended(dev->dev) ||
207 dev->state >= MSM_CTRL_ASLEEP) {
208 break;
209 } else {
210 ngd_slim_power_up(dev);
211 msm_slim_put_ctrl(dev);
212 }
213 default:
214 break;
215 }
216 return NOTIFY_DONE;
217}
218
Sagar Dharia71fcea52012-09-12 23:21:57 -0600219static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
220 u8 *tid, struct completion *done)
221{
222 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700223 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600224 if (ctrl->last_tid <= 255) {
225 ctrl->txnt = krealloc(ctrl->txnt,
226 (ctrl->last_tid + 1) *
227 sizeof(struct slim_msg_txn *),
228 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700229 if (!ctrl->txnt) {
230 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600231 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700232 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600233 dev->msg_cnt = ctrl->last_tid;
234 ctrl->last_tid++;
235 } else {
236 int i;
237 for (i = 0; i < 256; i++) {
238 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
239 if (ctrl->txnt[dev->msg_cnt] == NULL)
240 break;
241 }
242 if (i >= 256) {
243 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700244 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600245 return -ENOMEM;
246 }
247 }
248 ctrl->txnt[dev->msg_cnt] = txn;
249 txn->tid = dev->msg_cnt;
250 txn->comp = done;
251 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700252 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600253 return 0;
254}
255static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
256{
257 DECLARE_COMPLETION_ONSTACK(done);
258 DECLARE_COMPLETION_ONSTACK(tx_sent);
259
260 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
261 u32 *pbuf;
262 u8 *puc;
263 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600264 u8 la = txn->la;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600265 u8 txn_mt;
266 u16 txn_mc = txn->mc;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600267 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700268 bool report_sat = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600269
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700270 if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
271 txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
272 report_sat = true;
Sagar Dhariaa1398282013-01-22 13:26:20 -0700273 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700274 report_sat == false) {
Sagar Dhariaa1398282013-01-22 13:26:20 -0700275 /*
276 * Counter-part of system-suspend when runtime-pm is not enabled
277 * This way, resume can be left empty and device will be put in
278 * active mode only if client requests anything on the bus
279 * If the state was DOWN, SSR UP notification will take
280 * care of putting the device in active state.
281 */
282 ngd_slim_runtime_resume(dev->dev);
283 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600284 if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
285 SLIM_MSG_MC_RECONFIGURE_NOW)) &&
Sagar Dhariad1468b72013-07-16 12:56:22 -0600286 dev->state <= MSM_CTRL_IDLE) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600287 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
288 &dev->use_rx_msgqs);
289 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
290 &dev->use_tx_msgqs);
291 return msm_slim_qmi_power_request(dev, false);
Sagar Dharia24419e32013-01-14 17:56:32 -0700292 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700293 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
294 return 0;
295
Sagar Dharia71fcea52012-09-12 23:21:57 -0600296 if (txn->mt == SLIM_MSG_MT_CORE &&
297 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
298 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
299 return 0;
300 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600301 /* If txn is tried when controller is down, wait for ADSP to boot */
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700302 if (!report_sat) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600303 if (dev->state == MSM_CTRL_DOWN) {
304 u8 mc = (u8)txn->mc;
305 int timeout;
306 dev_err(dev->dev, "ADSP slimbus not up yet");
307 /*
308 * Messages related to data channel management can't
309 * wait since they are holding reconfiguration lock.
310 * clk_pause in resume (which can change state back to
Sagar Dharia32379162013-12-12 00:46:37 -0700311 * MSM_CTRL_AWAKE), will need that lock.
312 * Port disconnection, channel removal calls should pass
313 * through since there is no activity on the bus and
314 * those calls are triggered by clients due to
315 * device_down callback in that situation.
316 * Returning 0 on the disconnections and
317 * removals will ensure consistent state of channels,
318 * ports with the HW
Sagar Dharia55bced82014-01-20 16:00:44 -0700319 * Remote requests to remove channel/port will be
320 * returned from the path where they wait on
321 * acknowledgement from ADSP
Sagar Dharia33beca02012-10-22 16:21:46 -0600322 */
Sagar Dharia32379162013-12-12 00:46:37 -0700323 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
324 ((mc == SLIM_USR_MC_CHAN_CTRL ||
325 mc == SLIM_USR_MC_DISCONNECT_PORT ||
326 mc == SLIM_USR_MC_RECONFIG_NOW)))
Sagar Dharia55bced82014-01-20 16:00:44 -0700327 return -EREMOTEIO;
Sagar Dharia32379162013-12-12 00:46:37 -0700328 if ((txn->mt == SLIM_MSG_MT_CORE) &&
329 ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
330 mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
331 mc == SLIM_USR_MC_RECONFIG_NOW)))
332 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600333 if ((txn->mt == SLIM_MSG_MT_CORE) &&
334 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
335 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
336 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
337 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
338 return -EREMOTEIO;
339 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
340 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
Sagar Dharia32379162013-12-12 00:46:37 -0700341 mc < SLIM_USR_MC_DISCONNECT_PORT)))
Sagar Dharia33beca02012-10-22 16:21:46 -0600342 return -EREMOTEIO;
343 timeout = wait_for_completion_timeout(&dev->ctrl_up,
344 HZ);
Sagar Dharia4f240722014-01-15 13:50:58 -0700345 if (!timeout && dev->state == MSM_CTRL_DOWN)
Sagar Dharia33beca02012-10-22 16:21:46 -0600346 return -ETIMEDOUT;
347 }
Sagar Dharia129c7d82013-08-08 19:35:50 -0600348 ret = msm_slim_get_ctrl(dev);
349 /*
350 * Runtime-pm's callbacks are not called until runtime-pm's
351 * error status is cleared
352 * Setting runtime status to suspended clears the error
353 * It also makes HW status cosistent with what SW has it here
354 */
355 if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
356 pm_runtime_set_suspended(dev->dev);
357 msm_slim_put_ctrl(dev);
358 return -EREMOTEIO;
Sagar Dhariad1468b72013-07-16 12:56:22 -0600359 } else if (ret >= 0) {
360 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia129c7d82013-08-08 19:35:50 -0600361 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600362 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600363 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600364
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700365 if (report_sat == false && dev->state != MSM_CTRL_AWAKE) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600366 dev_err(dev->dev, "controller not ready");
367 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600368 msm_slim_put_ctrl(dev);
369 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600370 }
371 if (txn->mt == SLIM_MSG_MT_CORE &&
372 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
373 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
374 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
375 int i = 0;
376 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
377 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
378 txn->mc = SLIM_USR_MC_CONNECT_SRC;
379 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
380 txn->mc = SLIM_USR_MC_CONNECT_SINK;
381 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
382 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600383 if (txn->la == SLIM_LA_MGR) {
384 if (dev->pgdla == SLIM_LA_MGR) {
385 u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
386 QC_MFGID_LSB};
387 ea[2] = (u8)(dev->pdata.eapc & 0xFF);
388 ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
389 mutex_unlock(&dev->tx_lock);
390 ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
391 &dev->pgdla);
392 pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
393 ret);
394 if (ret) {
395 pr_err("Incorrect SLIM-PGD EAPC:0x%x",
396 dev->pdata.eapc);
397 return ret;
398 }
399 mutex_lock(&dev->tx_lock);
400 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600401 txn->la = dev->pgdla;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600402 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600403 wbuf[i++] = txn->la;
404 la = SLIM_LA_MGR;
405 wbuf[i++] = txn->wbuf[0];
406 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
407 wbuf[i++] = txn->wbuf[1];
408 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
409 if (ret) {
410 pr_err("TID for connect/disconnect fail:%d", ret);
411 goto ngd_xfer_err;
412 }
413 txn->len = i;
414 txn->wbuf = wbuf;
415 txn->rl = txn->len + 4;
416 }
417 txn->rl--;
418 pbuf = msm_get_msg_buf(dev, txn->rl);
419 if (!pbuf) {
420 dev_err(dev->dev, "Message buffer unavailable");
421 ret = -ENOMEM;
422 goto ngd_xfer_err;
423 }
424 dev->err = 0;
425
426 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
427 ret = -EPROTONOSUPPORT;
428 goto ngd_xfer_err;
429 }
430 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
431 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
432 la);
433 else
434 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
435 la);
436 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
437 puc = ((u8 *)pbuf) + 3;
438 else
439 puc = ((u8 *)pbuf) + 2;
440 if (txn->rbuf)
441 *(puc++) = txn->tid;
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700442 if (((txn->mt == SLIM_MSG_MT_CORE) &&
Sagar Dharia71fcea52012-09-12 23:21:57 -0600443 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
444 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
445 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700446 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) ||
447 (txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE &&
448 txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600449 *(puc++) = (txn->ec & 0xFF);
450 *(puc++) = (txn->ec >> 8)&0xFF;
451 }
452 if (txn->wbuf)
453 memcpy(puc, txn->wbuf, txn->len);
454 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
455 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
456 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
457 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
458 wbuf[0] == dev->pgdla) {
Sagar Dharia2d74c142013-05-17 02:24:06 -0600459 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600460 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
461 else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600462 /*
463 * Remove channel disconnects master-side ports from
464 * channel. No need to send that again on the bus
Sagar Dharia2d74c142013-05-17 02:24:06 -0600465 * Only disable port
Sagar Dharia71fcea52012-09-12 23:21:57 -0600466 */
Sagar Dharia2d74c142013-05-17 02:24:06 -0600467 writel_relaxed(0, PGD_PORT(PGD_PORT_CFGn,
468 (wbuf[1] + dev->port_b), dev->ver));
Sagar Dharia71fcea52012-09-12 23:21:57 -0600469 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700470 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600471 return 0;
472 }
473 if (dev->err) {
474 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
475 goto ngd_xfer_err;
476 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600477 /* Add port-base to port number if this is manager side port */
478 puc[1] += dev->port_b;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600479 }
480 dev->err = 0;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600481 /*
482 * If it's a read txn, it may be freed if a response is received by
483 * received thread before reaching end of this function.
484 * mc, mt may have changed to convert standard slimbus code/type to
485 * satellite user-defined message. Reinitialize again
486 */
487 txn_mc = txn->mc;
488 txn_mt = txn->mt;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600489 dev->wr_comp = &tx_sent;
490 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
491 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
492 if (!ret) {
493 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600494 if (!timeout) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600495 ret = -ETIMEDOUT;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600496 /*
497 * disconnect/recoonect pipe so that subsequent
498 * transactions don't timeout due to unavailable
499 * descriptors
500 */
501 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
502 &dev->use_tx_msgqs);
503 msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
504 } else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600505 ret = dev->err;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600506 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600507 }
508 dev->wr_comp = NULL;
509 if (ret) {
510 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
511 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
512 dev->ver);
513 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600514 txn_mc, txn_mt, ret, dev->ver);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600515 conf = readl_relaxed(ngd);
516 stat = readl_relaxed(ngd + NGD_STATUS);
517 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
518 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
519 int_en = readl_relaxed(ngd + NGD_INT_EN);
520 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
521
522 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
523 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
524 int_en, int_clr);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600525 } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
526 (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
527 txn_mc == SLIM_USR_MC_CONNECT_SINK ||
528 txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600529 int timeout;
530 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700531 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600532 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600533 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600534 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600535 else
536 ret = txn->ec;
537 if (ret) {
538 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
539 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700540 mutex_lock(&ctrl->m_ctrl);
541 ctrl->txnt[txn->tid] = NULL;
542 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600543 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600544 return ret ? ret : dev->err;
545 }
546ngd_xfer_err:
547 mutex_unlock(&dev->tx_lock);
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700548 if (!report_sat)
Sagar Dharia33beca02012-10-22 16:21:46 -0600549 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600550 return ret ? ret : dev->err;
551}
552
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700553static int ngd_user_msg(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
554 struct slim_ele_access *msg, u8 *buf, u8 len)
555{
556 struct slim_msg_txn txn;
557
558 if (mt != SLIM_MSG_MT_DEST_REFERRED_USER ||
559 mc != SLIM_USR_MC_REPEAT_CHANGE_VALUE) {
560 return -EPROTONOSUPPORT;
561 }
562 if (len > SLIM_MAX_VE_SLC_BYTES ||
563 msg->start_offset > MSM_SLIM_VE_MAX_MAP_ADDR)
564 return -EINVAL;
565 if (len <= 4) {
566 txn.ec = len - 1;
567 } else if (len <= 8) {
568 if (len & 0x1)
569 return -EINVAL;
570 txn.ec = ((len >> 1) + 1);
571 } else {
572 if (len & 0x3)
573 return -EINVAL;
574 txn.ec = ((len >> 2) + 3);
575 }
576 txn.ec |= (0x8 | ((msg->start_offset & 0xF) << 4));
577 txn.ec |= ((msg->start_offset & 0xFF0) << 4);
578
579 txn.la = la;
580 txn.mt = mt;
581 txn.mc = mc;
582 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
583 txn.len = len;
584 txn.rl = len + 6;
585 txn.wbuf = buf;
586 txn.rbuf = NULL;
587 txn.comp = msg->comp;
588 return ngd_xfer_msg(ctrl, &txn);
589}
590
Sagar Dharia71fcea52012-09-12 23:21:57 -0600591static int ngd_xferandwait_ack(struct slim_controller *ctrl,
592 struct slim_msg_txn *txn)
593{
594 int ret = ngd_xfer_msg(ctrl, txn);
595 if (!ret) {
596 int timeout;
597 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600598 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600599 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600600 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600601 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600602 }
Sagar Dharia55bced82014-01-20 16:00:44 -0700603
Sagar Dharia33beca02012-10-22 16:21:46 -0600604 if (ret) {
Sagar Dharia21f88552014-02-07 00:10:37 -0700605 if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL)
606 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
Sagar Dharia71fcea52012-09-12 23:21:57 -0600607 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600608 mutex_lock(&ctrl->m_ctrl);
609 ctrl->txnt[txn->tid] = NULL;
610 mutex_unlock(&ctrl->m_ctrl);
611 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600612
613 return ret;
614}
615
616static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
617{
618 int ret;
619 struct slim_pending_ch *pch;
620 struct slim_msg_txn txn;
621 struct slim_controller *ctrl = sb->ctrl;
622 DECLARE_COMPLETION_ONSTACK(done);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600623 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600624
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600625 *clkgear = ctrl->clkgear;
626 *subfrmc = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600627 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
628 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
629 txn.la = SLIM_LA_MGR;
630 txn.len = 0;
631 txn.ec = 0;
632 txn.wbuf = wbuf;
633 txn.rbuf = NULL;
634
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600635 if (ctrl->sched.msgsl != ctrl->sched.pending_msgsl) {
636 pr_debug("slim reserve BW for messaging: req: %d",
637 ctrl->sched.pending_msgsl);
638 txn.mc = SLIM_USR_MC_REQ_BW;
639 wbuf[txn.len++] = ((sb->laddr & 0x1f) |
640 ((u8)(ctrl->sched.pending_msgsl & 0x7) << 5));
641 wbuf[txn.len++] = (u8)(ctrl->sched.pending_msgsl >> 3);
642 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
643 if (ret)
644 return ret;
645 txn.rl = txn.len + 4;
646 ret = ngd_xferandwait_ack(ctrl, &txn);
647 if (ret)
648 return ret;
649
650 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
651 txn.len = 2;
652 wbuf[1] = sb->laddr;
653 txn.rl = txn.len + 4;
654 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
655 if (ret)
656 return ret;
657 ret = ngd_xferandwait_ack(ctrl, &txn);
658 if (ret)
659 return ret;
660
661 txn.len = 0;
662 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600663 list_for_each_entry(pch, &sb->mark_define, pending) {
664 struct slim_ich *slc;
665 slc = &ctrl->chans[pch->chan];
666 if (!slc) {
667 pr_err("no channel in define?");
668 return -ENXIO;
669 }
670 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600671 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600672 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600673 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600674 wbuf[txn.len] = slc->seglen;
675 if (slc->coeff == SLIM_COEFF_3)
676 wbuf[txn.len] |= 1 << 5;
677 wbuf[txn.len++] |= slc->prop.auxf << 6;
678 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
679 wbuf[txn.len++] = slc->prrate;
680 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
681 if (ret) {
682 pr_err("no tid for channel define?");
683 return -ENXIO;
684 }
685 }
686 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600687 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600688 }
689 if (txn.len) {
690 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
691 txn.rl = txn.len + 4;
692 ret = ngd_xferandwait_ack(ctrl, &txn);
693 if (ret)
694 return ret;
695
696 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
697 txn.len = 2;
698 wbuf[1] = sb->laddr;
699 txn.rl = txn.len + 4;
700 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
701 if (ret)
702 return ret;
703 ret = ngd_xferandwait_ack(ctrl, &txn);
704 if (ret)
705 return ret;
706 }
707 txn.len = 0;
708 list_for_each_entry(pch, &sb->mark_removal, pending) {
709 struct slim_ich *slc;
710 slc = &ctrl->chans[pch->chan];
711 if (!slc) {
712 pr_err("no channel in removal?");
713 return -ENXIO;
714 }
715 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600716 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600717 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600718 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600719 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
720 if (ret) {
721 pr_err("no tid for channel define?");
722 return -ENXIO;
723 }
724 }
725 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600726 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600727 }
728 if (txn.len) {
729 txn.mc = SLIM_USR_MC_CHAN_CTRL;
730 txn.rl = txn.len + 4;
731 ret = ngd_xferandwait_ack(ctrl, &txn);
Sagar Dharia21f88552014-02-07 00:10:37 -0700732 /* HW restarting, channel removal should succeed */
733 if (ret == -EREMOTEIO)
734 return 0;
735 else if (ret)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600736 return ret;
737
738 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
739 txn.len = 2;
740 wbuf[1] = sb->laddr;
741 txn.rl = txn.len + 4;
742 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
743 if (ret)
744 return ret;
745 ret = ngd_xferandwait_ack(ctrl, &txn);
746 if (ret)
747 return ret;
748 txn.len = 0;
749 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700750 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600751}
752
753static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
754 u8 elen, u8 laddr)
755{
756 return 0;
757}
758
759static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
760 u8 elen, u8 *laddr)
761{
762 int ret;
763 u8 wbuf[10];
764 struct slim_msg_txn txn;
765 DECLARE_COMPLETION_ONSTACK(done);
766 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
767 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
768 txn.la = SLIM_LA_MGR;
769 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600770 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
771 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600772 return ret;
773 }
774 memcpy(&wbuf[1], ea, elen);
775 txn.mc = SLIM_USR_MC_ADDR_QUERY;
776 txn.rl = 11;
777 txn.len = 7;
778 txn.wbuf = wbuf;
779 txn.rbuf = NULL;
780 ret = ngd_xferandwait_ack(ctrl, &txn);
781 if (!ret && txn.la == 0xFF)
782 ret = -ENXIO;
783 else if (!ret)
784 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600785 return ret;
786}
787
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600788static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
Sagar Dharia24419e32013-01-14 17:56:32 -0700789{
Sagar Dharia24419e32013-01-14 17:56:32 -0700790 if (dev->state == MSM_CTRL_DOWN) {
791 msm_slim_sps_init(dev, dev->bam_mem,
792 NGD_BASE(dev->ctrl.nr,
793 dev->ver) + NGD_STATUS, true);
794 } else {
795 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600796 goto setup_tx_msg_path;
797 msm_slim_connect_endp(dev, &dev->rx_msgq,
Sagar Dharia24419e32013-01-14 17:56:32 -0700798 &dev->rx_msgq_notify);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600799
800setup_tx_msg_path:
801 if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
802 return;
803 msm_slim_connect_endp(dev, &dev->tx_msgq,
804 NULL);
Sagar Dharia24419e32013-01-14 17:56:32 -0700805 }
806}
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600807
Sagar Dharia71fcea52012-09-12 23:21:57 -0600808static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
809{
810 u8 mc, mt, len;
811 int ret;
812 u32 msgq_en = 1;
813
814 len = buf[0] & 0x1F;
815 mt = (buf[0] >> 5) & 0x7;
816 mc = buf[1];
817 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
818 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
819 struct slim_msg_txn txn;
Sagar Dharia0a693332013-04-15 17:59:03 -0600820 int retries = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600821 u8 wbuf[8];
822 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
823 txn.ec = 0;
824 txn.rbuf = NULL;
825 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
826 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
827 txn.la = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600828 wbuf[0] = SAT_MAGIC_LSB;
829 wbuf[1] = SAT_MAGIC_MSB;
830 wbuf[2] = SAT_MSG_VER;
831 wbuf[3] = SAT_MSG_PROT;
832 txn.wbuf = wbuf;
833 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700834 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700835 if (dev->state >= MSM_CTRL_ASLEEP) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600836 ngd_slim_setup_msg_path(dev);
Sagar Dharia24419e32013-01-14 17:56:32 -0700837 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600838 msgq_en |= NGD_CFG_RX_MSGQ_EN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600839 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
840 msgq_en |= NGD_CFG_TX_MSGQ_EN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600841 writel_relaxed(msgq_en, dev->base +
842 NGD_BASE(dev->ctrl.nr, dev->ver));
843 /* make sure NGD MSG-Q config goes through */
844 mb();
845 }
Sagar Dharia0a693332013-04-15 17:59:03 -0600846capability_retry:
847 txn.rl = 8;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600848 ret = ngd_xfer_msg(&dev->ctrl, &txn);
849 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600850 enum msm_ctrl_state prev_state = dev->state;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600851 pr_info("SLIM SAT: capability exchange successful");
Sagar Dharia71fcea52012-09-12 23:21:57 -0600852 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600853 if (prev_state >= MSM_CTRL_ASLEEP)
854 complete(&dev->reconf);
855 else
856 pr_err("SLIM: unexpected capability, state:%d",
857 prev_state);
858 /* ADSP SSR, send device_up notifications */
859 if (prev_state == MSM_CTRL_DOWN)
860 schedule_work(&dev->slave_notify);
Sagar Dharia0a693332013-04-15 17:59:03 -0600861 } else if (ret == -EIO) {
862 pr_info("capability message NACKed, retrying");
863 if (retries < INIT_MX_RETRIES) {
864 msleep(DEF_RETRY_MS);
865 retries++;
866 goto capability_retry;
867 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600868 }
869 }
870 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
871 mc == SLIM_MSG_MC_REPLY_VALUE) {
872 u8 tid = buf[3];
873 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
874 slim_msg_response(&dev->ctrl, &buf[4], tid,
875 len - 4);
876 pm_runtime_mark_last_busy(dev->dev);
877 }
878 if (mc == SLIM_USR_MC_ADDR_REPLY &&
879 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700880 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600881 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700882 mutex_lock(&dev->ctrl.m_ctrl);
883 txn = dev->ctrl.txnt[buf[3]];
884 if (!txn) {
885 pr_err("LADDR response after timeout, tid:0x%x",
886 buf[3]);
887 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600888 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700889 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600890 if (memcmp(&buf[4], failed_ea, 6))
891 txn->la = buf[10];
892 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700893 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600894 complete(txn->comp);
895 }
896 if (mc == SLIM_USR_MC_GENERIC_ACK &&
897 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700898 struct slim_msg_txn *txn;
899 mutex_lock(&dev->ctrl.m_ctrl);
900 txn = dev->ctrl.txnt[buf[3]];
901 if (!txn) {
902 pr_err("ACK received after timeout, tid:0x%x",
903 buf[3]);
904 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600905 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700906 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600907 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
908 (int)buf[3], buf[4]);
909 if (!(buf[4] & MSM_SAT_SUCCSS)) {
910 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
911 buf[4]);
912 txn->ec = -EIO;
913 }
914 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700915 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600916 complete(txn->comp);
917 }
918}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700919
Sagar Dharia33beca02012-10-22 16:21:46 -0600920static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700921{
Sagar Dharia33beca02012-10-22 16:21:46 -0600922 void __iomem *ngd;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600923 int timeout, ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600924 enum msm_ctrl_state cur_state = dev->state;
925 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700926 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700927 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
928 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
929 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600930
931 if (cur_state == MSM_CTRL_DOWN) {
932 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
933 HZ);
934 if (!timeout)
935 pr_err("slimbus QMI init timed out");
936 }
937
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600938 /* No need to vote if contorller is not in low power mode */
939 if (cur_state == MSM_CTRL_DOWN || cur_state == MSM_CTRL_ASLEEP) {
940 ret = msm_slim_qmi_power_request(dev, true);
941 if (ret) {
942 pr_err("SLIM QMI power request failed:%d", ret);
943 return ret;
944 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600945 }
946 if (!dev->ver) {
947 dev->ver = readl_relaxed(dev->base);
948 /* Version info in 16 MSbits */
949 dev->ver >>= 16;
950 }
951 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
952 laddr = readl_relaxed(ngd + NGD_STATUS);
953 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700954 /*
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600955 * external MDM restart case where ADSP itself was active framer
956 * For example, modem restarted when playback was active
957 */
958 if (cur_state == MSM_CTRL_AWAKE) {
959 pr_err("SLIM MDM restart: ADSP active framer:NO OP");
960 return 0;
961 }
962 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600963 * ADSP power collapse case, where HW wasn't reset.
964 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700965 */
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600966 ngd_slim_setup_msg_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600967 return 0;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600968 } else if (cur_state == MSM_CTRL_ASLEEP) {
969 pr_debug("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
Sagar Dharia33beca02012-10-22 16:21:46 -0600970 dev->state, laddr);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600971 } else if (cur_state == MSM_CTRL_IDLE || cur_state == MSM_CTRL_AWAKE) {
972 /*
973 * external MDM SSR when only voice call is in progress.
974 * ADSP will reset slimbus HW. disconnect BAM pipes so that
975 * they can be connected after capability message is received.
976 * Set device state to ASLEEP to be synchronous with the HW
977 */
978 pr_err("SLIM MDM restart: MDM active framer: reinit HW");
979 dev->state = MSM_CTRL_ASLEEP;
980 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
981 &dev->use_rx_msgqs);
982 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
983 &dev->use_tx_msgqs);
Sagar Dharia33beca02012-10-22 16:21:46 -0600984 }
Sagar Dhariada48bd62013-03-21 18:02:40 -0600985 /* ADSP SSR scenario, need to disconnect pipe before connecting */
986 if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
987 struct msm_slim_endp *endpoint = &dev->rx_msgq;
988 sps_disconnect(endpoint->sps);
989 sps_free_endpoint(endpoint->sps);
990 dev->use_rx_msgqs = MSM_MSGQ_RESET;
991 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600992 if (dev->use_tx_msgqs == MSM_MSGQ_DOWN) {
993 struct msm_slim_endp *endpoint = &dev->tx_msgq;
994 sps_disconnect(endpoint->sps);
995 sps_free_endpoint(endpoint->sps);
996 dev->use_tx_msgqs = MSM_MSGQ_RESET;
997 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600998 /*
999 * ADSP power collapse case (OR SSR), where HW was reset
1000 * BAM programming will happen when capability message is received
1001 */
1002 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001003 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001004 /*
1005 * Enable NGD. Configure NGD in register acc. mode until master
1006 * announcement is received
1007 */
Sagar Dharia24419e32013-01-14 17:56:32 -07001008 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001009 /* make sure NGD enabling goes through */
1010 mb();
1011
1012 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
1013 if (!timeout) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001014 pr_err("Failed to receive master capability");
Sagar Dharia33beca02012-10-22 16:21:46 -06001015 return -ETIMEDOUT;
1016 }
1017 if (cur_state == MSM_CTRL_DOWN)
1018 complete(&dev->ctrl_up);
1019 return 0;
1020}
1021
1022static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
1023{
1024 int ret = 0;
1025 if (enable) {
1026 ret = msm_slim_qmi_init(dev, false);
1027 /* controller state should be in sync with framework state */
1028 if (!ret) {
1029 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
1030 SLIM_CLK_UNSPECIFIED);
1031 complete(&dev->qmi.qmi_comp);
1032 /*
1033 * Power-up won't be called if clock pause failed.
1034 * This can happen if ADSP SSR happened when audio
1035 * session is in progress. Framework will think that
1036 * clock pause failed so no need to wakeup controller.
1037 * Call power-up explicitly in that case, since slimbus
1038 * HW needs to be powered-on to be in sync with
1039 * framework state
1040 */
1041 if (ret)
1042 ngd_slim_power_up(dev);
1043 if (!pm_runtime_enabled(dev->dev) ||
1044 !pm_runtime_suspended(dev->dev))
1045 ngd_slim_runtime_resume(dev->dev);
1046 else
1047 pm_runtime_resume(dev->dev);
1048 pm_runtime_mark_last_busy(dev->dev);
1049 pm_runtime_put(dev->dev);
1050 } else
1051 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
1052 ret, dev->state);
1053 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001054 msm_slim_qmi_exit(dev);
1055 }
1056
Sagar Dharia33beca02012-10-22 16:21:46 -06001057 return ret;
1058}
1059
1060static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
1061{
1062 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
1063 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001064}
1065
Sagar Dharia71fcea52012-09-12 23:21:57 -06001066static int ngd_slim_rx_msgq_thread(void *data)
1067{
1068 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
1069 struct completion *notify = &dev->rx_msgq_notify;
1070 int ret = 0, index = 0;
1071 u32 mc = 0;
1072 u32 mt = 0;
1073 u32 buffer[10];
1074 u8 msg_len = 0;
1075
1076 while (!kthread_should_stop()) {
1077 set_current_state(TASK_INTERRUPTIBLE);
1078 ret = wait_for_completion_interruptible(notify);
1079 if (ret) {
1080 dev_err(dev->dev, "rx thread wait err:%d", ret);
1081 continue;
1082 }
1083 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -07001084 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001085 msm_slim_rx_dequeue(dev, (u8 *)buffer);
1086 ngd_slim_rx(dev, (u8 *)buffer);
1087 continue;
1088 }
1089 ret = msm_slim_rx_msgq_get(dev, buffer, index);
1090 if (ret) {
1091 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
1092 continue;
1093 }
1094
1095 /* Wait for complete message */
1096 if (index++ == 0) {
1097 msg_len = *buffer & 0x1F;
1098 mt = (buffer[0] >> 5) & 0x7;
1099 mc = (buffer[0] >> 8) & 0xff;
1100 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
1101 }
1102 if ((index * 4) >= msg_len) {
1103 index = 0;
1104 ngd_slim_rx(dev, (u8 *)buffer);
1105 } else
1106 continue;
1107 }
1108 return 0;
1109}
1110
Sagar Dharia33beca02012-10-22 16:21:46 -06001111static void ngd_laddr_lookup(struct work_struct *work)
1112{
1113 struct msm_slim_ctrl *dev =
1114 container_of(work, struct msm_slim_ctrl, slave_notify);
1115 struct slim_controller *ctrl = &dev->ctrl;
1116 struct slim_device *sbdev;
Sagar Dharia21f88552014-02-07 00:10:37 -07001117 struct list_head *pos, *next;
Sagar Dharia33beca02012-10-22 16:21:46 -06001118 int i;
Sagar Dharia722f9e22013-12-11 23:59:22 -07001119 slim_framer_booted(ctrl);
Sagar Dharia33beca02012-10-22 16:21:46 -06001120 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia21f88552014-02-07 00:10:37 -07001121 list_for_each_safe(pos, next, &ctrl->devs) {
Sagar Dharia33beca02012-10-22 16:21:46 -06001122 int ret = 0;
Sagar Dharia21f88552014-02-07 00:10:37 -07001123 sbdev = list_entry(pos, struct slim_device, dev_list);
Sagar Dharia33beca02012-10-22 16:21:46 -06001124 mutex_unlock(&ctrl->m_ctrl);
1125 for (i = 0; i < LADDR_RETRY; i++) {
1126 ret = slim_get_logical_addr(sbdev, sbdev->e_addr,
1127 6, &sbdev->laddr);
1128 if (!ret)
1129 break;
1130 else /* time for ADSP to assign LA */
1131 msleep(20);
1132 }
1133 mutex_lock(&ctrl->m_ctrl);
1134 }
1135 mutex_unlock(&ctrl->m_ctrl);
1136}
1137
1138static void ngd_adsp_down(struct work_struct *work)
1139{
1140 struct msm_slim_qmi *qmi =
1141 container_of(work, struct msm_slim_qmi, ssr_down);
1142 struct msm_slim_ctrl *dev =
1143 container_of(qmi, struct msm_slim_ctrl, qmi);
1144 struct slim_controller *ctrl = &dev->ctrl;
1145 struct slim_device *sbdev;
Sagar Dharia33beca02012-10-22 16:21:46 -06001146
1147 ngd_slim_enable(dev, false);
1148 /* disconnect BAM pipes */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001149 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
1150 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001151 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
1152 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -06001153 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001154 /* device up should be called again after SSR */
1155 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
Sagar Dhariaf68d71f2013-07-31 17:43:46 -06001156 slim_report_absent(sbdev);
Sagar Dharia33beca02012-10-22 16:21:46 -06001157 pr_info("SLIM ADSP SSR (DOWN) done");
1158}
1159
1160static void ngd_adsp_up(struct work_struct *work)
1161{
1162 struct msm_slim_qmi *qmi =
1163 container_of(work, struct msm_slim_qmi, ssr_up);
1164 struct msm_slim_ctrl *dev =
1165 container_of(qmi, struct msm_slim_ctrl, qmi);
1166 ngd_slim_enable(dev, true);
1167}
1168
Sagar Dharia71fcea52012-09-12 23:21:57 -06001169static int __devinit ngd_slim_probe(struct platform_device *pdev)
1170{
1171 struct msm_slim_ctrl *dev;
1172 int ret;
1173 struct resource *bam_mem;
1174 struct resource *slim_mem;
1175 struct resource *irq, *bam_irq;
1176 enum apr_subsys_state q6_state;
Sagar Dharia24419e32013-01-14 17:56:32 -07001177 bool rxreg_access = false;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001178 bool slim_mdm = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001179
1180 q6_state = apr_get_q6_state();
1181 if (q6_state == APR_SUBSYS_DOWN) {
1182 dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
1183 q6_state);
1184 return -EPROBE_DEFER;
1185 } else
1186 dev_dbg(&pdev->dev, "adsp is ready\n");
1187
1188 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1189 "slimbus_physical");
1190 if (!slim_mem) {
1191 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
1192 return -ENODEV;
1193 }
1194 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1195 "slimbus_bam_physical");
1196 if (!bam_mem) {
1197 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
1198 return -ENODEV;
1199 }
1200 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1201 "slimbus_irq");
1202 if (!irq) {
1203 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
1204 return -ENODEV;
1205 }
1206 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1207 "slimbus_bam_irq");
1208 if (!bam_irq) {
1209 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
1210 return -ENODEV;
1211 }
1212
1213 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
Kiran Gunda318cac42013-10-21 17:00:15 +05301214 if (IS_ERR_OR_NULL(dev)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001215 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
1216 return PTR_ERR(dev);
1217 }
1218 dev->dev = &pdev->dev;
1219 platform_set_drvdata(pdev, dev);
1220 slim_set_ctrldata(&dev->ctrl, dev);
1221 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
1222 if (!dev->base) {
1223 dev_err(&pdev->dev, "IOremap failed\n");
1224 ret = -ENOMEM;
1225 goto err_ioremap_failed;
1226 }
1227 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
1228 if (!dev->bam.base) {
1229 dev_err(&pdev->dev, "BAM IOremap failed\n");
1230 ret = -ENOMEM;
1231 goto err_ioremap_bam_failed;
1232 }
1233 if (pdev->dev.of_node) {
1234
1235 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1236 &dev->ctrl.nr);
1237 if (ret) {
1238 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1239 goto err_ctrl_failed;
1240 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001241 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1242 "qcom,rxreg-access");
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001243 of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
1244 &dev->pdata.apps_pipes);
1245 of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
1246 &dev->pdata.eapc);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001247 slim_mdm = of_property_read_bool(pdev->dev.of_node,
1248 "qcom,slim-mdm");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001249 } else {
1250 dev->ctrl.nr = pdev->id;
1251 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001252 /*
1253 * Keep PGD's logical address as manager's. Query it when first data
1254 * channel request comes in
1255 */
1256 dev->pgdla = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001257 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1258 dev->ctrl.nports = MSM_SLIM_NPORTS;
1259 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1260 dev->framer.superfreq =
1261 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1262 dev->ctrl.a_framer = &dev->framer;
1263 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1264 dev->ctrl.set_laddr = ngd_set_laddr;
1265 dev->ctrl.get_laddr = ngd_get_laddr;
1266 dev->ctrl.allocbw = ngd_allocbw;
1267 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariab046b3c2014-01-27 21:30:48 -07001268 dev->ctrl.xfer_user_msg = ngd_user_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001269 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia100e7212013-05-17 18:20:57 -06001270 dev->ctrl.alloc_port = msm_alloc_port;
1271 dev->ctrl.dealloc_port = msm_dealloc_port;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001272 dev->ctrl.port_xfer = msm_slim_port_xfer;
1273 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001274 dev->bam_mem = bam_mem;
1275
1276 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001277 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001278 mutex_init(&dev->tx_lock);
1279 spin_lock_init(&dev->rx_lock);
1280 dev->ee = 1;
1281 dev->irq = irq->start;
1282 dev->bam.irq = bam_irq->start;
1283
Sagar Dharia24419e32013-01-14 17:56:32 -07001284 if (rxreg_access)
1285 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1286 else
1287 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001288
1289 /* Enable TX message queues by default as recommended by HW */
1290 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1291
Sagar Dharia71fcea52012-09-12 23:21:57 -06001292 init_completion(&dev->rx_msgq_notify);
1293
1294 /* Register with framework */
1295 ret = slim_add_numbered_controller(&dev->ctrl);
1296 if (ret) {
1297 dev_err(dev->dev, "error adding controller\n");
1298 goto err_ctrl_failed;
1299 }
1300
1301 dev->ctrl.dev.parent = &pdev->dev;
1302 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001303 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001304
1305 ret = request_irq(dev->irq, ngd_slim_interrupt,
1306 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1307
1308 if (ret) {
1309 dev_err(&pdev->dev, "request IRQ failed\n");
1310 goto err_request_irq_failed;
1311 }
1312
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001313 init_completion(&dev->qmi.qmi_comp);
Sagar Dharia33beca02012-10-22 16:21:46 -06001314 pm_runtime_use_autosuspend(dev->dev);
1315 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1316 pm_runtime_set_suspended(dev->dev);
1317 pm_runtime_enable(dev->dev);
1318
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001319 if (slim_mdm) {
1320 dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
1321 dev->mdm.ssr = subsys_notif_register_notifier("external_modem",
1322 &dev->mdm.nb);
1323 if (IS_ERR_OR_NULL(dev->mdm.ssr))
1324 dev_err(dev->dev,
1325 "subsys_notif_register_notifier failed %p",
1326 dev->mdm.ssr);
1327 }
1328
Sagar Dharia33beca02012-10-22 16:21:46 -06001329 INIT_WORK(&dev->slave_notify, ngd_laddr_lookup);
1330 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1331 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001332 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001333 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001334 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001335 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001336 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1337 if (ret) {
1338 pr_err("Slimbus QMI service registration failed:%d", ret);
1339 goto qmi_register_failed;
1340 }
1341
Sagar Dharia33beca02012-10-22 16:21:46 -06001342
Sagar Dharia71fcea52012-09-12 23:21:57 -06001343 /* Fire up the Rx message queue thread */
1344 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
1345 NGD_SLIM_NAME "_ngd_msgq_thread");
1346 if (IS_ERR(dev->rx_msgq_thread)) {
1347 ret = PTR_ERR(dev->rx_msgq_thread);
1348 dev_err(dev->dev, "Failed to start Rx message queue thread\n");
1349 goto err_thread_create_failed;
1350 }
1351
Sagar Dharia71fcea52012-09-12 23:21:57 -06001352 if (pdev->dev.of_node)
1353 of_register_slim_devices(&dev->ctrl);
1354
1355 /* Add devices registered with board-info now that controller is up */
1356 slim_ctrl_add_boarddevs(&dev->ctrl);
1357
Sagar Dharia71fcea52012-09-12 23:21:57 -06001358 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1359 return 0;
1360
1361err_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001362 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001363 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001364 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1365qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001366 free_irq(dev->irq, dev);
1367err_request_irq_failed:
1368 slim_del_controller(&dev->ctrl);
1369err_ctrl_failed:
1370 iounmap(dev->bam.base);
1371err_ioremap_bam_failed:
1372 iounmap(dev->base);
1373err_ioremap_failed:
1374 kfree(dev);
1375 return ret;
1376}
1377
1378static int __devexit ngd_slim_remove(struct platform_device *pdev)
1379{
1380 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001381 ngd_slim_enable(dev, false);
1382 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001383 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001384 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001385 pm_runtime_disable(&pdev->dev);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001386 if (!IS_ERR_OR_NULL(dev->mdm.ssr))
1387 subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001388 free_irq(dev->irq, dev);
1389 slim_del_controller(&dev->ctrl);
1390 kthread_stop(dev->rx_msgq_thread);
1391 iounmap(dev->bam.base);
1392 iounmap(dev->base);
1393 kfree(dev);
1394 return 0;
1395}
1396
1397#ifdef CONFIG_PM_RUNTIME
1398static int ngd_slim_runtime_idle(struct device *device)
1399{
Sagar Dhariad1468b72013-07-16 12:56:22 -06001400 struct platform_device *pdev = to_platform_device(device);
1401 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1402 if (dev->state == MSM_CTRL_AWAKE)
1403 dev->state = MSM_CTRL_IDLE;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001404 dev_dbg(device, "pm_runtime: idle...\n");
1405 pm_request_autosuspend(device);
1406 return -EAGAIN;
1407}
1408#endif
1409
1410/*
1411 * If PM_RUNTIME is not defined, these 2 functions become helper
1412 * functions to be called from system suspend/resume. So they are not
1413 * inside ifdef CONFIG_PM_RUNTIME
1414 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001415static int ngd_slim_runtime_resume(struct device *device)
1416{
1417 struct platform_device *pdev = to_platform_device(device);
1418 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1419 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001420 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001421 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1422 if (ret) {
Sagar Dharia129c7d82013-08-08 19:35:50 -06001423 /* Did SSR cause this clock pause failure */
1424 if (dev->state != MSM_CTRL_DOWN)
1425 dev->state = MSM_CTRL_ASLEEP;
1426 else
1427 dev_err(device, "HW wakeup attempt during SSR");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001428 } else {
1429 dev->state = MSM_CTRL_AWAKE;
1430 }
1431 return ret;
1432}
1433
Sagar Dharia33beca02012-10-22 16:21:46 -06001434#ifdef CONFIG_PM_SLEEP
1435static int ngd_slim_runtime_suspend(struct device *device)
1436{
1437 struct platform_device *pdev = to_platform_device(device);
1438 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1439 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001440 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1441 if (ret) {
1442 if (ret != -EBUSY)
1443 dev_err(device, "clk pause not entered:%d", ret);
1444 dev->state = MSM_CTRL_AWAKE;
1445 } else {
1446 dev->state = MSM_CTRL_ASLEEP;
1447 }
1448 return ret;
1449}
1450
Sagar Dharia71fcea52012-09-12 23:21:57 -06001451static int ngd_slim_suspend(struct device *dev)
1452{
1453 int ret = -EBUSY;
Sagar Dhariad1468b72013-07-16 12:56:22 -06001454 struct platform_device *pdev = to_platform_device(dev);
1455 struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
1456 if (!pm_runtime_enabled(dev) ||
1457 (!pm_runtime_suspended(dev) &&
1458 cdev->state == MSM_CTRL_IDLE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001459 dev_dbg(dev, "system suspend");
1460 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001461 /*
1462 * If runtime-PM still thinks it's active, then make sure its
1463 * status is in sync with HW status.
1464 * Since this suspend calls QMI api, it results in holding a
1465 * wakelock. That results in failure of first suspend.
1466 * Subsequent suspend should not call low-power transition
1467 * again since the HW is already in suspended state.
1468 */
1469 if (!ret) {
1470 pm_runtime_disable(dev);
1471 pm_runtime_set_suspended(dev);
1472 pm_runtime_enable(dev);
1473 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001474 }
1475 if (ret == -EBUSY) {
1476 /*
1477 * There is a possibility that some audio stream is active
1478 * during suspend. We dont want to return suspend failure in
1479 * that case so that display and relevant components can still
1480 * go to suspend.
1481 * If there is some other error, then it should be passed-on
1482 * to system level suspend
1483 */
1484 ret = 0;
1485 }
1486 return ret;
1487}
1488
1489static int ngd_slim_resume(struct device *dev)
1490{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001491 /*
1492 * Rely on runtime-PM to call resume in case it is enabled.
1493 * Even if it's not enabled, rely on 1st client transaction to do
1494 * clock/power on
1495 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001496 return 0;
1497}
1498#endif /* CONFIG_PM_SLEEP */
1499
1500static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1501 SET_SYSTEM_SLEEP_PM_OPS(
1502 ngd_slim_suspend,
1503 ngd_slim_resume
1504 )
1505 SET_RUNTIME_PM_OPS(
1506 ngd_slim_runtime_suspend,
1507 ngd_slim_runtime_resume,
1508 ngd_slim_runtime_idle
1509 )
1510};
1511
1512static struct of_device_id ngd_slim_dt_match[] = {
1513 {
1514 .compatible = "qcom,slim-ngd",
1515 },
1516 {}
1517};
1518
1519static struct platform_driver ngd_slim_driver = {
1520 .probe = ngd_slim_probe,
1521 .remove = ngd_slim_remove,
1522 .driver = {
1523 .name = NGD_SLIM_NAME,
1524 .owner = THIS_MODULE,
1525 .pm = &ngd_slim_dev_pm_ops,
1526 .of_match_table = ngd_slim_dt_match,
1527 },
1528};
1529
1530static int ngd_slim_init(void)
1531{
1532 return platform_driver_register(&ngd_slim_driver);
1533}
1534late_initcall(ngd_slim_init);
1535
1536static void ngd_slim_exit(void)
1537{
1538 platform_driver_unregister(&ngd_slim_driver);
1539}
1540module_exit(ngd_slim_exit);
1541
1542MODULE_LICENSE("GPL v2");
1543MODULE_DESCRIPTION("MSM Slimbus controller");
1544MODULE_ALIAS("platform:msm-slim-ngd");