modem_modemctl_device_sc6500.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /* /linux/drivers/misc/modem_if/modem_modemctl_device_sprd6500.c
  2. *
  3. * Copyright (C) 2010 Google, Inc.
  4. * Copyright (C) 2010 Samsung Electronics.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/init.h>
  17. #include <linux/irq.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/gpio.h>
  20. #include <linux/delay.h>
  21. #include <linux/wait.h>
  22. #include <linux/sched.h>
  23. #include <linux/platform_device.h>
  24. #include <mach/gpiomux.h>
  25. #include <linux/platform_data/modem.h>
  26. #include "modem_prj.h"
  27. #include <linux/regulator/consumer.h>
  28. #if defined(CONFIG_LINK_DEVICE_DPRAM)
  29. #include "modem_link_device_dpram.h"
  30. #elif defined(CONFIG_LINK_DEVICE_PLD)
  31. #include "modem_link_device_pld.h"
  32. #elif defined(CONFIG_LINK_DEVICE_SPI)
  33. #include "modem_link_device_spi.h"
  34. #endif
  35. #if 0 //def CONFIG_OF
  36. void sprd6500_modem_cfg_gpio(struct platform_device *pdev);
  37. #endif
  38. #define PIF_TIMEOUT (180 * HZ)
  39. #define DPRAM_INIT_TIMEOUT (30 * HZ)
  40. int sprd_boot_done;
  41. #define GPIO_BT_UART_RTS 48
  42. #define GPIO_BT_UART_CTS 47
  43. #define GPIO_BT_UART_RXD 46
  44. #define GPIO_BT_UART_TXD 45
  45. static unsigned sprd6500_uart_on_table[] = {
  46. GPIO_CFG(GPIO_BT_UART_RTS, 2, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  47. GPIO_CFG_8MA),
  48. GPIO_CFG(GPIO_BT_UART_CTS, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
  49. GPIO_CFG_8MA),
  50. GPIO_CFG(GPIO_BT_UART_RXD, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
  51. GPIO_CFG_8MA),
  52. GPIO_CFG(GPIO_BT_UART_TXD, 2, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  53. GPIO_CFG_8MA),
  54. };
  55. static unsigned sprd6500_uart_off_table[] = {
  56. GPIO_CFG(GPIO_BT_UART_RTS, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  57. GPIO_CFG_8MA),
  58. GPIO_CFG(GPIO_BT_UART_CTS, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  59. GPIO_CFG_8MA),
  60. GPIO_CFG(GPIO_BT_UART_RXD, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  61. GPIO_CFG_8MA),
  62. GPIO_CFG(GPIO_BT_UART_TXD, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
  63. GPIO_CFG_8MA),
  64. };
  65. static int sprd6500_on(struct modem_ctl *mc)
  66. {
  67. int pin = 0;
  68. pr_err("[MODEM_IF:SC6500] <%s> start!!!\n", __func__);
  69. disable_irq(mc->irq_phone_active);
  70. for (pin = 0; pin < ARRAY_SIZE(sprd6500_uart_on_table); pin++) {
  71. gpio_tlmm_config(sprd6500_uart_on_table[pin], GPIO_CFG_ENABLE);
  72. }
  73. // UART_SEL for UART download
  74. gpio_tlmm_config(GPIO_CFG(mc->gpio_uart_sel, GPIOMUX_FUNC_GPIO,
  75. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
  76. GPIO_CFG_ENABLE);
  77. gpio_set_value(mc->gpio_uart_sel, 1);
  78. pr_err("[MODEM_IF:SC6500] <%s> CP On(%d,%d)\n", __func__,
  79. gpio_get_value(mc->gpio_cp_on),
  80. gpio_get_value(mc->gpio_phone_active));
  81. msleep(100);
  82. gpio_tlmm_config(GPIO_CFG(mc->gpio_cp_on, GPIOMUX_FUNC_GPIO,
  83. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
  84. GPIO_CFG_ENABLE);
  85. gpio_set_value(mc->gpio_cp_on, 1);
  86. // msleep(100);
  87. pr_err("[MODEM_IF:SC6500] <%s> IRQ enabled\n", __func__);
  88. pr_err("[MODEM_IF:SC6500] <%s> Active = %d\n", __func__,
  89. gpio_get_value(mc->gpio_phone_active));
  90. enable_irq(mc->irq_phone_active);
  91. // msleep(280);
  92. pr_err("[MODEM_IF:SC6500] <%s> Active = %d\n", __func__,
  93. gpio_get_value(mc->gpio_phone_active));
  94. #if defined(CONFIG_LINK_DEVICE_PLD)
  95. gpio_set_value(GPIO_FPGA_SPI_MOSI, 1);
  96. gpio_set_value(mc->gpio_fpga1_cs_n, 1);
  97. #endif
  98. gpio_set_value(mc->gpio_pda_active, 1);
  99. return 0;
  100. }
  101. static int sprd6500_off(struct modem_ctl *mc)
  102. {
  103. pr_info("[MODEM_IF:SC6500] sprd6500_off()\n");
  104. // UART_SEL for BT
  105. gpio_tlmm_config(GPIO_CFG(mc->gpio_uart_sel, GPIOMUX_FUNC_GPIO,
  106. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
  107. GPIO_CFG_ENABLE);
  108. gpio_set_value(mc->gpio_uart_sel, 0);
  109. gpio_tlmm_config(GPIO_CFG(mc->gpio_cp_on, GPIOMUX_FUNC_GPIO,
  110. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
  111. GPIO_CFG_ENABLE);
  112. gpio_set_value(mc->gpio_cp_on, 0);
  113. mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE);
  114. return 0;
  115. }
  116. static int sprd6500_reset(struct modem_ctl *mc)
  117. {
  118. int ret = 0;
  119. pr_debug("[MODEM_IF:SC6500] sprd6500_reset()\n");
  120. ret = sprd6500_off(mc);
  121. if (ret)
  122. return -ENXIO;
  123. msleep(100);
  124. ret = sprd6500_on(mc);
  125. if (ret)
  126. return -ENXIO;
  127. return 0;
  128. }
  129. int sprd6500_boot_on(struct modem_ctl *mc)
  130. {
  131. int pin, rc = 0;
  132. pr_err("[MODEM_IF:SC6500] <%s> BOOT_ON!!!\n", __func__);
  133. for (pin = 0; pin < ARRAY_SIZE(sprd6500_uart_on_table); pin++) {
  134. rc = gpio_tlmm_config(sprd6500_uart_on_table[pin],
  135. GPIO_CFG_ENABLE);
  136. if (rc < 0)
  137. pr_err("[MODEM_IF:SC6500] %s: gpio_tlmm_config(%#x)=%d\n",
  138. __func__, sprd6500_uart_on_table[pin], rc);
  139. }
  140. // UART_SEL for UART download
  141. gpio_tlmm_config(GPIO_CFG(mc->gpio_uart_sel, GPIOMUX_FUNC_GPIO,
  142. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
  143. GPIO_CFG_ENABLE);
  144. gpio_set_value(mc->gpio_uart_sel, 1);
  145. return 0;
  146. }
  147. static int sprd6500_boot_off(struct modem_ctl *mc)
  148. {
  149. int pin, rc = 0;
  150. pr_info("[MODEM_IF:SC6500] <%s>\n", __func__);
  151. // UART_SEL for BT
  152. gpio_tlmm_config(GPIO_CFG(mc->gpio_uart_sel, GPIOMUX_FUNC_GPIO,
  153. GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
  154. GPIO_CFG_ENABLE);
  155. gpio_set_value(mc->gpio_uart_sel, 0);
  156. for (pin = 0; pin < ARRAY_SIZE(sprd6500_uart_off_table); pin++) {
  157. rc = gpio_tlmm_config(sprd6500_uart_off_table[pin],
  158. GPIO_CFG_ENABLE);
  159. if (rc < 0)
  160. pr_err("[MODEM_IF:SC6500] %s: gpio_tlmm_config(%#x)=%d\n",
  161. __func__, sprd6500_uart_off_table[pin], rc);
  162. }
  163. gpio_set_value(GPIO_BT_UART_RTS, 0);
  164. gpio_set_value(GPIO_BT_UART_CTS, 0);
  165. gpio_set_value(GPIO_BT_UART_RXD, 0);
  166. gpio_set_value(GPIO_BT_UART_TXD, 0);
  167. // mc->iod->modem_state_changed(mc->iod, STATE_OFFLINE);
  168. return 0;
  169. }
  170. static irqreturn_t phone_active_irq_handler(int irq, void *arg)
  171. {
  172. struct modem_ctl *mc = (struct modem_ctl *)arg;
  173. int phone_active = 0;
  174. int phone_state = 0;
  175. int cp_dump_int = 0;
  176. int phone_reset = 0;
  177. if (!mc->gpio_phone_active) { /* || !mc->gpio_cp_dump_int) { */
  178. pr_err("[MODEM_IF:SC6500] no gpio data\n");
  179. return IRQ_HANDLED;
  180. }
  181. phone_active = gpio_get_value(mc->gpio_phone_active);
  182. pr_info("[MODEM_IF:SC6500] <%s> phone_active=%d, cp_dump_int=%d\n",
  183. __func__, phone_active, cp_dump_int);
  184. phone_reset = 1;
  185. if (phone_reset && phone_active) {
  186. phone_state = STATE_ONLINE;
  187. if (mc->iod && mc->iod->modem_state_changed) {
  188. struct spi_link_device *spi_ld =
  189. to_spi_link_device(get_current_link(mc->iod));
  190. mc->iod->modem_state_changed(mc->iod, phone_state);
  191. /* Do after PHONE_ACTIVE High */
  192. // spi_ld->dpram_init_status = DPRAM_INIT_STATE_READY;
  193. spi_ld->spi_state = SPI_STATE_IDLE;
  194. // spi_ld->cmd_phone_start_handler(dpram_ld);
  195. // complete_all(&spi_ld->dpram_init_cmd);
  196. }
  197. } else if (phone_reset && !phone_active) {
  198. if (mc->phone_state == STATE_ONLINE) {
  199. phone_state = STATE_CRASH_EXIT;
  200. if (mc->iod && mc->iod->modem_state_changed)
  201. mc->iod->modem_state_changed(mc->iod,
  202. phone_state);
  203. }
  204. } else {
  205. phone_state = STATE_OFFLINE;
  206. if (mc->iod && mc->iod->modem_state_changed)
  207. mc->iod->modem_state_changed(mc->iod, phone_state);
  208. }
  209. if (phone_active)
  210. irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_LOW);
  211. else
  212. irq_set_irq_type(mc->irq_phone_active, IRQ_TYPE_LEVEL_HIGH);
  213. pr_info("[MODEM_IF::SC6500] <%s> phone_state = %d\n",
  214. __func__, phone_state);
  215. return IRQ_HANDLED;
  216. }
  217. #if defined(CONFIG_SIM_DETECT)
  218. static irqreturn_t sim_detect_irq_handler(int irq, void *_mc)
  219. {
  220. struct modem_ctl *mc = (struct modem_ctl *)_mc;
  221. pr_info("[MODEM_IF:SC6500] <%s> gpio_sim_detect = %d\n",
  222. __func__, gpio_get_value(mc->gpio_sim_detect));
  223. if (mc->iod && mc->iod->sim_state_changed)
  224. mc->iod->sim_state_changed(mc->iod,
  225. !gpio_get_value(mc->gpio_sim_detect));
  226. return IRQ_HANDLED;
  227. }
  228. #endif
  229. static void sprd6500_get_ops(struct modem_ctl *mc)
  230. {
  231. pr_err("[MODEM_IF:SC6500] <%s> start\n", __func__);
  232. mc->ops.modem_on = sprd6500_on;
  233. mc->ops.modem_off = sprd6500_off;
  234. mc->ops.modem_reset = sprd6500_reset;
  235. mc->ops.modem_boot_on = sprd6500_boot_on;
  236. mc->ops.modem_boot_off = sprd6500_boot_off;
  237. }
  238. int sprd6500_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata)
  239. {
  240. int ret = 0;
  241. struct platform_device *pdev;
  242. pr_err("[MODEM_IF:SC6500] <%s> start\n", __func__);
  243. pdev = to_platform_device(mc->dev);
  244. #if 0 //def CONFIG_OF
  245. sprd6500_modem_cfg_gpio(pdev);
  246. #endif
  247. mc->gpio_cp_on = pdata->gpio_cp_on;
  248. mc->gpio_pda_active = pdata->gpio_pda_active;
  249. mc->gpio_phone_active = pdata->gpio_phone_active;
  250. mc->gpio_cp_dump_int = pdata->gpio_cp_dump_int;
  251. mc->gpio_sim_detect = pdata->gpio_sim_detect;
  252. mc->gpio_ap_cp_int1 = pdata->gpio_ap_cp_int1;
  253. mc->gpio_ap_cp_int2 = pdata->gpio_ap_cp_int2;
  254. mc->gpio_uart_sel = pdata->gpio_uart_sel;
  255. #ifdef CONFIG_SEC_DUAL_MODEM_MODE
  256. mc->gpio_sim_sel = pdata->gpio_sim_sel;
  257. #endif
  258. #if defined(CONFIG_LINK_DEVICE_PLD)
  259. mc->gpio_fpga1_cs_n = pdata->gpio_fpga1_cs_n;
  260. #endif
  261. gpio_set_value(mc->gpio_cp_on, 0);
  262. mc->irq_phone_active = platform_get_irq_byname(pdev, "cp_active_irq");
  263. pr_info("[MODEM_IF:SC6500] <%s> PHONE_ACTIVE IRQ# = %d\n",
  264. __func__, mc->irq_phone_active);
  265. sprd6500_get_ops(mc);
  266. if (mc->irq_phone_active) {
  267. ret = request_irq(mc->irq_phone_active,
  268. phone_active_irq_handler,
  269. IRQF_TRIGGER_HIGH,
  270. "esc_active",
  271. mc);
  272. if (ret) {
  273. pr_err("[MODEM_IF:SC6500] <%s> failed to request_irq IRQ# %d (err=%d)\n",
  274. __func__, mc->irq_phone_active, ret);
  275. dump_stack();
  276. return ret;
  277. }
  278. #if 1 // don't enable wake option in temp
  279. enable_irq(mc->irq_phone_active);
  280. #else
  281. ret = enable_irq_wake(mc->irq_phone_active);
  282. if (ret) {
  283. pr_err("[MODEM_IF:SC6500] %s: failed to enable_irq_wake IRQ# %d (err=%d)\n",
  284. __func__, mc->irq_phone_active, ret);
  285. free_irq(mc->irq_phone_active, mc);
  286. return ret;
  287. }
  288. #endif
  289. }
  290. #if defined(CONFIG_SIM_DETECT)
  291. mc->irq_sim_detect = platform_get_irq_byname(pdev, "sim_irq");
  292. pr_info("[MODEM_IF:SC6500] <%s> SIM_DECTCT IRQ# = %d\n",
  293. __func__, mc->irq_sim_detect);
  294. if (mc->irq_sim_detect) {
  295. ret = request_irq(mc->irq_sim_detect, sim_detect_irq_handler,
  296. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  297. "esc_sim_detect", mc);
  298. if (ret) {
  299. mif_err("failed to request_irq: %d\n", ret);
  300. mc->sim_state.online = false;
  301. mc->sim_state.changed = false;
  302. return ret;
  303. }
  304. ret = enable_irq_wake(mc->irq_sim_detect);
  305. if (ret) {
  306. mif_err("failed to enable_irq_wake: %d\n", ret);
  307. free_irq(mc->irq_sim_detect, mc);
  308. mc->sim_state.online = false;
  309. mc->sim_state.changed = false;
  310. return ret;
  311. }
  312. /* initialize sim_state => insert: gpio=0, remove: gpio=1 */
  313. mc->sim_state.online = !gpio_get_value(mc->gpio_sim_detect);
  314. }
  315. #endif
  316. return ret;
  317. }