combo_fxla2203_driver.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include <ssw.h>
  2. #include <mach/mt_ccci_common.h>
  3. #include "cust_gpio_usage.h"
  4. /*--------------Feature option---------------*/
  5. #define __ENABLE_SSW_SYSFS 1
  6. /*--------------SIM mode list----------------*/
  7. #define SINGLE_TALK_MDSYS (0x1)
  8. #define SINGLE_TALK_MDSYS_LITE (0x2)
  9. #define DUAL_TALK (0x3)
  10. #define DUAL_TALK_SWAP (0x4)
  11. static unsigned int ext_ssw_mode_curr = DUAL_TALK;
  12. static unsigned int sim_mode_curr = SINGLE_TALK_MDSYS;
  13. struct mutex sim_switch_mutex;
  14. static int set_sim_gpio(unsigned int mode);
  15. static int set_ext_sim_gpio(unsigned int mode);
  16. static int get_ext_current_ssw_mode(void);
  17. unsigned int get_sim_switch_type(void)
  18. {
  19. SSW_DBG("[ccci/ssw]COMBO_FXLA2203_V2\n");
  20. return SSW_EXT_DUAL_1X2;
  21. }
  22. /*---------------------------------------------------------------------------*/
  23. /*define sysfs entry for configuring debug level and sysrq*/
  24. ssize_t ssw_attr_show(struct kobject *kobj, struct attribute *attr,
  25. char *buffer)
  26. {
  27. struct ssw_sys_entry *entry =
  28. container_of(attr, struct ssw_sys_entry, attr);
  29. return entry->show(kobj, buffer);
  30. }
  31. ssize_t ssw_attr_store(struct kobject *kobj, struct attribute *attr,
  32. const char *buffer, size_t size)
  33. {
  34. struct ssw_sys_entry *entry =
  35. container_of(attr, struct ssw_sys_entry, attr);
  36. return entry->store(kobj, buffer, size);
  37. }
  38. ssize_t ssw_mode_show(struct kobject *kobj, char *buffer)
  39. {
  40. int remain = PAGE_SIZE;
  41. int len;
  42. char *ptr = buffer;
  43. len = scnprintf(ptr, remain, "0x%x\n", get_ext_current_ssw_mode());
  44. ptr += len;
  45. remain -= len;
  46. SSW_DBG("ssw_mode_show\n");
  47. return PAGE_SIZE - remain;
  48. }
  49. ssize_t ssw_mode_store(struct kobject *kobj, const char *buffer, size_t size)
  50. {
  51. unsigned int mode;
  52. int res = kstrtoint(buffer, 0, &mode);
  53. unsigned int type;
  54. if (res != 1) {
  55. SSW_DBG("%s: expect 1 numbers\n", __func__);
  56. } else {
  57. SSW_DBG("ssw_mode_store %x\n", mode);
  58. /*Switch sim mode */
  59. type = (mode & 0xFFFF0000) >> 16;
  60. mode = mode & 0x0000FFFF;
  61. if (type == 0) { /*Internal */
  62. SSW_DBG("Internal sim switch: %d-->%d\n", sim_mode_curr,
  63. mode);
  64. if ((sim_mode_curr != mode)
  65. && (SSW_SUCCESS == set_sim_gpio(mode))) {
  66. sim_mode_curr = mode;
  67. }
  68. } else {
  69. SSW_DBG("External sim switch: %d-->%d\n",
  70. ext_ssw_mode_curr, mode);
  71. if (ext_ssw_mode_curr != mode
  72. && (SSW_SUCCESS == set_ext_sim_gpio(mode))) {
  73. ext_ssw_mode_curr = mode;
  74. }
  75. }
  76. }
  77. return size;
  78. }
  79. const struct sysfs_ops ssw_sysfs_ops = {
  80. .show = ssw_attr_show,
  81. .store = ssw_attr_store,
  82. };
  83. struct ssw_sys_entry {
  84. struct attribute attr;
  85. ssize_t (*show)(struct kobject *kobj, char *page);
  86. ssize_t (*store)(struct kobject *kobj, const char *page, size_t size);
  87. };
  88. static struct ssw_sys_entry mode_entry = {
  89. {.name = "mode", .mode = S_IRUGO | S_IWUSR}, /*remove .owner = NULL, */
  90. ssw_mode_show,
  91. ssw_mode_store,
  92. };
  93. struct attribute *ssw_attributes[] = {
  94. &mode_entry.attr,
  95. NULL,
  96. };
  97. struct kobj_type ssw_ktype = {
  98. .sysfs_ops = &ssw_sysfs_ops,
  99. .default_attrs = ssw_attributes,
  100. };
  101. static struct ssw_sysobj_t {
  102. struct kobject kobj;
  103. } ssw_sysobj;
  104. int ssw_sysfs_init(void)
  105. {
  106. struct ssw_sysobj_t *obj = &ssw_sysobj;
  107. memset(&obj->kobj, 0x00, sizeof(obj->kobj));
  108. obj->kobj.parent = kernel_kobj;
  109. if (kobject_init_and_add(&obj->kobj, &ssw_ktype, NULL, "mtk_ssw")) {
  110. kobject_put(&obj->kobj);
  111. return -ENOMEM;
  112. }
  113. kobject_uevent(&obj->kobj, KOBJ_ADD);
  114. return 0;
  115. }
  116. /*---------------------------------------------------------------------------*/
  117. /*************************************************************************/
  118. /*external sim switch hardware operation */
  119. /**/
  120. /*************************************************************************/
  121. /*Exteranl sim switch hardware initial*/
  122. static int extern_ssw_init(void)
  123. {
  124. unsigned int mode = DUAL_TALK;
  125. #ifdef CONFIG_MTK_ENABLE_MD1
  126. mode = SINGLE_TALK_MDSYS;
  127. #ifdef CONFIG_MTK_ENABLE_MD5
  128. mode = DUAL_TALK;
  129. #endif
  130. #elif defined CONFIG_MTK_ENABLE_MD5
  131. mode = SINGLE_TALK_MDSYS_LITE;
  132. #endif
  133. SSW_DBG("extern_ssw_init: %d\n", mode);
  134. /*initial sim1 select pin: 1, host1->sim slot1; 0, host2->sim slot1 */
  135. mt_set_gpio_mode(GPIO_EXT_SSW_S1, GPIO_EXT_SSW_S1_M_GPIO);
  136. mt_set_gpio_dir(GPIO_EXT_SSW_S1, GPIO_DIR_OUT);
  137. /*initial sim2 select pin: 1, host1->sim slot2; 0, host2->sim slot2 */
  138. mt_set_gpio_mode(GPIO_EXT_SSW_S2, GPIO_EXT_SSW_S2_M_GPIO);
  139. mt_set_gpio_dir(GPIO_EXT_SSW_S2, GPIO_DIR_OUT);
  140. /*initial EN pin: 1, enable sim slot; 0, disable sim slot */
  141. mt_set_gpio_mode(GPIO_EXT_SSW_EN, GPIO_EXT_SSW_EN_M_GPIO);
  142. mt_set_gpio_dir(GPIO_EXT_SSW_EN, GPIO_DIR_OUT);
  143. mt_set_gpio_out(GPIO_EXT_SSW_EN, GPIO_OUT_ONE); /*SIM_ENABLE */
  144. SSW_DBG("GPIO_EXT_SSW_EN(%d, %d , %d)\n",
  145. GPIO_EXT_SSW_EN, mt_get_gpio_mode(GPIO_EXT_SSW_EN),
  146. mt_get_gpio_out(GPIO_EXT_SSW_EN));
  147. set_ext_sim_gpio(mode);
  148. ext_ssw_mode_curr = mode;
  149. return 0;
  150. }
  151. static int set_sim_gpio(unsigned int mode)
  152. {
  153. SSW_DBG("set_sim_gpio %d\n", mode);
  154. switch (mode) {
  155. case SINGLE_TALK_MDSYS:
  156. set_ext_sim_gpio(SINGLE_TALK_MDSYS);
  157. break;
  158. default:
  159. SSW_DBG("Mode(%d) not supported!!!", mode);
  160. break;
  161. }
  162. return SSW_SUCCESS;
  163. }
  164. static int set_ext_sim_gpio(unsigned int mode)
  165. {
  166. SSW_DBG("set_ext_sim_gpio %d\n", mode);
  167. switch (mode) {
  168. case SINGLE_TALK_MDSYS:
  169. mt_set_gpio_out(GPIO_EXT_SSW_S1, GPIO_OUT_ONE); /*SIM1_SELECT */
  170. mt_set_gpio_out(GPIO_EXT_SSW_S2, GPIO_OUT_ONE); /*SIM2_SELECT */
  171. break;
  172. case SINGLE_TALK_MDSYS_LITE:
  173. mt_set_gpio_out(GPIO_EXT_SSW_S1, GPIO_OUT_ZERO); /*SIM1_SELECT */
  174. mt_set_gpio_out(GPIO_EXT_SSW_S2, GPIO_OUT_ZERO); /*SIM2_SELECT */
  175. break;
  176. case DUAL_TALK:
  177. mt_set_gpio_out(GPIO_EXT_SSW_S1, GPIO_OUT_ONE); /*SIM1_SELECT */
  178. mt_set_gpio_out(GPIO_EXT_SSW_S2, GPIO_OUT_ZERO); /*SIM2_SELECT */
  179. break;
  180. case DUAL_TALK_SWAP:
  181. mt_set_gpio_out(GPIO_EXT_SSW_S1, GPIO_OUT_ZERO); /*SIM1_SELECT */
  182. mt_set_gpio_out(GPIO_EXT_SSW_S2, GPIO_OUT_ONE); /*SIM2_SELECT */
  183. break;
  184. default:
  185. SSW_DBG("Mode(%d) not supported!!!", mode);
  186. return SSW_INVALID_PARA;
  187. }
  188. SSW_DBG
  189. ("Current sim mode(%d), GPIO_EXT_SSW_S1(%d, %d , %d),
  190. GPIO_EXT_SSW_S2(%d, %d , %d), GPIO_EXT_SSW_EN(%d, %d , %d)\n",
  191. mode, GPIO_EXT_SSW_S1, mt_get_gpio_mode(GPIO_EXT_SSW_S1),
  192. mt_get_gpio_out(GPIO_EXT_SSW_S1), GPIO_EXT_SSW_S2,
  193. mt_get_gpio_mode(GPIO_EXT_SSW_S2),
  194. mt_get_gpio_out(GPIO_EXT_SSW_S2), GPIO_EXT_SSW_EN,
  195. mt_get_gpio_mode(GPIO_EXT_SSW_EN),
  196. mt_get_gpio_out(GPIO_EXT_SSW_EN));
  197. return SSW_SUCCESS;
  198. }
  199. int get_ext_current_ssw_mode(void)
  200. {
  201. return ext_ssw_mode_curr;
  202. }
  203. int switch_sim_mode(int id, char *buf, unsigned int len)
  204. {
  205. unsigned int mode = *((unsigned int *)buf);
  206. unsigned int type = (mode & 0xFFFF0000) >> 16;
  207. SSW_DBG("switch_sim_mode:mode=0x%x, type=%d\n", mode, type);
  208. mode = mode & 0x0000FFFF;
  209. mutex_lock(&sim_switch_mutex);
  210. if (type == 0) { /*Internal */
  211. SSW_DBG("Internal sim switch: %d --> %d\n", sim_mode_curr,
  212. mode);
  213. if ((sim_mode_curr != mode)
  214. && (SSW_SUCCESS == set_sim_gpio(mode))) {
  215. sim_mode_curr = mode;
  216. }
  217. } else { /*External */
  218. SSW_DBG("External sim switch: %d --> %d\n", ext_ssw_mode_curr,
  219. mode);
  220. if (ext_ssw_mode_curr != mode
  221. && (SSW_SUCCESS == set_ext_sim_gpio(mode))) {
  222. ext_ssw_mode_curr = mode;
  223. }
  224. }
  225. mutex_unlock(&sim_switch_mutex);
  226. SSW_DBG("sim switch sim_mode_curr(%d),ext_ssw_mode_curr(%d) OK\n",
  227. sim_mode_curr, ext_ssw_mode_curr);
  228. return 0;
  229. }
  230. /*To decide sim mode according to compile option*/
  231. static int get_sim_mode_init(void)
  232. {
  233. unsigned int sim_mode = 0;
  234. #if 0
  235. unsigned int md1_enable, md2_enable = 0;
  236. md1_enable = get_modem_is_enabled(MD_SYS1);
  237. md2_enable = get_modem_is_enabled(MD_SYS2);
  238. if (md1_enable) {
  239. sim_mode = SINGLE_TALK_MDSYS;
  240. if (md2_enable)
  241. sim_mode = DUAL_TALK;
  242. } else if (md2_enable)
  243. sim_mode = SINGLE_TALK_MDSYS_LITE;
  244. #endif
  245. return sim_mode;
  246. }
  247. /*sim switch hardware initial*/
  248. static int sim_switch_init(void)
  249. {
  250. SSW_DBG("sim_switch_init\n");
  251. sim_mode_curr = get_sim_mode_init();
  252. if (SSW_SUCCESS != set_sim_gpio(sim_mode_curr)) {
  253. SSW_DBG("sim_switch_init fail\n");
  254. return SSW_INVALID_PARA;
  255. }
  256. extern_ssw_init();
  257. return 0;
  258. }
  259. static int sim_switch_probe(struct platform_device *dev)
  260. {
  261. SSW_DBG("Enter sim_switch_probe\n");
  262. /*move this to sim_switch_driver_init(). Because this function not exceute on device tree branch. */
  263. /*mutex_init(&sim_switch_mutex); */
  264. sim_switch_init();
  265. /*register_ccci_kern_func(ID_SSW_SWITCH_MODE, switch_sim_mode); */
  266. return 0;
  267. }
  268. static int sim_switch_remove(struct platform_device *dev)
  269. {
  270. /*SSW_DBG("sim_switch_remove\n"); */
  271. return 0;
  272. }
  273. static void sim_switch_shutdown(struct platform_device *dev)
  274. {
  275. /*SSW_DBG("sim_switch_shutdown\n"); */
  276. }
  277. static int sim_switch_suspend(struct platform_device *dev, pm_message_t state)
  278. {
  279. /*SSW_DBG("sim_switch_suspend\n"); */
  280. return 0;
  281. }
  282. static int sim_switch_resume(struct platform_device *dev)
  283. {
  284. /*SSW_DBG("sim_switch_resume\n"); */
  285. return 0;
  286. }
  287. static struct platform_driver sim_switch_driver = {
  288. .driver = {
  289. .name = "sim-switch",
  290. },
  291. .probe = sim_switch_probe,
  292. .remove = sim_switch_remove,
  293. .shutdown = sim_switch_shutdown,
  294. .suspend = sim_switch_suspend,
  295. .resume = sim_switch_resume,
  296. };
  297. static int __init sim_switch_driver_init(void)
  298. {
  299. int ret = 0;
  300. SSW_DBG("sim_switch_driver_init\n");
  301. ret = platform_driver_register(&sim_switch_driver);
  302. if (ret) {
  303. SSW_DBG("ssw_driver register fail(%d)\n", ret);
  304. return ret;
  305. }
  306. mutex_init(&sim_switch_mutex);
  307. #if __ENABLE_SSW_SYSFS
  308. ssw_sysfs_init();
  309. #endif
  310. sim_switch_init();
  311. return ret;
  312. }
  313. static void __exit sim_switch_driver_exit(void)
  314. {
  315. }
  316. module_init(sim_switch_driver_init);
  317. module_exit(sim_switch_driver_exit);
  318. MODULE_DESCRIPTION("MTK SIM Switch Driver");
  319. MODULE_AUTHOR("MTK");
  320. MODULE_LICENSE("GPL");