msm_otg_sec.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * drivers/usb/otg/msm_otg_sec.c
  3. *
  4. * Copyright (c) 2013, Samsung Electronics
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 and
  8. * only version 2 as published by the Free Software Foundation.
  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/gpio.h>
  17. #include <linux/host_notify.h>
  18. #ifdef CONFIG_USB_SWITCH_FSA9485
  19. #include <linux/i2c/fsa9485.h>
  20. #endif
  21. #ifdef CONFIG_MFD_MAX77693
  22. #include <linux/mfd/max77693.h>
  23. #endif
  24. #ifdef pr_fmt
  25. #undef pr_fmt
  26. #endif
  27. #define pr_fmt(fmt) "otg %s %d: " fmt, __func__, __LINE__
  28. static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg);
  29. static int ulpi_read(struct usb_phy *phy, u32 reg);
  30. static void msm_hsusb_vbus_power(struct msm_otg *motg, bool on);
  31. #if defined(CONFIG_MUIC_SM5502_SUPPORT_LANHUB_TA)
  32. extern bool lanhub_ta_case;
  33. #endif
  34. #ifdef CONFIG_EXTCON_MAX77804K
  35. extern int muic_otg_control(int enable);
  36. #endif
  37. #ifndef CONFIG_EXTCON_MAX77804K
  38. int sec_battery_otg_control(int enable)
  39. {
  40. union power_supply_propval value;
  41. struct power_supply *psy;
  42. int current_cable_type;
  43. int ret = 0;
  44. pr_info("%s: enable(%d)\n", __func__, enable);
  45. psy = power_supply_get_by_name("battery");
  46. if (!psy) {
  47. pr_err("%s: ERROR! failed to get battery!\n", __func__);
  48. return -1;
  49. }
  50. #if defined(CONFIG_MUIC_SM5502_SUPPORT_LANHUB_TA)
  51. if (enable) {
  52. current_cable_type = lanhub_ta_case ? POWER_SUPPLY_TYPE_LAN_HUB : POWER_SUPPLY_TYPE_OTG;
  53. pr_info("%s: LANHUB+TA Case cable type change for the (%d) \n",
  54. __func__,current_cable_type);
  55. }
  56. #else
  57. if (enable)
  58. current_cable_type = POWER_SUPPLY_TYPE_OTG;
  59. #endif
  60. else
  61. current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
  62. value.intval = current_cable_type;
  63. ret = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
  64. if (ret) {
  65. pr_err("%s: fail to set power_suppy ONLINE property(%d)\n",
  66. __func__, ret);
  67. }
  68. return ret;
  69. }
  70. #endif
  71. struct booster_data sec_booster_batt = {
  72. .name = "sec_battery",
  73. #ifdef CONFIG_EXTCON_MAX77804K
  74. .boost = muic_otg_control,
  75. #else
  76. .boost = sec_battery_otg_control,
  77. #endif
  78. };
  79. int msm_otg_sec_power(bool on)
  80. {
  81. int ret = 0;
  82. pr_info("msm_otg_sec_power: %d\n", on);
  83. #if defined(CONFIG_MFD_MAX77693) || defined(CONFIG_EXTCON_MAX77804K)
  84. muic_otg_control(on);
  85. #else
  86. ret = sec_battery_otg_control(on);
  87. #endif
  88. return ret;
  89. }
  90. static void msm_otg_late_power_work(struct work_struct *w)
  91. {
  92. struct msm_otg *motg = container_of((struct delayed_work *)w,
  93. struct msm_otg, late_power_work);
  94. int booster = sec_get_notification(HNOTIFY_BOOSTER);
  95. pr_info("%s, ID=%d, booster=%d\n", __func__,
  96. test_bit(ID, &motg->inputs), booster);
  97. if (!test_bit(ID, &motg->inputs) && (booster == NOTIFY_POWER_OFF)) {
  98. msm_hsusb_vbus_power(motg, 0);
  99. msleep(100);
  100. msm_hsusb_vbus_power(motg, 1);
  101. }
  102. }
  103. static void msm_otg_host_phy_tune(struct msm_otg *otg,
  104. u32 paramb, u32 paramc, u32 paramd)
  105. {
  106. pr_info("ULPI 0x%x: 0x%x: 0x%x: 0x%x - orig\n",
  107. ulpi_read(&otg->phy, 0x80),
  108. ulpi_read(&otg->phy, 0x81),
  109. ulpi_read(&otg->phy, 0x82),
  110. ulpi_read(&otg->phy, 0x83));
  111. ulpi_write(&otg->phy, paramb, 0x81);
  112. ulpi_write(&otg->phy, paramc, 0x82);
  113. ulpi_write(&otg->phy, paramd, 0x83);
  114. pr_info("ULPI 0x%x: 0x%x: 0x%x: 0x%x\n",
  115. ulpi_read(&otg->phy, 0x80),
  116. ulpi_read(&otg->phy, 0x81),
  117. ulpi_read(&otg->phy, 0x82),
  118. ulpi_read(&otg->phy, 0x83));
  119. mdelay(100);
  120. }
  121. static int msm_otg_host_notify_set(struct msm_otg *motg, int state)
  122. {
  123. pr_info("boost : %d\n", state);
  124. if (state)
  125. sec_otg_notify(HNOTIFY_OTG_POWER_ON);
  126. else
  127. sec_otg_notify(HNOTIFY_OTG_POWER_OFF);
  128. return state;
  129. }
  130. static void msm_otg_host_notify(struct msm_otg *motg, int on)
  131. {
  132. pr_info("host_notify: %d, dock %d\n", on, motg->smartdock);
  133. if (on)
  134. msm_otg_host_phy_tune(motg, 0x33, 0xB, 0x13);
  135. }
  136. static int msm_host_notify_init(struct device *dev, struct msm_otg *motg)
  137. {
  138. sec_otg_register_booster(&sec_booster_batt);
  139. INIT_DELAYED_WORK(&motg->late_power_work, msm_otg_late_power_work);
  140. return 0;
  141. }
  142. static int msm_host_notify_exit(struct device *dev, struct msm_otg *motg)
  143. {
  144. cancel_delayed_work_sync(&motg->late_power_work);
  145. return 0;
  146. }
  147. /*
  148. * Exported functions
  149. */
  150. void sec_otg_set_dock_state(int enable)
  151. {
  152. struct msm_otg *motg = the_msm_otg;
  153. struct usb_phy *phy = &motg->phy;
  154. if (enable) {
  155. pr_info("DOCK : attached\n");
  156. motg->smartdock = true;
  157. clear_bit(ID, &motg->inputs);
  158. if (atomic_read(&motg->in_lpm)) {
  159. pr_info("DOCK : in LPM\n");
  160. pm_runtime_resume(phy->dev);
  161. }
  162. if (test_bit(B_SESS_VLD, &motg->inputs)) {
  163. pr_info("clear B_SESS_VLD\n");
  164. clear_bit(B_SESS_VLD, &motg->inputs);
  165. }
  166. /* use use non-reentrant wq, so that we don't run sm_work on multiple cpus */
  167. queue_work(system_nrt_wq, &motg->sm_work);
  168. } else {
  169. pr_info("DOCK : detached\n");
  170. motg->smartdock = false;
  171. set_bit(ID, &motg->inputs);
  172. }
  173. }
  174. EXPORT_SYMBOL(sec_otg_set_dock_state);
  175. void sec_otg_set_id_state(int id)
  176. {
  177. struct msm_otg *motg = the_msm_otg;
  178. struct usb_phy *phy = &motg->phy;
  179. pr_info("msm_otg_set_id_state is called, ID : %d\n", id);
  180. if (id)
  181. set_bit(ID, &motg->inputs);
  182. else
  183. clear_bit(ID, &motg->inputs);
  184. if (atomic_read(&motg->in_lpm)) {
  185. pr_info("msm_otg_set_id_state : in LPM\n");
  186. pm_runtime_resume(phy->dev);
  187. }
  188. /* defer work-handling until pm_resume callback is handled */
  189. if (motg->phy.state != OTG_STATE_UNDEFINED) {
  190. if (atomic_read(&motg->pm_suspended))
  191. motg->sm_work_pending = true;
  192. else
  193. /* use use non-reentrant wq, so that we don't run sm_work on multiple cpus */
  194. queue_work(system_nrt_wq, &motg->sm_work);
  195. }
  196. }
  197. EXPORT_SYMBOL(sec_otg_set_id_state);
  198. void msm_otg_set_smartdock_state(bool online)
  199. {
  200. struct msm_otg *motg = the_msm_otg;
  201. if (online) {
  202. dev_info(motg->phy.dev, "SMARTDOCK : ID set\n");
  203. motg->smartdock = false;
  204. set_bit(ID, &motg->inputs);
  205. } else {
  206. dev_info(motg->phy.dev, "SMARTDOCK : ID clear\n");
  207. motg->smartdock = true;
  208. clear_bit(ID, &motg->inputs);
  209. }
  210. if (test_bit(B_SESS_VLD, &motg->inputs))
  211. clear_bit(B_SESS_VLD, &motg->inputs);
  212. if (atomic_read(&motg->pm_suspended))
  213. motg->sm_work_pending = true;
  214. else
  215. queue_work(system_nrt_wq, &motg->sm_work);
  216. }
  217. EXPORT_SYMBOL_GPL(msm_otg_set_smartdock_state);
  218. int sec_handle_event(int enable)
  219. {
  220. sec_otg_set_id_state(!enable);
  221. return 0;
  222. }
  223. EXPORT_SYMBOL(sec_handle_event);