mdm2.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  2. *
  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/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/err.h>
  16. #include <linux/slab.h>
  17. #include <linux/io.h>
  18. #include <linux/mutex.h>
  19. #include <linux/miscdevice.h>
  20. #include <linux/fs.h>
  21. #include <linux/gpio.h>
  22. #include <linux/kernel.h>
  23. #include <linux/irq.h>
  24. #include <linux/ioctl.h>
  25. #include <linux/delay.h>
  26. #include <linux/reboot.h>
  27. #include <linux/debugfs.h>
  28. #include <linux/completion.h>
  29. #include <linux/workqueue.h>
  30. #include <linux/clk.h>
  31. #include <asm/mach-types.h>
  32. #include "mdm2.h"
  33. #include <mach/restart.h>
  34. #include <mach/subsystem_notif.h>
  35. #include <mach/subsystem_restart.h>
  36. #include <linux/msm_charm.h>
  37. #include <mach/../../msm_watchdog.h>
  38. #include <mach/../../devices.h>
  39. #include <mach/../../clock.h>
  40. #include "mdm_private.h"
  41. #define MDM_PBLRDY_CNT 20
  42. static int mdm_debug_mask;
  43. extern int poweroff_charging;
  44. static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
  45. {
  46. pr_err("%s %d\n", __func__,__LINE__);
  47. if (!mdm_drv->pdata->peripheral_platform_device)
  48. return;
  49. pr_err("%s %d\n", __func__,__LINE__);
  50. mutex_lock(&mdm_drv->peripheral_status_lock);
  51. if (mdm_drv->peripheral_status)
  52. goto out;
  53. pr_err("%s %d\n", __func__,__LINE__);
  54. platform_device_add(mdm_drv->pdata->peripheral_platform_device);
  55. pr_err("%s %d\n", __func__,__LINE__);
  56. mdm_drv->peripheral_status = 1;
  57. out:
  58. mutex_unlock(&mdm_drv->peripheral_status_lock);
  59. pr_err("%s %d\n", __func__,__LINE__);
  60. }
  61. static void mdm_peripheral_disconnect(struct mdm_modem_drv *mdm_drv)
  62. {
  63. if (!mdm_drv->pdata->peripheral_platform_device)
  64. return;
  65. mutex_lock(&mdm_drv->peripheral_status_lock);
  66. if (!mdm_drv->peripheral_status)
  67. goto out;
  68. platform_device_del(mdm_drv->pdata->peripheral_platform_device);
  69. mdm_drv->peripheral_status = 0;
  70. out:
  71. mutex_unlock(&mdm_drv->peripheral_status_lock);
  72. }
  73. static void mdm_do_clean_reset(struct mdm_modem_drv *mdm_drv)
  74. {
  75. /* mdm clean reset
  76. *
  77. * Shutdown PMIC and up if needed
  78. */
  79. #if 0 // no need workardoun code.
  80. if (mdm_drv->need_clean_reset) {
  81. gpio_direction_output(MDM_GPIO(AP2MDM_PMIC_PWR_EN), 0);
  82. mdelay(10);
  83. gpio_direction_output(MDM_GPIO(AP2MDM_PMIC_PWR_EN), 1);
  84. mdelay(10);
  85. mdm_drv->need_clean_reset = false;
  86. }
  87. #endif
  88. }
  89. /* This function can be called from atomic context. */
  90. static void mdm_toggle_soft_reset(struct mdm_modem_drv *mdm_drv)
  91. {
  92. int soft_reset_direction_assert = 0,
  93. soft_reset_direction_de_assert = 1;
  94. if (mdm_drv->pdata->soft_reset_inverted) {
  95. soft_reset_direction_assert = 1;
  96. soft_reset_direction_de_assert = 0;
  97. }
  98. #if 0// TD_CDMA
  99. gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
  100. soft_reset_direction_assert);
  101. /* Use mdelay because this function can be called from atomic
  102. * context.
  103. */
  104. mdelay(10);
  105. gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
  106. soft_reset_direction_de_assert);
  107. #endif//TD_CDMA
  108. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET),
  109. soft_reset_direction_assert);
  110. mdelay(10);
  111. mdm_do_clean_reset(mdm_drv);
  112. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET),
  113. soft_reset_direction_de_assert);
  114. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 1);
  115. mdelay(1000);
  116. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 0);
  117. }
  118. /* This function can be called from atomic context. */
  119. static void mdm_atomic_soft_reset(struct mdm_modem_drv *mdm_drv)
  120. {
  121. mdm_toggle_soft_reset(mdm_drv);
  122. }
  123. static void mdm_power_down_common(struct mdm_modem_drv *mdm_drv)
  124. {
  125. int i = 0;
  126. int soft_reset_direction =
  127. mdm_drv->pdata->soft_reset_inverted ? 1 : 0;
  128. mdm_peripheral_disconnect(mdm_drv);
  129. #if 0 // because we don't use the graceful shutdown function, we don't need this checking
  130. /* Wait for the modem to complete its power down actions. */
  131. for (i = 20; i > 0; i--) {
  132. if (gpio_get_value(MDM_GPIO(MDM2AP_STATUS)) == 0) {
  133. if (mdm_debug_mask & MDM_DEBUG_MASK_SHDN_LOG)
  134. pr_debug("%s:id %d: mdm2ap_statuswent low, i=%d\n",
  135. __func__, mdm_drv->device_id, i);
  136. break;
  137. }
  138. msleep(100);
  139. }
  140. #endif
  141. /* Assert the soft reset line whether mdm2ap_status went low or not */
  142. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET), soft_reset_direction);
  143. if (i == 0) {
  144. pr_debug("%s:id %d: MDM2AP_STATUS never went low. Doing a hard reset\n",
  145. __func__, mdm_drv->device_id);
  146. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET), soft_reset_direction);
  147. }
  148. /*
  149. * Currently, there is a debounce timer on the charm PMIC. It is
  150. * necessary to hold the PMIC RESET low for ~3.5 seconds
  151. * for the reset to fully take place. Sleep here to ensure the
  152. * reset has occured before the function exits.
  153. */
  154. msleep(4000);
  155. }
  156. static void mdm_do_first_power_on(struct mdm_modem_drv *mdm_drv)
  157. {
  158. #ifdef USE_MDM_MODEM
  159. int i;
  160. int pblrdy;
  161. #endif
  162. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET), 0);
  163. gpio_direction_output(MDM_GPIO(AP2MDM_PMIC_PWR_EN), 1);
  164. msleep(10);
  165. if (mdm_drv->power_on_count != 1) {
  166. pr_debug("%s:id %d: Calling fn when power_on_count != 1\n",
  167. __func__, mdm_drv->device_id);
  168. return;
  169. }
  170. pr_err("%s \n", __func__);
  171. pr_err("%s:id %d: Powering on modem for the first time\n",
  172. __func__, mdm_drv->device_id);
  173. mdm_peripheral_disconnect(mdm_drv);
  174. /* If this is the first power-up after a panic, the modem may still
  175. * be in a power-on state, in which case we need to toggle the gpio
  176. * instead of just de-asserting it. No harm done if the modem was
  177. * powered down.
  178. */
  179. if (!mdm_drv->pdata->no_reset_on_first_powerup)
  180. mdm_toggle_soft_reset(mdm_drv);
  181. /* If the device has a kpd pwr gpio then toggle it. */
  182. if (GPIO_IS_VALID(MDM_GPIO(AP2MDM_KPDPWR))) { // HSLEE qsc en
  183. /* Pull AP2MDM_KPDPWR gpio high and wait for PS_HOLD to settle,
  184. * then pull it back low.
  185. */
  186. pr_err("%s:id %d: Pulling AP2MDM_KPDPWR gpio high\n",
  187. __func__, mdm_drv->device_id);
  188. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 1);
  189. //gpio_direction_output(MDM_GPIO(AP2MDM_STATUS), 1);
  190. msleep(1000);
  191. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 0);
  192. }//else
  193. gpio_direction_output(MDM_GPIO(AP2MDM_STATUS), 1);
  194. msleep(5000);
  195. if (!gpio_get_value(MDM_GPIO(MDM2AP_STATUS))) {
  196. pr_err("%s: QSC failed. reboot\n", __func__);
  197. gpio_direction_output(MDM_GPIO(AP2MDM_STATUS), 0);
  198. gpio_direction_output(MDM_GPIO(AP2MDM_PMIC_PWR_EN), 0);
  199. msleep(5000);
  200. gpio_direction_output(MDM_GPIO(AP2MDM_PMIC_PWR_EN), 1);
  201. msleep(10);
  202. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 1);
  203. msleep(1000);
  204. gpio_direction_output(MDM_GPIO(AP2MDM_KPDPWR), 0);
  205. gpio_direction_output(MDM_GPIO(AP2MDM_STATUS), 1);
  206. }
  207. /* check if qsc is in dload mode */
  208. if (gpio_get_value(MDM_GPIO(MDM2AP_ERRFATAL))) {
  209. pr_err("%s: QSC is in dload. reset\n", __func__);
  210. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET), 1);
  211. mdelay(10);
  212. gpio_direction_output(MDM_GPIO(AP2MDM_SOFT_RESET), 0);
  213. }
  214. #ifdef USE_MDM_MODEM
  215. if (!GPIO_IS_VALID(MDM_GPIO(MDM2AP_PBLRDY)))
  216. goto start_mdm_peripheral;
  217. for (i = 0; i < MDM_PBLRDY_CNT; i++) {
  218. pblrdy = gpio_get_value(MDM_GPIO(MDM2AP_PBLRDY));
  219. if (pblrdy)
  220. break;
  221. usleep_range(5000, 5000);
  222. }
  223. pr_info("%s: id %d: pblrdy i:%d\n", __func__,
  224. mdm_drv->device_id, i);
  225. start_mdm_peripheral:
  226. #endif
  227. pr_err("%s %d\n", __func__,__LINE__);
  228. mdm_peripheral_connect(mdm_drv);
  229. msleep(200);
  230. }
  231. static void mdm_do_soft_power_on(struct mdm_modem_drv *mdm_drv)
  232. {
  233. #ifdef USE_MDM_MODEM
  234. int i;
  235. int pblrdy;
  236. #endif
  237. pr_err("%s: id %d: soft resetting mdm modem\n",
  238. __func__, mdm_drv->device_id);
  239. mdm_peripheral_disconnect(mdm_drv);
  240. mdm_toggle_soft_reset(mdm_drv);
  241. #ifdef USE_MDM_MODEM
  242. if (!GPIO_IS_VALID(MDM_GPIO(MDM2AP_PBLRDY)))
  243. goto start_mdm_peripheral;
  244. for (i = 0; i < MDM_PBLRDY_CNT; i++) {
  245. pblrdy = gpio_get_value(MDM_GPIO(MDM2AP_PBLRDY));
  246. if (pblrdy)
  247. break;
  248. usleep_range(5000, 5000);
  249. }
  250. pr_info("%s: id %d: pblrdy i:%d\n", __func__,
  251. mdm_drv->device_id, i);
  252. start_mdm_peripheral:
  253. #endif
  254. mdm_peripheral_connect(mdm_drv);
  255. msleep(200);
  256. }
  257. static void mdm_power_on_common(struct mdm_modem_drv *mdm_drv)
  258. {
  259. mdm_drv->power_on_count++;
  260. /* this gpio will be used to indicate apq readiness,
  261. * de-assert it now so that it can be asserted later.
  262. * May not be used.
  263. */
  264. pr_err("%s \n", __func__);
  265. if (GPIO_IS_VALID(MDM_GPIO(AP2MDM_CHNLRDY)))
  266. gpio_direction_output(MDM_GPIO(AP2MDM_CHNLRDY), 0);
  267. /*
  268. * If we did an "early power on" then ignore the very next
  269. * power-on request because it would the be first request from
  270. * user space but we're already powered on. Ignore it.
  271. */
  272. if (mdm_drv->pdata->early_power_on &&
  273. (mdm_drv->power_on_count == 2))
  274. return;
  275. if(poweroff_charging){
  276. pr_debug("%s: do not power on in lpm\n", __func__);
  277. return;
  278. }
  279. if (mdm_drv->power_on_count == 1)
  280. mdm_do_first_power_on(mdm_drv);
  281. else
  282. mdm_do_soft_power_on(mdm_drv);
  283. }
  284. static void debug_state_changed(int value)
  285. {
  286. mdm_debug_mask = value;
  287. }
  288. static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
  289. {
  290. if (!mdm_drv->pdata->peripheral_platform_device)
  291. return;
  292. pr_debug("%s: id %d: value:%d\n", __func__,
  293. value, mdm_drv->device_id);
  294. if (value) {
  295. mdm_peripheral_disconnect(mdm_drv);
  296. msleep(100);
  297. mdm_peripheral_connect(mdm_drv);
  298. if (GPIO_IS_VALID(MDM_GPIO(AP2MDM_CHNLRDY)))
  299. gpio_direction_output(MDM_GPIO(AP2MDM_CHNLRDY), 0);
  300. }
  301. }
  302. static void mdm_image_upgrade(struct mdm_modem_drv *mdm_drv, int type)
  303. {
  304. switch (type) {
  305. case APQ_CONTROLLED_UPGRADE:
  306. pr_info("%s: id %d: APQ controlled modem image upgrade\n",
  307. __func__, mdm_drv->device_id);
  308. atomic_set(&mdm_drv->mdm_ready, 0);
  309. mdm_toggle_soft_reset(mdm_drv);
  310. break;
  311. case MDM_CONTROLLED_UPGRADE:
  312. pr_info("%s: id %d: MDM controlled modem image upgrade\n",
  313. __func__, mdm_drv->device_id);
  314. atomic_set(&mdm_drv->mdm_ready, 0);
  315. /*
  316. * If we have no image currently present on the modem, then we
  317. * would be in PBL, in which case the status gpio would not go
  318. * high.
  319. */
  320. mdm_drv->disable_status_check = 1;
  321. if (GPIO_IS_VALID(MDM_GPIO(USB_SW))) {
  322. pr_debug("%s: id %d: Switching usb control to MDM\n",
  323. __func__, mdm_drv->device_id);
  324. gpio_direction_output(MDM_GPIO(USB_SW), 1);
  325. } else
  326. pr_err("%s: id %d: usb switch gpio unavailable\n",
  327. __func__, mdm_drv->device_id);
  328. break;
  329. default:
  330. pr_err("%s: id %d: invalid upgrade type\n",
  331. __func__, mdm_drv->device_id);
  332. }
  333. }
  334. static struct mdm_ops mdm_cb = {
  335. .power_on_mdm_cb = mdm_power_on_common,
  336. .reset_mdm_cb = mdm_power_on_common,
  337. .atomic_reset_mdm_cb = mdm_atomic_soft_reset,
  338. .power_down_mdm_cb = mdm_power_down_common,
  339. .debug_state_changed_cb = debug_state_changed,
  340. .status_cb = mdm_status_changed,
  341. .image_upgrade_cb = mdm_image_upgrade,
  342. };
  343. int mdm_get_ops(struct mdm_ops **mdm_ops)
  344. {
  345. *mdm_ops = &mdm_cb;
  346. return 0;
  347. }