blob: bbec9d3b33f7176f2cc156b71612d6f8348daee0 [file] [log] [blame]
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -07001/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/coresight.h>
14#include <linux/coresight-cti.h>
15#include <linux/workqueue.h>
16#include <soc/qcom/sysmon.h>
17#include "esoc-mdm.h"
18
19enum gpio_update_config {
20 GPIO_UPDATE_BOOTING_CONFIG = 1,
21 GPIO_UPDATE_RUNNING_CONFIG,
22};
23
24enum irq_mask {
25 IRQ_ERRFATAL = 0x1,
26 IRQ_STATUS = 0x2,
27 IRQ_PBLRDY = 0x4,
28};
29
30
31static struct gpio_map {
32 const char *name;
33 int index;
34} gpio_map[] = {
35 {"qcom,mdm2ap-errfatal-gpio", MDM2AP_ERRFATAL},
36 {"qcom,ap2mdm-errfatal-gpio", AP2MDM_ERRFATAL},
37 {"qcom,mdm2ap-status-gpio", MDM2AP_STATUS},
38 {"qcom,ap2mdm-status-gpio", AP2MDM_STATUS},
39 {"qcom,mdm2ap-pblrdy-gpio", MDM2AP_PBLRDY},
40 {"qcom,ap2mdm-wakeup-gpio", AP2MDM_WAKEUP},
41 {"qcom,ap2mdm-chnlrdy-gpio", AP2MDM_CHNLRDY},
42 {"qcom,mdm2ap-wakeup-gpio", MDM2AP_WAKEUP},
43 {"qcom,ap2mdm-vddmin-gpio", AP2MDM_VDDMIN},
44 {"qcom,mdm2ap-vddmin-gpio", MDM2AP_VDDMIN},
45 {"qcom,ap2mdm-pmic-pwr-en-gpio", AP2MDM_PMIC_PWR_EN},
46 {"qcom,mdm-link-detect-gpio", MDM_LINK_DETECT},
47};
48
49/* Required gpios */
50static const int required_gpios[] = {
51 MDM2AP_ERRFATAL,
52 AP2MDM_ERRFATAL,
53 MDM2AP_STATUS,
54 AP2MDM_STATUS,
55};
56
57static void mdm_debug_gpio_show(struct mdm_ctrl *mdm)
58{
59 struct device *dev = mdm->dev;
60
61 dev_dbg(dev, "%s: MDM2AP_ERRFATAL gpio = %d\n",
62 __func__, MDM_GPIO(mdm, MDM2AP_ERRFATAL));
63 dev_dbg(dev, "%s: AP2MDM_ERRFATAL gpio = %d\n",
64 __func__, MDM_GPIO(mdm, AP2MDM_ERRFATAL));
65 dev_dbg(dev, "%s: MDM2AP_STATUS gpio = %d\n",
66 __func__, MDM_GPIO(mdm, MDM2AP_STATUS));
67 dev_dbg(dev, "%s: AP2MDM_STATUS gpio = %d\n",
68 __func__, MDM_GPIO(mdm, AP2MDM_STATUS));
69 dev_dbg(dev, "%s: AP2MDM_SOFT_RESET gpio = %d\n",
70 __func__, MDM_GPIO(mdm, AP2MDM_SOFT_RESET));
71 dev_dbg(dev, "%s: MDM2AP_WAKEUP gpio = %d\n",
72 __func__, MDM_GPIO(mdm, MDM2AP_WAKEUP));
73 dev_dbg(dev, "%s: AP2MDM_WAKEUP gpio = %d\n",
74 __func__, MDM_GPIO(mdm, AP2MDM_WAKEUP));
75 dev_dbg(dev, "%s: AP2MDM_PMIC_PWR_EN gpio = %d\n",
76 __func__, MDM_GPIO(mdm, AP2MDM_PMIC_PWR_EN));
77 dev_dbg(dev, "%s: MDM2AP_PBLRDY gpio = %d\n",
78 __func__, MDM_GPIO(mdm, MDM2AP_PBLRDY));
79 dev_dbg(dev, "%s: AP2MDM_VDDMIN gpio = %d\n",
80 __func__, MDM_GPIO(mdm, AP2MDM_VDDMIN));
81 dev_dbg(dev, "%s: MDM2AP_VDDMIN gpio = %d\n",
82 __func__, MDM_GPIO(mdm, MDM2AP_VDDMIN));
83}
84
85static void mdm_enable_irqs(struct mdm_ctrl *mdm)
86{
87 if (!mdm)
88 return;
89 if (mdm->irq_mask & IRQ_ERRFATAL) {
90 enable_irq(mdm->errfatal_irq);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -080091 mdm->irq_mask &= ~IRQ_ERRFATAL;
92 }
93 if (mdm->irq_mask & IRQ_STATUS) {
94 enable_irq(mdm->status_irq);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -080095 mdm->irq_mask &= ~IRQ_STATUS;
96 }
97 if (mdm->irq_mask & IRQ_PBLRDY) {
98 enable_irq(mdm->pblrdy_irq);
99 mdm->irq_mask &= ~IRQ_PBLRDY;
100 }
101}
102
103static void mdm_disable_irqs(struct mdm_ctrl *mdm)
104{
105 if (!mdm)
106 return;
107 if (!(mdm->irq_mask & IRQ_ERRFATAL)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800108 disable_irq_nosync(mdm->errfatal_irq);
109 mdm->irq_mask |= IRQ_ERRFATAL;
110 }
111 if (!(mdm->irq_mask & IRQ_STATUS)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800112 disable_irq_nosync(mdm->status_irq);
113 mdm->irq_mask |= IRQ_STATUS;
114 }
115 if (!(mdm->irq_mask & IRQ_PBLRDY)) {
116 disable_irq_nosync(mdm->pblrdy_irq);
117 mdm->irq_mask |= IRQ_PBLRDY;
118 }
119}
120
121static void mdm_deconfigure_ipc(struct mdm_ctrl *mdm)
122{
123 int i;
124
125 for (i = 0; i < NUM_GPIOS; ++i) {
126 if (gpio_is_valid(MDM_GPIO(mdm, i)))
127 gpio_free(MDM_GPIO(mdm, i));
128 }
129 if (mdm->mdm_queue) {
130 destroy_workqueue(mdm->mdm_queue);
131 mdm->mdm_queue = NULL;
132 }
133}
134
135static void mdm_update_gpio_configs(struct mdm_ctrl *mdm,
136 enum gpio_update_config gpio_config)
137{
138 struct pinctrl_state *pins_state = NULL;
139 /* Some gpio configuration may need updating after modem bootup.*/
140 switch (gpio_config) {
141 case GPIO_UPDATE_RUNNING_CONFIG:
142 pins_state = mdm->gpio_state_running;
143 break;
144 case GPIO_UPDATE_BOOTING_CONFIG:
145 pins_state = mdm->gpio_state_booting;
146 break;
147 default:
148 pins_state = NULL;
149 dev_err(mdm->dev, "%s: called with no config\n", __func__);
150 break;
151 }
152 if (pins_state != NULL) {
153 if (pinctrl_select_state(mdm->pinctrl, pins_state))
154 dev_err(mdm->dev, "switching gpio config failed\n");
155 }
156}
157
158static void mdm_trigger_dbg(struct mdm_ctrl *mdm)
159{
160 int ret;
161
162 if (mdm->dbg_mode && !mdm->trig_cnt) {
163 ret = coresight_cti_pulse_trig(mdm->cti, MDM_CTI_CH);
164 mdm->trig_cnt++;
165 if (ret)
166 dev_err(mdm->dev, "unable to trigger cti pulse on\n");
167 }
168}
169
170static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
171{
172 unsigned long end_time;
173 bool status_down = false;
174 struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
175 struct device *dev = mdm->dev;
176 int ret;
177 bool graceful_shutdown = false;
Arun KS0cb73fd2017-01-16 17:47:03 +0530178 u32 status, err_fatal;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800179
180 switch (cmd) {
181 case ESOC_PWR_ON:
Arun KS0cb73fd2017-01-16 17:47:03 +0530182 if (esoc->auto_boot) {
183 /*
184 * If esoc has already booted, we would have missed
185 * status change interrupt. Read status and err_fatal
186 * signals to arrive at the state of esoc.
187 */
188 esoc->clink_ops->get_status(&status, esoc);
189 esoc->clink_ops->get_err_fatal(&err_fatal, esoc);
190 if (err_fatal)
191 return -EIO;
192 if (status && !mdm->ready) {
193 mdm->ready = true;
194 esoc->clink_ops->notify(ESOC_BOOT_DONE, esoc);
195 }
196 }
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800197 gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800198 mdm->init = 1;
199 mdm_do_first_power_on(mdm);
Arun KS0cb73fd2017-01-16 17:47:03 +0530200 mdm_enable_irqs(mdm);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800201 break;
202 case ESOC_PWR_OFF:
203 mdm_disable_irqs(mdm);
204 mdm->debug = 0;
205 mdm->ready = false;
206 mdm->trig_cnt = 0;
Arun KS0cb73fd2017-01-16 17:47:03 +0530207 if (esoc->primary)
208 break;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800209 graceful_shutdown = true;
Arun KS35fa1602017-03-02 18:12:54 +0530210 if (!esoc->userspace_handle_shutdown) {
211 ret = sysmon_send_shutdown(&esoc->subsys);
212 if (ret) {
213 dev_err(mdm->dev,
214 "sysmon shutdown fail, ret = %d\n", ret);
215 graceful_shutdown = false;
216 goto force_poff;
217 }
218 } else {
219 esoc_clink_queue_request(ESOC_REQ_SEND_SHUTDOWN, esoc);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800220 }
221 dev_dbg(mdm->dev, "Waiting for status gpio go low\n");
222 status_down = false;
223 end_time = jiffies + msecs_to_jiffies(10000);
224 while (time_before(jiffies, end_time)) {
225 if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS))
226 == 0) {
227 dev_dbg(dev, "Status went low\n");
228 status_down = true;
229 break;
230 }
231 msleep(100);
232 }
233 if (status_down)
234 dev_dbg(dev, "shutdown successful\n");
235 else
236 dev_err(mdm->dev, "graceful poff ipc fail\n");
237 break;
238force_poff:
239 case ESOC_FORCE_PWR_OFF:
240 if (!graceful_shutdown) {
241 mdm_disable_irqs(mdm);
242 mdm->debug = 0;
243 mdm->ready = false;
244 mdm->trig_cnt = 0;
245
246 dev_err(mdm->dev, "Graceful shutdown fail, ret = %d\n",
247 esoc->subsys.sysmon_shutdown_ret);
248 }
249
Arun KS0cb73fd2017-01-16 17:47:03 +0530250 if (esoc->primary)
251 break;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800252 /*
253 * Force a shutdown of the mdm. This is required in order
254 * to prevent the mdm from immediately powering back on
Arun KS35fa1602017-03-02 18:12:54 +0530255 * after the shutdown. Avoid setting status to 0, if line is
256 * monitored by multiple mdms(might be wrongly interpreted as
257 * a primary crash).
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800258 */
Arun KS35fa1602017-03-02 18:12:54 +0530259 if (esoc->statusline_not_a_powersource == false)
260 gpio_set_value(MDM_GPIO(mdm, AP2MDM_STATUS), 0);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800261 esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc);
262 mdm_power_down(mdm);
263 mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
264 break;
265 case ESOC_RESET:
266 mdm_toggle_soft_reset(mdm, false);
267 break;
268 case ESOC_PREPARE_DEBUG:
269 /*
270 * disable all irqs except request irq (pblrdy)
271 * force a reset of the mdm by signaling
272 * an APQ crash, wait till mdm is ready for ramdumps.
273 */
274 mdm->ready = false;
275 cancel_delayed_work(&mdm->mdm2ap_status_check_work);
Arun KS0cb73fd2017-01-16 17:47:03 +0530276 if (!mdm->esoc->auto_boot) {
277 gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
278 dev_dbg(mdm->dev,
279 "set ap2mdm errfatal to force reset\n");
280 msleep(mdm->ramdump_delay_ms);
281 }
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800282 break;
283 case ESOC_EXE_DEBUG:
284 mdm->debug = 1;
285 mdm->trig_cnt = 0;
286 mdm_toggle_soft_reset(mdm, false);
287 /*
288 * wait for ramdumps to be collected
289 * then power down the mdm and switch gpios to booting
290 * config
291 */
292 wait_for_completion(&mdm->debug_done);
293 if (mdm->debug_fail) {
294 dev_err(mdm->dev, "unable to collect ramdumps\n");
295 mdm->debug = 0;
296 return -EIO;
297 }
298 dev_dbg(mdm->dev, "ramdump collection done\n");
299 mdm->debug = 0;
300 init_completion(&mdm->debug_done);
301 break;
302 case ESOC_EXIT_DEBUG:
303 /*
304 * Deassert APQ to mdm err fatal
305 * Power on the mdm
306 */
307 gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
308 dev_dbg(mdm->dev, "exiting debug state after power on\n");
309 mdm->get_restart_reason = true;
310 break;
311 default:
312 return -EINVAL;
313 };
314 return 0;
315}
316
317static void mdm2ap_status_check(struct work_struct *work)
318{
319 struct mdm_ctrl *mdm =
320 container_of(work, struct mdm_ctrl,
321 mdm2ap_status_check_work.work);
322 struct device *dev = mdm->dev;
323 struct esoc_clink *esoc = mdm->esoc;
324
325 if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) {
326 dev_dbg(dev, "MDM2AP_STATUS did not go high\n");
327 esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
328 }
329}
330
331static void mdm_status_fn(struct work_struct *work)
332{
333 struct mdm_ctrl *mdm =
334 container_of(work, struct mdm_ctrl, mdm_status_work);
335 struct device *dev = mdm->dev;
336 int value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));
337
338 dev_dbg(dev, "%s: status:%d\n", __func__, value);
339 /* Update gpio configuration to "running" config. */
340 mdm_update_gpio_configs(mdm, GPIO_UPDATE_RUNNING_CONFIG);
341}
342
343static void mdm_get_restart_reason(struct work_struct *work)
344{
345 int ret, ntries = 0;
346 char sfr_buf[RD_BUF_SIZE];
347 struct mdm_ctrl *mdm =
348 container_of(work, struct mdm_ctrl, restart_reason_work);
349 struct device *dev = mdm->dev;
350
351 do {
352 ret = sysmon_get_reason(&mdm->esoc->subsys, sfr_buf,
353 sizeof(sfr_buf));
354 if (!ret) {
355 dev_err(dev, "mdm restart reason is %s\n", sfr_buf);
356 break;
357 }
358 msleep(SFR_RETRY_INTERVAL);
359 } while (++ntries < SFR_MAX_RETRIES);
360 if (ntries == SFR_MAX_RETRIES)
361 dev_dbg(dev, "%s: Error retrieving restart reason: %d\n",
362 __func__, ret);
363 mdm->get_restart_reason = false;
364}
365
366static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc)
367{
368 bool status_down;
369 uint64_t timeout;
370 uint64_t now;
371 struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
372 struct device *dev = mdm->dev;
373
374 switch (notify) {
375 case ESOC_IMG_XFER_DONE:
376 if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0)
377 schedule_delayed_work(&mdm->mdm2ap_status_check_work,
378 msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
379 break;
380 case ESOC_BOOT_DONE:
381 esoc_clink_evt_notify(ESOC_RUN_STATE, esoc);
382 break;
383 case ESOC_IMG_XFER_RETRY:
384 mdm->init = 1;
385 mdm_toggle_soft_reset(mdm, false);
386 break;
387 case ESOC_IMG_XFER_FAIL:
388 esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
389 break;
390 case ESOC_BOOT_FAIL:
391 esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc);
392 break;
393 case ESOC_UPGRADE_AVAILABLE:
394 break;
395 case ESOC_DEBUG_DONE:
396 mdm->debug_fail = false;
397 mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG);
398 complete(&mdm->debug_done);
399 break;
400 case ESOC_DEBUG_FAIL:
401 mdm->debug_fail = true;
402 complete(&mdm->debug_done);
403 break;
404 case ESOC_PRIMARY_CRASH:
405 mdm_disable_irqs(mdm);
406 status_down = false;
407 dev_dbg(dev, "signal apq err fatal for graceful restart\n");
408 gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1);
Arun KS0cb73fd2017-01-16 17:47:03 +0530409 if (esoc->primary)
410 break;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800411 timeout = local_clock();
412 do_div(timeout, NSEC_PER_MSEC);
413 timeout += MDM_MODEM_TIMEOUT;
414 do {
415 if (gpio_get_value(MDM_GPIO(mdm,
416 MDM2AP_STATUS)) == 0) {
417 status_down = true;
418 break;
419 }
420 now = local_clock();
421 do_div(now, NSEC_PER_MSEC);
422 } while (!time_after64(now, timeout));
423
424 if (!status_down) {
425 dev_err(mdm->dev, "%s MDM2AP status did not go low\n",
426 __func__);
427 mdm_toggle_soft_reset(mdm, true);
428 }
429 break;
430 case ESOC_PRIMARY_REBOOT:
431 mdm_disable_irqs(mdm);
432 mdm->debug = 0;
433 mdm->ready = false;
434 mdm_cold_reset(mdm);
435 break;
436 };
437}
438
439static irqreturn_t mdm_errfatal(int irq, void *dev_id)
440{
441 struct mdm_ctrl *mdm = (struct mdm_ctrl *)dev_id;
442 struct esoc_clink *esoc;
443 struct device *dev;
444
445 if (!mdm)
446 goto no_mdm_irq;
447 dev = mdm->dev;
448 if (!mdm->ready)
449 goto mdm_pwroff_irq;
450 esoc = mdm->esoc;
451 dev_err(dev, "%s: mdm sent errfatal interrupt\n",
Arun KS0cb73fd2017-01-16 17:47:03 +0530452 __func__);
Arun KS39c69e22017-03-06 13:25:56 +0530453 subsys_set_crash_status(esoc->subsys_dev, true);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800454 /* disable irq ?*/
455 esoc_clink_evt_notify(ESOC_ERR_FATAL, esoc);
456 return IRQ_HANDLED;
457mdm_pwroff_irq:
458 dev_info(dev, "errfatal irq when in pwroff\n");
459no_mdm_irq:
460 return IRQ_HANDLED;
461}
462
463static irqreturn_t mdm_status_change(int irq, void *dev_id)
464{
465 int value;
466 struct esoc_clink *esoc;
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700467 struct device *dev;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800468 struct mdm_ctrl *mdm = (struct mdm_ctrl *)dev_id;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800469
470 if (!mdm)
471 return IRQ_HANDLED;
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700472 dev = mdm->dev;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800473 esoc = mdm->esoc;
Arun KS0cb73fd2017-01-16 17:47:03 +0530474 /*
475 * On auto boot devices, there is a possibility of receiving
476 * status change interrupt before esoc_clink structure is
477 * initialized. Ignore them.
478 */
479 if (!esoc)
480 return IRQ_HANDLED;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800481 value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS));
482 if (value == 0 && mdm->ready) {
483 dev_err(dev, "unexpected reset external modem\n");
Arun KS39c69e22017-03-06 13:25:56 +0530484 subsys_set_crash_status(esoc->subsys_dev, true);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800485 esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc);
486 } else if (value == 1) {
Arun KS0cb73fd2017-01-16 17:47:03 +0530487 /*
488 * In auto_boot cases, bailout early if mdm
489 * is up already.
490 */
491 if (esoc->auto_boot && mdm->ready)
492 return IRQ_HANDLED;
493
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800494 cancel_delayed_work(&mdm->mdm2ap_status_check_work);
495 dev_dbg(dev, "status = 1: mdm is now ready\n");
496 mdm->ready = true;
497 mdm_trigger_dbg(mdm);
498 queue_work(mdm->mdm_queue, &mdm->mdm_status_work);
499 if (mdm->get_restart_reason)
500 queue_work(mdm->mdm_queue, &mdm->restart_reason_work);
Arun KS0cb73fd2017-01-16 17:47:03 +0530501 if (esoc->auto_boot)
502 esoc->clink_ops->notify(ESOC_BOOT_DONE, esoc);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800503 }
504 return IRQ_HANDLED;
505}
506
507static irqreturn_t mdm_pblrdy_change(int irq, void *dev_id)
508{
509 struct mdm_ctrl *mdm;
510 struct device *dev;
511 struct esoc_clink *esoc;
512
513 mdm = (struct mdm_ctrl *)dev_id;
514 if (!mdm)
515 return IRQ_HANDLED;
516 esoc = mdm->esoc;
517 dev = mdm->dev;
518 dev_dbg(dev, "pbl ready %d:\n",
519 gpio_get_value(MDM_GPIO(mdm, MDM2AP_PBLRDY)));
520 if (mdm->init) {
521 mdm->init = 0;
522 mdm_trigger_dbg(mdm);
523 esoc_clink_queue_request(ESOC_REQ_IMG, esoc);
524 return IRQ_HANDLED;
525 }
526 if (mdm->debug)
527 esoc_clink_queue_request(ESOC_REQ_DEBUG, esoc);
528 return IRQ_HANDLED;
529}
530
Arun KS55b33a42017-01-16 15:27:48 +0530531static void mdm_get_status(u32 *status, struct esoc_clink *esoc)
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800532{
533 struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
534
535 if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0)
536 *status = 0;
537 else
538 *status = 1;
Arun KS55b33a42017-01-16 15:27:48 +0530539}
540
541static void mdm_get_err_fatal(u32 *status, struct esoc_clink *esoc)
542{
543 struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
544
545 if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_ERRFATAL)) == 0)
546 *status = 0;
547 else
548 *status = 1;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800549}
550
551static void mdm_configure_debug(struct mdm_ctrl *mdm)
552{
553 void __iomem *addr;
554 unsigned int val;
555 int ret;
556 struct device_node *node = mdm->dev->of_node;
557
558 addr = of_iomap(node, 0);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700559 if (IS_ERR_OR_NULL(addr)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800560 dev_err(mdm->dev, "failed to get debug base address\n");
561 return;
562 }
563 mdm->dbg_addr = addr + MDM_DBG_OFFSET;
564 val = readl_relaxed(mdm->dbg_addr);
565 if (val == MDM_DBG_MODE) {
566 mdm->dbg_mode = true;
567 mdm->cti = coresight_cti_get(MDM_CTI_NAME);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700568 if (IS_ERR_OR_NULL(mdm->cti)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800569 dev_err(mdm->dev, "unable to get cti handle\n");
570 goto cti_get_err;
571 }
572 ret = coresight_cti_map_trigout(mdm->cti, MDM_CTI_TRIG,
573 MDM_CTI_CH);
574 if (ret) {
575 dev_err(mdm->dev, "unable to map trig to channel\n");
576 goto cti_map_err;
577 }
578 mdm->trig_cnt = 0;
579 } else {
580 dev_dbg(mdm->dev, "Not in debug mode. debug mode = %u\n", val);
581 mdm->dbg_mode = false;
582 }
583 return;
584cti_map_err:
585 coresight_cti_put(mdm->cti);
586cti_get_err:
587 mdm->dbg_mode = false;
588}
589
590/* Fail if any of the required gpios is absent. */
591static int mdm_dt_parse_gpios(struct mdm_ctrl *mdm)
592{
593 int i, val, rc = 0;
594 struct device_node *node = mdm->dev->of_node;
595
596 for (i = 0; i < NUM_GPIOS; i++)
597 mdm->gpios[i] = INVALID_GPIO;
598
599 for (i = 0; i < ARRAY_SIZE(gpio_map); i++) {
600 val = of_get_named_gpio(node, gpio_map[i].name, 0);
601 if (val >= 0)
602 MDM_GPIO(mdm, gpio_map[i].index) = val;
603 }
604 /* These two are special because they can be inverted. */
605 /* Verify that the required gpios have valid values */
606 for (i = 0; i < ARRAY_SIZE(required_gpios); i++) {
607 if (MDM_GPIO(mdm, required_gpios[i]) == INVALID_GPIO) {
608 rc = -ENXIO;
609 break;
610 }
611 }
612 mdm_debug_gpio_show(mdm);
613 return rc;
614}
615
616static int mdm_configure_ipc(struct mdm_ctrl *mdm, struct platform_device *pdev)
617{
618 int ret = -1;
619 int irq;
620 struct device *dev = mdm->dev;
621 struct device_node *node = pdev->dev.of_node;
622
623 ret = of_property_read_u32(node, "qcom,ramdump-timeout-ms",
624 &mdm->dump_timeout_ms);
625 if (ret)
626 mdm->dump_timeout_ms = DEF_RAMDUMP_TIMEOUT;
627 ret = of_property_read_u32(node, "qcom,ramdump-delay-ms",
628 &mdm->ramdump_delay_ms);
629 if (ret)
630 mdm->ramdump_delay_ms = DEF_RAMDUMP_DELAY;
Arun KS0cb73fd2017-01-16 17:47:03 +0530631 /*
632 * In certain scenarios, multiple esoc devices are monitoring
633 * same AP2MDM_STATUS line. But only one of them will have a
634 * successful gpio_request call. Initialize gpio only if request
635 * succeeds.
636 */
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800637 if (gpio_request(MDM_GPIO(mdm, AP2MDM_STATUS), "AP2MDM_STATUS"))
638 dev_err(dev, "Failed to configure AP2MDM_STATUS gpio\n");
Arun KS0cb73fd2017-01-16 17:47:03 +0530639 else
640 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_STATUS), 0);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800641 if (gpio_request(MDM_GPIO(mdm, AP2MDM_ERRFATAL), "AP2MDM_ERRFATAL"))
642 dev_err(dev, "%s Failed to configure AP2MDM_ERRFATAL gpio\n",
643 __func__);
Arun KS0cb73fd2017-01-16 17:47:03 +0530644 else
645 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800646 if (gpio_request(MDM_GPIO(mdm, MDM2AP_STATUS), "MDM2AP_STATUS")) {
647 dev_err(dev, "%s Failed to configure MDM2AP_STATUS gpio\n",
648 __func__);
649 goto fatal_err;
650 }
651 if (gpio_request(MDM_GPIO(mdm, MDM2AP_ERRFATAL), "MDM2AP_ERRFATAL")) {
652 dev_err(dev, "%s Failed to configure MDM2AP_ERRFATAL gpio\n",
653 __func__);
654 goto fatal_err;
655 }
656 if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) {
657 if (gpio_request(MDM_GPIO(mdm, MDM2AP_PBLRDY),
658 "MDM2AP_PBLRDY")) {
659 dev_err(dev, "Cannot configure MDM2AP_PBLRDY gpio\n");
660 goto fatal_err;
661 }
662 }
663 if (gpio_is_valid(MDM_GPIO(mdm, AP2MDM_WAKEUP))) {
664 if (gpio_request(MDM_GPIO(mdm, AP2MDM_WAKEUP),
665 "AP2MDM_WAKEUP")) {
666 dev_err(dev, "Cannot configure AP2MDM_WAKEUP gpio\n");
667 goto fatal_err;
668 }
669 }
670 if (gpio_is_valid(MDM_GPIO(mdm, AP2MDM_CHNLRDY))) {
671 if (gpio_request(MDM_GPIO(mdm, AP2MDM_CHNLRDY),
672 "AP2MDM_CHNLRDY")) {
673 dev_err(dev, "Cannot configure AP2MDM_CHNLRDY gpio\n");
674 goto fatal_err;
675 }
676 }
677
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800678 if (gpio_is_valid(MDM_GPIO(mdm, AP2MDM_CHNLRDY)))
679 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_CHNLRDY), 0);
680
681 gpio_direction_input(MDM_GPIO(mdm, MDM2AP_STATUS));
682 gpio_direction_input(MDM_GPIO(mdm, MDM2AP_ERRFATAL));
683
684 /* ERR_FATAL irq. */
685 irq = gpio_to_irq(MDM_GPIO(mdm, MDM2AP_ERRFATAL));
686 if (irq < 0) {
687 dev_err(dev, "bad MDM2AP_ERRFATAL IRQ resource\n");
688 goto errfatal_err;
689
690 }
691 ret = request_irq(irq, mdm_errfatal,
692 IRQF_TRIGGER_RISING, "mdm errfatal", mdm);
693
694 if (ret < 0) {
695 dev_err(dev, "%s: MDM2AP_ERRFATAL IRQ#%d request failed,\n",
696 __func__, irq);
697 goto errfatal_err;
698 }
699 mdm->errfatal_irq = irq;
Arun KSce5f7bf2017-07-14 10:20:53 +0530700 irq_set_irq_wake(mdm->errfatal_irq, 1);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800701
702errfatal_err:
703 /* status irq */
704 irq = gpio_to_irq(MDM_GPIO(mdm, MDM2AP_STATUS));
705 if (irq < 0) {
706 dev_err(dev, "%s: bad MDM2AP_STATUS IRQ resource, err = %d\n",
707 __func__, irq);
708 goto status_err;
709 }
710 ret = request_threaded_irq(irq, NULL, mdm_status_change,
711 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
712 "mdm status", mdm);
713 if (ret < 0) {
714 dev_err(dev, "%s: MDM2AP_STATUS IRQ#%d request failed, err=%d",
715 __func__, irq, ret);
716 goto status_err;
717 }
718 mdm->status_irq = irq;
Arun KSce5f7bf2017-07-14 10:20:53 +0530719 irq_set_irq_wake(mdm->status_irq, 1);
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800720status_err:
721 if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) {
722 irq = platform_get_irq_byname(pdev, "plbrdy_irq");
723 if (irq < 0) {
724 dev_err(dev, "%s: MDM2AP_PBLRDY IRQ request failed\n",
725 __func__);
726 goto pblrdy_err;
727 }
728
729 ret = request_threaded_irq(irq, NULL, mdm_pblrdy_change,
730 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
731 "mdm pbl ready", mdm);
732 if (ret < 0) {
733 dev_err(dev, "MDM2AP_PBL IRQ#%d request failed %d\n",
734 irq, ret);
735 goto pblrdy_err;
736 }
737 mdm->pblrdy_irq = irq;
738 }
739 mdm_disable_irqs(mdm);
740pblrdy_err:
741 return 0;
742fatal_err:
743 mdm_deconfigure_ipc(mdm);
744 return ret;
745
746}
747
748static int mdm_pinctrl_init(struct mdm_ctrl *mdm)
749{
750 int retval = 0;
751
752 mdm->pinctrl = devm_pinctrl_get(mdm->dev);
753 if (IS_ERR_OR_NULL(mdm->pinctrl)) {
754 retval = PTR_ERR(mdm->pinctrl);
755 goto err_state_suspend;
756 }
757 mdm->gpio_state_booting =
758 pinctrl_lookup_state(mdm->pinctrl,
759 "mdm_booting");
760 if (IS_ERR_OR_NULL(mdm->gpio_state_booting)) {
761 mdm->gpio_state_running = NULL;
762 mdm->gpio_state_booting = NULL;
763 } else {
764 mdm->gpio_state_running =
765 pinctrl_lookup_state(mdm->pinctrl,
766 "mdm_running");
767 if (IS_ERR_OR_NULL(mdm->gpio_state_running)) {
768 mdm->gpio_state_booting = NULL;
769 mdm->gpio_state_running = NULL;
770 }
771 }
772 mdm->gpio_state_active =
773 pinctrl_lookup_state(mdm->pinctrl,
774 "mdm_active");
775 if (IS_ERR_OR_NULL(mdm->gpio_state_active)) {
776 retval = PTR_ERR(mdm->gpio_state_active);
777 goto err_state_active;
778 }
779 mdm->gpio_state_suspend =
780 pinctrl_lookup_state(mdm->pinctrl,
781 "mdm_suspend");
782 if (IS_ERR_OR_NULL(mdm->gpio_state_suspend)) {
783 retval = PTR_ERR(mdm->gpio_state_suspend);
784 goto err_state_suspend;
785 }
786 retval = pinctrl_select_state(mdm->pinctrl, mdm->gpio_state_active);
787 return retval;
788
789err_state_suspend:
790 mdm->gpio_state_active = NULL;
791err_state_active:
792 mdm->gpio_state_suspend = NULL;
793 mdm->gpio_state_booting = NULL;
794 mdm->gpio_state_running = NULL;
795 return retval;
796}
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -0700797
798static void mdm_release_ipc_gpio(struct mdm_ctrl *mdm)
799{
800 int i;
801
802 if (!mdm)
803 return;
804
805 for (i = 0; i < NUM_GPIOS; ++i)
806 if (gpio_is_valid(MDM_GPIO(mdm, i)))
807 gpio_free(MDM_GPIO(mdm, i));
808}
809
810static void mdm_free_irq(struct mdm_ctrl *mdm)
811{
812 if (!mdm)
813 return;
814
815 free_irq(mdm->errfatal_irq, mdm);
816 free_irq(mdm->status_irq, mdm);
817}
818
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800819static int mdm9x25_setup_hw(struct mdm_ctrl *mdm,
820 const struct mdm_ops *ops,
821 struct platform_device *pdev)
822{
823 int ret;
824 struct esoc_clink *esoc;
825 const struct esoc_clink_ops *clink_ops = ops->clink_ops;
826 const struct mdm_pon_ops *pon_ops = ops->pon_ops;
827
828 mdm->dev = &pdev->dev;
829 mdm->pon_ops = pon_ops;
830 esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700831 if (IS_ERR_OR_NULL(esoc)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800832 dev_err(mdm->dev, "cannot allocate esoc device\n");
833 return PTR_ERR(esoc);
834 }
Arun KS04389762017-01-16 14:39:52 +0530835 esoc->pdev = pdev;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800836 mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
837 if (!mdm->mdm_queue) {
838 dev_err(mdm->dev, "could not create mdm_queue\n");
839 return -ENOMEM;
840 }
841 mdm->irq_mask = 0;
842 mdm->ready = false;
843 ret = mdm_dt_parse_gpios(mdm);
844 if (ret)
845 return ret;
846 dev_err(mdm->dev, "parsing gpio done\n");
847 ret = mdm_pon_dt_init(mdm);
848 if (ret)
849 return ret;
850 dev_dbg(mdm->dev, "pon dt init done\n");
851 ret = mdm_pinctrl_init(mdm);
852 if (ret)
853 return ret;
854 dev_err(mdm->dev, "pinctrl init done\n");
855 ret = mdm_pon_setup(mdm);
856 if (ret)
857 return ret;
858 dev_dbg(mdm->dev, "pon setup done\n");
859 ret = mdm_configure_ipc(mdm, pdev);
860 if (ret)
861 return ret;
862 mdm_configure_debug(mdm);
863 dev_err(mdm->dev, "ipc configure done\n");
864 esoc->name = MDM9x25_LABEL;
865 esoc->link_name = MDM9x25_HSIC;
866 esoc->clink_ops = clink_ops;
867 esoc->parent = mdm->dev;
868 esoc->owner = THIS_MODULE;
869 esoc->np = pdev->dev.of_node;
870 set_esoc_clink_data(esoc, mdm);
871 ret = esoc_clink_register(esoc);
872 if (ret) {
873 dev_err(mdm->dev, "esoc registration failed\n");
874 return ret;
875 }
876 dev_dbg(mdm->dev, "esoc registration done\n");
877 init_completion(&mdm->debug_done);
878 INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
879 INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
880 INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
881 mdm->get_restart_reason = false;
882 mdm->debug_fail = false;
883 mdm->esoc = esoc;
884 mdm->init = 0;
885 return 0;
886}
887
888static int mdm9x35_setup_hw(struct mdm_ctrl *mdm,
889 const struct mdm_ops *ops,
890 struct platform_device *pdev)
891{
892 int ret;
893 struct device_node *node;
894 struct esoc_clink *esoc;
895 const struct esoc_clink_ops *clink_ops = ops->clink_ops;
896 const struct mdm_pon_ops *pon_ops = ops->pon_ops;
897
898 mdm->dev = &pdev->dev;
899 mdm->pon_ops = pon_ops;
900 node = pdev->dev.of_node;
901 esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700902 if (IS_ERR_OR_NULL(esoc)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800903 dev_err(mdm->dev, "cannot allocate esoc device\n");
904 return PTR_ERR(esoc);
905 }
Arun KS04389762017-01-16 14:39:52 +0530906 esoc->pdev = pdev;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800907 mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
908 if (!mdm->mdm_queue) {
909 dev_err(mdm->dev, "could not create mdm_queue\n");
910 return -ENOMEM;
911 }
912 mdm->irq_mask = 0;
913 mdm->ready = false;
914 ret = mdm_dt_parse_gpios(mdm);
915 if (ret)
916 return ret;
917 dev_dbg(mdm->dev, "parsing gpio done\n");
918 ret = mdm_pon_dt_init(mdm);
919 if (ret)
920 return ret;
921 dev_dbg(mdm->dev, "pon dt init done\n");
922 ret = mdm_pinctrl_init(mdm);
923 if (ret)
924 return ret;
925 dev_dbg(mdm->dev, "pinctrl init done\n");
926 ret = mdm_pon_setup(mdm);
927 if (ret)
928 return ret;
929 dev_dbg(mdm->dev, "pon setup done\n");
930 ret = mdm_configure_ipc(mdm, pdev);
931 if (ret)
932 return ret;
933 mdm_configure_debug(mdm);
934 dev_dbg(mdm->dev, "ipc configure done\n");
935 esoc->name = MDM9x35_LABEL;
936 mdm->dual_interface = of_property_read_bool(node,
937 "qcom,mdm-dual-link");
938 /* Check if link gpio is available */
939 if (gpio_is_valid(MDM_GPIO(mdm, MDM_LINK_DETECT))) {
940 if (mdm->dual_interface) {
941 if (gpio_get_value(MDM_GPIO(mdm, MDM_LINK_DETECT)))
942 esoc->link_name = MDM9x35_DUAL_LINK;
943 else
944 esoc->link_name = MDM9x35_PCIE;
945 } else {
946 if (gpio_get_value(MDM_GPIO(mdm, MDM_LINK_DETECT)))
947 esoc->link_name = MDM9x35_HSIC;
948 else
949 esoc->link_name = MDM9x35_PCIE;
950 }
951 } else if (mdm->dual_interface)
952 esoc->link_name = MDM9x35_DUAL_LINK;
953 else
954 esoc->link_name = MDM9x35_HSIC;
955 esoc->clink_ops = clink_ops;
956 esoc->parent = mdm->dev;
957 esoc->owner = THIS_MODULE;
958 esoc->np = pdev->dev.of_node;
959 set_esoc_clink_data(esoc, mdm);
960 ret = esoc_clink_register(esoc);
961 if (ret) {
962 dev_err(mdm->dev, "esoc registration failed\n");
963 return ret;
964 }
965 dev_dbg(mdm->dev, "esoc registration done\n");
966 init_completion(&mdm->debug_done);
967 INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
968 INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
969 INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
970 mdm->get_restart_reason = false;
971 mdm->debug_fail = false;
972 mdm->esoc = esoc;
973 mdm->init = 0;
974 return 0;
975}
976
977static int mdm9x55_setup_hw(struct mdm_ctrl *mdm,
978 const struct mdm_ops *ops,
979 struct platform_device *pdev)
980{
981 int ret;
982 struct device_node *node;
983 struct esoc_clink *esoc;
984 const struct esoc_clink_ops *clink_ops = ops->clink_ops;
985 const struct mdm_pon_ops *pon_ops = ops->pon_ops;
986
987 mdm->dev = &pdev->dev;
988 mdm->pon_ops = pon_ops;
989 node = pdev->dev.of_node;
990 esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -0700991 if (IS_ERR_OR_NULL(esoc)) {
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800992 dev_err(mdm->dev, "cannot allocate esoc device\n");
993 return PTR_ERR(esoc);
994 }
Arun KS04389762017-01-16 14:39:52 +0530995 esoc->pdev = pdev;
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800996 mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
997 if (!mdm->mdm_queue) {
998 dev_err(mdm->dev, "could not create mdm_queue\n");
999 return -ENOMEM;
1000 }
1001 mdm->irq_mask = 0;
1002 mdm->ready = false;
1003 ret = mdm_dt_parse_gpios(mdm);
1004 if (ret)
1005 return ret;
1006 dev_dbg(mdm->dev, "parsing gpio done\n");
1007 ret = mdm_pon_dt_init(mdm);
1008 if (ret)
1009 return ret;
1010 dev_dbg(mdm->dev, "pon dt init done\n");
1011 ret = mdm_pinctrl_init(mdm);
1012 if (ret)
1013 return ret;
1014 dev_dbg(mdm->dev, "pinctrl init done\n");
1015 ret = mdm_pon_setup(mdm);
1016 if (ret)
1017 return ret;
1018 dev_dbg(mdm->dev, "pon setup done\n");
1019 ret = mdm_configure_ipc(mdm, pdev);
1020 if (ret)
1021 return ret;
1022 dev_dbg(mdm->dev, "ipc configure done\n");
1023 esoc->name = MDM9x55_LABEL;
1024 mdm->dual_interface = of_property_read_bool(node,
1025 "qcom,mdm-dual-link");
1026 esoc->link_name = MDM9x55_PCIE;
Satya Durga Srinivasu Prabhalab8a2a4e2017-03-14 16:51:50 -07001027 ret = of_property_read_string(node, "qcom,mdm-link-info",
1028 &esoc->link_info);
1029 if (ret)
1030 dev_info(mdm->dev, "esoc link info missing\n");
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001031 esoc->clink_ops = clink_ops;
1032 esoc->parent = mdm->dev;
1033 esoc->owner = THIS_MODULE;
1034 esoc->np = pdev->dev.of_node;
1035 set_esoc_clink_data(esoc, mdm);
1036 ret = esoc_clink_register(esoc);
1037 if (ret) {
1038 dev_err(mdm->dev, "esoc registration failed\n");
1039 return ret;
1040 }
1041 dev_dbg(mdm->dev, "esoc registration done\n");
1042 init_completion(&mdm->debug_done);
1043 INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
1044 INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
1045 INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
1046 mdm->get_restart_reason = false;
1047 mdm->debug_fail = false;
1048 mdm->esoc = esoc;
1049 mdm->init = 0;
1050 return 0;
1051}
1052
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -07001053static int sdxpoorwills_setup_hw(struct mdm_ctrl *mdm,
1054 const struct mdm_ops *ops,
1055 struct platform_device *pdev)
1056{
1057 int ret;
1058 struct device_node *node;
1059 struct esoc_clink *esoc;
1060 const struct esoc_clink_ops *clink_ops = ops->clink_ops;
1061 const struct mdm_pon_ops *pon_ops = ops->pon_ops;
1062
1063 mdm->dev = &pdev->dev;
1064 mdm->pon_ops = pon_ops;
1065 node = pdev->dev.of_node;
1066
1067 esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
1068 if (IS_ERR_OR_NULL(esoc)) {
1069 dev_err(mdm->dev, "cannot allocate esoc device\n");
1070 return PTR_ERR(esoc);
1071 }
1072
1073 esoc->pdev = pdev;
1074
1075 mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
1076 if (!mdm->mdm_queue) {
1077 dev_err(mdm->dev, "could not create mdm_queue\n");
1078 return -ENOMEM;
1079 }
1080
1081 mdm->irq_mask = 0;
1082 mdm->ready = false;
1083
1084 ret = mdm_dt_parse_gpios(mdm);
1085 if (ret) {
1086 dev_err(mdm->dev, "Failed to parse DT gpios\n");
1087 goto err_destroy_wrkq;
1088 }
1089
1090 ret = mdm_pon_dt_init(mdm);
1091 if (ret) {
1092 dev_err(mdm->dev, "Failed to parse PON DT gpio\n");
1093 goto err_destroy_wrkq;
1094 }
1095
1096 ret = mdm_pinctrl_init(mdm);
1097 if (ret) {
1098 dev_err(mdm->dev, "Failed to init pinctrl\n");
1099 goto err_destroy_wrkq;
1100 }
1101
1102 ret = mdm_pon_setup(mdm);
1103 if (ret) {
1104 dev_err(mdm->dev, "Failed to setup PON\n");
1105 goto err_destroy_wrkq;
1106 }
1107
1108 ret = mdm_configure_ipc(mdm, pdev);
1109 if (ret) {
1110 dev_err(mdm->dev, "Failed to configure the ipc\n");
1111 goto err_release_ipc;
1112 }
1113
1114 esoc->name = SDXPOORWILLS_LABEL;
1115 esoc->link_name = SDXPOORWILLS_PCIE;
1116
1117 ret = of_property_read_string(node, "qcom,mdm-link-info",
1118 &esoc->link_info);
1119 if (ret)
1120 dev_info(mdm->dev, "esoc link info missing\n");
1121
1122 esoc->clink_ops = clink_ops;
1123 esoc->parent = mdm->dev;
1124 esoc->owner = THIS_MODULE;
1125 esoc->np = pdev->dev.of_node;
1126 set_esoc_clink_data(esoc, mdm);
1127
1128 ret = esoc_clink_register(esoc);
1129 if (ret) {
1130 dev_err(mdm->dev, "esoc registration failed\n");
1131 goto err_free_irq;
1132 }
1133 dev_dbg(mdm->dev, "esoc registration done\n");
1134
1135 init_completion(&mdm->debug_done);
1136 INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
1137 INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
1138 INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
1139 mdm->get_restart_reason = false;
1140 mdm->debug_fail = false;
1141 mdm->esoc = esoc;
1142 mdm->init = 0;
1143
1144 return 0;
1145
1146err_free_irq:
1147 mdm_free_irq(mdm);
1148err_release_ipc:
1149 mdm_release_ipc_gpio(mdm);
1150err_destroy_wrkq:
1151 destroy_workqueue(mdm->mdm_queue);
1152 return ret;
1153}
1154
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001155static struct esoc_clink_ops mdm_cops = {
1156 .cmd_exe = mdm_cmd_exe,
1157 .get_status = mdm_get_status,
Arun KS55b33a42017-01-16 15:27:48 +05301158 .get_err_fatal = mdm_get_err_fatal,
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001159 .notify = mdm_notify,
1160};
1161
1162static struct mdm_ops mdm9x25_ops = {
1163 .clink_ops = &mdm_cops,
1164 .config_hw = mdm9x25_setup_hw,
1165 .pon_ops = &mdm9x25_pon_ops,
1166};
1167
1168static struct mdm_ops mdm9x35_ops = {
1169 .clink_ops = &mdm_cops,
1170 .config_hw = mdm9x35_setup_hw,
1171 .pon_ops = &mdm9x35_pon_ops,
1172};
1173
1174static struct mdm_ops mdm9x55_ops = {
1175 .clink_ops = &mdm_cops,
1176 .config_hw = mdm9x55_setup_hw,
1177 .pon_ops = &mdm9x55_pon_ops,
1178};
1179
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -07001180static struct mdm_ops sdxpoorwills_ops = {
1181 .clink_ops = &mdm_cops,
1182 .config_hw = sdxpoorwills_setup_hw,
1183 .pon_ops = &sdxpoorwills_pon_ops,
1184};
1185
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001186static const struct of_device_id mdm_dt_match[] = {
1187 { .compatible = "qcom,ext-mdm9x25",
1188 .data = &mdm9x25_ops, },
1189 { .compatible = "qcom,ext-mdm9x35",
1190 .data = &mdm9x35_ops, },
1191 { .compatible = "qcom,ext-mdm9x55",
1192 .data = &mdm9x55_ops, },
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -07001193 { .compatible = "qcom,ext-sdxpoorwills",
1194 .data = &sdxpoorwills_ops, },
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001195 {},
1196};
1197MODULE_DEVICE_TABLE(of, mdm_dt_match);
1198
1199static int mdm_probe(struct platform_device *pdev)
1200{
1201 const struct of_device_id *match;
1202 const struct mdm_ops *mdm_ops;
1203 struct device_node *node = pdev->dev.of_node;
1204 struct mdm_ctrl *mdm;
1205
1206 match = of_match_node(mdm_dt_match, node);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -07001207 if (IS_ERR_OR_NULL(match))
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001208 return PTR_ERR(match);
1209 mdm_ops = match->data;
1210 mdm = devm_kzalloc(&pdev->dev, sizeof(*mdm), GFP_KERNEL);
Satya Durga Srinivasu Prabhala377d32f2017-03-15 11:09:28 -07001211 if (IS_ERR_OR_NULL(mdm))
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08001212 return PTR_ERR(mdm);
1213 return mdm_ops->config_hw(mdm, mdm_ops, pdev);
1214}
1215
1216static struct platform_driver mdm_driver = {
1217 .probe = mdm_probe,
1218 .driver = {
1219 .name = "ext-mdm",
1220 .owner = THIS_MODULE,
1221 .of_match_table = of_match_ptr(mdm_dt_match),
1222 },
1223};
1224
1225static int __init mdm_register(void)
1226{
1227 return platform_driver_register(&mdm_driver);
1228}
1229module_init(mdm_register);
1230
1231static void __exit mdm_unregister(void)
1232{
1233 platform_driver_unregister(&mdm_driver);
1234}
1235module_exit(mdm_unregister);
1236MODULE_LICENSE("GPL v2");