sec-dock.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * drivers/usb/core/sec-dock.h
  3. *
  4. * Copyright (C) 2013 Samsung Electronics
  5. * Author: Woo-kwang Lee <wookwang.lee@samsung.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include <linux/power_supply.h>
  13. #ifdef CONFIG_USB_SWITCH_FSA9485
  14. #include <linux/i2c/fsa9485.h>
  15. #endif
  16. #define PSY_CHG_NAME "battery"
  17. #define SMARTDOCK_INDEX 1
  18. #define MMDOCK_INDEX 2
  19. struct dev_table {
  20. struct usb_device_id dev;
  21. int index;
  22. };
  23. static struct dev_table enable_notify_hub_table[] = {
  24. { .dev = { USB_DEVICE(0x0424, 0x2514), },
  25. .index = SMARTDOCK_INDEX,
  26. }, /* SMART DOCK HUB 1 */
  27. { .dev = { USB_DEVICE(0x1a40, 0x0101), },
  28. .index = SMARTDOCK_INDEX,
  29. }, /* SMART DOCK HUB 2 */
  30. { .dev = { USB_DEVICE(0x0424, 0x9512), },
  31. .index = MMDOCK_INDEX,
  32. }, /* SMSC USB LAN HUB 9512 */
  33. {}
  34. };
  35. static struct dev_table essential_device_table[] = {
  36. { .dev = { USB_DEVICE(0x08bb, 0x2704), },
  37. .index = SMARTDOCK_INDEX,
  38. }, /* TI USB Audio DAC 1 */
  39. { .dev = { USB_DEVICE(0x08bb, 0x27c4), },
  40. .index = SMARTDOCK_INDEX,
  41. }, /* TI USB Audio DAC 2 */
  42. { .dev = { USB_DEVICE(0x0424, 0xec00), },
  43. .index = MMDOCK_INDEX,
  44. }, /* SMSC LAN Driver */
  45. {}
  46. };
  47. #ifdef CONFIG_USB_SWITCH_FSA9485
  48. /* real battery driver notification function */
  49. static void set_online(int host_state)
  50. {
  51. struct power_supply *psy = power_supply_get_by_name(PSY_CHG_NAME);
  52. union power_supply_propval value;
  53. if (!psy) {
  54. pr_err("%s: fail to get %s psy\n", __func__, PSY_CHG_NAME);
  55. return;
  56. }
  57. if (host_state)
  58. value.intval = POWER_SUPPLY_TYPE_SMART_OTG;
  59. else
  60. value.intval = POWER_SUPPLY_TYPE_SMART_NOTG;
  61. psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
  62. return;
  63. }
  64. #endif
  65. #ifdef CONFIG_USB_SWITCH_FSA9485
  66. /* real battery driver notification function for mmdock */
  67. static void set_online_mmdock(int host_state)
  68. {
  69. struct power_supply *psy = power_supply_get_by_name(PSY_CHG_NAME);
  70. union power_supply_propval value;
  71. if (!psy) {
  72. pr_err("%s: fail to get %s psy\n", __func__, PSY_CHG_NAME);
  73. return;
  74. }
  75. if (host_state)
  76. value.intval = POWER_SUPPLY_TYPE_SMART_OTG;
  77. else
  78. value.intval = POWER_SUPPLY_TYPE_SMART_NOTG;
  79. psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
  80. return;
  81. }
  82. #endif
  83. static int check_essential_device(struct usb_device *dev, int index)
  84. {
  85. struct dev_table *id;
  86. int ret = 0;
  87. /* check VID, PID */
  88. for (id = essential_device_table; id->dev.match_flags; id++) {
  89. if ((id->dev.match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
  90. (id->dev.match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
  91. id->dev.idVendor == le16_to_cpu(dev->descriptor.idVendor) &&
  92. id->dev.idProduct == le16_to_cpu(dev->descriptor.idProduct) &&
  93. id->index == index) {
  94. ret = 1;
  95. break;
  96. }
  97. }
  98. return ret;
  99. }
  100. static int is_notify_hub(struct usb_device *dev)
  101. {
  102. struct dev_table *id;
  103. struct usb_device *hdev;
  104. int ret = 0;
  105. hdev = dev->parent;
  106. if (!hdev)
  107. goto skip;
  108. /* check VID, PID */
  109. for (id = enable_notify_hub_table; id->dev.match_flags; id++) {
  110. if ((id->dev.match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
  111. (id->dev.match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
  112. id->dev.idVendor == le16_to_cpu(hdev->descriptor.idVendor) &&
  113. id->dev.idProduct == le16_to_cpu(hdev->descriptor.idProduct)) {
  114. ret = (hdev->parent
  115. && (hdev->parent == dev->bus->root_hub)) ? id->index : 0;
  116. break;
  117. }
  118. }
  119. skip:
  120. return ret;
  121. }
  122. static int call_battery_notify(struct usb_device *dev, bool bOnOff)
  123. {
  124. struct usb_device *hdev;
  125. struct usb_device *udev;
  126. int index = 0;
  127. int count = 0;
  128. int port;
  129. index = is_notify_hub(dev);
  130. if (!index)
  131. goto skip;
  132. if (check_essential_device(dev, index))
  133. goto skip;
  134. hdev = dev->parent;
  135. for (port = 1; port <= hdev->maxchild; port++) {
  136. udev = hdev->children [port-1];
  137. if (udev) {
  138. if (!check_essential_device(udev, index)) {
  139. if (!bOnOff && (udev == dev))
  140. continue;
  141. else
  142. count++;
  143. }
  144. }
  145. }
  146. pr_info("%s : VID : 0x%x, PID : 0x%x, bOnOff=%d, count=%d\n", __func__,
  147. dev->descriptor.idVendor, dev->descriptor.idProduct,
  148. bOnOff, count);
  149. #ifdef CONFIG_USB_SWITCH_FSA9485
  150. if (bOnOff) {
  151. if (count == 1) {
  152. if (check_mmdock_connect()) {
  153. if (index == SMARTDOCK_INDEX) {
  154. set_online(1);
  155. pr_info("%s : request smartdock charging current = 1000mA\n", __func__);
  156. } else if (index == MMDOCK_INDEX) {
  157. set_online_mmdock(1);
  158. pr_info("%s : request mmdock charging current = 900mA\n", __func__);
  159. }
  160. }
  161. }
  162. } else {
  163. if (!count) {
  164. if (check_mmdock_connect()) {
  165. if (index == SMARTDOCK_INDEX) {
  166. set_online(0);
  167. pr_info("%s : request smartdock charging current = 1700mA\n", __func__);
  168. } else if (index == MMDOCK_INDEX) {
  169. set_online_mmdock(0);
  170. pr_info("%s : request mmdock charging current = 1400mA\n", __func__);
  171. }
  172. }
  173. }
  174. }
  175. #endif
  176. skip:
  177. return 0;
  178. }