musbfsh_icusb.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /*
  2. * ICUSB - for MUSB Host Driver
  3. *
  4. * Copyright 2015 Mediatek Inc.
  5. * Marvin Lin <marvin.lin@mediatek.com>
  6. * Arvin Wang <arvin.wang@mediatek.com>
  7. * Vincent Fan <vincent.fan@mediatek.com>
  8. * Bryant Lu <bryant.lu@mediatek.com>
  9. * Yu-Chang Wang <yu-chang.wang@mediatek.com>
  10. * Macpaul Lin <macpaul.lin@mediatek.com>
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * version 2 as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program.
  23. *
  24. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  25. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  27. * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  29. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  30. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  31. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  33. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. #include <linux/kernel.h>
  36. #include <linux/slab.h>
  37. #include <linux/module.h>
  38. #include <linux/init.h>
  39. #include <linux/usb/input.h>
  40. #include <linux/hid.h>
  41. #include <linux/proc_fs.h>
  42. #include <linux/uaccess.h>
  43. #include <net/sock.h>
  44. #include <net/netlink.h>
  45. #include <linux/skbuff.h>
  46. /*
  47. * Version Information
  48. */
  49. #define DRIVER_VERSION ""
  50. #define DRIVER_AUTHOR ""
  51. #define DRIVER_DESC "USB ICUSB DRIVER"
  52. #define DRIVER_LICENSE "GPL"
  53. MODULE_AUTHOR(DRIVER_AUTHOR);
  54. MODULE_DESCRIPTION(DRIVER_DESC);
  55. MODULE_LICENSE(DRIVER_LICENSE);
  56. #define ICCD_INTERFACE_CLASS 0x0B
  57. #define ICCD_CLASS_DESCRIPTOR_LENGTH (0x36)
  58. #include "usb.h"
  59. #include "musbfsh_icusb.h"
  60. struct usb_icusb {
  61. char name[128];
  62. };
  63. struct my_attr power_resume_time_neogo_attr = {
  64. .attr.name = "power_resume_time_neogo",
  65. .attr.mode = 0644,
  66. #ifdef MTK_ICUSB_POWER_AND_RESUME_TIME_NEOGO_SUPPORT
  67. .value = 1
  68. #else
  69. .value = 0
  70. #endif
  71. };
  72. static struct my_attr my_attr_test = {
  73. .attr.name = "my_attr_test",
  74. .attr.mode = 0644,
  75. .value = 1
  76. };
  77. static struct attribute *myattr[] = {
  78. (struct attribute *)&my_attr_test,
  79. (struct attribute *)&power_resume_time_neogo_attr,
  80. (struct attribute *)&skip_session_req_attr,
  81. (struct attribute *)&skip_enable_session_attr,
  82. (struct attribute *)&skip_mac_init_attr,
  83. (struct attribute *)&resistor_control_attr,
  84. (struct attribute *)&hw_dbg_attr,
  85. (struct attribute *)&skip_port_pm_attr,
  86. NULL
  87. };
  88. static struct IC_USB_CMD ic_cmd;
  89. unsigned int g_ic_usb_status =
  90. ((USB_PORT1_DISCONNECT_DONE) << USB_PORT1_STS_SHIFT);
  91. static struct sock *netlink_sock;
  92. static u_int g_pid;
  93. static struct proc_dir_entry *proc_drv_icusb_dir_entry;
  94. static void icusb_dump_data(char *buf, int len);
  95. static void set_icusb_phy_power_negotiation_fail(void);
  96. static void set_icusb_phy_power_negotiation_ok(void);
  97. static void set_icusb_data_of_interface_power_request(short data);
  98. static void icusb_resume_time_negotiation(struct usb_device *dev)
  99. {
  100. int ret;
  101. int retries = IC_USB_RETRIES_RESUME_TIME_NEGOTIATION;
  102. char resume_time_negotiation_data[IC_USB_LEN_RESUME_TIME_NEGOTIATION];
  103. while (retries-- > 0) {
  104. MYDBG("");
  105. ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  106. IC_USB_REQ_GET_INTERFACE_RESUME_TIME,
  107. IC_USB_REQ_TYPE_GET_INTERFACE_RESUME_TIME,
  108. IC_USB_WVALUE_RESUME_TIME_NEGOTIATION,
  109. IC_USB_WINDEX_RESUME_TIME_NEGOTIATION,
  110. resume_time_negotiation_data,
  111. IC_USB_LEN_RESUME_TIME_NEGOTIATION,
  112. USB_CTRL_GET_TIMEOUT);
  113. if (ret < 0) {
  114. MYDBG("ret : %d\n", ret);
  115. continue;
  116. } else {
  117. MYDBG("");
  118. icusb_dump_data(resume_time_negotiation_data,
  119. IC_USB_LEN_RESUME_TIME_NEGOTIATION);
  120. break;
  121. }
  122. }
  123. }
  124. void icusb_power_negotiation(struct usb_device *dev)
  125. {
  126. int ret;
  127. int retries = IC_USB_RETRIES_POWER_NEGOTIATION;
  128. char get_power_negotiation_data[IC_USB_LEN_POWER_NEGOTIATION];
  129. char set_power_negotiation_data[IC_USB_LEN_POWER_NEGOTIATION];
  130. int power_negotiation_done = 0;
  131. enum PHY_VOLTAGE_TYPE phy_volt;
  132. while (retries-- > 0) {
  133. MYDBG("");
  134. power_negotiation_done = 0;
  135. ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  136. IC_USB_REQ_GET_IFACE_POWER,
  137. IC_USB_REQ_TYPE_GET_IFACE_POWER,
  138. IC_USB_WVALUE_POWER_NEGOTIATION,
  139. IC_USB_WINDEX_POWER_NEGOTIATION,
  140. get_power_negotiation_data,
  141. IC_USB_LEN_POWER_NEGOTIATION,
  142. USB_CTRL_GET_TIMEOUT);
  143. if (ret < 0) {
  144. MYDBG("ret : %d\n", ret);
  145. continue;
  146. } else {
  147. MYDBG("");
  148. icusb_dump_data(get_power_negotiation_data,
  149. IC_USB_LEN_POWER_NEGOTIATION);
  150. /* copy the prefer bit from get interface power */
  151. set_power_negotiation_data[0] =
  152. (get_power_negotiation_data[0] &
  153. IC_USB_PREFER_CLASSB_ENABLE_BIT);
  154. /* set our current voltage */
  155. phy_volt = get_usb11_phy_voltage();
  156. if (phy_volt == VOL_33)
  157. set_power_negotiation_data[0] |=
  158. (char)IC_USB_CLASSB;
  159. else if (phy_volt == VOL_18)
  160. set_power_negotiation_data[0] |=
  161. (char)IC_USB_CLASSC;
  162. else
  163. MYDBG("");
  164. /* set current */
  165. if (set_power_negotiation_data[1] > IC_USB_CURRENT) {
  166. MYDBG("");
  167. set_power_negotiation_data[1] = IC_USB_CURRENT;
  168. } else {
  169. MYDBG("");
  170. set_power_negotiation_data[1] =
  171. get_power_negotiation_data[1];
  172. }
  173. MYDBG("power_negotiation_data[0] : 0x%x",
  174. set_power_negotiation_data[0]);
  175. MYDBG("power_negotiation_data[1] : 0x%x",
  176. set_power_negotiation_data[1]);
  177. MYDBG("IC_USB_CURRENT :%d\n", IC_USB_CURRENT);
  178. ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  179. IC_USB_REQ_SET_IFACE_POWER,
  180. IC_USB_REQ_TYPE_SET_IFACE_POWER,
  181. IC_USB_WVALUE_POWER_NEGOTIATION,
  182. IC_USB_WINDEX_POWER_NEGOTIATION,
  183. set_power_negotiation_data,
  184. IC_USB_LEN_POWER_NEGOTIATION,
  185. USB_CTRL_SET_TIMEOUT);
  186. if (ret < 0) {
  187. MYDBG("ret : %d\n", ret);
  188. } else {
  189. MYDBG("");
  190. power_negotiation_done = 1;
  191. break;
  192. }
  193. /* break; */
  194. }
  195. }
  196. MYDBG("retries : %d\n", retries);
  197. if (!power_negotiation_done) {
  198. set_icusb_phy_power_negotiation_fail();
  199. } else {
  200. set_icusb_data_of_interface_power_request(
  201. *((short *)get_power_negotiation_data));
  202. set_icusb_phy_power_negotiation_ok();
  203. }
  204. }
  205. void usb11_wait_disconnect_done(int value)
  206. {
  207. if (is_usb11_enabled()) {
  208. while (1) {
  209. unsigned int ic_usb_status = g_ic_usb_status;
  210. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  211. ic_usb_status &=
  212. (USB_PORT1_STS_MSK << USB_PORT1_STS_SHIFT);
  213. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  214. if (ic_usb_status ==
  215. (USB_PORT1_DISCONNECT_DONE <<
  216. USB_PORT1_STS_SHIFT)) {
  217. MYDBG("USB_PORT1_DISCONNECT_DONE\n");
  218. break;
  219. }
  220. if (ic_usb_status ==
  221. (USB_PORT1_DISCONNECTING <<
  222. USB_PORT1_STS_SHIFT))
  223. MYDBG("USB_PORT1_DISCONNECTING\n");
  224. mdelay(10);
  225. }
  226. } else {
  227. MYDBG("usb11 is not enabled, skip\n");
  228. MYDBG("usb11_wait_disconnect_done()\n");
  229. }
  230. }
  231. int check_usb11_sts_disconnect_done(void)
  232. {
  233. unsigned int ic_usb_status = g_ic_usb_status;
  234. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  235. ic_usb_status &= (USB_PORT1_STS_MSK << USB_PORT1_STS_SHIFT);
  236. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  237. if (ic_usb_status ==
  238. (USB_PORT1_DISCONNECT_DONE << USB_PORT1_STS_SHIFT)) {
  239. MYDBG("USB_PORT1_DISCONNECT_DONE got\n");
  240. return 1;
  241. } else {
  242. return 0;
  243. }
  244. }
  245. void set_usb11_sts_connect(void)
  246. {
  247. MYDBG("...................");
  248. g_ic_usb_status &= ~(USB_PORT1_STS_MSK << USB_PORT1_STS_SHIFT);
  249. g_ic_usb_status |= ((USB_PORT1_CONNECT) << USB_PORT1_STS_SHIFT);
  250. }
  251. void set_usb11_sts_disconnecting(void)
  252. {
  253. MYDBG("...................");
  254. g_ic_usb_status &= ~(USB_PORT1_STS_MSK << USB_PORT1_STS_SHIFT);
  255. g_ic_usb_status |= ((USB_PORT1_DISCONNECTING) << USB_PORT1_STS_SHIFT);
  256. }
  257. void set_icusb_sts_disconnect_done(void)
  258. {
  259. MYDBG("...................");
  260. g_ic_usb_status &= ~(USB_PORT1_STS_MSK << USB_PORT1_STS_SHIFT);
  261. g_ic_usb_status |= ((USB_PORT1_DISCONNECT_DONE) << USB_PORT1_STS_SHIFT);
  262. }
  263. void set_icusb_data_of_interface_power_request(short data)
  264. {
  265. MYDBG("...................");
  266. g_ic_usb_status |= ((data) << PREFER_VOL_CLASS_SHIFT);
  267. }
  268. void reset_usb11_phy_power_negotiation_status(void)
  269. {
  270. MYDBG("...................");
  271. g_ic_usb_status &= ~(PREFER_VOL_STS_MSK << PREFER_VOL_STS_SHIFT);
  272. g_ic_usb_status |= ((PREFER_VOL_NOT_INITED) << PREFER_VOL_STS_SHIFT);
  273. }
  274. void set_icusb_phy_power_negotiation_fail(void)
  275. {
  276. MYDBG("...................");
  277. g_ic_usb_status &= ~(PREFER_VOL_STS_MSK << PREFER_VOL_STS_SHIFT);
  278. g_ic_usb_status |= ((PREFER_VOL_PWR_NEG_FAIL) << PREFER_VOL_STS_SHIFT);
  279. }
  280. void set_icusb_phy_power_negotiation_ok(void)
  281. {
  282. MYDBG("...................");
  283. g_ic_usb_status &= ~(PREFER_VOL_STS_MSK << PREFER_VOL_STS_SHIFT);
  284. g_ic_usb_status |= ((PREFER_VOL_PWR_NEG_OK) << PREFER_VOL_STS_SHIFT);
  285. }
  286. void usb11_phy_prefer_3v_status_check(void)
  287. {
  288. unsigned int ic_usb_status = g_ic_usb_status;
  289. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  290. ic_usb_status &= (PREFER_VOL_STS_MSK << PREFER_VOL_STS_SHIFT);
  291. MYDBG("ic_usb_status : %x\n", ic_usb_status);
  292. }
  293. void icusb_dump_data(char *buf, int len)
  294. {
  295. int i;
  296. for (i = 0; i < len; i++)
  297. MYDBG("data[%d]: %x\n", i, buf[i]);
  298. }
  299. int usb11_init_phy_by_voltage(enum PHY_VOLTAGE_TYPE phy_volt)
  300. {
  301. musbfsh_init_phy_by_voltage(phy_volt);
  302. return 0;
  303. }
  304. int usb11_session_control(enum SESSION_CONTROL_ACTION action)
  305. {
  306. if (action == START_SESSION)
  307. musbfsh_start_session();
  308. else if (action == STOP_SESSION) {
  309. /* musbfsh_stop_session(); */
  310. if (!is_usb11_enabled()) {
  311. mt65xx_usb11_mac_reset_and_phy_stress_set();
  312. } else {
  313. MYDBG("usb11 has been enabled, skip");
  314. MYDBG("mt65xx_usb11_mac_reset_and_phy_stress_set()\n");
  315. }
  316. } else
  317. MYDBG("unknown action\n");
  318. return 0;
  319. }
  320. static void udp_reply(int pid, int seq, void *payload)
  321. {
  322. struct sk_buff *skb;
  323. struct nlmsghdr *nlh;
  324. int size = strlen(payload) + 1;
  325. int len = NLMSG_SPACE(size);
  326. void *data;
  327. int ret;
  328. skb = alloc_skb(len, GFP_ATOMIC);
  329. if (!skb)
  330. return;
  331. /* 3.10 specific */
  332. nlh = __nlmsg_put(skb, pid, seq, 0, size, 0);
  333. nlh->nlmsg_flags = 0;
  334. data = NLMSG_DATA(nlh);
  335. memcpy(data, payload, size);
  336. /* 3.10 specific */
  337. NETLINK_CB(skb).portid = 0; /* from kernel */
  338. NETLINK_CB(skb).dst_group = 0; /* unicast */
  339. ret = netlink_unicast(netlink_sock, skb, pid, MSG_DONTWAIT);
  340. if (ret < 0)
  341. MYDBG("send failed\n");
  342. return;
  343. #if 0
  344. nlmsg_failure: /* Used by NLMSG_PUT */
  345. if (skb)
  346. kfree_skb(skb);
  347. #endif
  348. }
  349. /* Receive messages from netlink socket. */
  350. static void udp_receive(struct sk_buff *skb)
  351. {
  352. kuid_t uid,
  353. u_int seq;
  354. void *data;
  355. struct nlmsghdr *nlh;
  356. char reply_data[16];
  357. MYDBG("");
  358. nlh = (struct nlmsghdr *)skb->data;
  359. /* global here */
  360. g_pid = NETLINK_CREDS(skb)->pid;
  361. uid = NETLINK_CREDS(skb)->uid;
  362. seq = nlh->nlmsg_seq;
  363. data = NLMSG_DATA(nlh);
  364. MYDBG("recv skb from user space pid:%d seq:%d\n",
  365. g_pid, seq);
  366. MYDBG("data is :%s\n", (char *)data);
  367. sprintf(reply_data, "%d", g_pid);
  368. udp_reply(g_pid, 0, reply_data);
  369. }
  370. struct netlink_kernel_cfg nl_cfg = {
  371. .input = udp_receive,
  372. };
  373. static ssize_t default_show(struct kobject *kobj, struct attribute *attr,
  374. char *buf)
  375. {
  376. struct my_attr *a = container_of(attr, struct my_attr, attr);
  377. return scnprintf(buf, PAGE_SIZE, "%d\n", a->value);
  378. }
  379. static ssize_t default_store(struct kobject *kobj, struct attribute *attr,
  380. const char *buf, size_t len)
  381. {
  382. struct my_attr *a = container_of(attr, struct my_attr, attr);
  383. int result = kstrtoul(buf, 0, (unsigned long *)&a->value);
  384. if (result)
  385. return sizeof(int);
  386. else
  387. return -EINVAL;
  388. }
  389. static const struct sysfs_ops myops = {
  390. .show = default_show,
  391. .store = default_store,
  392. };
  393. static struct kobj_type mytype = {
  394. .sysfs_ops = &myops,
  395. .default_attrs = myattr,
  396. };
  397. struct kobject *mykobj;
  398. void create_icusb_sysfs_attr(void)
  399. {
  400. int err = -1;
  401. mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
  402. if (mykobj) {
  403. MYDBG("");
  404. kobject_init(mykobj, &mytype);
  405. if (kobject_add(mykobj, NULL, "%s", "icusb_attr")) {
  406. err = -1;
  407. MYDBG("Sysfs creation failed\n");
  408. kobject_put(mykobj);
  409. mykobj = NULL;
  410. }
  411. err = 0;
  412. }
  413. return;
  414. }
  415. static ssize_t musbfsh_ic_tmp_proc_entry(struct file *file_ptr,
  416. const char __user *user_buffer,
  417. size_t count, loff_t *position)
  418. {
  419. char cmd[64];
  420. int ret = copy_from_user((char *)&cmd, user_buffer, count);
  421. if (ret != 0)
  422. return -EFAULT;
  423. if (cmd[0] == '4') {
  424. MYDBG("");
  425. udp_reply(g_pid, 0, "HELLO, SS7_IC_USB!!!");
  426. }
  427. MYDBG("");
  428. return count;
  429. }
  430. const struct file_operations musbfsh_ic_tmp_proc_fops = {
  431. .write = musbfsh_ic_tmp_proc_entry
  432. };
  433. void create_ic_tmp_entry(void)
  434. {
  435. struct proc_dir_entry *pr_entry;
  436. if (NULL == proc_drv_icusb_dir_entry) {
  437. MYDBG("[%s]: /proc/driver/icusb not exist\n", __func__);
  438. return;
  439. }
  440. pr_entry =
  441. proc_create("IC_TMP_ENTRY", 0660, proc_drv_icusb_dir_entry,
  442. &musbfsh_ic_tmp_proc_fops);
  443. if (pr_entry)
  444. MYDBG("add /proc/IC_TMP_ENTRY ok\n");
  445. else
  446. MYDBG("add /proc/IC_TMP_ENTRY fail\n");
  447. }
  448. static ssize_t musbfsh_ic_usb_cmd_proc_status_read(struct file *file_ptr,
  449. char __user *user_buffer,
  450. size_t count,
  451. loff_t *position)
  452. {
  453. int len;
  454. MYDBG("");
  455. if (copy_to_user(user_buffer,
  456. &g_ic_usb_status, sizeof(g_ic_usb_status)) != 0)
  457. return -EFAULT;
  458. /* *position += count; */
  459. len = sizeof(g_ic_usb_status);
  460. return len;
  461. }
  462. ssize_t musbfsh_ic_usb_cmd_proc_entry(struct file *file_ptr,
  463. const char __user *user_buffer,
  464. size_t count, loff_t *position)
  465. {
  466. int ret = copy_from_user((char *)&ic_cmd, user_buffer, count);
  467. if (ret != 0)
  468. return -EFAULT;
  469. MYDBG("type : %x, length : %x, data[0] : %x\n",
  470. ic_cmd.type, ic_cmd.length, ic_cmd.data[0]);
  471. switch (ic_cmd.type) {
  472. case USB11_SESSION_CONTROL:
  473. MYDBG("");
  474. usb11_session_control(ic_cmd.data[0]);
  475. break;
  476. case USB11_INIT_PHY_BY_VOLTAGE:
  477. MYDBG("");
  478. usb11_init_phy_by_voltage(ic_cmd.data[0]);
  479. break;
  480. case USB11_WAIT_DISCONNECT_DONE:
  481. MYDBG("");
  482. usb11_wait_disconnect_done(ic_cmd.data[0]);
  483. break;
  484. /*--- special purpose ---*/
  485. case 's':
  486. MYDBG("create sysfs\n");
  487. create_icusb_sysfs_attr();
  488. break;
  489. case 't':
  490. MYDBG("create tmp proc\n");
  491. create_ic_tmp_entry();
  492. break;
  493. }
  494. return count;
  495. }
  496. static const struct file_operations musbfsh_ic_usb_cmd_proc_fops = {
  497. .read = musbfsh_ic_usb_cmd_proc_status_read,
  498. .write = musbfsh_ic_usb_cmd_proc_entry
  499. };
  500. void create_ic_usb_cmd_proc_entry(void)
  501. {
  502. struct proc_dir_entry *prEntry;
  503. MYDBG("");
  504. proc_drv_icusb_dir_entry = proc_mkdir("driver/icusb", NULL);
  505. if (NULL == proc_drv_icusb_dir_entry) {
  506. MYDBG("[%s]: mkdir /proc/driver/icusb failed\n", __func__);
  507. return;
  508. }
  509. prEntry =
  510. proc_create("IC_USB_CMD_ENTRY", 0660, proc_drv_icusb_dir_entry,
  511. &musbfsh_ic_usb_cmd_proc_fops);
  512. if (prEntry) {
  513. MYDBG("add IC_USB_CMD_ENTRY ok\n");
  514. netlink_sock = netlink_kernel_create(&init_net,
  515. NETLINK_USERSOCK, &nl_cfg);
  516. } else {
  517. MYDBG("add IC_USB_CMD_ENTRY fail\n");
  518. }
  519. }
  520. void set_icusb_phy_power_negotiation(struct usb_device *udev)
  521. {
  522. if (power_resume_time_neogo_attr.value) {
  523. icusb_power_negotiation(udev);
  524. icusb_resume_time_negotiation(udev);
  525. } else {
  526. set_icusb_phy_power_negotiation_ok();
  527. }
  528. }
  529. #if 0
  530. static int usb_icusb_probe(struct usb_interface *iface,
  531. const struct usb_device_id *id)
  532. {
  533. struct usb_device *dev = interface_to_usbdev(iface);
  534. struct usb_host_interface *interface;
  535. struct usb_icusb *icusb;
  536. interface = iface->altsetting;
  537. pr_debug(" extralen = %d\n", interface->extralen);
  538. if (interface->extralen < ICCD_CLASS_DESCRIPTOR_LENGTH)
  539. return -ENODEV;
  540. icusb = kzalloc(sizeof(struct usb_icusb), GFP_KERNEL);
  541. if (dev->manufacturer)
  542. strlcpy(icusb->name, dev->manufacturer, sizeof(icusb->name));
  543. if (dev->product) {
  544. if (dev->manufacturer)
  545. strlcat(icusb->name, " ", sizeof(icusb->name));
  546. strlcat(icusb->name, dev->product, sizeof(icusb->name));
  547. }
  548. if (!strlen(icusb->name))
  549. snprintf(icusb->name, sizeof(icusb->name),
  550. "USB ICUSB = %04x:%04x",
  551. le16_to_cpu(dev->descriptor.idVendor),
  552. le16_to_cpu(dev->descriptor.idProduct));
  553. pr_debug("icusb_DRIVER = %s\n", icusb->name);
  554. if (power_resume_time_neogo_attr.value) {
  555. icusb_power_negotiation(dev);
  556. icusb_resume_time_negotiation(dev);
  557. } else {
  558. set_icusb_phy_power_negotiation_ok();
  559. }
  560. /* usb_set_intfdata(iface, icusb); */
  561. return -ENODEV;
  562. }
  563. static void usb_icusb_disconnect(struct usb_interface *intf)
  564. {
  565. struct usb_icusb *icusb = usb_get_intfdata(intf);
  566. pr_debug("usb_icusb_disconnect\n");
  567. if (!check_usb11_sts_disconnect_done())
  568. set_usb11_sts_disconnecting();
  569. mt65xx_usb11_mac_reset_and_phy_stress_set();
  570. /* usb_set_intfdata(intf, NULL); */
  571. if (icusb != NULL)
  572. kfree(icusb);
  573. set_icusb_sts_disconnect_done();
  574. }
  575. static int usb_icusb_suspend(struct usb_interface *intf, pm_message_t message)
  576. {
  577. pr_debug("usb_icusb_suspend\n");
  578. return 0;
  579. }
  580. static int usb_icusb_resume(struct usb_interface *intf)
  581. {
  582. pr_debug("usb_icusb_resume\n");
  583. return 0;
  584. }
  585. static int usb_icusb_pre_reset(struct usb_interface *intf)
  586. {
  587. pr_debug("usb_icusb_pre_reset\n");
  588. return 0;
  589. }
  590. static int usb_icusb_post_reset(struct usb_interface *intf)
  591. {
  592. pr_debug("usb_icusb_post_reset\n");
  593. return 0;
  594. }
  595. static int usb_icusb_reset_resume(struct usb_interface *intf)
  596. {
  597. pr_debug("usb_icusb_reset_resume\n");
  598. return 0;
  599. }
  600. static struct usb_device_id usb_icusb_id_table[] = {
  601. {.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
  602. .bInterfaceClass = ICCD_INTERFACE_CLASS},
  603. {} /* Terminating entry */
  604. };
  605. MODULE_DEVICE_TABLE(usb, usb_icusb_id_table);
  606. static struct usb_driver usb_icusb_driver = {
  607. .name = "usbicusb",
  608. .probe = usb_icusb_probe,
  609. .disconnect = usb_icusb_disconnect,
  610. .suspend = usb_icusb_suspend,
  611. .resume = usb_icusb_resume,
  612. .pre_reset = usb_icusb_pre_reset,
  613. .post_reset = usb_icusb_post_reset,
  614. .reset_resume = usb_icusb_reset_resume,
  615. .id_table = usb_icusb_id_table,
  616. };
  617. static int __init icusb_init(void)
  618. {
  619. int rc;
  620. pr_debug("icusb_init\n");
  621. rc = usb_register(&usb_icusb_driver);
  622. if (rc != 0)
  623. goto err_register;
  624. pr_debug("icusb_register done\n");
  625. /* create_icusb_cmd_proc_entry(); */
  626. /* 3.10 specific */
  627. netlink_sock = netlink_kernel_create(&init_net,
  628. NETLINK_USERSOCK, &nl_cfg);
  629. err_register:
  630. return rc;
  631. }
  632. static void __exit icusb_exit(void)
  633. {
  634. usb_deregister(&usb_icusb_driver);
  635. }
  636. module_init(icusb_init);
  637. module_exit(icusb_exit);
  638. #endif