combo_fxla2203_driver.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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_V3\n");
  20. return SSW_EXT_SINGLE_2X2;
  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. SSW_DBG("extern_ssw_init: %d\n", mode);
  126. /*SIM_CH_SWAP */
  127. mt_set_gpio_mode(GPIO_SSW_CH_SWAP_PIN, GPIO_SSW_CH_SWAP_PIN_M_GPIO);
  128. mt_set_gpio_dir(GPIO_SSW_CH_SWAP_PIN, GPIO_DIR_OUT);
  129. /*SIM_ENABLE */
  130. mt_set_gpio_mode(GPIO_SSW_EN_PIN, GPIO_SSW_EN_PIN_M_GPIO);
  131. mt_set_gpio_dir(GPIO_SSW_EN_PIN, GPIO_DIR_OUT);
  132. mt_set_gpio_out(GPIO_SSW_EN_PIN, GPIO_OUT_ONE);
  133. SSW_DBG("extern_ssw_init: ch_swap=(%x %d %d), en=(%x %d %d)\n",
  134. GPIO_SSW_CH_SWAP_PIN, GPIO_SSW_CH_SWAP_PIN_M_GPIO,
  135. mt_get_gpio_out(GPIO_SSW_CH_SWAP_PIN), GPIO_SSW_EN_PIN,
  136. GPIO_SSW_EN_PIN_M_GPIO, mt_get_gpio_out(GPIO_SSW_EN_PIN));
  137. set_ext_sim_gpio(mode);
  138. ext_ssw_mode_curr = mode;
  139. return 0;
  140. }
  141. static int set_sim_gpio(unsigned int mode)
  142. {
  143. SSW_DBG("set_sim_gpio %d\n", mode);
  144. switch (mode) {
  145. case SINGLE_TALK_MDSYS:
  146. set_ext_sim_gpio(SINGLE_TALK_MDSYS);
  147. break;
  148. default:
  149. SSW_DBG("Mode(%d) not supported!!!", mode);
  150. break;
  151. }
  152. return SSW_SUCCESS;
  153. }
  154. static int set_ext_sim_gpio(unsigned int mode)
  155. {
  156. SSW_DBG("set_ext_sim_gpio %d\n", mode);
  157. switch (mode) {
  158. case DUAL_TALK:
  159. mt_set_gpio_out(GPIO_SSW_CH_SWAP_PIN, GPIO_OUT_ZERO);
  160. break;
  161. case DUAL_TALK_SWAP:
  162. mt_set_gpio_out(GPIO_SSW_CH_SWAP_PIN, GPIO_OUT_ONE);
  163. break;
  164. default:
  165. SSW_DBG("Mode(%d) not supported!!!", mode);
  166. return SSW_INVALID_PARA;
  167. }
  168. SSW_DBG("set_ext_sim_gpio: ch_swap=(%x %d %d), en=(%x %d %d)\n",
  169. GPIO_SSW_CH_SWAP_PIN, GPIO_SSW_CH_SWAP_PIN_M_GPIO,
  170. mt_get_gpio_out(GPIO_SSW_CH_SWAP_PIN), GPIO_SSW_EN_PIN,
  171. GPIO_SSW_EN_PIN_M_GPIO, mt_get_gpio_out(GPIO_SSW_EN_PIN));
  172. return SSW_SUCCESS;
  173. }
  174. int get_ext_current_ssw_mode(void)
  175. {
  176. return ext_ssw_mode_curr;
  177. }
  178. int switch_sim_mode(int id, char *buf, unsigned int len)
  179. {
  180. unsigned int mode = *((unsigned int *)buf);
  181. unsigned int type = (mode & 0xFFFF0000) >> 16;
  182. SSW_DBG("switch_sim_mode:mode=0x%x, type=%d\n", mode, type);
  183. mode = mode & 0x0000FFFF;
  184. mutex_lock(&sim_switch_mutex);
  185. if (type == 0) { /*Internal */
  186. SSW_DBG("Internal sim switch: %d --> %d\n", sim_mode_curr,
  187. mode);
  188. if ((sim_mode_curr != mode)
  189. && (SSW_SUCCESS == set_sim_gpio(mode))) {
  190. sim_mode_curr = mode;
  191. }
  192. } else { /*External */
  193. SSW_DBG("External sim switch: %d --> %d\n", ext_ssw_mode_curr,
  194. mode);
  195. if (ext_ssw_mode_curr != mode
  196. && (SSW_SUCCESS == set_ext_sim_gpio(mode))) {
  197. ext_ssw_mode_curr = mode;
  198. }
  199. }
  200. mutex_unlock(&sim_switch_mutex);
  201. SSW_DBG("sim switch sim_mode_curr(%d),ext_ssw_mode_curr(%d) OK\n",
  202. sim_mode_curr, ext_ssw_mode_curr);
  203. return 0;
  204. }
  205. /*To decide sim mode according to compile option*/
  206. static int get_sim_mode_init(void)
  207. {
  208. unsigned int sim_mode = 0;
  209. #if 0
  210. unsigned int md1_enable, md2_enable = 0;
  211. md1_enable = get_modem_is_enabled(MD_SYS1);
  212. md2_enable = get_modem_is_enabled(MD_SYS2);
  213. if (md1_enable) {
  214. sim_mode = SINGLE_TALK_MDSYS;
  215. if (md2_enable)
  216. sim_mode = DUAL_TALK;
  217. } else if (md2_enable)
  218. sim_mode = SINGLE_TALK_MDSYS_LITE;
  219. #endif
  220. return sim_mode;
  221. }
  222. /*sim switch hardware initial*/
  223. static int sim_switch_init(void)
  224. {
  225. SSW_DBG("sim_switch_init\n");
  226. sim_mode_curr = get_sim_mode_init();
  227. if (SSW_SUCCESS != set_sim_gpio(sim_mode_curr)) {
  228. SSW_DBG("sim_switch_init fail\n");
  229. return SSW_INVALID_PARA;
  230. }
  231. extern_ssw_init();
  232. return 0;
  233. }
  234. static int sim_switch_probe(struct platform_device *dev)
  235. {
  236. SSW_DBG("Enter sim_switch_probe\n");
  237. /*move this to sim_switch_driver_init(). Because this function not exceute on device tree branch. */
  238. /*mutex_init(&sim_switch_mutex); */
  239. sim_switch_init();
  240. /*register_ccci_kern_func(ID_SSW_SWITCH_MODE, switch_sim_mode); */
  241. return 0;
  242. }
  243. static int sim_switch_remove(struct platform_device *dev)
  244. {
  245. /*SSW_DBG("sim_switch_remove\n"); */
  246. return 0;
  247. }
  248. static void sim_switch_shutdown(struct platform_device *dev)
  249. {
  250. /*SSW_DBG("sim_switch_shutdown\n"); */
  251. }
  252. static int sim_switch_suspend(struct platform_device *dev, pm_message_t state)
  253. {
  254. /*SSW_DBG("sim_switch_suspend\n"); */
  255. return 0;
  256. }
  257. static int sim_switch_resume(struct platform_device *dev)
  258. {
  259. /*SSW_DBG("sim_switch_resume\n"); */
  260. return 0;
  261. }
  262. static struct platform_driver sim_switch_driver = {
  263. .driver = {
  264. .name = "sim-switch",
  265. },
  266. .probe = sim_switch_probe,
  267. .remove = sim_switch_remove,
  268. .shutdown = sim_switch_shutdown,
  269. .suspend = sim_switch_suspend,
  270. .resume = sim_switch_resume,
  271. };
  272. static int __init sim_switch_driver_init(void)
  273. {
  274. int ret = 0;
  275. SSW_DBG("sim_switch_driver_init\n");
  276. ret = platform_driver_register(&sim_switch_driver);
  277. if (ret) {
  278. SSW_DBG("ssw_driver register fail(%d)\n", ret);
  279. return ret;
  280. }
  281. mutex_init(&sim_switch_mutex);
  282. #if __ENABLE_SSW_SYSFS
  283. ssw_sysfs_init();
  284. #endif
  285. sim_switch_init();
  286. return ret;
  287. }
  288. static void __exit sim_switch_driver_exit(void)
  289. {
  290. }
  291. module_init(sim_switch_driver_init);
  292. module_exit(sim_switch_driver_exit);
  293. MODULE_DESCRIPTION("MTK SIM Switch Driver");
  294. MODULE_AUTHOR("MTK");
  295. MODULE_LICENSE("GPL");