c2k_hw.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #include <linux/gpio.h>
  2. #include <linux/interrupt.h>
  3. #include "c2k_hw.h"
  4. /*#if defined(CONFIG_MTK_C2K_SUPPORT)*/
  5. #include <linux/interrupt.h>
  6. #include <linux/irq.h>
  7. #if defined(CONFIG_MTK_LEGACY)
  8. #include <cust_eint.h>
  9. #else
  10. /*#include <mach/eint.h>*/
  11. #endif
  12. /*config the gpio to be input for irq if the SOC need*/
  13. int c2k_gpio_direction_input_for_irq(int gpio)
  14. {
  15. #ifdef CONFIG_EVDO_DT_VIA_SUPPORT
  16. switch (gpio) {
  17. case GPIO_C2K_MDM_RST_IND:
  18. mt_set_gpio_mode(gpio, GPIO_VIA_MDM_RST_IND_M_EINT);
  19. break;
  20. case GPIO_C2K_SDIO_DATA_ACK:
  21. mt_set_gpio_mode(gpio, GPIO_VIA_SDIO_ACK_M_EINT);
  22. break;
  23. case GPIO_C2K_SDIO_FLOW_CTRL:
  24. mt_set_gpio_mode(gpio, GPIO_VIA_FLOW_CTRL_M_EINT);
  25. break;
  26. case GPIO_C2K_SDIO_MDM_WAKE_AP:
  27. mt_set_gpio_mode(gpio, GPIO_VIA_MDM_WAKE_AP_M_EINT);
  28. break;
  29. case GPIO_C2K_SDIO_MDM_RDY:
  30. mt_set_gpio_mode(gpio, GPIO_VIA_MDM_RDY_M_EINT);
  31. break;
  32. }
  33. mt_set_gpio_dir(gpio, GPIO_DIR_IN);
  34. #endif
  35. return 0;
  36. }
  37. /*this routine will not be called unless GPIO is valid. So don't worry.*/
  38. int c2k_gpio_direction_output(int gpio, int value)
  39. {
  40. #ifdef CONFIG_EVDO_DT_VIA_SUPPORT
  41. mt_set_gpio_mode(gpio, GPIO_MODE_GPIO);
  42. mt_set_gpio_dir(gpio, GPIO_DIR_OUT);
  43. mt_set_gpio_out(gpio, !!value);
  44. #endif
  45. return 0;
  46. }
  47. int c2k_gpio_get_value(int gpio)
  48. {
  49. #ifdef CONFIG_EVDO_DT_VIA_SUPPORT
  50. if (GPIO_DIR_IN == mt_get_gpio_dir(gpio))
  51. return mt_get_gpio_in(gpio);
  52. else
  53. return mt_get_gpio_out(gpio);
  54. #else
  55. return c2k_gpio_get_ls(gpio);
  56. #endif
  57. }
  58. struct mtk_c2k_gpio_des {
  59. int gpio;
  60. int irq;
  61. unsigned int deb_en;
  62. unsigned int pol;
  63. void (*redirect)(void);
  64. irq_handler_t handle;
  65. void *data;
  66. #ifndef CONFIG_EVDO_DT_VIA_SUPPORT
  67. unsigned int irq_type;
  68. /*
  69. in order to save the current EINT line status,
  70. because there is no way to directly get internal EINT line status.
  71. */
  72. unsigned int eint_ls;
  73. #endif
  74. };
  75. static void gpio_irq_handle_sdio_mdm_rdy(void);
  76. static void gpio_irq_handle_sdio_mdm_wake_ap(void);
  77. static void gpio_irq_handle_rst_ind(void);
  78. static void gpio_irq_handle_data_ack(void);
  79. static void gpio_irq_handle_flow_crtl(void);
  80. #ifndef CONFIG_EVDO_DT_VIA_SUPPORT
  81. static void gpio_irq_handle_excp(void);
  82. #endif
  83. #ifdef CONFIG_EVDO_DT_VIA_SUPPORT
  84. struct mtk_c2k_gpio_des c2k_gpio_list[] = {
  85. {GPIO_C2K_SDIO_MDM_RDY, CUST_EINT_EVDO_DT_EXT_MDM_RDY_NUM,
  86. CUST_EINT_EVDO_DT_EXT_MDM_RDY_DEBOUNCE_EN, 2,
  87. gpio_irq_handle_sdio_mdm_rdy, NULL, NULL},
  88. {GPIO_C2K_SDIO_MDM_WAKE_AP, CUST_EINT_EVDO_DT_EXT_MDM_WAKE_AP_NUM,
  89. CUST_EINT_EVDO_DT_EXT_MDM_WAKE_AP_DEBOUNCE_EN, 2,
  90. gpio_irq_handle_sdio_mdm_wake_ap, NULL, NULL},
  91. {GPIO_C2K_MDM_RST_IND, CUST_EINT_EVDO_DT_EXT_MDM_RST_IND_NUM,
  92. CUST_EINT_EVDO_DT_EXT_MDM_RST_IND_DEBOUNCE_EN, 2,
  93. gpio_irq_handle_rst_ind, NULL, NULL},
  94. {GPIO_C2K_SDIO_DATA_ACK, CUST_EINT_EVDO_DT_EXT_MDM_ACK_NUM,
  95. CUST_EINT_EVDO_DT_EXT_MDM_ACK_DEBOUNCE_EN, 2,
  96. gpio_irq_handle_data_ack, NULL, NULL},
  97. {GPIO_C2K_SDIO_FLOW_CTRL, CUST_EINT_EVDO_DT_EXT_MDM_FLOW_CTRL_NUM,
  98. CUST_EINT_EVDO_DT_EXT_MDM_FLOW_CTRL_DEBOUNCE_EN, 1,
  99. gpio_irq_handle_flow_crtl, NULL, NULL},
  100. };
  101. #else
  102. struct mtk_c2k_gpio_des c2k_gpio_list[] = {
  103. /*gpio irq deb_en, pol, resirect, handle, data, eint_ls */
  104. {GPIO_C2K_SDIO_MDM_RDY, GPIO_C2K_SDIO_MDM_RDY, 0, 2,
  105. gpio_irq_handle_sdio_mdm_rdy, NULL, NULL, IRQ_TYPE_EDGE_FALLING, 1},
  106. {GPIO_C2K_SDIO_MDM_WAKE_AP, GPIO_C2K_SDIO_MDM_WAKE_AP, 0, 2,
  107. gpio_irq_handle_sdio_mdm_wake_ap, NULL, NULL, IRQ_TYPE_EDGE_FALLING,
  108. 1},
  109. {GPIO_C2K_MDM_RST_IND, GPIO_C2K_MDM_RST_IND, 0, 2,
  110. gpio_irq_handle_rst_ind, NULL, NULL, IRQ_TYPE_EDGE_FALLING, 1},
  111. {GPIO_C2K_SDIO_DATA_ACK, GPIO_C2K_SDIO_DATA_ACK, 0, 2,
  112. gpio_irq_handle_data_ack, NULL, NULL, IRQ_TYPE_EDGE_FALLING, 1},
  113. {GPIO_C2K_SDIO_FLOW_CTRL, GPIO_C2K_SDIO_FLOW_CTRL, 0, 1,
  114. gpio_irq_handle_flow_crtl, NULL, NULL, IRQ_TYPE_EDGE_RISING, 1},
  115. {GPIO_C2K_EXCEPTION, GPIO_C2K_EXCEPTION, 0, 2, gpio_irq_handle_excp,
  116. NULL, NULL, IRQ_TYPE_EDGE_FALLING, 1},
  117. };
  118. #endif
  119. static struct mtk_c2k_gpio_des *gpio_des_find_by_gpio(int gpio)
  120. {
  121. int i = 0;
  122. struct mtk_c2k_gpio_des *des = NULL;
  123. /*if(gpio < 0){
  124. return NULL;
  125. } */
  126. for (i = 0; i < sizeof(c2k_gpio_list) / sizeof(struct mtk_c2k_gpio_des);
  127. i++) {
  128. des = c2k_gpio_list + i;
  129. if (des->gpio == gpio)
  130. return des;
  131. }
  132. return NULL;
  133. }
  134. static struct mtk_c2k_gpio_des *gpio_des_find_by_irq(int irq)
  135. {
  136. int i = 0;
  137. struct mtk_c2k_gpio_des *des = NULL;
  138. for (i = 0; i < sizeof(c2k_gpio_list) / sizeof(struct mtk_c2k_gpio_des);
  139. i++) {
  140. des = c2k_gpio_list + i;
  141. if (des->irq == irq)
  142. return des;
  143. }
  144. return NULL;
  145. }
  146. static void gpio_irq_handle_sdio_mdm_rdy(void)
  147. {
  148. struct mtk_c2k_gpio_des *des = NULL;
  149. des = gpio_des_find_by_gpio(GPIO_C2K_SDIO_MDM_RDY);
  150. if (des && des->handle)
  151. des->handle(des->irq, des->data);
  152. }
  153. static void gpio_irq_handle_sdio_mdm_wake_ap(void)
  154. {
  155. struct mtk_c2k_gpio_des *des = NULL;
  156. des = gpio_des_find_by_gpio(GPIO_C2K_SDIO_MDM_WAKE_AP);
  157. if (des && des->handle)
  158. des->handle(des->irq, des->data);
  159. }
  160. static void gpio_irq_handle_rst_ind(void)
  161. {
  162. struct mtk_c2k_gpio_des *des = NULL;
  163. des = gpio_des_find_by_gpio(GPIO_C2K_MDM_RST_IND);
  164. if (des && des->handle)
  165. des->handle(des->irq, des->data);
  166. }
  167. static void gpio_irq_handle_data_ack(void)
  168. {
  169. struct mtk_c2k_gpio_des *des = NULL;
  170. des = gpio_des_find_by_gpio(GPIO_C2K_SDIO_DATA_ACK);
  171. if (des && des->handle)
  172. des->handle(des->irq, des->data);
  173. }
  174. static void gpio_irq_handle_flow_crtl(void)
  175. {
  176. struct mtk_c2k_gpio_des *des = NULL;
  177. des = gpio_des_find_by_gpio(GPIO_C2K_SDIO_FLOW_CTRL);
  178. if (des && des->handle)
  179. des->handle(des->irq, des->data);
  180. }
  181. int c2k_gpio_to_irq(int gpio)
  182. {
  183. struct mtk_c2k_gpio_des *des = NULL;
  184. des = gpio_des_find_by_gpio(gpio);
  185. if (NULL == des) {
  186. pr_debug("%s: no irq for gpio %d\n", __func__, gpio);
  187. return -1;
  188. }
  189. #if defined(CONFIG_MTK_LEGACY)
  190. return des->irq;
  191. #else
  192. des->irq = mt_gpio_to_irq(gpio);
  193. return des->irq;
  194. #endif
  195. }
  196. int c2k_irq_to_gpio(int irq)
  197. {
  198. struct mtk_c2k_gpio_des *des = NULL;
  199. des = gpio_des_find_by_irq(irq);
  200. if (NULL == des) {
  201. pr_debug("%s: no gpio for irq %d\n", __func__, irq);
  202. return -1;
  203. } else {
  204. return des->gpio;
  205. }
  206. }
  207. #ifndef CONFIG_EVDO_DT_VIA_SUPPORT
  208. static void gpio_irq_handle_excp(void)
  209. {
  210. struct mtk_c2k_gpio_des *des = NULL;
  211. des = gpio_des_find_by_gpio(GPIO_C2K_EXCEPTION);
  212. if (des && des->handle)
  213. des->handle(des->irq, des->data);
  214. }
  215. int c2k_irq_set_type(int irq, unsigned int type)
  216. {
  217. struct mtk_c2k_gpio_des *des = NULL;
  218. des = gpio_des_find_by_irq(irq);
  219. if (NULL == des) {
  220. pr_debug("%s: no gpio for irq %d\n", __func__, irq);
  221. return -1;
  222. }
  223. des->irq_type = type;
  224. /*pr_debug("[C2K]set irq(%d) type %d\n", irq, type); */
  225. return 0;
  226. }
  227. int c2k_gpio_get_irq_type(int gpio)
  228. {
  229. struct mtk_c2k_gpio_des *des = NULL;
  230. des = gpio_des_find_by_gpio(gpio);
  231. if (NULL == des) {
  232. pr_debug("%s: no irqtype for gpio %d\n", __func__, gpio);
  233. return -1;
  234. } else {
  235. return des->irq_type;
  236. }
  237. }
  238. int c2k_gpio_set_ls(int gpio, unsigned int ls)
  239. {
  240. struct mtk_c2k_gpio_des *des = NULL;
  241. des = gpio_des_find_by_gpio(gpio);
  242. if (NULL == des) {
  243. pr_debug("%s: no des for gpio %d\n", __func__, gpio);
  244. return -1;
  245. }
  246. des->eint_ls = ls;
  247. return 0;
  248. }
  249. int c2k_gpio_get_ls(int gpio)
  250. {
  251. struct mtk_c2k_gpio_des *des = NULL;
  252. des = gpio_des_find_by_gpio(gpio);
  253. if (NULL == des) {
  254. pr_debug("%s: no des for gpio %d\n", __func__, gpio);
  255. return -1;
  256. } else {
  257. return des->eint_ls;
  258. }
  259. }
  260. int c2k_gpio_to_ls(int gpio)
  261. {
  262. struct mtk_c2k_gpio_des *des = NULL;
  263. des = gpio_des_find_by_gpio(gpio);
  264. if (NULL == des) {
  265. pr_debug("%s: no des for gpio %d\n", __func__, gpio);
  266. return -1;
  267. }
  268. if (des->irq_type == IRQ_TYPE_EDGE_FALLING)
  269. /*
  270. irq triggerred by edge falling interrupt,
  271. so line status should be low
  272. */
  273. des->eint_ls = 0;
  274. else if (des->irq_type == IRQ_TYPE_EDGE_RISING)
  275. /*
  276. irq triggerred by edge rising interrupt,
  277. so line status should be high
  278. */
  279. des->eint_ls = 1;
  280. else if (des->irq_type == IRQ_TYPE_LEVEL_LOW)
  281. des->eint_ls = 0;
  282. else if (des->irq_type == IRQ_TYPE_LEVEL_HIGH)
  283. des->eint_ls = 1;
  284. /*pr_debug("[C2K]gpio(%d) ls(%d)", gpio, des->eint_ls); */
  285. return des->eint_ls;
  286. }
  287. int c2k_ap_ready_indicate(int value)
  288. {
  289. if (value != 0 && value != 1) {
  290. pr_debug("%s: invalid para %d\n", __func__, value);
  291. return -1;
  292. }
  293. set_ap_ready(value);
  294. return 0;
  295. }
  296. int c2k_ap_wake_cp(int value)
  297. {
  298. if (value != 0 && value != 1) {
  299. pr_debug("%s: invalid para %d\n", __func__, value);
  300. return -1;
  301. }
  302. set_ap_wake_cp(value);
  303. return 0;
  304. }
  305. #endif
  306. int c2k_gpio_set_irq_type(int gpio, unsigned int type)
  307. {
  308. int irq, level;
  309. irq = c2k_gpio_to_irq(gpio);
  310. if (irq < 0)
  311. return irq;
  312. level = c2k_gpio_get_value(gpio);
  313. if (type == IRQ_TYPE_EDGE_BOTH) {
  314. if (level)
  315. type = IRQ_TYPE_EDGE_FALLING;
  316. else
  317. type = IRQ_TYPE_EDGE_RISING;
  318. }
  319. if (type == IRQ_TYPE_LEVEL_MASK) {
  320. if (level)
  321. type = IRQ_TYPE_LEVEL_LOW;
  322. else
  323. type = IRQ_TYPE_LEVEL_HIGH;
  324. }
  325. #ifndef CONFIG_EVDO_DT_VIA_SUPPORT
  326. c2k_irq_set_type(irq, type);
  327. #endif
  328. #if defined(CONFIG_MTK_LEGACY)
  329. mt_eint_set_hw_debounce(irq, 0);
  330. switch (type) {
  331. case IRQ_TYPE_EDGE_RISING:
  332. mt_eint_set_sens(irq, MT_EDGE_SENSITIVE);
  333. mt_eint_set_polarity(irq, MT_POLARITY_HIGH);
  334. break;
  335. case IRQ_TYPE_EDGE_FALLING:
  336. mt_eint_set_sens(irq, MT_EDGE_SENSITIVE);
  337. mt_eint_set_polarity(irq, MT_POLARITY_LOW);
  338. break;
  339. case IRQ_TYPE_LEVEL_HIGH:
  340. mt_eint_set_sens(irq, MT_LEVEL_SENSITIVE);
  341. mt_eint_set_polarity(irq, MT_POLARITY_HIGH);
  342. break;
  343. case IRQ_TYPE_LEVEL_LOW:
  344. mt_eint_set_sens(irq, MT_LEVEL_SENSITIVE);
  345. mt_eint_set_polarity(irq, MT_POLARITY_LOW);
  346. break;
  347. default:
  348. return -EINVAL;
  349. }
  350. #else
  351. irq_set_irq_type(irq, type);
  352. #endif
  353. /*pr_debug("[C2K]set irq(%d) type(%d) done\n", irq, type); */
  354. return 0;
  355. }
  356. int c2k_gpio_request_irq(int gpio, irq_handler_t handler, unsigned long flags,
  357. const char *name, void *dev)
  358. {
  359. struct mtk_c2k_gpio_des *des = NULL;
  360. int ret = 0;
  361. des = gpio_des_find_by_gpio(gpio);
  362. if (des == NULL)
  363. return -1;
  364. des->data = dev;
  365. des->handle = handler;
  366. #if defined(CONFIG_MTK_LEGACY)
  367. pr_debug("[C2K] c2k_gpio_request_irq eintnum %d\n", des->irq);
  368. /*mt_eint_registration(des->irq, des->deb_en, des->pol, des->redirect, 0); */
  369. mt_eint_registration(des->irq, des->pol, des->redirect, 0);
  370. #else
  371. pr_info("[C2K] c2k_gpio_request_irq gpio %d irq %d\n", gpio, des->irq);
  372. /*mt_eint_registration(des->irq, des->pol, des->redirect, 0); */
  373. ret = request_irq(des->irq, handler, flags, name, dev);
  374. if (ret)
  375. pr_err("[C2K] request irq fail\n");
  376. #endif
  377. return 0;
  378. }
  379. void c2k_gpio_irq_mask(int gpio)
  380. {
  381. int irq;
  382. irq = c2k_gpio_to_irq(gpio);
  383. if (irq < 0)
  384. return;
  385. #if defined(CONFIG_MTK_LEGACY)
  386. mt_eint_mask(irq);
  387. #else
  388. disable_irq_nosync(irq);
  389. #endif
  390. }
  391. void c2k_gpio_irq_unmask(int gpio)
  392. {
  393. int irq;
  394. irq = c2k_gpio_to_irq(gpio);
  395. if (irq < 0)
  396. return;
  397. #if defined(CONFIG_MTK_LEGACY)
  398. mt_eint_unmask(irq);
  399. #else
  400. enable_irq(irq);
  401. #endif
  402. }
  403. /*#endif*/
  404. void c2k_reset_tx_gpio_ready(int gpio)
  405. {
  406. struct mtk_c2k_gpio_des *des;
  407. des = gpio_des_find_by_gpio(gpio);
  408. des->eint_ls = 1;
  409. des->irq_type = IRQ_TYPE_EDGE_FALLING;
  410. c2k_gpio_set_irq_type(gpio, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING);
  411. }