blob: f591be28abac2a6ea3274437d38866575b418879 [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);
Sagar Dhariab94aa312014-01-14 17:36:32 -070085static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart);
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{
Sagar Dhariab94aa312014-01-14 17:36:32 -0700186 void __iomem *ngd;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600187 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);
Sagar Dhariab94aa312014-01-14 17:36:32 -0700190 struct slim_controller *ctrl = &dev->ctrl;
191 u32 laddr;
192 struct slim_device *sbdev;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600193
194 switch (code) {
195 case SUBSYS_BEFORE_SHUTDOWN:
Sagar Dhariab94aa312014-01-14 17:36:32 -0700196 dev_err(dev->dev,
197 "SLIM %lu external_modem SSR notify cb", code);
198 /* vote for runtime-pm so that ADSP doesn't go down */
199 pm_runtime_get_sync(dev->dev);
200 /*
201 * checking framer here will wake-up ADSP and may avoid framer
202 * handover later
203 */
204 msm_slim_qmi_check_framer_request(dev);
205 dev->mdm.state = MSM_CTRL_DOWN;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600206 break;
207 case SUBSYS_AFTER_POWERUP:
Sagar Dhariab94aa312014-01-14 17:36:32 -0700208 if (dev->mdm.state != MSM_CTRL_DOWN)
209 return NOTIFY_DONE;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600210 dev_err(dev->dev,
Sagar Dhariab94aa312014-01-14 17:36:32 -0700211 "SLIM %lu external_modem SSR notify cb", code);
212 msm_slim_qmi_check_framer_request(dev);
213 /* If NGD enumeration is lost, we will need to power us up */
214 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
215 laddr = readl_relaxed(ngd + NGD_STATUS);
216 if (!(laddr & NGD_LADDR)) {
217 pr_err("SLIM MDM SSR (active framer on MDM) dev-down");
218 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
219 slim_report_absent(sbdev);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600220 }
Sagar Dhariab94aa312014-01-14 17:36:32 -0700221 ngd_slim_power_up(dev, true);
222 msm_slim_put_ctrl(dev);
223 dev->mdm.state = MSM_CTRL_AWAKE;
224 break;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600225 default:
226 break;
227 }
228 return NOTIFY_DONE;
229}
230
Sagar Dharia71fcea52012-09-12 23:21:57 -0600231static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
232 u8 *tid, struct completion *done)
233{
234 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariad2959352012-12-01 15:43:01 -0700235 mutex_lock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600236 if (ctrl->last_tid <= 255) {
237 ctrl->txnt = krealloc(ctrl->txnt,
238 (ctrl->last_tid + 1) *
239 sizeof(struct slim_msg_txn *),
240 GFP_KERNEL);
Sagar Dhariad2959352012-12-01 15:43:01 -0700241 if (!ctrl->txnt) {
242 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600243 return -ENOMEM;
Sagar Dhariad2959352012-12-01 15:43:01 -0700244 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600245 dev->msg_cnt = ctrl->last_tid;
246 ctrl->last_tid++;
247 } else {
248 int i;
249 for (i = 0; i < 256; i++) {
250 dev->msg_cnt = ((dev->msg_cnt + 1) & 0xFF);
251 if (ctrl->txnt[dev->msg_cnt] == NULL)
252 break;
253 }
254 if (i >= 256) {
255 dev_err(&ctrl->dev, "out of TID");
Sagar Dhariad2959352012-12-01 15:43:01 -0700256 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600257 return -ENOMEM;
258 }
259 }
260 ctrl->txnt[dev->msg_cnt] = txn;
261 txn->tid = dev->msg_cnt;
262 txn->comp = done;
263 *tid = dev->msg_cnt;
Sagar Dhariad2959352012-12-01 15:43:01 -0700264 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600265 return 0;
266}
267static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
268{
269 DECLARE_COMPLETION_ONSTACK(done);
270 DECLARE_COMPLETION_ONSTACK(tx_sent);
271
272 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
273 u32 *pbuf;
274 u8 *puc;
275 int ret = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600276 u8 la = txn->la;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600277 u8 txn_mt;
278 u16 txn_mc = txn->mc;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600279 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700280 bool report_sat = false;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600281
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700282 if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
283 txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
284 report_sat = true;
Sagar Dhariaa1398282013-01-22 13:26:20 -0700285 if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700286 report_sat == false) {
Sagar Dhariaa1398282013-01-22 13:26:20 -0700287 /*
288 * Counter-part of system-suspend when runtime-pm is not enabled
289 * This way, resume can be left empty and device will be put in
290 * active mode only if client requests anything on the bus
291 * If the state was DOWN, SSR UP notification will take
292 * care of putting the device in active state.
293 */
294 ngd_slim_runtime_resume(dev->dev);
295 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600296 if ((txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
297 SLIM_MSG_MC_RECONFIGURE_NOW)) &&
Sagar Dhariad1468b72013-07-16 12:56:22 -0600298 dev->state <= MSM_CTRL_IDLE) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600299 msm_slim_disconnect_endp(dev, &dev->rx_msgq,
300 &dev->use_rx_msgqs);
301 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
302 &dev->use_tx_msgqs);
303 return msm_slim_qmi_power_request(dev, false);
Sagar Dharia24419e32013-01-14 17:56:32 -0700304 }
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700305 else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
306 return 0;
307
Sagar Dharia71fcea52012-09-12 23:21:57 -0600308 if (txn->mt == SLIM_MSG_MT_CORE &&
309 (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
310 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
311 return 0;
312 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600313 /* If txn is tried when controller is down, wait for ADSP to boot */
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700314 if (!report_sat) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600315 if (dev->state == MSM_CTRL_DOWN) {
316 u8 mc = (u8)txn->mc;
317 int timeout;
318 dev_err(dev->dev, "ADSP slimbus not up yet");
319 /*
320 * Messages related to data channel management can't
321 * wait since they are holding reconfiguration lock.
322 * clk_pause in resume (which can change state back to
Sagar Dharia32379162013-12-12 00:46:37 -0700323 * MSM_CTRL_AWAKE), will need that lock.
324 * Port disconnection, channel removal calls should pass
325 * through since there is no activity on the bus and
326 * those calls are triggered by clients due to
327 * device_down callback in that situation.
328 * Returning 0 on the disconnections and
329 * removals will ensure consistent state of channels,
330 * ports with the HW
Sagar Dharia55bced82014-01-20 16:00:44 -0700331 * Remote requests to remove channel/port will be
332 * returned from the path where they wait on
333 * acknowledgement from ADSP
Sagar Dharia33beca02012-10-22 16:21:46 -0600334 */
Sagar Dharia32379162013-12-12 00:46:37 -0700335 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
336 ((mc == SLIM_USR_MC_CHAN_CTRL ||
337 mc == SLIM_USR_MC_DISCONNECT_PORT ||
338 mc == SLIM_USR_MC_RECONFIG_NOW)))
Sagar Dharia55bced82014-01-20 16:00:44 -0700339 return -EREMOTEIO;
Sagar Dharia32379162013-12-12 00:46:37 -0700340 if ((txn->mt == SLIM_MSG_MT_CORE) &&
341 ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
342 mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
343 mc == SLIM_USR_MC_RECONFIG_NOW)))
344 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600345 if ((txn->mt == SLIM_MSG_MT_CORE) &&
346 ((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
347 mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
348 (mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
349 mc <= SLIM_MSG_MC_RECONFIGURE_NOW)))
350 return -EREMOTEIO;
351 if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
352 ((mc >= SLIM_USR_MC_DEFINE_CHAN &&
Sagar Dharia32379162013-12-12 00:46:37 -0700353 mc < SLIM_USR_MC_DISCONNECT_PORT)))
Sagar Dharia33beca02012-10-22 16:21:46 -0600354 return -EREMOTEIO;
355 timeout = wait_for_completion_timeout(&dev->ctrl_up,
356 HZ);
Sagar Dharia4f240722014-01-15 13:50:58 -0700357 if (!timeout && dev->state == MSM_CTRL_DOWN)
Sagar Dharia33beca02012-10-22 16:21:46 -0600358 return -ETIMEDOUT;
359 }
Sagar Dharia129c7d82013-08-08 19:35:50 -0600360 ret = msm_slim_get_ctrl(dev);
361 /*
362 * Runtime-pm's callbacks are not called until runtime-pm's
363 * error status is cleared
364 * Setting runtime status to suspended clears the error
365 * It also makes HW status cosistent with what SW has it here
366 */
367 if (ret == -ENETRESET && dev->state == MSM_CTRL_DOWN) {
368 pm_runtime_set_suspended(dev->dev);
369 msm_slim_put_ctrl(dev);
370 return -EREMOTEIO;
Sagar Dhariad1468b72013-07-16 12:56:22 -0600371 } else if (ret >= 0) {
372 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia129c7d82013-08-08 19:35:50 -0600373 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600374 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600375 mutex_lock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600376
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700377 if (report_sat == false && dev->state != MSM_CTRL_AWAKE) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600378 dev_err(dev->dev, "controller not ready");
379 mutex_unlock(&dev->tx_lock);
Sagar Dharia33beca02012-10-22 16:21:46 -0600380 msm_slim_put_ctrl(dev);
381 return -EREMOTEIO;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600382 }
383 if (txn->mt == SLIM_MSG_MT_CORE &&
384 (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
385 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
386 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
387 int i = 0;
388 txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
389 if (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE)
390 txn->mc = SLIM_USR_MC_CONNECT_SRC;
391 else if (txn->mc == SLIM_MSG_MC_CONNECT_SINK)
392 txn->mc = SLIM_USR_MC_CONNECT_SINK;
393 else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
394 txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600395 if (txn->la == SLIM_LA_MGR) {
396 if (dev->pgdla == SLIM_LA_MGR) {
397 u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
398 QC_MFGID_LSB};
399 ea[2] = (u8)(dev->pdata.eapc & 0xFF);
400 ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
401 mutex_unlock(&dev->tx_lock);
402 ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
403 &dev->pgdla);
404 pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
405 ret);
406 if (ret) {
407 pr_err("Incorrect SLIM-PGD EAPC:0x%x",
408 dev->pdata.eapc);
409 return ret;
410 }
411 mutex_lock(&dev->tx_lock);
412 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600413 txn->la = dev->pgdla;
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600414 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600415 wbuf[i++] = txn->la;
416 la = SLIM_LA_MGR;
417 wbuf[i++] = txn->wbuf[0];
418 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
419 wbuf[i++] = txn->wbuf[1];
420 ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done);
421 if (ret) {
422 pr_err("TID for connect/disconnect fail:%d", ret);
423 goto ngd_xfer_err;
424 }
425 txn->len = i;
426 txn->wbuf = wbuf;
427 txn->rl = txn->len + 4;
428 }
429 txn->rl--;
430 pbuf = msm_get_msg_buf(dev, txn->rl);
431 if (!pbuf) {
432 dev_err(dev->dev, "Message buffer unavailable");
433 ret = -ENOMEM;
434 goto ngd_xfer_err;
435 }
436 dev->err = 0;
437
438 if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
439 ret = -EPROTONOSUPPORT;
440 goto ngd_xfer_err;
441 }
442 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
443 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
444 la);
445 else
446 *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
447 la);
448 if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
449 puc = ((u8 *)pbuf) + 3;
450 else
451 puc = ((u8 *)pbuf) + 2;
452 if (txn->rbuf)
453 *(puc++) = txn->tid;
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700454 if (((txn->mt == SLIM_MSG_MT_CORE) &&
Sagar Dharia71fcea52012-09-12 23:21:57 -0600455 ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
456 txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
457 (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700458 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) ||
459 (txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE &&
460 txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600461 *(puc++) = (txn->ec & 0xFF);
462 *(puc++) = (txn->ec >> 8)&0xFF;
463 }
464 if (txn->wbuf)
465 memcpy(puc, txn->wbuf, txn->len);
466 if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
467 (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
468 txn->mc == SLIM_USR_MC_CONNECT_SINK ||
469 txn->mc == SLIM_USR_MC_DISCONNECT_PORT) && txn->wbuf &&
470 wbuf[0] == dev->pgdla) {
Sagar Dharia2d74c142013-05-17 02:24:06 -0600471 if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600472 dev->err = msm_slim_connect_pipe_port(dev, wbuf[1]);
473 else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600474 /*
475 * Remove channel disconnects master-side ports from
476 * channel. No need to send that again on the bus
Sagar Dharia2d74c142013-05-17 02:24:06 -0600477 * Only disable port
Sagar Dharia71fcea52012-09-12 23:21:57 -0600478 */
Sagar Dharia2d74c142013-05-17 02:24:06 -0600479 writel_relaxed(0, PGD_PORT(PGD_PORT_CFGn,
480 (wbuf[1] + dev->port_b), dev->ver));
Sagar Dharia71fcea52012-09-12 23:21:57 -0600481 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700482 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600483 return 0;
484 }
485 if (dev->err) {
486 dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
487 goto ngd_xfer_err;
488 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -0600489 /* Add port-base to port number if this is manager side port */
490 puc[1] += dev->port_b;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600491 }
492 dev->err = 0;
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600493 /*
494 * If it's a read txn, it may be freed if a response is received by
495 * received thread before reaching end of this function.
496 * mc, mt may have changed to convert standard slimbus code/type to
497 * satellite user-defined message. Reinitialize again
498 */
499 txn_mc = txn->mc;
500 txn_mt = txn->mt;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600501 dev->wr_comp = &tx_sent;
502 ret = msm_send_msg_buf(dev, pbuf, txn->rl,
503 NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
504 if (!ret) {
505 int timeout = wait_for_completion_timeout(&tx_sent, HZ);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600506 if (!timeout) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600507 ret = -ETIMEDOUT;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600508 /*
509 * disconnect/recoonect pipe so that subsequent
510 * transactions don't timeout due to unavailable
511 * descriptors
512 */
513 msm_slim_disconnect_endp(dev, &dev->tx_msgq,
514 &dev->use_tx_msgqs);
515 msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
516 } else {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600517 ret = dev->err;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600518 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600519 }
520 dev->wr_comp = NULL;
521 if (ret) {
522 u32 conf, stat, rx_msgq, int_stat, int_en, int_clr;
523 void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
524 dev->ver);
525 dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600526 txn_mc, txn_mt, ret, dev->ver);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600527 conf = readl_relaxed(ngd);
528 stat = readl_relaxed(ngd + NGD_STATUS);
529 rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
530 int_stat = readl_relaxed(ngd + NGD_INT_STAT);
531 int_en = readl_relaxed(ngd + NGD_INT_EN);
532 int_clr = readl_relaxed(ngd + NGD_INT_CLR);
533
534 pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
535 pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
536 int_en, int_clr);
Sagar Dharia8e554ed2013-07-19 15:48:15 -0600537 } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
538 (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
539 txn_mc == SLIM_USR_MC_CONNECT_SINK ||
540 txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600541 int timeout;
542 mutex_unlock(&dev->tx_lock);
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700543 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600544 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600545 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600546 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600547 else
548 ret = txn->ec;
549 if (ret) {
550 pr_err("connect/disconnect:0x%x,tid:%d err:%d", txn->mc,
551 txn->tid, ret);
Sagar Dhariad2959352012-12-01 15:43:01 -0700552 mutex_lock(&ctrl->m_ctrl);
553 ctrl->txnt[txn->tid] = NULL;
554 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600555 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600556 return ret ? ret : dev->err;
557 }
558ngd_xfer_err:
559 mutex_unlock(&dev->tx_lock);
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700560 if (!report_sat)
Sagar Dharia33beca02012-10-22 16:21:46 -0600561 msm_slim_put_ctrl(dev);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600562 return ret ? ret : dev->err;
563}
564
Sagar Dhariab046b3c2014-01-27 21:30:48 -0700565static int ngd_user_msg(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
566 struct slim_ele_access *msg, u8 *buf, u8 len)
567{
568 struct slim_msg_txn txn;
569
570 if (mt != SLIM_MSG_MT_DEST_REFERRED_USER ||
571 mc != SLIM_USR_MC_REPEAT_CHANGE_VALUE) {
572 return -EPROTONOSUPPORT;
573 }
574 if (len > SLIM_MAX_VE_SLC_BYTES ||
575 msg->start_offset > MSM_SLIM_VE_MAX_MAP_ADDR)
576 return -EINVAL;
577 if (len <= 4) {
578 txn.ec = len - 1;
579 } else if (len <= 8) {
580 if (len & 0x1)
581 return -EINVAL;
582 txn.ec = ((len >> 1) + 1);
583 } else {
584 if (len & 0x3)
585 return -EINVAL;
586 txn.ec = ((len >> 2) + 3);
587 }
588 txn.ec |= (0x8 | ((msg->start_offset & 0xF) << 4));
589 txn.ec |= ((msg->start_offset & 0xFF0) << 4);
590
591 txn.la = la;
592 txn.mt = mt;
593 txn.mc = mc;
594 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
595 txn.len = len;
596 txn.rl = len + 6;
597 txn.wbuf = buf;
598 txn.rbuf = NULL;
599 txn.comp = msg->comp;
600 return ngd_xfer_msg(ctrl, &txn);
601}
602
Sagar Dharia71fcea52012-09-12 23:21:57 -0600603static int ngd_xferandwait_ack(struct slim_controller *ctrl,
604 struct slim_msg_txn *txn)
605{
606 int ret = ngd_xfer_msg(ctrl, txn);
607 if (!ret) {
608 int timeout;
609 timeout = wait_for_completion_timeout(txn->comp, HZ);
Sagar Dharia33beca02012-10-22 16:21:46 -0600610 if (!timeout)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600611 ret = -ETIMEDOUT;
Sagar Dharia33beca02012-10-22 16:21:46 -0600612 else
Sagar Dharia71fcea52012-09-12 23:21:57 -0600613 ret = txn->ec;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600614 }
Sagar Dharia55bced82014-01-20 16:00:44 -0700615
Sagar Dharia33beca02012-10-22 16:21:46 -0600616 if (ret) {
Sagar Dharia21f88552014-02-07 00:10:37 -0700617 if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL)
618 pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
Sagar Dharia71fcea52012-09-12 23:21:57 -0600619 txn->tid, ret);
Sagar Dharia33beca02012-10-22 16:21:46 -0600620 mutex_lock(&ctrl->m_ctrl);
621 ctrl->txnt[txn->tid] = NULL;
622 mutex_unlock(&ctrl->m_ctrl);
623 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600624
625 return ret;
626}
627
628static int ngd_allocbw(struct slim_device *sb, int *subfrmc, int *clkgear)
629{
630 int ret;
631 struct slim_pending_ch *pch;
632 struct slim_msg_txn txn;
633 struct slim_controller *ctrl = sb->ctrl;
634 DECLARE_COMPLETION_ONSTACK(done);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600635 u8 wbuf[SLIM_MSGQ_BUF_LEN];
Sagar Dharia71fcea52012-09-12 23:21:57 -0600636
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600637 *clkgear = ctrl->clkgear;
638 *subfrmc = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600639 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
640 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
641 txn.la = SLIM_LA_MGR;
642 txn.len = 0;
643 txn.ec = 0;
644 txn.wbuf = wbuf;
645 txn.rbuf = NULL;
646
Sagar Dharia5ee34ae2013-04-26 18:05:37 -0600647 if (ctrl->sched.msgsl != ctrl->sched.pending_msgsl) {
648 pr_debug("slim reserve BW for messaging: req: %d",
649 ctrl->sched.pending_msgsl);
650 txn.mc = SLIM_USR_MC_REQ_BW;
651 wbuf[txn.len++] = ((sb->laddr & 0x1f) |
652 ((u8)(ctrl->sched.pending_msgsl & 0x7) << 5));
653 wbuf[txn.len++] = (u8)(ctrl->sched.pending_msgsl >> 3);
654 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
655 if (ret)
656 return ret;
657 txn.rl = txn.len + 4;
658 ret = ngd_xferandwait_ack(ctrl, &txn);
659 if (ret)
660 return ret;
661
662 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
663 txn.len = 2;
664 wbuf[1] = sb->laddr;
665 txn.rl = txn.len + 4;
666 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
667 if (ret)
668 return ret;
669 ret = ngd_xferandwait_ack(ctrl, &txn);
670 if (ret)
671 return ret;
672
673 txn.len = 0;
674 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600675 list_for_each_entry(pch, &sb->mark_define, pending) {
676 struct slim_ich *slc;
677 slc = &ctrl->chans[pch->chan];
678 if (!slc) {
679 pr_err("no channel in define?");
680 return -ENXIO;
681 }
682 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600683 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600684 wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600685 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600686 wbuf[txn.len] = slc->seglen;
687 if (slc->coeff == SLIM_COEFF_3)
688 wbuf[txn.len] |= 1 << 5;
689 wbuf[txn.len++] |= slc->prop.auxf << 6;
690 wbuf[txn.len++] = slc->rootexp << 4 | slc->prop.prot;
691 wbuf[txn.len++] = slc->prrate;
692 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
693 if (ret) {
694 pr_err("no tid for channel define?");
695 return -ENXIO;
696 }
697 }
698 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600699 pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600700 }
701 if (txn.len) {
702 txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
703 txn.rl = txn.len + 4;
704 ret = ngd_xferandwait_ack(ctrl, &txn);
705 if (ret)
706 return ret;
707
708 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
709 txn.len = 2;
710 wbuf[1] = sb->laddr;
711 txn.rl = txn.len + 4;
712 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
713 if (ret)
714 return ret;
715 ret = ngd_xferandwait_ack(ctrl, &txn);
716 if (ret)
717 return ret;
718 }
719 txn.len = 0;
720 list_for_each_entry(pch, &sb->mark_removal, pending) {
721 struct slim_ich *slc;
722 slc = &ctrl->chans[pch->chan];
723 if (!slc) {
724 pr_err("no channel in removal?");
725 return -ENXIO;
726 }
727 if (txn.len == 0) {
Sagar Dhariab47c8962012-10-30 13:44:08 -0600728 /* Per protocol, only last 5 bits for client no. */
Sagar Dharia71fcea52012-09-12 23:21:57 -0600729 wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
Sagar Dhariab47c8962012-10-30 13:44:08 -0600730 (sb->laddr & 0x1f);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600731 ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
732 if (ret) {
733 pr_err("no tid for channel define?");
734 return -ENXIO;
735 }
736 }
737 wbuf[txn.len++] = slc->chan;
Sagar Dhariab47c8962012-10-30 13:44:08 -0600738 pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600739 }
740 if (txn.len) {
741 txn.mc = SLIM_USR_MC_CHAN_CTRL;
742 txn.rl = txn.len + 4;
743 ret = ngd_xferandwait_ack(ctrl, &txn);
Sagar Dharia21f88552014-02-07 00:10:37 -0700744 /* HW restarting, channel removal should succeed */
745 if (ret == -EREMOTEIO)
746 return 0;
747 else if (ret)
Sagar Dharia71fcea52012-09-12 23:21:57 -0600748 return ret;
749
750 txn.mc = SLIM_USR_MC_RECONFIG_NOW;
751 txn.len = 2;
752 wbuf[1] = sb->laddr;
753 txn.rl = txn.len + 4;
754 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
755 if (ret)
756 return ret;
757 ret = ngd_xferandwait_ack(ctrl, &txn);
758 if (ret)
759 return ret;
760 txn.len = 0;
761 }
Sagar Dharia24419e32013-01-14 17:56:32 -0700762 return 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600763}
764
765static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
766 u8 elen, u8 laddr)
767{
768 return 0;
769}
770
771static int ngd_get_laddr(struct slim_controller *ctrl, const u8 *ea,
772 u8 elen, u8 *laddr)
773{
774 int ret;
775 u8 wbuf[10];
776 struct slim_msg_txn txn;
777 DECLARE_COMPLETION_ONSTACK(done);
778 txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
779 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
780 txn.la = SLIM_LA_MGR;
781 txn.ec = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600782 ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
783 if (ret) {
Sagar Dharia71fcea52012-09-12 23:21:57 -0600784 return ret;
785 }
786 memcpy(&wbuf[1], ea, elen);
787 txn.mc = SLIM_USR_MC_ADDR_QUERY;
788 txn.rl = 11;
789 txn.len = 7;
790 txn.wbuf = wbuf;
791 txn.rbuf = NULL;
792 ret = ngd_xferandwait_ack(ctrl, &txn);
793 if (!ret && txn.la == 0xFF)
794 ret = -ENXIO;
795 else if (!ret)
796 *laddr = txn.la;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600797 return ret;
798}
799
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600800static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
Sagar Dharia24419e32013-01-14 17:56:32 -0700801{
Sagar Dharia24419e32013-01-14 17:56:32 -0700802 if (dev->state == MSM_CTRL_DOWN) {
803 msm_slim_sps_init(dev, dev->bam_mem,
804 NGD_BASE(dev->ctrl.nr,
805 dev->ver) + NGD_STATUS, true);
806 } else {
807 if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600808 goto setup_tx_msg_path;
809 msm_slim_connect_endp(dev, &dev->rx_msgq,
Sagar Dharia24419e32013-01-14 17:56:32 -0700810 &dev->rx_msgq_notify);
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600811
812setup_tx_msg_path:
813 if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
814 return;
815 msm_slim_connect_endp(dev, &dev->tx_msgq,
816 NULL);
Sagar Dharia24419e32013-01-14 17:56:32 -0700817 }
818}
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600819
Sagar Dharia71fcea52012-09-12 23:21:57 -0600820static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
821{
822 u8 mc, mt, len;
823 int ret;
824 u32 msgq_en = 1;
825
826 len = buf[0] & 0x1F;
827 mt = (buf[0] >> 5) & 0x7;
828 mc = buf[1];
829 if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
830 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
831 struct slim_msg_txn txn;
Sagar Dharia0a693332013-04-15 17:59:03 -0600832 int retries = 0;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600833 u8 wbuf[8];
834 txn.dt = SLIM_MSG_DEST_LOGICALADDR;
835 txn.ec = 0;
836 txn.rbuf = NULL;
837 txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
838 txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
839 txn.la = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600840 wbuf[0] = SAT_MAGIC_LSB;
841 wbuf[1] = SAT_MAGIC_MSB;
842 wbuf[2] = SAT_MSG_VER;
843 wbuf[3] = SAT_MSG_PROT;
844 txn.wbuf = wbuf;
845 txn.len = 4;
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700846 pr_info("SLIM SAT: Received master capability");
Sagar Dharia24419e32013-01-14 17:56:32 -0700847 if (dev->state >= MSM_CTRL_ASLEEP) {
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600848 ngd_slim_setup_msg_path(dev);
Sagar Dharia24419e32013-01-14 17:56:32 -0700849 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
Sagar Dharia33beca02012-10-22 16:21:46 -0600850 msgq_en |= NGD_CFG_RX_MSGQ_EN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600851 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
852 msgq_en |= NGD_CFG_TX_MSGQ_EN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600853 writel_relaxed(msgq_en, dev->base +
854 NGD_BASE(dev->ctrl.nr, dev->ver));
855 /* make sure NGD MSG-Q config goes through */
856 mb();
857 }
Sagar Dharia0a693332013-04-15 17:59:03 -0600858capability_retry:
859 txn.rl = 8;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600860 ret = ngd_xfer_msg(&dev->ctrl, &txn);
861 if (!ret) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600862 enum msm_ctrl_state prev_state = dev->state;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600863 pr_info("SLIM SAT: capability exchange successful");
Sagar Dharia71fcea52012-09-12 23:21:57 -0600864 dev->state = MSM_CTRL_AWAKE;
Sagar Dharia33beca02012-10-22 16:21:46 -0600865 if (prev_state >= MSM_CTRL_ASLEEP)
866 complete(&dev->reconf);
867 else
868 pr_err("SLIM: unexpected capability, state:%d",
869 prev_state);
870 /* ADSP SSR, send device_up notifications */
871 if (prev_state == MSM_CTRL_DOWN)
Sagar Dhariae44cc822014-02-07 21:32:34 -0700872 complete(&dev->qmi.slave_notify);
Sagar Dharia0a693332013-04-15 17:59:03 -0600873 } else if (ret == -EIO) {
874 pr_info("capability message NACKed, retrying");
875 if (retries < INIT_MX_RETRIES) {
876 msleep(DEF_RETRY_MS);
877 retries++;
878 goto capability_retry;
879 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600880 }
881 }
882 if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
883 mc == SLIM_MSG_MC_REPLY_VALUE) {
884 u8 tid = buf[3];
885 dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len);
886 slim_msg_response(&dev->ctrl, &buf[4], tid,
887 len - 4);
888 pm_runtime_mark_last_busy(dev->dev);
889 }
890 if (mc == SLIM_USR_MC_ADDR_REPLY &&
891 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700892 struct slim_msg_txn *txn;
Sagar Dharia71fcea52012-09-12 23:21:57 -0600893 u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
Sagar Dhariad2959352012-12-01 15:43:01 -0700894 mutex_lock(&dev->ctrl.m_ctrl);
895 txn = dev->ctrl.txnt[buf[3]];
896 if (!txn) {
897 pr_err("LADDR response after timeout, tid:0x%x",
898 buf[3]);
899 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600900 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700901 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600902 if (memcmp(&buf[4], failed_ea, 6))
903 txn->la = buf[10];
904 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700905 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600906 complete(txn->comp);
907 }
908 if (mc == SLIM_USR_MC_GENERIC_ACK &&
909 mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
Sagar Dhariad2959352012-12-01 15:43:01 -0700910 struct slim_msg_txn *txn;
911 mutex_lock(&dev->ctrl.m_ctrl);
912 txn = dev->ctrl.txnt[buf[3]];
913 if (!txn) {
914 pr_err("ACK received after timeout, tid:0x%x",
915 buf[3]);
916 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600917 return;
Sagar Dhariad2959352012-12-01 15:43:01 -0700918 }
Sagar Dharia71fcea52012-09-12 23:21:57 -0600919 dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
920 (int)buf[3], buf[4]);
921 if (!(buf[4] & MSM_SAT_SUCCSS)) {
922 dev_err(dev->dev, "TID:%d, NACK code:0x%x", (int)buf[3],
923 buf[4]);
924 txn->ec = -EIO;
925 }
926 dev->ctrl.txnt[buf[3]] = NULL;
Sagar Dhariad2959352012-12-01 15:43:01 -0700927 mutex_unlock(&dev->ctrl.m_ctrl);
Sagar Dharia71fcea52012-09-12 23:21:57 -0600928 complete(txn->comp);
929 }
930}
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700931
Sagar Dhariab94aa312014-01-14 17:36:32 -0700932static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart)
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700933{
Sagar Dharia33beca02012-10-22 16:21:46 -0600934 void __iomem *ngd;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600935 int timeout, ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -0600936 enum msm_ctrl_state cur_state = dev->state;
937 u32 laddr;
Sagar Dharia24419e32013-01-14 17:56:32 -0700938 u32 ngd_int = (NGD_INT_TX_NACKED_2 |
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700939 NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
940 NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
941 NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
Sagar Dharia33beca02012-10-22 16:21:46 -0600942
Sagar Dhariab94aa312014-01-14 17:36:32 -0700943 if (!mdm_restart && cur_state == MSM_CTRL_DOWN) {
Sagar Dharia33beca02012-10-22 16:21:46 -0600944 int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
945 HZ);
946 if (!timeout)
947 pr_err("slimbus QMI init timed out");
948 }
949
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600950 /* No need to vote if contorller is not in low power mode */
Sagar Dhariab94aa312014-01-14 17:36:32 -0700951 if (!mdm_restart &&
952 (cur_state == MSM_CTRL_DOWN || cur_state == MSM_CTRL_ASLEEP)) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600953 ret = msm_slim_qmi_power_request(dev, true);
954 if (ret) {
955 pr_err("SLIM QMI power request failed:%d", ret);
956 return ret;
957 }
Sagar Dharia33beca02012-10-22 16:21:46 -0600958 }
959 if (!dev->ver) {
960 dev->ver = readl_relaxed(dev->base);
961 /* Version info in 16 MSbits */
962 dev->ver >>= 16;
963 }
964 ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
965 laddr = readl_relaxed(ngd + NGD_STATUS);
966 if (laddr & NGD_LADDR) {
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700967 /*
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600968 * external MDM restart case where ADSP itself was active framer
969 * For example, modem restarted when playback was active
970 */
971 if (cur_state == MSM_CTRL_AWAKE) {
Sagar Dhariab94aa312014-01-14 17:36:32 -0700972 pr_err("Subsys restart: ADSP active framer");
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600973 return 0;
974 }
975 /*
Sagar Dharia33beca02012-10-22 16:21:46 -0600976 * ADSP power collapse case, where HW wasn't reset.
977 * Reconnect BAM pipes if disconnected
Sagar Dhariacc1001e2012-11-06 13:56:42 -0700978 */
Sagar Dharia5c8ad192013-05-31 11:39:05 -0600979 ngd_slim_setup_msg_path(dev);
Sagar Dharia33beca02012-10-22 16:21:46 -0600980 return 0;
Sagar Dhariab94aa312014-01-14 17:36:32 -0700981 }
982
983 if (mdm_restart) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600984 /*
Sagar Dhariab94aa312014-01-14 17:36:32 -0700985 * external MDM SSR when MDM is active framer
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600986 * ADSP will reset slimbus HW. disconnect BAM pipes so that
987 * they can be connected after capability message is received.
988 * Set device state to ASLEEP to be synchronous with the HW
989 */
Sagar Dhariab94aa312014-01-14 17:36:32 -0700990 /* make current state as DOWN */
991 cur_state = MSM_CTRL_DOWN;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -0600992 pr_err("SLIM MDM restart: MDM active framer: reinit HW");
Sagar Dhariab94aa312014-01-14 17:36:32 -0700993 /* disconnect BAM pipes */
994 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
995 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
996 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
997 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
998 dev->state = MSM_CTRL_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -0600999 }
Sagar Dhariab94aa312014-01-14 17:36:32 -07001000 /* SSR scenario, need to disconnect pipe before connecting */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001001 if (dev->use_rx_msgqs == MSM_MSGQ_DOWN) {
1002 struct msm_slim_endp *endpoint = &dev->rx_msgq;
1003 sps_disconnect(endpoint->sps);
1004 sps_free_endpoint(endpoint->sps);
1005 dev->use_rx_msgqs = MSM_MSGQ_RESET;
1006 }
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001007 if (dev->use_tx_msgqs == MSM_MSGQ_DOWN) {
1008 struct msm_slim_endp *endpoint = &dev->tx_msgq;
1009 sps_disconnect(endpoint->sps);
1010 sps_free_endpoint(endpoint->sps);
1011 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1012 }
Sagar Dharia33beca02012-10-22 16:21:46 -06001013 /*
1014 * ADSP power collapse case (OR SSR), where HW was reset
1015 * BAM programming will happen when capability message is received
1016 */
1017 writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001018 NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001019 /*
1020 * Enable NGD. Configure NGD in register acc. mode until master
1021 * announcement is received
1022 */
Sagar Dharia24419e32013-01-14 17:56:32 -07001023 writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
Sagar Dharia33beca02012-10-22 16:21:46 -06001024 /* make sure NGD enabling goes through */
1025 mb();
1026
1027 timeout = wait_for_completion_timeout(&dev->reconf, HZ);
1028 if (!timeout) {
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001029 pr_err("Failed to receive master capability");
Sagar Dharia33beca02012-10-22 16:21:46 -06001030 return -ETIMEDOUT;
1031 }
1032 if (cur_state == MSM_CTRL_DOWN)
1033 complete(&dev->ctrl_up);
1034 return 0;
1035}
1036
1037static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
1038{
1039 int ret = 0;
1040 if (enable) {
1041 ret = msm_slim_qmi_init(dev, false);
1042 /* controller state should be in sync with framework state */
1043 if (!ret) {
1044 ret = slim_ctrl_clk_pause(&dev->ctrl, false,
1045 SLIM_CLK_UNSPECIFIED);
1046 complete(&dev->qmi.qmi_comp);
1047 /*
1048 * Power-up won't be called if clock pause failed.
1049 * This can happen if ADSP SSR happened when audio
1050 * session is in progress. Framework will think that
1051 * clock pause failed so no need to wakeup controller.
1052 * Call power-up explicitly in that case, since slimbus
1053 * HW needs to be powered-on to be in sync with
1054 * framework state
1055 */
1056 if (ret)
Sagar Dhariab94aa312014-01-14 17:36:32 -07001057 ngd_slim_power_up(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001058 if (!pm_runtime_enabled(dev->dev) ||
1059 !pm_runtime_suspended(dev->dev))
1060 ngd_slim_runtime_resume(dev->dev);
1061 else
1062 pm_runtime_resume(dev->dev);
1063 pm_runtime_mark_last_busy(dev->dev);
1064 pm_runtime_put(dev->dev);
1065 } else
1066 dev_err(dev->dev, "qmi init fail, ret:%d, state:%d",
1067 ret, dev->state);
1068 } else {
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001069 msm_slim_qmi_exit(dev);
1070 }
1071
Sagar Dharia33beca02012-10-22 16:21:46 -06001072 return ret;
1073}
1074
1075static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
1076{
1077 struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
Sagar Dhariab94aa312014-01-14 17:36:32 -07001078 return ngd_slim_power_up(dev, false);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001079}
1080
Sagar Dharia71fcea52012-09-12 23:21:57 -06001081static int ngd_slim_rx_msgq_thread(void *data)
1082{
1083 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
1084 struct completion *notify = &dev->rx_msgq_notify;
1085 int ret = 0, index = 0;
1086 u32 mc = 0;
1087 u32 mt = 0;
1088 u32 buffer[10];
1089 u8 msg_len = 0;
1090
1091 while (!kthread_should_stop()) {
1092 set_current_state(TASK_INTERRUPTIBLE);
Kiran Gundabbb3e312014-03-17 16:11:40 +05301093 wait_for_completion(notify);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001094 /* 1 irq notification per message */
Sagar Dharia24419e32013-01-14 17:56:32 -07001095 if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001096 msm_slim_rx_dequeue(dev, (u8 *)buffer);
1097 ngd_slim_rx(dev, (u8 *)buffer);
1098 continue;
1099 }
1100 ret = msm_slim_rx_msgq_get(dev, buffer, index);
1101 if (ret) {
1102 dev_err(dev->dev, "rx_msgq_get() failed 0x%x\n", ret);
1103 continue;
1104 }
1105
1106 /* Wait for complete message */
1107 if (index++ == 0) {
1108 msg_len = *buffer & 0x1F;
1109 mt = (buffer[0] >> 5) & 0x7;
1110 mc = (buffer[0] >> 8) & 0xff;
1111 dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
1112 }
1113 if ((index * 4) >= msg_len) {
1114 index = 0;
1115 ngd_slim_rx(dev, (u8 *)buffer);
1116 } else
1117 continue;
1118 }
1119 return 0;
1120}
1121
Sagar Dhariae44cc822014-02-07 21:32:34 -07001122static int ngd_notify_slaves(void *data)
Sagar Dharia33beca02012-10-22 16:21:46 -06001123{
Sagar Dhariae44cc822014-02-07 21:32:34 -07001124 struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
Sagar Dharia33beca02012-10-22 16:21:46 -06001125 struct slim_controller *ctrl = &dev->ctrl;
1126 struct slim_device *sbdev;
Sagar Dharia21f88552014-02-07 00:10:37 -07001127 struct list_head *pos, *next;
Sagar Dhariae44cc822014-02-07 21:32:34 -07001128 int ret, i = 0;
1129 while (!kthread_should_stop()) {
1130 set_current_state(TASK_INTERRUPTIBLE);
Kiran Gundabbb3e312014-03-17 16:11:40 +05301131 wait_for_completion(&dev->qmi.slave_notify);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001132 /* Probe devices for first notification */
1133 if (!i) {
Kiran Gunda2b457b02014-04-04 14:58:56 +05301134 i++;
Sagar Dhariae44cc822014-02-07 21:32:34 -07001135 dev->err = 0;
1136 if (dev->dev->of_node)
1137 of_register_slim_devices(&dev->ctrl);
1138
1139 /*
1140 * Add devices registered with board-info now that
1141 * controller is up
1142 */
1143 slim_ctrl_add_boarddevs(&dev->ctrl);
1144 } else {
1145 slim_framer_booted(ctrl);
1146 }
Sagar Dharia33beca02012-10-22 16:21:46 -06001147 mutex_lock(&ctrl->m_ctrl);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001148 list_for_each_safe(pos, next, &ctrl->devs) {
Kiran Gunda2b457b02014-04-04 14:58:56 +05301149 int j;
Sagar Dhariae44cc822014-02-07 21:32:34 -07001150 sbdev = list_entry(pos, struct slim_device, dev_list);
1151 mutex_unlock(&ctrl->m_ctrl);
Kiran Gunda2b457b02014-04-04 14:58:56 +05301152 for (j = 0; j < LADDR_RETRY; j++) {
Sagar Dhariae44cc822014-02-07 21:32:34 -07001153 ret = slim_get_logical_addr(sbdev,
1154 sbdev->e_addr,
1155 6, &sbdev->laddr);
1156 if (!ret)
1157 break;
1158 else /* time for ADSP to assign LA */
1159 msleep(20);
1160 }
1161 mutex_lock(&ctrl->m_ctrl);
1162 }
1163 mutex_unlock(&ctrl->m_ctrl);
Sagar Dharia33beca02012-10-22 16:21:46 -06001164 }
Sagar Dhariae44cc822014-02-07 21:32:34 -07001165 return 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001166}
1167
1168static void ngd_adsp_down(struct work_struct *work)
1169{
1170 struct msm_slim_qmi *qmi =
1171 container_of(work, struct msm_slim_qmi, ssr_down);
1172 struct msm_slim_ctrl *dev =
1173 container_of(qmi, struct msm_slim_ctrl, qmi);
1174 struct slim_controller *ctrl = &dev->ctrl;
1175 struct slim_device *sbdev;
Sagar Dharia33beca02012-10-22 16:21:46 -06001176
1177 ngd_slim_enable(dev, false);
1178 /* disconnect BAM pipes */
Sagar Dhariada48bd62013-03-21 18:02:40 -06001179 if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
1180 dev->use_rx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001181 if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
1182 dev->use_tx_msgqs = MSM_MSGQ_DOWN;
Sagar Dharia33beca02012-10-22 16:21:46 -06001183 msm_slim_sps_exit(dev, false);
Sagar Dharia33beca02012-10-22 16:21:46 -06001184 /* device up should be called again after SSR */
1185 list_for_each_entry(sbdev, &ctrl->devs, dev_list)
Sagar Dhariaf68d71f2013-07-31 17:43:46 -06001186 slim_report_absent(sbdev);
Sagar Dharia33beca02012-10-22 16:21:46 -06001187 pr_info("SLIM ADSP SSR (DOWN) done");
1188}
1189
1190static void ngd_adsp_up(struct work_struct *work)
1191{
1192 struct msm_slim_qmi *qmi =
1193 container_of(work, struct msm_slim_qmi, ssr_up);
1194 struct msm_slim_ctrl *dev =
1195 container_of(qmi, struct msm_slim_ctrl, qmi);
1196 ngd_slim_enable(dev, true);
1197}
1198
Sagar Dharia71fcea52012-09-12 23:21:57 -06001199static int __devinit ngd_slim_probe(struct platform_device *pdev)
1200{
1201 struct msm_slim_ctrl *dev;
1202 int ret;
1203 struct resource *bam_mem;
1204 struct resource *slim_mem;
1205 struct resource *irq, *bam_irq;
Sagar Dharia24419e32013-01-14 17:56:32 -07001206 bool rxreg_access = false;
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001207 bool slim_mdm = false;
Naveen Kaje284da552014-03-26 09:54:29 -06001208 const char *ext_modem_id = NULL;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001209
Sagar Dharia71fcea52012-09-12 23:21:57 -06001210 slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1211 "slimbus_physical");
1212 if (!slim_mem) {
1213 dev_err(&pdev->dev, "no slimbus physical memory resource\n");
1214 return -ENODEV;
1215 }
1216 bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1217 "slimbus_bam_physical");
1218 if (!bam_mem) {
1219 dev_err(&pdev->dev, "no slimbus BAM memory resource\n");
1220 return -ENODEV;
1221 }
1222 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1223 "slimbus_irq");
1224 if (!irq) {
1225 dev_err(&pdev->dev, "no slimbus IRQ resource\n");
1226 return -ENODEV;
1227 }
1228 bam_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1229 "slimbus_bam_irq");
1230 if (!bam_irq) {
1231 dev_err(&pdev->dev, "no slimbus BAM IRQ resource\n");
1232 return -ENODEV;
1233 }
1234
1235 dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
Kiran Gunda318cac42013-10-21 17:00:15 +05301236 if (IS_ERR_OR_NULL(dev)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001237 dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
1238 return PTR_ERR(dev);
1239 }
1240 dev->dev = &pdev->dev;
1241 platform_set_drvdata(pdev, dev);
1242 slim_set_ctrldata(&dev->ctrl, dev);
1243 dev->base = ioremap(slim_mem->start, resource_size(slim_mem));
1244 if (!dev->base) {
1245 dev_err(&pdev->dev, "IOremap failed\n");
1246 ret = -ENOMEM;
1247 goto err_ioremap_failed;
1248 }
1249 dev->bam.base = ioremap(bam_mem->start, resource_size(bam_mem));
1250 if (!dev->bam.base) {
1251 dev_err(&pdev->dev, "BAM IOremap failed\n");
1252 ret = -ENOMEM;
1253 goto err_ioremap_bam_failed;
1254 }
1255 if (pdev->dev.of_node) {
1256
1257 ret = of_property_read_u32(pdev->dev.of_node, "cell-index",
1258 &dev->ctrl.nr);
1259 if (ret) {
1260 dev_err(&pdev->dev, "Cell index not specified:%d", ret);
1261 goto err_ctrl_failed;
1262 }
Sagar Dharia24419e32013-01-14 17:56:32 -07001263 rxreg_access = of_property_read_bool(pdev->dev.of_node,
1264 "qcom,rxreg-access");
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001265 of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
1266 &dev->pdata.apps_pipes);
1267 of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
1268 &dev->pdata.eapc);
Naveen Kaje284da552014-03-26 09:54:29 -06001269 ret = of_property_read_string(pdev->dev.of_node,
1270 "qcom,slim-mdm", &ext_modem_id);
1271 if (!ret)
1272 slim_mdm = true;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001273 } else {
1274 dev->ctrl.nr = pdev->id;
1275 }
Sagar Dhariaa3c6a382013-06-21 12:18:20 -06001276 /*
1277 * Keep PGD's logical address as manager's. Query it when first data
1278 * channel request comes in
1279 */
1280 dev->pgdla = SLIM_LA_MGR;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001281 dev->ctrl.nchans = MSM_SLIM_NCHANS;
1282 dev->ctrl.nports = MSM_SLIM_NPORTS;
1283 dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1284 dev->framer.superfreq =
1285 dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1286 dev->ctrl.a_framer = &dev->framer;
1287 dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1288 dev->ctrl.set_laddr = ngd_set_laddr;
1289 dev->ctrl.get_laddr = ngd_get_laddr;
1290 dev->ctrl.allocbw = ngd_allocbw;
1291 dev->ctrl.xfer_msg = ngd_xfer_msg;
Sagar Dhariab046b3c2014-01-27 21:30:48 -07001292 dev->ctrl.xfer_user_msg = ngd_user_msg;
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001293 dev->ctrl.wakeup = ngd_clk_pause_wakeup;
Sagar Dharia100e7212013-05-17 18:20:57 -06001294 dev->ctrl.alloc_port = msm_alloc_port;
1295 dev->ctrl.dealloc_port = msm_dealloc_port;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001296 dev->ctrl.port_xfer = msm_slim_port_xfer;
1297 dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001298 dev->bam_mem = bam_mem;
1299
1300 init_completion(&dev->reconf);
Sagar Dharia33beca02012-10-22 16:21:46 -06001301 init_completion(&dev->ctrl_up);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001302 mutex_init(&dev->tx_lock);
1303 spin_lock_init(&dev->rx_lock);
1304 dev->ee = 1;
1305 dev->irq = irq->start;
1306 dev->bam.irq = bam_irq->start;
1307
Sagar Dharia24419e32013-01-14 17:56:32 -07001308 if (rxreg_access)
1309 dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
1310 else
1311 dev->use_rx_msgqs = MSM_MSGQ_RESET;
Sagar Dharia5c8ad192013-05-31 11:39:05 -06001312
1313 /* Enable TX message queues by default as recommended by HW */
1314 dev->use_tx_msgqs = MSM_MSGQ_RESET;
1315
Sagar Dharia71fcea52012-09-12 23:21:57 -06001316 init_completion(&dev->rx_msgq_notify);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001317 init_completion(&dev->qmi.slave_notify);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001318
1319 /* Register with framework */
1320 ret = slim_add_numbered_controller(&dev->ctrl);
1321 if (ret) {
1322 dev_err(dev->dev, "error adding controller\n");
1323 goto err_ctrl_failed;
1324 }
1325
1326 dev->ctrl.dev.parent = &pdev->dev;
1327 dev->ctrl.dev.of_node = pdev->dev.of_node;
Sagar Dharia33beca02012-10-22 16:21:46 -06001328 dev->state = MSM_CTRL_DOWN;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001329
1330 ret = request_irq(dev->irq, ngd_slim_interrupt,
1331 IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev);
1332
1333 if (ret) {
1334 dev_err(&pdev->dev, "request IRQ failed\n");
1335 goto err_request_irq_failed;
1336 }
1337
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001338 init_completion(&dev->qmi.qmi_comp);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001339 dev->err = -EPROBE_DEFER;
Sagar Dharia33beca02012-10-22 16:21:46 -06001340 pm_runtime_use_autosuspend(dev->dev);
1341 pm_runtime_set_autosuspend_delay(dev->dev, MSM_SLIM_AUTOSUSPEND);
1342 pm_runtime_set_suspended(dev->dev);
1343 pm_runtime_enable(dev->dev);
1344
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001345 if (slim_mdm) {
1346 dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
Naveen Kaje284da552014-03-26 09:54:29 -06001347 dev->mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001348 &dev->mdm.nb);
1349 if (IS_ERR_OR_NULL(dev->mdm.ssr))
1350 dev_err(dev->dev,
1351 "subsys_notif_register_notifier failed %p",
1352 dev->mdm.ssr);
1353 }
1354
Sagar Dharia33beca02012-10-22 16:21:46 -06001355 INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
1356 INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001357 dev->qmi.nb.notifier_call = ngd_qmi_available;
Sagar Dharia33beca02012-10-22 16:21:46 -06001358 pm_runtime_get_noresume(dev->dev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001359 ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001360 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001361 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1362 if (ret) {
1363 pr_err("Slimbus QMI service registration failed:%d", ret);
1364 goto qmi_register_failed;
1365 }
1366
Sagar Dharia33beca02012-10-22 16:21:46 -06001367
Sagar Dharia71fcea52012-09-12 23:21:57 -06001368 /* Fire up the Rx message queue thread */
1369 dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
Sagar Dhariae44cc822014-02-07 21:32:34 -07001370 "ngd_rx_thread%d", dev->ctrl.nr);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001371 if (IS_ERR(dev->rx_msgq_thread)) {
1372 ret = PTR_ERR(dev->rx_msgq_thread);
Sagar Dhariae44cc822014-02-07 21:32:34 -07001373 dev_err(dev->dev, "Failed to start Rx thread:%d\n", ret);
1374 goto err_rx_thread_create_failed;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001375 }
1376
Sagar Dhariae44cc822014-02-07 21:32:34 -07001377 /* Start thread to probe, and notify slaves */
1378 dev->qmi.slave_thread = kthread_run(ngd_notify_slaves, dev,
1379 "ngd_notify_sl%d", dev->ctrl.nr);
1380 if (IS_ERR(dev->qmi.slave_thread)) {
1381 ret = PTR_ERR(dev->qmi.slave_thread);
1382 dev_err(dev->dev, "Failed to start notifier thread:%d\n", ret);
1383 goto err_notify_thread_create_failed;
1384 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001385 dev_dbg(dev->dev, "NGD SB controller is up!\n");
1386 return 0;
1387
Sagar Dhariae44cc822014-02-07 21:32:34 -07001388err_notify_thread_create_failed:
1389 kthread_stop(dev->rx_msgq_thread);
1390err_rx_thread_create_failed:
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001391 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001392 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001393 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
1394qmi_register_failed:
Sagar Dharia71fcea52012-09-12 23:21:57 -06001395 free_irq(dev->irq, dev);
1396err_request_irq_failed:
1397 slim_del_controller(&dev->ctrl);
1398err_ctrl_failed:
1399 iounmap(dev->bam.base);
1400err_ioremap_bam_failed:
1401 iounmap(dev->base);
1402err_ioremap_failed:
1403 kfree(dev);
1404 return ret;
1405}
1406
1407static int __devexit ngd_slim_remove(struct platform_device *pdev)
1408{
1409 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001410 ngd_slim_enable(dev, false);
1411 qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
Karthikeyan Ramasubramaniane6e24952013-09-20 15:45:18 -06001412 SLIMBUS_QMI_SVC_V1,
Sagar Dhariacc1001e2012-11-06 13:56:42 -07001413 SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001414 pm_runtime_disable(&pdev->dev);
Naveen Kaje0ba80fa2013-10-29 18:24:15 -06001415 if (!IS_ERR_OR_NULL(dev->mdm.ssr))
1416 subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
Sagar Dharia71fcea52012-09-12 23:21:57 -06001417 free_irq(dev->irq, dev);
1418 slim_del_controller(&dev->ctrl);
1419 kthread_stop(dev->rx_msgq_thread);
1420 iounmap(dev->bam.base);
1421 iounmap(dev->base);
1422 kfree(dev);
1423 return 0;
1424}
1425
1426#ifdef CONFIG_PM_RUNTIME
1427static int ngd_slim_runtime_idle(struct device *device)
1428{
Sagar Dhariad1468b72013-07-16 12:56:22 -06001429 struct platform_device *pdev = to_platform_device(device);
1430 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1431 if (dev->state == MSM_CTRL_AWAKE)
1432 dev->state = MSM_CTRL_IDLE;
Sagar Dharia71fcea52012-09-12 23:21:57 -06001433 dev_dbg(device, "pm_runtime: idle...\n");
1434 pm_request_autosuspend(device);
1435 return -EAGAIN;
1436}
1437#endif
1438
1439/*
1440 * If PM_RUNTIME is not defined, these 2 functions become helper
1441 * functions to be called from system suspend/resume. So they are not
1442 * inside ifdef CONFIG_PM_RUNTIME
1443 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001444static int ngd_slim_runtime_resume(struct device *device)
1445{
1446 struct platform_device *pdev = to_platform_device(device);
1447 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1448 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001449 if (dev->state >= MSM_CTRL_ASLEEP)
Sagar Dharia71fcea52012-09-12 23:21:57 -06001450 ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
1451 if (ret) {
Sagar Dharia129c7d82013-08-08 19:35:50 -06001452 /* Did SSR cause this clock pause failure */
1453 if (dev->state != MSM_CTRL_DOWN)
1454 dev->state = MSM_CTRL_ASLEEP;
1455 else
1456 dev_err(device, "HW wakeup attempt during SSR");
Sagar Dharia71fcea52012-09-12 23:21:57 -06001457 } else {
1458 dev->state = MSM_CTRL_AWAKE;
1459 }
1460 return ret;
1461}
1462
Sagar Dharia33beca02012-10-22 16:21:46 -06001463#ifdef CONFIG_PM_SLEEP
1464static int ngd_slim_runtime_suspend(struct device *device)
1465{
1466 struct platform_device *pdev = to_platform_device(device);
1467 struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
1468 int ret = 0;
Sagar Dharia33beca02012-10-22 16:21:46 -06001469 ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
1470 if (ret) {
1471 if (ret != -EBUSY)
1472 dev_err(device, "clk pause not entered:%d", ret);
1473 dev->state = MSM_CTRL_AWAKE;
1474 } else {
1475 dev->state = MSM_CTRL_ASLEEP;
1476 }
1477 return ret;
1478}
1479
Sagar Dharia71fcea52012-09-12 23:21:57 -06001480static int ngd_slim_suspend(struct device *dev)
1481{
1482 int ret = -EBUSY;
Sagar Dhariad1468b72013-07-16 12:56:22 -06001483 struct platform_device *pdev = to_platform_device(dev);
1484 struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
1485 if (!pm_runtime_enabled(dev) ||
1486 (!pm_runtime_suspended(dev) &&
1487 cdev->state == MSM_CTRL_IDLE)) {
Sagar Dharia71fcea52012-09-12 23:21:57 -06001488 dev_dbg(dev, "system suspend");
1489 ret = ngd_slim_runtime_suspend(dev);
Sagar Dhariaa1398282013-01-22 13:26:20 -07001490 /*
1491 * If runtime-PM still thinks it's active, then make sure its
1492 * status is in sync with HW status.
1493 * Since this suspend calls QMI api, it results in holding a
1494 * wakelock. That results in failure of first suspend.
1495 * Subsequent suspend should not call low-power transition
1496 * again since the HW is already in suspended state.
1497 */
1498 if (!ret) {
1499 pm_runtime_disable(dev);
1500 pm_runtime_set_suspended(dev);
1501 pm_runtime_enable(dev);
1502 }
Sagar Dharia71fcea52012-09-12 23:21:57 -06001503 }
1504 if (ret == -EBUSY) {
1505 /*
1506 * There is a possibility that some audio stream is active
1507 * during suspend. We dont want to return suspend failure in
1508 * that case so that display and relevant components can still
1509 * go to suspend.
1510 * If there is some other error, then it should be passed-on
1511 * to system level suspend
1512 */
1513 ret = 0;
1514 }
1515 return ret;
1516}
1517
1518static int ngd_slim_resume(struct device *dev)
1519{
Sagar Dhariaa1398282013-01-22 13:26:20 -07001520 /*
1521 * Rely on runtime-PM to call resume in case it is enabled.
1522 * Even if it's not enabled, rely on 1st client transaction to do
1523 * clock/power on
1524 */
Sagar Dharia71fcea52012-09-12 23:21:57 -06001525 return 0;
1526}
1527#endif /* CONFIG_PM_SLEEP */
1528
1529static const struct dev_pm_ops ngd_slim_dev_pm_ops = {
1530 SET_SYSTEM_SLEEP_PM_OPS(
1531 ngd_slim_suspend,
1532 ngd_slim_resume
1533 )
1534 SET_RUNTIME_PM_OPS(
1535 ngd_slim_runtime_suspend,
1536 ngd_slim_runtime_resume,
1537 ngd_slim_runtime_idle
1538 )
1539};
1540
1541static struct of_device_id ngd_slim_dt_match[] = {
1542 {
1543 .compatible = "qcom,slim-ngd",
1544 },
1545 {}
1546};
1547
1548static struct platform_driver ngd_slim_driver = {
1549 .probe = ngd_slim_probe,
1550 .remove = ngd_slim_remove,
1551 .driver = {
1552 .name = NGD_SLIM_NAME,
1553 .owner = THIS_MODULE,
1554 .pm = &ngd_slim_dev_pm_ops,
1555 .of_match_table = ngd_slim_dt_match,
1556 },
1557};
1558
1559static int ngd_slim_init(void)
1560{
1561 return platform_driver_register(&ngd_slim_driver);
1562}
1563late_initcall(ngd_slim_init);
1564
1565static void ngd_slim_exit(void)
1566{
1567 platform_driver_unregister(&ngd_slim_driver);
1568}
1569module_exit(ngd_slim_exit);
1570
1571MODULE_LICENSE("GPL v2");
1572MODULE_DESCRIPTION("MSM Slimbus controller");
1573MODULE_ALIAS("platform:msm-slim-ngd");