blob: d03c3f18160888719bfb2c450cb6d8f8489478c2 [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"
Sagar Dharia71fcea52012-09-12 23:21:57 -060030
31#define NGD_SLIM_NAME "ngd_msm_ctrl"
32#define SLIM_LA_MGR 0xFF
33#define SLIM_ROOT_FREQ 24576000
Sagar Dharia33beca02012-10-22 16:21:46 -060034#define LADDR_RETRY 5
Sagar Dharia71fcea52012-09-12 23:21:57 -060035
36#define NGD_BASE_V1(r) (((r) % 2) ? 0x800 : 0xA00)
37#define NGD_BASE_V2(r) (((r) % 2) ? 0x1000 : 0x2000)
38#define NGD_BASE(r, v) ((v) ? NGD_BASE_V2(r) : NGD_BASE_V1(r))
39/* NGD (Non-ported Generic Device) registers */
40enum ngd_reg {
41 NGD_CFG = 0x0,
42 NGD_STATUS = 0x4,
43 NGD_RX_MSGQ_CFG = 0x8,
44 NGD_INT_EN = 0x10,
45 NGD_INT_STAT = 0x14,
46 NGD_INT_CLR = 0x18,
47 NGD_TX_MSG = 0x30,
48 NGD_RX_MSG = 0x70,
49 NGD_IE_STAT = 0xF0,
50 NGD_VE_STAT = 0x100,
51};
52
53enum ngd_msg_cfg {
54 NGD_CFG_ENABLE = 1,
55 NGD_CFG_RX_MSGQ_EN = 1 << 1,
56 NGD_CFG_TX_MSGQ_EN = 1 << 2,
57};
58
59enum ngd_intr {
60 NGD_INT_RECFG_DONE = 1 << 24,
61 NGD_INT_TX_NACKED_2 = 1 << 25,
62 NGD_INT_MSG_BUF_CONTE = 1 << 26,
63 NGD_INT_MSG_TX_INVAL = 1 << 27,
64 NGD_INT_IE_VE_CHG = 1 << 28,
65 NGD_INT_DEV_ERR = 1 << 29,
66 NGD_INT_RX_MSG_RCVD = 1 << 30,
67 NGD_INT_TX_MSG_SENT = 1 << 31,
68};
69
70enum ngd_offsets {
71 NGD_NACKED_MC = 0x7F00000,
72 NGD_ACKED_MC = 0xFE000,
73 NGD_ERROR = 0x1800,
74 NGD_MSGQ_SUPPORT = 0x400,
75 NGD_RX_MSGQ_TIME_OUT = 0x16,
76 NGD_ENUMERATED = 0x1,
77 NGD_TX_BUSY = 0x0,
78};
79
Sagar Dharia33beca02012-10-22 16:21:46 -060080enum ngd_status {
81 NGD_LADDR = 1 << 1,
82};
83
84static int ngd_slim_runtime_resume(struct device *device);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -060085static int ngd_slim_power_up(struct msm_slim_ctrl *dev);
Sagar Dharia33beca02012-10-22 16:21:46 -060086
Sagar Dharia71fcea52012-09-12 23:21:57 -060087static irqreturn_t ngd_slim_interrupt(int irq, void *d)
88{
89 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)d;
90 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
91 u32 stat = readl_relaxed(ngd + NGD_INT_STAT);
Sagar Dharia2b8a4b52013-05-15 20:01:45 -060092 u32 pstat;
Sagar Dharia71fcea52012-09-12 23:21:57 -060093
Sagar Dhariafc690502014-02-03 12:17:04 -070094 if ((stat & NGD_INT_MSG_BUF_CONTE) ||
95 (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
96 (stat & NGD_INT_TX_NACKED_2)) {
97 writel_relaxed(stat, ngd + NGD_INT_CLR);
98 dev->err = -EIO;
99
100 dev_err(dev->dev, "NGD interrupt error:0x%x, err:%d", stat,
101 dev->err);
102 /* Guarantee that error interrupts are cleared */
103 mb();
104 if (dev->wr_comp)
105 complete(dev->wr_comp);
106
107 } else if (stat & NGD_INT_TX_MSG_SENT) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600108 writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR);
109 /* Make sure interrupt is cleared */
110 mb();
111 if (dev->wr_comp)
112 complete(dev->wr_comp);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600113 }
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 }
Sagar Dharia2b8a4b52013-05-15 20:01:45 -0600151
152 pstat = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_ST_EEn, dev->ver));
153 if (pstat != 0)
154 return msm_slim_port_irq_handler(dev, pstat);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600155 return IRQ_HANDLED;
156}
157
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700158static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
159 void *_cmd)
160{
161 struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
Sagar Dharia33beca02012-10-22 16:21:46 -0600162 struct msm_slim_ctrl *dev =
163 container_of(qmi, struct msm_slim_ctrl, qmi);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700164 pr_info("Slimbus QMI NGD CB received event:%ld", code);
165 switch (code) {
166 case QMI_SERVER_ARRIVE:
Sagar Dharia33beca02012-10-22 16:21:46 -0600167 schedule_work(&qmi->ssr_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700168 break;
169 case QMI_SERVER_EXIT:
Sagar Dharia33beca02012-10-22 16:21:46 -0600170 dev->state = MSM_CTRL_DOWN;
171 /* make sure autosuspend is not called until ADSP comes up*/
172 pm_runtime_get_noresume(dev->dev);
173 /* Reset ctrl_up completion */
174 init_completion(&dev->ctrl_up);
175 schedule_work(&qmi->ssr_down);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700176 break;
177 default:
178 break;
179 }
180 return 0;
181}
182
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600183static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
184 void *_cmd)
185{
186 struct msm_slim_mdm *mdm = container_of(n, struct msm_slim_mdm, nb);
187 struct msm_slim_ctrl *dev = container_of(mdm, struct msm_slim_ctrl,
188 mdm);
189 int ret;
190
191 switch (code) {
192 case SUBSYS_BEFORE_SHUTDOWN:
193 /* make sure runtime-pm doesn't suspend during modem SSR */
194 pm_runtime_get_noresume(dev->dev);
195 break;
196 case SUBSYS_AFTER_POWERUP:
197 ret = msm_slim_qmi_check_framer_request(dev);
198 dev_err(dev->dev,
199 "%s:SLIM %lu external_modem SSR notify cb, ret %d",
200 __func__, code, ret);
201 /*
202 * Next codec transaction will reinit the HW
203 * if it was suspended
204 */
205 if (pm_runtime_suspended(dev->dev) ||
206 dev->state >= MSM_CTRL_ASLEEP) {
207 break;
208 } else {
209 ngd_slim_power_up(dev);
210 msm_slim_put_ctrl(dev);
211 }
212 default:
213 break;
214 }
215 return NOTIFY_DONE;
216}
217
Sagar Dharia71fcea52012-09-12 23:21:57 -0600218static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
219 u8 *tid, struct completion *done)
220{
221 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700222 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600223 if (ctrl->last_tid <= 255) {
224 ctrl->txnt = krealloc(ctrl->txnt,
225 (ctrl->last_tid + 1) *
226 sizeof(struct slim_msg_txn *),
227 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700228 if (!ctrl->txnt) {
229 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600230 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700231 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600232 dev->msg_cnt = ctrl->last_tid;
233 ctrl->last_tid++;
234 } else {
235 int i;
236 for (i = 0; i < 256; i++) {
237 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
238 if (ctrl->txnt[dev->msg_cnt] == NULL)
239 break;
240 }
241 if (i >= 256) {
242 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700243 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600244 return -ENOMEM;
245 }
246 }
247 ctrl->txnt[dev->msg_cnt] = txn;
248 txn->tid = dev->msg_cnt;
249 txn->comp = done;
250 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700251 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600252 return 0;
253}
254static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
255{
256 DECLARE_COMPLETION_ONSTACK(done);
257 DECLARE_COMPLETION_ONSTACK(tx_sent);
258
259 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
260 u32 *pbuf;
261 u8 *puc;
262 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600263 u8 la = txn->la;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600264 u8 txn_mt;
265 u16 txn_mc = txn->mc;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600266 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700267 bool report_sat = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600268
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700269 if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
270 txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
271 report_sat = true;
Sagar Dhariaa1398282013-01-22 13:26:20 -0700272 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700273 report_sat == false) {
Sagar Dhariaa1398282013-01-22 13:26:20 -0700274 /*
275 * Counter-part of system-suspend when runtime-pm is not enabled
276 * This way, resume can be left empty and device will be put in
277 * active mode only if client requests anything on the bus
278 * If the state was DOWN, SSR UP notification will take
279 * care of putting the device in active state.
280 */
281 ngd_slim_runtime_resume(dev->dev);
282 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600283 if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
284 SLIM_MSG_MC_RECONFIGURE_NOW)) &&
Sagar Dhariad1468b72013-07-16 12:56:22 -0600285 dev->state <= MSM_CTRL_IDLE) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600286 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
287 &dev->use_rx_msgqs);
288 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
289 &dev->use_tx_msgqs);
290 return msm_slim_qmi_power_request(dev, false);
Sagar Dharia24419e32013-01-14 17:56:32 -0700291 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700292 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
293 return 0;
294
Sagar Dharia71fcea52012-09-12 23:21:57 -0600295 if (txn->mt == SLIM_MSG_MT_CORE &&
296 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
297 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
298 return 0;
299 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600300 /* If txn is tried when controller is down, wait for ADSP to boot */
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700301 if (!report_sat) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600302 if (dev->state == MSM_CTRL_DOWN) {
303 u8 mc = (u8)txn->mc;
304 int timeout;
305 dev_err(dev->dev, "ADSP slimbus not up yet");
306 /*
307 * Messages related to data channel management can't
308 * wait since they are holding reconfiguration lock.
309 * clk_pause in resume (which can change state back to
Sagar Dharia32379162013-12-12 00:46:37 -0700310 * MSM_CTRL_AWAKE), will need that lock.
311 * Port disconnection, channel removal calls should pass
312 * through since there is no activity on the bus and
313 * those calls are triggered by clients due to
314 * device_down callback in that situation.
315 * Returning 0 on the disconnections and
316 * removals will ensure consistent state of channels,
317 * ports with the HW
Sagar Dharia55bced82014-01-20 16:00:44 -0700318 * Remote requests to remove channel/port will be
319 * returned from the path where they wait on
320 * acknowledgement from ADSP
Sagar Dharia33beca02012-10-22 16:21:46 -0600321 */
Sagar Dharia32379162013-12-12 00:46:37 -0700322 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
323 ((mc == SLIM_USR_MC_CHAN_CTRL ||
324 mc == SLIM_USR_MC_DISCONNECT_PORT ||
325 mc == SLIM_USR_MC_RECONFIG_NOW)))
Sagar Dharia55bced82014-01-20 16:00:44 -0700326 return -EREMOTEIO;
Sagar Dharia32379162013-12-12 00:46:37 -0700327 if ((txn->mt == SLIM_MSG_MT_CORE) &&
328 ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
329 mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
330 mc == SLIM_USR_MC_RECONFIG_NOW)))
331 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600332 if ((txn->mt == SLIM_MSG_MT_CORE) &&
333 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
334 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
335 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
336 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
337 return -EREMOTEIO;
338 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
339 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
Sagar Dharia32379162013-12-12 00:46:37 -0700340 mc < SLIM_USR_MC_DISCONNECT_PORT)))
Sagar Dharia33beca02012-10-22 16:21:46 -0600341 return -EREMOTEIO;
342 timeout = wait_for_completion_timeout(&dev->ctrl_up,
343 HZ);
Sagar Dharia4f240722014-01-15 13:50:58 -0700344 if (!timeout && dev->state == MSM_CTRL_DOWN)
Sagar Dharia33beca02012-10-22 16:21:46 -0600345 return -ETIMEDOUT;
346 }
Sagar Dharia129c7d82013-08-08 19:35:50 -0600347 ret = msm_slim_get_ctrl(dev);
348 /*
349 * Runtime-pm's callbacks are not called until runtime-pm's
350 * error status is cleared
351 * Setting runtime status to suspended clears the error
352 * It also makes HW status cosistent with what SW has it here
353 */
354 if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
355 pm_runtime_set_suspended(dev->dev);
356 msm_slim_put_ctrl(dev);
357 return -EREMOTEIO;
Sagar Dhariad1468b72013-07-16 12:56:22 -0600358 } else if (ret >= 0) {
359 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia129c7d82013-08-08 19:35:50 -0600360 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600361 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600362 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600363
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700364 if (report_sat == false && dev->state != MSM_CTRL_AWAKE) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600365 dev_err(dev->dev, "controller not ready");
366 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600367 msm_slim_put_ctrl(dev);
368 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600369 }
370 if (txn->mt == SLIM_MSG_MT_CORE &&
371 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
372 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
373 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
374 int i = 0;
375 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
376 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
377 txn->mc = SLIM_USR_MC_CONNECT_SRC;
378 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
379 txn->mc = SLIM_USR_MC_CONNECT_SINK;
380 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
381 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600382 if (txn->la == SLIM_LA_MGR) {
383 if (dev->pgdla == SLIM_LA_MGR) {
384 u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
385 QC_MFGID_LSB};
386 ea[2] = (u8)(dev->pdata.eapc & 0xFF);
387 ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
388 mutex_unlock(&dev->tx_lock);
389 ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
390 &dev->pgdla);
391 pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
392 ret);
393 if (ret) {
394 pr_err("Incorrect SLIM-PGD EAPC:0x%x",
395 dev->pdata.eapc);
396 return ret;
397 }
398 mutex_lock(&dev->tx_lock);
399 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600400 txn->la = dev->pgdla;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600401 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600402 wbuf[i++] = txn->la;
403 la = SLIM_LA_MGR;
404 wbuf[i++] = txn->wbuf[0];
405 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
406 wbuf[i++] = txn->wbuf[1];
407 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
408 if (ret) {
409 pr_err("TID for connect/disconnect fail:%d", ret);
410 goto ngd_xfer_err;
411 }
412 txn->len = i;
413 txn->wbuf = wbuf;
414 txn->rl = txn->len + 4;
415 }
416 txn->rl--;
417 pbuf = msm_get_msg_buf(dev, txn->rl);
418 if (!pbuf) {
419 dev_err(dev->dev, "Message buffer unavailable");
420 ret = -ENOMEM;
421 goto ngd_xfer_err;
422 }
423 dev->err = 0;
424
425 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
426 ret = -EPROTONOSUPPORT;
427 goto ngd_xfer_err;
428 }
429 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
430 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
431 la);
432 else
433 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
434 la);
435 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
436 puc = ((u8 *)pbuf) + 3;
437 else
438 puc = ((u8 *)pbuf) + 2;
439 if (txn->rbuf)
440 *(puc++) = txn->tid;
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700441 if (((txn->mt == SLIM_MSG_MT_CORE) &&
Sagar Dharia71fcea52012-09-12 23:21:57 -0600442 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
443 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
444 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700445 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) ||
446 (txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE &&
447 txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600448 *(puc++) = (txn->ec & 0xFF);
449 *(puc++) = (txn->ec >> 8)&0xFF;
450 }
451 if (txn->wbuf)
452 memcpy(puc, txn->wbuf, txn->len);
453 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
454 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
455 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
456 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
457 wbuf[0] == dev->pgdla) {
Sagar Dharia2d74c142013-05-17 02:24:06 -0600458 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600459 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
460 else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600461 /*
462 * Remove channel disconnects master-side ports from
463 * channel. No need to send that again on the bus
Sagar Dharia2d74c142013-05-17 02:24:06 -0600464 * Only disable port
Sagar Dharia71fcea52012-09-12 23:21:57 -0600465 */
Sagar Dharia2d74c142013-05-17 02:24:06 -0600466 writel_relaxed(0, PGD_PORT(PGD_PORT_CFGn,
467 (wbuf[1] + dev->port_b), dev->ver));
Sagar Dharia71fcea52012-09-12 23:21:57 -0600468 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700469 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600470 return 0;
471 }
472 if (dev->err) {
473 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
474 goto ngd_xfer_err;
475 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600476 /* Add port-base to port number if this is manager side port */
477 puc[1] += dev->port_b;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600478 }
479 dev->err = 0;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600480 /*
481 * If it's a read txn, it may be freed if a response is received by
482 * received thread before reaching end of this function.
483 * mc, mt may have changed to convert standard slimbus code/type to
484 * satellite user-defined message. Reinitialize again
485 */
486 txn_mc = txn->mc;
487 txn_mt = txn->mt;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600488 dev->wr_comp = &tx_sent;
489 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
490 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
491 if (!ret) {
492 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600493 if (!timeout) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600494 ret = -ETIMEDOUT;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600495 /*
496 * disconnect/recoonect pipe so that subsequent
497 * transactions don't timeout due to unavailable
498 * descriptors
499 */
500 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
501 &dev->use_tx_msgqs);
502 msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
503 } else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600504 ret = dev->err;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600505 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600506 }
507 dev->wr_comp = NULL;
508 if (ret) {
509 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
510 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
511 dev->ver);
512 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600513 txn_mc, txn_mt, ret, dev->ver);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600514 conf = readl_relaxed(ngd);
515 stat = readl_relaxed(ngd + NGD_STATUS);
516 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
517 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
518 int_en = readl_relaxed(ngd + NGD_INT_EN);
519 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
520
521 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
522 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
523 int_en, int_clr);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600524 } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
525 (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
526 txn_mc == SLIM_USR_MC_CONNECT_SINK ||
527 txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600528 int timeout;
529 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700530 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600531 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600532 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600533 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600534 else
535 ret = txn->ec;
536 if (ret) {
537 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
538 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700539 mutex_lock(&ctrl->m_ctrl);
540 ctrl->txnt[txn->tid] = NULL;
541 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600542 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600543 return ret ? ret : dev->err;
544 }
545ngd_xfer_err:
546 mutex_unlock(&dev->tx_lock);
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700547 if (!report_sat)
Sagar Dharia33beca02012-10-22 16:21:46 -0600548 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600549 return ret ? ret : dev->err;
550}
551
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700552static int ngd_user_msg(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
553 struct slim_ele_access *msg, u8 *buf, u8 len)
554{
555 struct slim_msg_txn txn;
556
557 if (mt != SLIM_MSG_MT_DEST_REFERRED_USER ||
558 mc != SLIM_USR_MC_REPEAT_CHANGE_VALUE) {
559 return -EPROTONOSUPPORT;
560 }
561 if (len > SLIM_MAX_VE_SLC_BYTES ||
562 msg->start_offset > MSM_SLIM_VE_MAX_MAP_ADDR)
563 return -EINVAL;
564 if (len <= 4) {
565 txn.ec = len - 1;
566 } else if (len <= 8) {
567 if (len & 0x1)
568 return -EINVAL;
569 txn.ec = ((len >> 1) + 1);
570 } else {
571 if (len & 0x3)
572 return -EINVAL;
573 txn.ec = ((len >> 2) + 3);
574 }
575 txn.ec |= (0x8 | ((msg->start_offset & 0xF) << 4));
576 txn.ec |= ((msg->start_offset & 0xFF0) << 4);
577
578 txn.la = la;
579 txn.mt = mt;
580 txn.mc = mc;
581 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
582 txn.len = len;
583 txn.rl = len + 6;
584 txn.wbuf = buf;
585 txn.rbuf = NULL;
586 txn.comp = msg->comp;
587 return ngd_xfer_msg(ctrl, &txn);
588}
589
Sagar Dharia71fcea52012-09-12 23:21:57 -0600590static int ngd_xferandwait_ack(struct slim_controller *ctrl,
591 struct slim_msg_txn *txn)
592{
593 int ret = ngd_xfer_msg(ctrl, txn);
594 if (!ret) {
595 int timeout;
596 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600597 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600598 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600599 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600600 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600601 }
Sagar Dharia55bced82014-01-20 16:00:44 -0700602
Sagar Dharia33beca02012-10-22 16:21:46 -0600603 if (ret) {
Sagar Dharia21f88552014-02-07 00:10:37 -0700604 if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL)
605 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
Sagar Dharia71fcea52012-09-12 23:21:57 -0600606 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600607 mutex_lock(&ctrl->m_ctrl);
608 ctrl->txnt[txn->tid] = NULL;
609 mutex_unlock(&ctrl->m_ctrl);
610 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600611
612 return ret;
613}
614
615static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
616{
617 int ret;
618 struct slim_pending_ch *pch;
619 struct slim_msg_txn txn;
620 struct slim_controller *ctrl = sb->ctrl;
621 DECLARE_COMPLETION_ONSTACK(done);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600622 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600623
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600624 *clkgear = ctrl->clkgear;
625 *subfrmc = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600626 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
627 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
628 txn.la = SLIM_LA_MGR;
629 txn.len = 0;
630 txn.ec = 0;
631 txn.wbuf = wbuf;
632 txn.rbuf = NULL;
633
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600634 if (ctrl->sched.msgsl != ctrl->sched.pending_msgsl) {
635 pr_debug("slim reserve BW for messaging: req: %d",
636 ctrl->sched.pending_msgsl);
637 txn.mc = SLIM_USR_MC_REQ_BW;
638 wbuf[txn.len++] = ((sb->laddr & 0x1f) |
639 ((u8)(ctrl->sched.pending_msgsl & 0x7) << 5));
640 wbuf[txn.len++] = (u8)(ctrl->sched.pending_msgsl >> 3);
641 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
642 if (ret)
643 return ret;
644 txn.rl = txn.len + 4;
645 ret = ngd_xferandwait_ack(ctrl, &txn);
646 if (ret)
647 return ret;
648
649 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
650 txn.len = 2;
651 wbuf[1] = sb->laddr;
652 txn.rl = txn.len + 4;
653 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
654 if (ret)
655 return ret;
656 ret = ngd_xferandwait_ack(ctrl, &txn);
657 if (ret)
658 return ret;
659
660 txn.len = 0;
661 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600662 list_for_each_entry(pch, &sb->mark_define, pending) {
663 struct slim_ich *slc;
664 slc = &ctrl->chans[pch->chan];
665 if (!slc) {
666 pr_err("no channel in define?");
667 return -ENXIO;
668 }
669 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600670 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600671 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600672 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600673 wbuf[txn.len] = slc->seglen;
674 if (slc->coeff == SLIM_COEFF_3)
675 wbuf[txn.len] |= 1 << 5;
676 wbuf[txn.len++] |= slc->prop.auxf << 6;
677 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
678 wbuf[txn.len++] = slc->prrate;
679 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
680 if (ret) {
681 pr_err("no tid for channel define?");
682 return -ENXIO;
683 }
684 }
685 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600686 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600687 }
688 if (txn.len) {
689 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
690 txn.rl = txn.len + 4;
691 ret = ngd_xferandwait_ack(ctrl, &txn);
692 if (ret)
693 return ret;
694
695 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
696 txn.len = 2;
697 wbuf[1] = sb->laddr;
698 txn.rl = txn.len + 4;
699 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
700 if (ret)
701 return ret;
702 ret = ngd_xferandwait_ack(ctrl, &txn);
703 if (ret)
704 return ret;
705 }
706 txn.len = 0;
707 list_for_each_entry(pch, &sb->mark_removal, pending) {
708 struct slim_ich *slc;
709 slc = &ctrl->chans[pch->chan];
710 if (!slc) {
711 pr_err("no channel in removal?");
712 return -ENXIO;
713 }
714 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600715 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600716 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600717 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600718 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
719 if (ret) {
720 pr_err("no tid for channel define?");
721 return -ENXIO;
722 }
723 }
724 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600725 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600726 }
727 if (txn.len) {
728 txn.mc = SLIM_USR_MC_CHAN_CTRL;
729 txn.rl = txn.len + 4;
730 ret = ngd_xferandwait_ack(ctrl, &txn);
Sagar Dharia21f88552014-02-07 00:10:37 -0700731 /* HW restarting, channel removal should succeed */
732 if (ret == -EREMOTEIO)
733 return 0;
734 else if (ret)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600735 return ret;
736
737 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
738 txn.len = 2;
739 wbuf[1] = sb->laddr;
740 txn.rl = txn.len + 4;
741 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
742 if (ret)
743 return ret;
744 ret = ngd_xferandwait_ack(ctrl, &txn);
745 if (ret)
746 return ret;
747 txn.len = 0;
748 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700749 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600750}
751
752static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
753 u8 elen, u8 laddr)
754{
755 return 0;
756}
757
758static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
759 u8 elen, u8 *laddr)
760{
761 int ret;
762 u8 wbuf[10];
763 struct slim_msg_txn txn;
764 DECLARE_COMPLETION_ONSTACK(done);
765 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
766 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
767 txn.la = SLIM_LA_MGR;
768 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600769 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
770 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600771 return ret;
772 }
773 memcpy(&wbuf[1], ea, elen);
774 txn.mc = SLIM_USR_MC_ADDR_QUERY;
775 txn.rl = 11;
776 txn.len = 7;
777 txn.wbuf = wbuf;
778 txn.rbuf = NULL;
779 ret = ngd_xferandwait_ack(ctrl, &txn);
780 if (!ret && txn.la == 0xFF)
781 ret = -ENXIO;
782 else if (!ret)
783 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600784 return ret;
785}
786
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600787static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
Sagar Dharia24419e32013-01-14 17:56:32 -0700788{
Sagar Dharia24419e32013-01-14 17:56:32 -0700789 if (dev->state == MSM_CTRL_DOWN) {
790 msm_slim_sps_init(dev, dev->bam_mem,
791 NGD_BASE(dev->ctrl.nr,
792 dev->ver) + NGD_STATUS, true);
793 } else {
794 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600795 goto setup_tx_msg_path;
796 msm_slim_connect_endp(dev, &dev->rx_msgq,
Sagar Dharia24419e32013-01-14 17:56:32 -0700797 &dev->rx_msgq_notify);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600798
799setup_tx_msg_path:
800 if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
801 return;
802 msm_slim_connect_endp(dev, &dev->tx_msgq,
803 NULL);
Sagar Dharia24419e32013-01-14 17:56:32 -0700804 }
805}
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600806
Sagar Dharia71fcea52012-09-12 23:21:57 -0600807static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
808{
809 u8 mc, mt, len;
810 int ret;
811 u32 msgq_en = 1;
812
813 len = buf[0] & 0x1F;
814 mt = (buf[0] >> 5) & 0x7;
815 mc = buf[1];
816 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
817 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
818 struct slim_msg_txn txn;
Sagar Dharia0a693332013-04-15 17:59:03 -0600819 int retries = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600820 u8 wbuf[8];
821 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
822 txn.ec = 0;
823 txn.rbuf = NULL;
824 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
825 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
826 txn.la = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600827 wbuf[0] = SAT_MAGIC_LSB;
828 wbuf[1] = SAT_MAGIC_MSB;
829 wbuf[2] = SAT_MSG_VER;
830 wbuf[3] = SAT_MSG_PROT;
831 txn.wbuf = wbuf;
832 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700833 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700834 if (dev->state >= MSM_CTRL_ASLEEP) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600835 ngd_slim_setup_msg_path(dev);
Sagar Dharia24419e32013-01-14 17:56:32 -0700836 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600837 msgq_en |= NGD_CFG_RX_MSGQ_EN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600838 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
839 msgq_en |= NGD_CFG_TX_MSGQ_EN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600840 writel_relaxed(msgq_en, dev->base +
841 NGD_BASE(dev->ctrl.nr, dev->ver));
842 /* make sure NGD MSG-Q config goes through */
843 mb();
844 }
Sagar Dharia0a693332013-04-15 17:59:03 -0600845capability_retry:
846 txn.rl = 8;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600847 ret = ngd_xfer_msg(&dev->ctrl, &txn);
848 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600849 enum msm_ctrl_state prev_state = dev->state;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600850 pr_info("SLIM SAT: capability exchange successful");
Sagar Dharia71fcea52012-09-12 23:21:57 -0600851 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600852 if (prev_state >= MSM_CTRL_ASLEEP)
853 complete(&dev->reconf);
854 else
855 pr_err("SLIM: unexpected capability, state:%d",
856 prev_state);
857 /* ADSP SSR, send device_up notifications */
858 if (prev_state == MSM_CTRL_DOWN)
Sagar Dhariae44cc822014-02-07 21:32:34 -0700859 complete(&dev->qmi.slave_notify);
Sagar Dharia0a693332013-04-15 17:59:03 -0600860 } else if (ret == -EIO) {
861 pr_info("capability message NACKed, retrying");
862 if (retries < INIT_MX_RETRIES) {
863 msleep(DEF_RETRY_MS);
864 retries++;
865 goto capability_retry;
866 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600867 }
868 }
869 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
870 mc == SLIM_MSG_MC_REPLY_VALUE) {
871 u8 tid = buf[3];
872 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
873 slim_msg_response(&dev->ctrl, &buf[4], tid,
874 len - 4);
875 pm_runtime_mark_last_busy(dev->dev);
876 }
877 if (mc == SLIM_USR_MC_ADDR_REPLY &&
878 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700879 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600880 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700881 mutex_lock(&dev->ctrl.m_ctrl);
882 txn = dev->ctrl.txnt[buf[3]];
883 if (!txn) {
884 pr_err("LADDR response after timeout, tid:0x%x",
885 buf[3]);
886 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600887 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700888 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600889 if (memcmp(&buf[4], failed_ea, 6))
890 txn->la = buf[10];
891 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700892 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600893 complete(txn->comp);
894 }
895 if (mc == SLIM_USR_MC_GENERIC_ACK &&
896 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700897 struct slim_msg_txn *txn;
898 mutex_lock(&dev->ctrl.m_ctrl);
899 txn = dev->ctrl.txnt[buf[3]];
900 if (!txn) {
901 pr_err("ACK received after timeout, tid:0x%x",
902 buf[3]);
903 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600904 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700905 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600906 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
907 (int)buf[3], buf[4]);
908 if (!(buf[4] & MSM_SAT_SUCCSS)) {
909 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
910 buf[4]);
911 txn->ec = -EIO;
912 }
913 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700914 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600915 complete(txn->comp);
916 }
917}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700918
Sagar Dharia33beca02012-10-22 16:21:46 -0600919static int ngd_slim_power_up(struct msm_slim_ctrl *dev)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700920{
Sagar Dharia33beca02012-10-22 16:21:46 -0600921 void __iomem *ngd;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600922 int timeout, ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600923 enum msm_ctrl_state cur_state = dev->state;
924 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700925 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700926 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
927 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
928 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600929
930 if (cur_state == MSM_CTRL_DOWN) {
931 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
932 HZ);
933 if (!timeout)
934 pr_err("slimbus QMI init timed out");
935 }
936
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600937 /* No need to vote if contorller is not in low power mode */
938 if (cur_state == MSM_CTRL_DOWN || cur_state == MSM_CTRL_ASLEEP) {
939 ret = msm_slim_qmi_power_request(dev, true);
940 if (ret) {
941 pr_err("SLIM QMI power request failed:%d", ret);
942 return ret;
943 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600944 }
945 if (!dev->ver) {
946 dev->ver = readl_relaxed(dev->base);
947 /* Version info in 16 MSbits */
948 dev->ver >>= 16;
949 }
950 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
951 laddr = readl_relaxed(ngd + NGD_STATUS);
952 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700953 /*
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600954 * external MDM restart case where ADSP itself was active framer
955 * For example, modem restarted when playback was active
956 */
957 if (cur_state == MSM_CTRL_AWAKE) {
958 pr_err("SLIM MDM restart: ADSP active framer:NO OP");
959 return 0;
960 }
961 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600962 * ADSP power collapse case, where HW wasn't reset.
963 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700964 */
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600965 ngd_slim_setup_msg_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600966 return 0;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600967 } else if (cur_state == MSM_CTRL_ASLEEP) {
968 pr_debug("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
Sagar Dharia33beca02012-10-22 16:21:46 -0600969 dev->state, laddr);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600970 } else if (cur_state == MSM_CTRL_IDLE || cur_state == MSM_CTRL_AWAKE) {
971 /*
972 * external MDM SSR when only voice call is in progress.
973 * ADSP will reset slimbus HW. disconnect BAM pipes so that
974 * they can be connected after capability message is received.
975 * Set device state to ASLEEP to be synchronous with the HW
976 */
977 pr_err("SLIM MDM restart: MDM active framer: reinit HW");
978 dev->state = MSM_CTRL_ASLEEP;
979 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
980 &dev->use_rx_msgqs);
981 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
982 &dev->use_tx_msgqs);
Sagar Dharia33beca02012-10-22 16:21:46 -0600983 }
Sagar Dhariada48bd62013-03-21 18:02:40 -0600984 /* ADSP SSR scenario, need to disconnect pipe before connecting */
985 if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
986 struct msm_slim_endp *endpoint = &dev->rx_msgq;
987 sps_disconnect(endpoint->sps);
988 sps_free_endpoint(endpoint->sps);
989 dev->use_rx_msgqs = MSM_MSGQ_RESET;
990 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600991 if (dev->use_tx_msgqs == MSM_MSGQ_DOWN) {
992 struct msm_slim_endp *endpoint = &dev->tx_msgq;
993 sps_disconnect(endpoint->sps);
994 sps_free_endpoint(endpoint->sps);
995 dev->use_tx_msgqs = MSM_MSGQ_RESET;
996 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600997 /*
998 * ADSP power collapse case (OR SSR), where HW was reset
999 * BAM programming will happen when capability message is received
1000 */
1001 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001002 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001003 /*
1004 * Enable NGD. Configure NGD in register acc. mode until master
1005 * announcement is received
1006 */
Sagar Dharia24419e32013-01-14 17:56:32 -07001007 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001008 /* make sure NGD enabling goes through */
1009 mb();
1010
1011 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
1012 if (!timeout) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001013 pr_err("Failed to receive master capability");
Sagar Dharia33beca02012-10-22 16:21:46 -06001014 return -ETIMEDOUT;
1015 }
1016 if (cur_state == MSM_CTRL_DOWN)
1017 complete(&dev->ctrl_up);
1018 return 0;
1019}
1020
1021static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
1022{
1023 int ret = 0;
1024 if (enable) {
1025 ret = msm_slim_qmi_init(dev, false);
1026 /* controller state should be in sync with framework state */
1027 if (!ret) {
1028 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
1029 SLIM_CLK_UNSPECIFIED);
1030 complete(&dev->qmi.qmi_comp);
1031 /*
1032 * Power-up won't be called if clock pause failed.
1033 * This can happen if ADSP SSR happened when audio
1034 * session is in progress. Framework will think that
1035 * clock pause failed so no need to wakeup controller.
1036 * Call power-up explicitly in that case, since slimbus
1037 * HW needs to be powered-on to be in sync with
1038 * framework state
1039 */
1040 if (ret)
1041 ngd_slim_power_up(dev);
1042 if (!pm_runtime_enabled(dev->dev) ||
1043 !pm_runtime_suspended(dev->dev))
1044 ngd_slim_runtime_resume(dev->dev);
1045 else
1046 pm_runtime_resume(dev->dev);
1047 pm_runtime_mark_last_busy(dev->dev);
1048 pm_runtime_put(dev->dev);
1049 } else
1050 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
1051 ret, dev->state);
1052 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001053 msm_slim_qmi_exit(dev);
1054 }
1055
Sagar Dharia33beca02012-10-22 16:21:46 -06001056 return ret;
1057}
1058
1059static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
1060{
1061 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
1062 return ngd_slim_power_up(dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001063}
1064
Sagar Dharia71fcea52012-09-12 23:21:57 -06001065static int ngd_slim_rx_msgq_thread(void *data)
1066{
1067 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
1068 struct completion *notify = &dev->rx_msgq_notify;
1069 int ret = 0, index = 0;
1070 u32 mc = 0;
1071 u32 mt = 0;
1072 u32 buffer[10];
1073 u8 msg_len = 0;
1074
1075 while (!kthread_should_stop()) {
1076 set_current_state(TASK_INTERRUPTIBLE);
1077 ret = wait_for_completion_interruptible(notify);
1078 if (ret) {
1079 dev_err(dev->dev, "rx thread wait err:%d", ret);
1080 continue;
1081 }
1082 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -07001083 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001084 msm_slim_rx_dequeue(dev, (u8 *)buffer);
1085 ngd_slim_rx(dev, (u8 *)buffer);
1086 continue;
1087 }
1088 ret = msm_slim_rx_msgq_get(dev, buffer, index);
1089 if (ret) {
1090 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
1091 continue;
1092 }
1093
1094 /* Wait for complete message */
1095 if (index++ == 0) {
1096 msg_len = *buffer & 0x1F;
1097 mt = (buffer[0] >> 5) & 0x7;
1098 mc = (buffer[0] >> 8) & 0xff;
1099 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
1100 }
1101 if ((index * 4) >= msg_len) {
1102 index = 0;
1103 ngd_slim_rx(dev, (u8 *)buffer);
1104 } else
1105 continue;
1106 }
1107 return 0;
1108}
1109
Sagar Dhariae44cc822014-02-07 21:32:34 -07001110static int ngd_notify_slaves(void *data)
Sagar Dharia33beca02012-10-22 16:21:46 -06001111{
Sagar Dhariae44cc822014-02-07 21:32:34 -07001112 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
Sagar Dharia33beca02012-10-22 16:21:46 -06001113 struct slim_controller *ctrl = &dev->ctrl;
1114 struct slim_device *sbdev;
Sagar Dharia21f88552014-02-07 00:10:37 -07001115 struct list_head *pos, *next;
Sagar Dhariae44cc822014-02-07 21:32:34 -07001116 int ret, i = 0;
1117 while (!kthread_should_stop()) {
1118 set_current_state(TASK_INTERRUPTIBLE);
1119 ret = wait_for_completion_timeout(&dev->qmi.slave_notify,
1120 HZ);
1121 if (!ret) {
Naveen Kajefe030de2014-03-14 16:30:04 -06001122 dev_dbg(dev->dev, "slave thread wait err:%d", ret);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001123 continue;
Sagar Dharia33beca02012-10-22 16:21:46 -06001124 }
Sagar Dhariae44cc822014-02-07 21:32:34 -07001125 /* Probe devices for first notification */
1126 if (!i) {
1127 dev->err = 0;
1128 if (dev->dev->of_node)
1129 of_register_slim_devices(&dev->ctrl);
1130
1131 /*
1132 * Add devices registered with board-info now that
1133 * controller is up
1134 */
1135 slim_ctrl_add_boarddevs(&dev->ctrl);
1136 } else {
1137 slim_framer_booted(ctrl);
1138 }
1139 i++;
Sagar Dharia33beca02012-10-22 16:21:46 -06001140 mutex_lock(&ctrl->m_ctrl);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001141 list_for_each_safe(pos, next, &ctrl->devs) {
1142 sbdev = list_entry(pos, struct slim_device, dev_list);
1143 mutex_unlock(&ctrl->m_ctrl);
1144 for (i = 0; i < LADDR_RETRY; i++) {
1145 ret = slim_get_logical_addr(sbdev,
1146 sbdev->e_addr,
1147 6, &sbdev->laddr);
1148 if (!ret)
1149 break;
1150 else /* time for ADSP to assign LA */
1151 msleep(20);
1152 }
1153 mutex_lock(&ctrl->m_ctrl);
1154 }
1155 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia33beca02012-10-22 16:21:46 -06001156 }
Sagar Dhariae44cc822014-02-07 21:32:34 -07001157 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001158}
1159
1160static void ngd_adsp_down(struct work_struct *work)
1161{
1162 struct msm_slim_qmi *qmi =
1163 container_of(work, struct msm_slim_qmi, ssr_down);
1164 struct msm_slim_ctrl *dev =
1165 container_of(qmi, struct msm_slim_ctrl, qmi);
1166 struct slim_controller *ctrl = &dev->ctrl;
1167 struct slim_device *sbdev;
Sagar Dharia33beca02012-10-22 16:21:46 -06001168
1169 ngd_slim_enable(dev, false);
1170 /* disconnect BAM pipes */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001171 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
1172 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001173 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
1174 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -06001175 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001176 /* device up should be called again after SSR */
1177 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
Sagar Dhariaf68d71f2013-07-31 17:43:46 -06001178 slim_report_absent(sbdev);
Sagar Dharia33beca02012-10-22 16:21:46 -06001179 pr_info("SLIM ADSP SSR (DOWN) done");
1180}
1181
1182static void ngd_adsp_up(struct work_struct *work)
1183{
1184 struct msm_slim_qmi *qmi =
1185 container_of(work, struct msm_slim_qmi, ssr_up);
1186 struct msm_slim_ctrl *dev =
1187 container_of(qmi, struct msm_slim_ctrl, qmi);
1188 ngd_slim_enable(dev, true);
1189}
1190
Sagar Dharia71fcea52012-09-12 23:21:57 -06001191static int __devinit ngd_slim_probe(struct platform_device *pdev)
1192{
1193 struct msm_slim_ctrl *dev;
1194 int ret;
1195 struct resource *bam_mem;
1196 struct resource *slim_mem;
1197 struct resource *irq, *bam_irq;
Sagar Dharia24419e32013-01-14 17:56:32 -07001198 bool rxreg_access = false;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001199 bool slim_mdm = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001200
Sagar Dharia71fcea52012-09-12 23:21:57 -06001201 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1202 "slimbus_physical");
1203 if (!slim_mem) {
1204 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
1205 return -ENODEV;
1206 }
1207 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1208 "slimbus_bam_physical");
1209 if (!bam_mem) {
1210 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
1211 return -ENODEV;
1212 }
1213 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1214 "slimbus_irq");
1215 if (!irq) {
1216 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
1217 return -ENODEV;
1218 }
1219 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1220 "slimbus_bam_irq");
1221 if (!bam_irq) {
1222 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
1223 return -ENODEV;
1224 }
1225
1226 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
Kiran Gunda318cac42013-10-21 17:00:15 +05301227 if (IS_ERR_OR_NULL(dev)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001228 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
1229 return PTR_ERR(dev);
1230 }
1231 dev->dev = &pdev->dev;
1232 platform_set_drvdata(pdev, dev);
1233 slim_set_ctrldata(&dev->ctrl, dev);
1234 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
1235 if (!dev->base) {
1236 dev_err(&pdev->dev, "IOremap failed\n");
1237 ret = -ENOMEM;
1238 goto err_ioremap_failed;
1239 }
1240 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
1241 if (!dev->bam.base) {
1242 dev_err(&pdev->dev, "BAM IOremap failed\n");
1243 ret = -ENOMEM;
1244 goto err_ioremap_bam_failed;
1245 }
1246 if (pdev->dev.of_node) {
1247
1248 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1249 &dev->ctrl.nr);
1250 if (ret) {
1251 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1252 goto err_ctrl_failed;
1253 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001254 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1255 "qcom,rxreg-access");
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001256 of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
1257 &dev->pdata.apps_pipes);
1258 of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
1259 &dev->pdata.eapc);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001260 slim_mdm = of_property_read_bool(pdev->dev.of_node,
1261 "qcom,slim-mdm");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001262 } else {
1263 dev->ctrl.nr = pdev->id;
1264 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001265 /*
1266 * Keep PGD's logical address as manager's. Query it when first data
1267 * channel request comes in
1268 */
1269 dev->pgdla = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001270 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1271 dev->ctrl.nports = MSM_SLIM_NPORTS;
1272 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1273 dev->framer.superfreq =
1274 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1275 dev->ctrl.a_framer = &dev->framer;
1276 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1277 dev->ctrl.set_laddr = ngd_set_laddr;
1278 dev->ctrl.get_laddr = ngd_get_laddr;
1279 dev->ctrl.allocbw = ngd_allocbw;
1280 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariab046b3c2014-01-27 21:30:48 -07001281 dev->ctrl.xfer_user_msg = ngd_user_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001282 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia100e7212013-05-17 18:20:57 -06001283 dev->ctrl.alloc_port = msm_alloc_port;
1284 dev->ctrl.dealloc_port = msm_dealloc_port;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001285 dev->ctrl.port_xfer = msm_slim_port_xfer;
1286 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001287 dev->bam_mem = bam_mem;
1288
1289 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001290 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001291 mutex_init(&dev->tx_lock);
1292 spin_lock_init(&dev->rx_lock);
1293 dev->ee = 1;
1294 dev->irq = irq->start;
1295 dev->bam.irq = bam_irq->start;
1296
Sagar Dharia24419e32013-01-14 17:56:32 -07001297 if (rxreg_access)
1298 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1299 else
1300 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001301
1302 /* Enable TX message queues by default as recommended by HW */
1303 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1304
Sagar Dharia71fcea52012-09-12 23:21:57 -06001305 init_completion(&dev->rx_msgq_notify);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001306 init_completion(&dev->qmi.slave_notify);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001307
1308 /* Register with framework */
1309 ret = slim_add_numbered_controller(&dev->ctrl);
1310 if (ret) {
1311 dev_err(dev->dev, "error adding controller\n");
1312 goto err_ctrl_failed;
1313 }
1314
1315 dev->ctrl.dev.parent = &pdev->dev;
1316 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001317 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001318
1319 ret = request_irq(dev->irq, ngd_slim_interrupt,
1320 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1321
1322 if (ret) {
1323 dev_err(&pdev->dev, "request IRQ failed\n");
1324 goto err_request_irq_failed;
1325 }
1326
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001327 init_completion(&dev->qmi.qmi_comp);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001328 dev->err = -EPROBE_DEFER;
Sagar Dharia33beca02012-10-22 16:21:46 -06001329 pm_runtime_use_autosuspend(dev->dev);
1330 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1331 pm_runtime_set_suspended(dev->dev);
1332 pm_runtime_enable(dev->dev);
1333
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001334 if (slim_mdm) {
1335 dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
1336 dev->mdm.ssr = subsys_notif_register_notifier("external_modem",
1337 &dev->mdm.nb);
1338 if (IS_ERR_OR_NULL(dev->mdm.ssr))
1339 dev_err(dev->dev,
1340 "subsys_notif_register_notifier failed %p",
1341 dev->mdm.ssr);
1342 }
1343
Sagar Dharia33beca02012-10-22 16:21:46 -06001344 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1345 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001346 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001347 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001348 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001349 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001350 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1351 if (ret) {
1352 pr_err("Slimbus QMI service registration failed:%d", ret);
1353 goto qmi_register_failed;
1354 }
1355
Sagar Dharia33beca02012-10-22 16:21:46 -06001356
Sagar Dharia71fcea52012-09-12 23:21:57 -06001357 /* Fire up the Rx message queue thread */
1358 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
Sagar Dhariae44cc822014-02-07 21:32:34 -07001359 "ngd_rx_thread%d", dev->ctrl.nr);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001360 if (IS_ERR(dev->rx_msgq_thread)) {
1361 ret = PTR_ERR(dev->rx_msgq_thread);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001362 dev_err(dev->dev, "Failed to start Rx thread:%d\n", ret);
1363 goto err_rx_thread_create_failed;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001364 }
1365
Sagar Dhariae44cc822014-02-07 21:32:34 -07001366 /* Start thread to probe, and notify slaves */
1367 dev->qmi.slave_thread = kthread_run(ngd_notify_slaves, dev,
1368 "ngd_notify_sl%d", dev->ctrl.nr);
1369 if (IS_ERR(dev->qmi.slave_thread)) {
1370 ret = PTR_ERR(dev->qmi.slave_thread);
1371 dev_err(dev->dev, "Failed to start notifier thread:%d\n", ret);
1372 goto err_notify_thread_create_failed;
1373 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001374 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1375 return 0;
1376
Sagar Dhariae44cc822014-02-07 21:32:34 -07001377err_notify_thread_create_failed:
1378 kthread_stop(dev->rx_msgq_thread);
1379err_rx_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001380 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001381 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001382 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1383qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001384 free_irq(dev->irq, dev);
1385err_request_irq_failed:
1386 slim_del_controller(&dev->ctrl);
1387err_ctrl_failed:
1388 iounmap(dev->bam.base);
1389err_ioremap_bam_failed:
1390 iounmap(dev->base);
1391err_ioremap_failed:
1392 kfree(dev);
1393 return ret;
1394}
1395
1396static int __devexit ngd_slim_remove(struct platform_device *pdev)
1397{
1398 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001399 ngd_slim_enable(dev, false);
1400 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001401 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001402 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001403 pm_runtime_disable(&pdev->dev);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001404 if (!IS_ERR_OR_NULL(dev->mdm.ssr))
1405 subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001406 free_irq(dev->irq, dev);
1407 slim_del_controller(&dev->ctrl);
1408 kthread_stop(dev->rx_msgq_thread);
1409 iounmap(dev->bam.base);
1410 iounmap(dev->base);
1411 kfree(dev);
1412 return 0;
1413}
1414
1415#ifdef CONFIG_PM_RUNTIME
1416static int ngd_slim_runtime_idle(struct device *device)
1417{
Sagar Dhariad1468b72013-07-16 12:56:22 -06001418 struct platform_device *pdev = to_platform_device(device);
1419 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1420 if (dev->state == MSM_CTRL_AWAKE)
1421 dev->state = MSM_CTRL_IDLE;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001422 dev_dbg(device, "pm_runtime: idle...\n");
1423 pm_request_autosuspend(device);
1424 return -EAGAIN;
1425}
1426#endif
1427
1428/*
1429 * If PM_RUNTIME is not defined, these 2 functions become helper
1430 * functions to be called from system suspend/resume. So they are not
1431 * inside ifdef CONFIG_PM_RUNTIME
1432 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001433static int ngd_slim_runtime_resume(struct device *device)
1434{
1435 struct platform_device *pdev = to_platform_device(device);
1436 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1437 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001438 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001439 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1440 if (ret) {
Sagar Dharia129c7d82013-08-08 19:35:50 -06001441 /* Did SSR cause this clock pause failure */
1442 if (dev->state != MSM_CTRL_DOWN)
1443 dev->state = MSM_CTRL_ASLEEP;
1444 else
1445 dev_err(device, "HW wakeup attempt during SSR");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001446 } else {
1447 dev->state = MSM_CTRL_AWAKE;
1448 }
1449 return ret;
1450}
1451
Sagar Dharia33beca02012-10-22 16:21:46 -06001452#ifdef CONFIG_PM_SLEEP
1453static int ngd_slim_runtime_suspend(struct device *device)
1454{
1455 struct platform_device *pdev = to_platform_device(device);
1456 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1457 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001458 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1459 if (ret) {
1460 if (ret != -EBUSY)
1461 dev_err(device, "clk pause not entered:%d", ret);
1462 dev->state = MSM_CTRL_AWAKE;
1463 } else {
1464 dev->state = MSM_CTRL_ASLEEP;
1465 }
1466 return ret;
1467}
1468
Sagar Dharia71fcea52012-09-12 23:21:57 -06001469static int ngd_slim_suspend(struct device *dev)
1470{
1471 int ret = -EBUSY;
Sagar Dhariad1468b72013-07-16 12:56:22 -06001472 struct platform_device *pdev = to_platform_device(dev);
1473 struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
1474 if (!pm_runtime_enabled(dev) ||
1475 (!pm_runtime_suspended(dev) &&
1476 cdev->state == MSM_CTRL_IDLE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001477 dev_dbg(dev, "system suspend");
1478 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001479 /*
1480 * If runtime-PM still thinks it's active, then make sure its
1481 * status is in sync with HW status.
1482 * Since this suspend calls QMI api, it results in holding a
1483 * wakelock. That results in failure of first suspend.
1484 * Subsequent suspend should not call low-power transition
1485 * again since the HW is already in suspended state.
1486 */
1487 if (!ret) {
1488 pm_runtime_disable(dev);
1489 pm_runtime_set_suspended(dev);
1490 pm_runtime_enable(dev);
1491 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001492 }
1493 if (ret == -EBUSY) {
1494 /*
1495 * There is a possibility that some audio stream is active
1496 * during suspend. We dont want to return suspend failure in
1497 * that case so that display and relevant components can still
1498 * go to suspend.
1499 * If there is some other error, then it should be passed-on
1500 * to system level suspend
1501 */
1502 ret = 0;
1503 }
1504 return ret;
1505}
1506
1507static int ngd_slim_resume(struct device *dev)
1508{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001509 /*
1510 * Rely on runtime-PM to call resume in case it is enabled.
1511 * Even if it's not enabled, rely on 1st client transaction to do
1512 * clock/power on
1513 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001514 return 0;
1515}
1516#endif /* CONFIG_PM_SLEEP */
1517
1518static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1519 SET_SYSTEM_SLEEP_PM_OPS(
1520 ngd_slim_suspend,
1521 ngd_slim_resume
1522 )
1523 SET_RUNTIME_PM_OPS(
1524 ngd_slim_runtime_suspend,
1525 ngd_slim_runtime_resume,
1526 ngd_slim_runtime_idle
1527 )
1528};
1529
1530static struct of_device_id ngd_slim_dt_match[] = {
1531 {
1532 .compatible = "qcom,slim-ngd",
1533 },
1534 {}
1535};
1536
1537static struct platform_driver ngd_slim_driver = {
1538 .probe = ngd_slim_probe,
1539 .remove = ngd_slim_remove,
1540 .driver = {
1541 .name = NGD_SLIM_NAME,
1542 .owner = THIS_MODULE,
1543 .pm = &ngd_slim_dev_pm_ops,
1544 .of_match_table = ngd_slim_dt_match,
1545 },
1546};
1547
1548static int ngd_slim_init(void)
1549{
1550 return platform_driver_register(&ngd_slim_driver);
1551}
1552late_initcall(ngd_slim_init);
1553
1554static void ngd_slim_exit(void)
1555{
1556 platform_driver_unregister(&ngd_slim_driver);
1557}
1558module_exit(ngd_slim_exit);
1559
1560MODULE_LICENSE("GPL v2");
1561MODULE_DESCRIPTION("MSM Slimbus controller");
1562MODULE_ALIAS("platform:msm-slim-ngd");