/drivers/omap_hsi/hsi_protocol_cmd.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 429 lines · 319 code · 75 blank · 35 comment · 29 complexity · 56c6e891ba1679c20ddebab668a7626a MD5 · raw file

  1. /*
  2. * File - hsi_protocol_if_cmd.c
  3. *
  4. * Implements HSI protocol for Infineon Modem.
  5. *
  6. * Copyright (C) 2011 Samsung Electronics. All rights reserved.
  7. *
  8. * Author: Rupesh Gujare <rupesh.g@samsung.com>
  9. *
  10. * This package is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. *
  14. * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18. #include <linux/errno.h>
  19. #include <linux/module.h>
  20. #include <linux/types.h>
  21. #include <linux/init.h>
  22. #include <linux/device.h>
  23. #include <linux/err.h>
  24. #include <linux/delay.h>
  25. #include <linux/wait.h>
  26. #include <linux/sched.h>
  27. #include <linux/hsi_driver_if.h>
  28. #include "hsi-protocol-if.h"
  29. extern struct if_hsi_iface hsi_protocol_iface;
  30. extern wait_queue_head_t ipc_read_wait, ipc_write_wait;
  31. int if_hsi_openchannel(struct if_hsi_channel *channel);
  32. int if_hsi_closechannel(struct if_hsi_channel *channel);
  33. extern struct if_hsi_cmd hsi_cmd_history;
  34. extern int tx_cmd_history_p;
  35. extern int rx_cmd_history_p;
  36. /*Decode command from received PDU on channle 0*/
  37. int hsi_decode_cmd(u32 *cmd_data, u32 *cmd, u32 *ch, u32 *param)
  38. {
  39. int ret = 0;
  40. u32 data = *cmd_data;
  41. u8 lrc_cal, lrc_act;
  42. u8 val1, val2, val3;
  43. *cmd = ((data & 0xF0000000) >> 28);
  44. switch (*cmd) {
  45. case HSI_LL_MSG_BREAK:
  46. pr_err("Command MSG_BREAK Received.\n");
  47. break;
  48. case HSI_LL_MSG_OPEN_CONN:
  49. *ch = ((data & 0x0F000000) >> 24);
  50. *param = ((data & 0x00FFFF00) >> 8);
  51. /*Check LRC*/
  52. val1 = ((data & 0xFF000000) >> 24);
  53. val2 = ((data & 0x00FF0000) >> 16);
  54. val3 = ((data & 0x0000FF00) >> 8);
  55. lrc_act = (data & 0x000000FF);
  56. lrc_cal = val1 ^ val2 ^ val3;
  57. if (lrc_cal != lrc_act)
  58. ret = -1;
  59. break;
  60. case HSI_LL_MSG_CONN_READY:
  61. case HSI_LL_MSG_CONN_CLOSED:
  62. case HSI_LL_MSG_CANCEL_CONN:
  63. case HSI_LL_MSG_NAK:
  64. *ch = ((data & 0x0F000000) >> 24);
  65. break;
  66. case HSI_LL_MSG_ACK:
  67. *ch = ((data & 0x0F000000) >> 24);
  68. *param = (data & 0x00FFFFFF);
  69. //printk(KERN_INFO "ACK Received ch=%d, param=%d\n",*ch, *param);
  70. break;
  71. case HSI_LL_MSG_CONF_RATE:
  72. *ch = ((data & 0x0F000000) >> 24);
  73. *param = ((data & 0x0F000000) >> 24);
  74. break;
  75. case HSI_LL_MSG_OPEN_CONN_OCTET:
  76. *ch = ((data & 0x0F000000) >> 24);
  77. *param = (data & 0x00FFFFFF);
  78. break;
  79. case HSI_LL_MSG_ECHO:
  80. case HSI_LL_MSG_INFO_REQ:
  81. case HSI_LL_MSG_INFO:
  82. case HSI_LL_MSG_CONFIGURE:
  83. case HSI_LL_MSG_ALLOCATE_CH:
  84. case HSI_LL_MSG_RELEASE_CH:
  85. case HSI_LL_MSG_INVALID:
  86. *cmd = HSI_LL_MSG_INVALID;
  87. *ch = HSI_LL_INVALID_CHANNEL;
  88. ret = -1;
  89. break;
  90. }
  91. return ret;
  92. }
  93. int protocol_create_cmd(int cmd_type, unsigned int channel, void *arg)
  94. {
  95. unsigned int command = 0;
  96. int ret = 0;
  97. switch (cmd_type) {
  98. case HSI_LL_MSG_BREAK:
  99. {
  100. command = 0;
  101. }
  102. break;
  103. case HSI_LL_MSG_OPEN_CONN:
  104. {
  105. unsigned int size = *(unsigned int *)arg;
  106. unsigned int lcr = 0;
  107. /* if(size > 4)
  108. size = (size & 0x3) ? ((size >> 2) + 1):(size >> 2);
  109. else
  110. size = 1;*/
  111. command = ((HSI_LL_MSG_OPEN_CONN & 0x0000000F) << 28) |
  112. ((channel & 0x000000FF) << 24) |
  113. ((size & 0x0000FFFF) << 8);
  114. lcr = ((command & 0xFF000000) >> 24) ^
  115. ((command & 0x00FF0000) >> 16) ^
  116. ((command & 0x0000FF00) >> 8);
  117. command = command | (lcr & 0x000000FF);
  118. }
  119. break;
  120. case HSI_LL_MSG_CONN_READY:
  121. {
  122. command = ((HSI_LL_MSG_CONN_READY & 0x0000000F) << 28) |
  123. ((channel & 0x000000FF) << 24);
  124. }
  125. break;
  126. case HSI_LL_MSG_CONN_CLOSED:
  127. {
  128. command = ((HSI_LL_MSG_CONN_CLOSED & 0x0000000F) << 28) |
  129. ((channel & 0x000000FF) << 24);
  130. }
  131. break;
  132. case HSI_LL_MSG_CANCEL_CONN:
  133. {
  134. unsigned int role = *(unsigned int *)arg;
  135. command = ((HSI_LL_MSG_CANCEL_CONN & 0x0000000F) << 28) |
  136. ((channel & 0x000000FF) << 24) |
  137. ((role & 0x000000FF) << 16);
  138. }
  139. break;
  140. case HSI_LL_MSG_ACK:
  141. {
  142. unsigned int echo_params = *(unsigned int *)arg;
  143. command = ((HSI_LL_MSG_ACK & 0x0000000F) << 28) |
  144. ((channel & 0x000000FF) << 24) |
  145. ((echo_params & 0x00FFFFFF));
  146. }
  147. break;
  148. case HSI_LL_MSG_NAK:
  149. {
  150. command = ((HSI_LL_MSG_NAK & 0x0000000F) << 28) |
  151. ((channel & 0x000000FF) << 24);
  152. }
  153. break;
  154. case HSI_LL_MSG_CONF_RATE:
  155. {
  156. unsigned int baud_rate = *(unsigned int *)arg;
  157. command = ((HSI_LL_MSG_CONF_RATE & 0x0000000F) << 28) |
  158. ((channel & 0x000000FF) << 24) |
  159. ((baud_rate & 0x00FFFFFF));
  160. }
  161. break;
  162. case HSI_LL_MSG_OPEN_CONN_OCTET:
  163. {
  164. unsigned int size = *(unsigned int *)arg;
  165. command = ((HSI_LL_MSG_OPEN_CONN_OCTET & 0x0000000F) << 28) |
  166. ((channel & 0x000000FF) << 24) |
  167. ((size & 0x00FFFFFF));
  168. }
  169. break;
  170. case HSI_LL_MSG_ECHO:
  171. case HSI_LL_MSG_INFO_REQ:
  172. case HSI_LL_MSG_INFO:
  173. case HSI_LL_MSG_CONFIGURE:
  174. case HSI_LL_MSG_ALLOCATE_CH:
  175. case HSI_LL_MSG_RELEASE_CH:
  176. case HSI_LL_MSG_INVALID:
  177. ret = -1;
  178. break;
  179. }
  180. return command;
  181. }
  182. int set_tx_config(struct if_hsi_channel *ch, u32 mode, u32 max_channels)
  183. {
  184. struct hst_ctx tx_config;
  185. int ret;
  186. hsi_ioctl(ch->dev, HSI_IOCTL_GET_TX, &tx_config);
  187. tx_config.mode = mode;
  188. tx_config.channels = max_channels;
  189. ret = hsi_ioctl(ch->dev, HSI_IOCTL_SET_TX, &tx_config);
  190. return ret;
  191. }
  192. static int saved_cmd_queue = 0;
  193. static u32 cmd_saved[5];
  194. int hsi_protocol_send_command(u32 cmd, u32 channel, u32 param)
  195. {
  196. struct if_hsi_channel *channel_zero;
  197. u32 cmd_array[4] = {0x00000000, 0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC}, ret = -1;
  198. channel_zero = &hsi_protocol_iface.channels[0];
  199. cmd_array[0] = protocol_create_cmd(cmd, channel, &param);
  200. pr_debug("[%s] CMD = %08x\n",__func__, cmd_array[0]);
  201. while (channel_zero->tx_state != HSI_LL_TX_STATE_IDLE) {
  202. cmd_saved[saved_cmd_queue] = cmd_array[0];
  203. saved_cmd_queue++;
  204. pr_debug("(%s) cmd_saved : %x(%d)\n", __func__, cmd_array[0], saved_cmd_queue);
  205. return 0;
  206. }
  207. send_retry:
  208. channel_zero->tx_state = HSI_LL_TX_STATE_TX;
  209. // For es 2.1 ver.
  210. ret = hsi_proto_write(0, cmd_array, 4);
  211. if (ret < 0) {
  212. pr_err("(%s) Command Write failed, CMD->%X\n", __func__, cmd_array[0]);
  213. channel_zero->tx_state = HSI_LL_TX_STATE_IDLE;
  214. return -1;
  215. } else {
  216. channel_zero->tx_state = HSI_LL_TX_STATE_IDLE;
  217. pr_debug("[%s] CMD = %08x\n", __func__, cmd_array[0]);
  218. hsi_cmd_history.tx_cmd[tx_cmd_history_p] = cmd_array[0];
  219. hsi_cmd_history.tx_cmd_time[tx_cmd_history_p] = CURRENT_TIME;
  220. tx_cmd_history_p++;
  221. if (tx_cmd_history_p >= 50)
  222. tx_cmd_history_p = 0;
  223. if (saved_cmd_queue) {
  224. saved_cmd_queue--;
  225. cmd_array[0] = cmd_saved[saved_cmd_queue];
  226. goto send_retry;
  227. }
  228. return 0;
  229. }
  230. }
  231. void rx_stm(u32 cmd, u32 ch, u32 param)
  232. {
  233. struct if_hsi_channel *channel;
  234. u32 size = 0, tmp_cmd = 0, ret, i;
  235. channel = &hsi_protocol_iface.channels[ch];
  236. switch (cmd) {
  237. case HSI_LL_MSG_OPEN_CONN:
  238. pr_err("ERROR... OPEN_CONN Not supported. Should use OPEN_CONN_OCTECT instead.\n");
  239. break;
  240. case HSI_LL_MSG_ECHO:
  241. pr_err("ERROR... HSI_LL_MSG_ECHO not supported.\n");
  242. break;
  243. case HSI_LL_MSG_CONN_CLOSED:
  244. switch (channel->tx_state) {
  245. case HSI_LL_TX_STATE_WAIT_FOR_CONN_CLOSED:
  246. channel->tx_state = HSI_LL_TX_STATE_IDLE;
  247. /* ACWAKE ->LOW */
  248. ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_DOWN, NULL);
  249. if (ret == 0)
  250. pr_debug("ACWAKE pulled low in %s()\n", __func__);
  251. else
  252. pr_err("ACWAKE pulled low in %s() ERROR : %d\n", __func__, ret);
  253. pr_debug("[%s] Received CONN_CLOSED. ch-> %d\n", __func__,ch);
  254. break;
  255. default:
  256. pr_err("Wrong STATE for CONN_CLOSED\n");
  257. }
  258. break;
  259. case HSI_LL_MSG_CANCEL_CONN:
  260. pr_debug("Received CANCEL_CONN\n");
  261. break;
  262. case HSI_LL_MSG_ACK:
  263. switch (channel->tx_state) {
  264. case HSI_LL_TX_STATE_WAIT_FOR_ACK:
  265. case HSI_LL_TX_STATE_SEND_OPEN_CONN:
  266. //printk(KERN_INFO "ACK received %s()\n",__func__);
  267. channel->tx_state = HSI_LL_TX_STATE_TX;
  268. size = param;
  269. #if 0
  270. // TEMP: send/read by 16 byte unit for v.11A(CP)
  271. if ((size > 16) && (size % 16))
  272. size += (16 - (size % 16));
  273. else if (size < 16)
  274. size = 16;
  275. #endif
  276. // For es 2.1 ver.
  277. if (size % 4)
  278. size += (4 - (size % 4));
  279. pr_debug("Writing %d bytes data on channel %d, tx_buf = %x, in %s()\n", size, ch, channel->tx_buf, __func__);
  280. ret = hsi_proto_write(ch, channel->tx_buf, size);
  281. channel->tx_state = HSI_LL_TX_STATE_WAIT_FOR_CONN_CLOSED;
  282. wake_up_interruptible(&ipc_write_wait);
  283. channel->tx_nak_count = 0;
  284. break;
  285. case HSI_LL_TX_STATE_CLOSED:/* ACK as response to CANCEL_CONN */
  286. if (channel->rx_state == HSI_LL_RX_STATE_WAIT_FOR_CANCEL_CONN_ACK)
  287. channel->rx_state = HSI_LL_RX_STATE_IDLE;
  288. break;
  289. case HSI_LL_TX_STATE_WAIT_FOR_CONF_ACK: /* ACK as response to CONF_RATE */
  290. //TODO: SET CONF RATE
  291. pr_debug("ACK Received for CONF_RATE\n");
  292. break;
  293. default:
  294. pr_err("ACK Received for Unknown state\n");
  295. }
  296. break;
  297. case HSI_LL_MSG_NAK:
  298. switch (channel->tx_state) {
  299. case HSI_LL_TX_STATE_WAIT_FOR_ACK:
  300. printk(KERN_INFO "(%s) NAK received. ch->%d\n", __func__, ch);
  301. //channel->tx_state = HSI_LL_TX_STATE_NACK;
  302. if (channel->tx_nak_count < 10) {
  303. msleep(10);
  304. tmp_cmd = ((HSI_LL_MSG_OPEN_CONN_OCTET & 0x0000000F) << 28) |
  305. ((ch & 0x000000FF) << 24);
  306. for (i = 49; i >= 0; i--) {
  307. if ((hsi_cmd_history.tx_cmd[i] & 0xFFF00000) == tmp_cmd)
  308. break;
  309. }
  310. size = (hsi_cmd_history.tx_cmd[i] & 0x000FFFFF);
  311. pr_debug("(%s) Re Send OPEN CONN ch->%d, size->%d, count->%d\n", __func__, ch, size, channel->tx_nak_count);
  312. hsi_protocol_send_command(HSI_LL_MSG_OPEN_CONN_OCTET, ch, size);
  313. channel->tx_nak_count++;
  314. } else {
  315. hsi_protocol_send_command(HSI_LL_MSG_BREAK, ch, size);
  316. pr_debug("(%s) Sending MSG_BREAK. ch->%d\n", __func__, ch);
  317. //TODO Reset All channels and inform IPC write about failure (Possibly by sending signal)
  318. }
  319. break;
  320. case HSI_LL_TX_STATE_WAIT_FOR_CONF_ACK: /* NAK as response to CONF_RATE */
  321. channel->tx_state = HSI_LL_TX_STATE_IDLE;
  322. break;
  323. default:
  324. pr_err("ERROR - Received NAK in invalid state. state->%d\n", channel->tx_state);
  325. }
  326. break;
  327. case HSI_LL_MSG_CONF_RATE:
  328. //TODO: Set Conf Rate
  329. pr_debug("CONF_RATE Received\n");
  330. break;
  331. case HSI_LL_MSG_OPEN_CONN_OCTET:
  332. switch (channel->rx_state) {
  333. /* case HSI_LL_RX_STATE_CLOSED: */
  334. case HSI_LL_RX_STATE_IDLE:
  335. pr_debug("OPEN_CONN_OCTET in %s(), ch-> %d\n", __func__, ch);
  336. channel->rx_state = HSI_LL_RX_STATE_TO_ACK;
  337. hsi_protocol_send_command(HSI_LL_MSG_ACK, ch, param);
  338. channel->rx_count = param;
  339. channel->rx_state = HSI_LL_RX_STATE_RX;
  340. wake_up_interruptible(&ipc_read_wait);
  341. break;
  342. case HSI_LL_RX_STATE_BLOCKED:
  343. /* TODO */
  344. break;
  345. default:
  346. pr_err("OPEN_CONN_OCTET in invalid state, Current State -> %d\n", channel->rx_state);
  347. pr_info("Sending NAK to channel-> %d\n", ch);
  348. hsi_protocol_send_command(HSI_LL_MSG_NAK, ch, param);
  349. }
  350. break;
  351. default:
  352. pr_err("Invalid Command encountered in rx_state()\n");
  353. }
  354. }