ccci_logical.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/slab.h>
  5. #include <mach/irqs.h>
  6. #include <linux/kallsyms.h>
  7. #include <linux/delay.h>
  8. #include <linux/wakelock.h>
  9. #include <ccci.h>
  10. #define FIRST_PENDING (1<<0)
  11. #define PENDING_50MS (1<<1)
  12. /* #define PENDING_100MS (1<<2) */
  13. #define PENDING_1500MS (1<<2)
  14. const struct logic_channel_static_info_t logic_ch_static_info_tab[] = {
  15. {CCCI_CONTROL_RX, 8, "ctl_rx", L_CH_MUST_RDY_FOR_BOOT},
  16. {CCCI_CONTROL_TX, 0, "ctl_tx",
  17. L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_PRVLG0 | L_CH_ATTR_PRVLG2},
  18. {CCCI_SYSTEM_RX, 16, "sys_rx", 0},
  19. {CCCI_SYSTEM_TX, 0, "sys_tx", L_CH_ATTR_TX},
  20. {CCCI_PCM_RX, 128, "audio_rx", 0},
  21. {CCCI_PCM_TX, 0, "audio_tx", L_CH_ATTR_TX},
  22. {CCCI_UART1_RX, 8, "meta_rx", L_CH_DROP_TOLERATED},
  23. {CCCI_UART1_RX_ACK, 0, "meta_rx_ack",
  24. L_CH_ATTR_TX | L_CH_ATTR_DUMMY_WRITE},
  25. {CCCI_UART1_TX, 0, "meta_tx", L_CH_ATTR_TX | L_CH_ATTR_DUMMY_WRITE},
  26. {CCCI_UART1_TX_ACK, 8, "meta_tx_ack", L_CH_DROP_TOLERATED},
  27. {CCCI_UART2_RX, 8, "muxd_rx", L_CH_DROP_TOLERATED},
  28. {CCCI_UART2_RX_ACK, 0, "muxd_rx_ack", L_CH_ATTR_TX},
  29. {CCCI_UART2_TX, 0, "muxd_tx", L_CH_ATTR_TX},
  30. {CCCI_UART2_TX_ACK, 8, "muxd_tx_ack", L_CH_DROP_TOLERATED},
  31. {CCCI_FS_RX, 16, "md_nvram_rx", 0},
  32. {CCCI_FS_TX, 0, "md_nvram_tx",
  33. L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_OPEN_CLEAR |
  34. L_CH_ATTR_PRVLG0 | L_CH_ATTR_PRVLG2},
  35. {CCCI_PMIC_RX, 0, "pmic_rx", 0},
  36. {CCCI_PMIC_TX, 0, "pmic_tx", L_CH_ATTR_TX},
  37. {CCCI_UEM_RX, 8, "uem_rx", 0},
  38. {CCCI_UEM_TX, 0, "uem_tx", L_CH_ATTR_TX},
  39. {CCCI_CCMNI1_RX, 8, "ccmni1_rx", L_CH_DROP_TOLERATED},
  40. {CCCI_CCMNI1_RX_ACK, 0, "ccmni1_rx_ack", L_CH_ATTR_TX},
  41. {CCCI_CCMNI1_TX, 0, "ccmni1_tx", L_CH_ATTR_TX},
  42. {CCCI_CCMNI1_TX_ACK, 8, "ccmni1_tx_ack", L_CH_DROP_TOLERATED},
  43. {CCCI_CCMNI2_RX, 8, "ccmni2_rx", L_CH_DROP_TOLERATED},
  44. {CCCI_CCMNI2_RX_ACK, 0, "ccmni2_rx_ack", L_CH_ATTR_TX},
  45. {CCCI_CCMNI2_TX, 0, "ccmni2_tx", L_CH_ATTR_TX},
  46. {CCCI_CCMNI2_TX_ACK, 8, "ccmni2_tx_ack", L_CH_DROP_TOLERATED},
  47. {CCCI_CCMNI3_RX, 8, "ccmni3_rx", L_CH_DROP_TOLERATED},
  48. {CCCI_CCMNI3_RX_ACK, 0, "ccmni3_rx_ack", L_CH_ATTR_TX},
  49. {CCCI_CCMNI3_TX, 0, "ccmni3_tx", L_CH_ATTR_TX},
  50. {CCCI_CCMNI3_TX_ACK, 8, "ccmni3_tx_ack", L_CH_DROP_TOLERATED},
  51. {CCCI_RPC_RX, 8, "rpc_rx", 0},
  52. {CCCI_RPC_TX, 0, "rpc_tx", L_CH_ATTR_TX | L_CH_ATTR_PRVLG1},
  53. {CCCI_IPC_RX, 8, "ipc_rx", 0},
  54. {CCCI_IPC_RX_ACK, 0, "ipc_rx_ack", L_CH_ATTR_TX},
  55. {CCCI_IPC_TX, 0, "ipc_tx", L_CH_ATTR_TX},
  56. {CCCI_IPC_TX_ACK, 8, "ipc_tx_ack", 0},
  57. {CCCI_IPC_UART_RX, 8, "ipc_uart_rx", L_CH_DROP_TOLERATED},
  58. {CCCI_IPC_UART_RX_ACK, 0, "ipc_uart_rx_ack", L_CH_ATTR_TX},
  59. {CCCI_IPC_UART_TX, 0, "ipc_uart_tx", L_CH_ATTR_TX},
  60. {CCCI_IPC_UART_TX_ACK, 8, "ipc_uart_tx_ack", L_CH_DROP_TOLERATED},
  61. {CCCI_MD_LOG_RX, 256, "md_log_rx", 0},
  62. {CCCI_MD_LOG_TX, 0, "md_log_tx",
  63. L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_PRVLG2},
  64. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  65. {CCCI_ICUSB_RX, 8, "icusb_rx", L_CH_DROP_TOLERATED},
  66. {CCCI_ICUSB_RX_ACK, 0, "icusb_rx_ack", L_CH_ATTR_TX},
  67. {CCCI_ICUSB_TX, 0, "icusb_tx", L_CH_ATTR_TX},
  68. {CCCI_ICUSB_TX_ACK, 8, "icusb_tx_ack", L_CH_DROP_TOLERATED},
  69. #endif
  70. };
  71. #define MAX_LOGIC_CH_ID (sizeof(logic_ch_static_info_tab)/sizeof(struct logic_channel_static_info_t))
  72. static struct logic_dispatch_ctl_block_t *logic_dispatch_ctlb[MAX_MD_NUM];
  73. static unsigned char md_enabled[MAX_MD_NUM]; /* Boot up time will determine this */
  74. static unsigned char active_md[MAX_MD_NUM];
  75. static unsigned int max_md_sys;
  76. /****************************************************************************/
  77. /* update&get md sys info */
  78. /* */
  79. /****************************************************************************/
  80. void set_md_sys_max_num(unsigned int max_num)
  81. {
  82. max_md_sys = max_num;
  83. }
  84. void set_md_enable(int md_id, int en)
  85. {
  86. md_enabled[md_id] = en;
  87. }
  88. void update_active_md_sys_state(int md_id, int active)
  89. {
  90. if (md_enabled[md_id]) {
  91. active_md[md_id] = active;
  92. if (active) {
  93. /* CCCI_DBG_MSG(md_id, "cci", "enable modem intr\n"); */
  94. ccci_enable_md_intr(md_id);
  95. }
  96. } else {
  97. CCCI_MSG("md_sys%d is not enable\n", md_id);
  98. }
  99. }
  100. int get_md_wakeup_src(int md_id, char *buf, unsigned int len)
  101. {
  102. unsigned int i, rx, ch;
  103. struct ccif_msg_t data;
  104. unsigned int rx_ch[CCIF_STD_V1_MAX_CH_NUM][2] = {
  105. {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0},
  106. {-1, 0}, {-1, 0}, {-1, 0}
  107. };
  108. char str[64];
  109. char log_buf[256] = "";
  110. int ret = 0;
  111. char *channel_name;
  112. struct ccif_t *ccif;
  113. int curr_str_len = 0;
  114. struct logic_dispatch_ctl_block_t *ctlb;
  115. ctlb = logic_dispatch_ctlb[md_id];
  116. ccif = ctlb->m_ccif;
  117. rx = ccif->ccif_get_rx_ch(ccif);
  118. if (rx == 0)
  119. return ret;
  120. for (i = 0; i < CCIF_STD_V1_MAX_CH_NUM; i++) {
  121. if (rx & (1 << i)) {
  122. ccif->ccif_read_phy_ch_data(ccif, i,
  123. (unsigned int *)&data);
  124. for (ch = 0; ch < i; ch++)
  125. if (data.channel == rx_ch[ch][0])
  126. break;
  127. rx_ch[ch][0] = data.channel;
  128. rx_ch[ch][1]++;
  129. }
  130. }
  131. for (i = 0; i < CCIF_STD_V1_MAX_CH_NUM; i++) {
  132. if (rx_ch[i][1]) {
  133. if ((rx_ch[i][0] >= 0)
  134. && (rx_ch[i][0] < MAX_LOGIC_CH_ID)) {
  135. channel_name =
  136. logic_ch_static_info_tab[rx_ch[i]
  137. [0]].m_ch_name;
  138. sprintf(str, "%s(%d,%d) ", channel_name,
  139. rx_ch[i][0], rx_ch[i][1]);
  140. } else
  141. sprintf(str, "%s(%d,%d) ", "unknown",
  142. rx_ch[i][0], rx_ch[i][1]);
  143. curr_str_len += strlen(str);
  144. if (curr_str_len < 255)
  145. strcat(log_buf, str);
  146. }
  147. }
  148. if (curr_str_len > 255) {
  149. CCCI_MSG
  150. ("[ccci/ctl] wakeup source buffer not enough(req:%d>255) for MD%d\n",
  151. curr_str_len, md_id + 1);
  152. }
  153. CCCI_MSG("[ccci/ctl] (%d)CCIF_MD%d wakeup source: %s\n", md_id + 1,
  154. md_id + 1, log_buf);
  155. return ret;
  156. }
  157. /****************************************************************************/
  158. /* logical channel handle function */
  159. /* */
  160. /****************************************************************************/
  161. int register_to_logic_ch(int md_id, int ch, void (*func) (void *), void *owner)
  162. {
  163. struct logic_channel_info_t *ch_info;
  164. int ret = 0;
  165. unsigned long flags;
  166. struct logic_dispatch_ctl_block_t *ctl_b;
  167. ctl_b = logic_dispatch_ctlb[md_id];
  168. ch_info = &(ctl_b->m_logic_ch_table[ch]);
  169. if ((ch_info->m_attrs & L_CH_ATTR_TX) && (func != NULL))
  170. return 0;
  171. spin_lock_irqsave(&ch_info->m_lock, flags);
  172. /* Check whether call back function has been registered */
  173. if (!ch_info->m_register) {
  174. ch_info->m_register = 1;
  175. ch_info->m_call_back = func;
  176. ch_info->m_owner = owner;
  177. } else {
  178. CCCI_MSG_INF(md_id, "cci",
  179. "%s fail: %s(ch%d) cb func has registered\n",
  180. __func__, ch_info->m_ch_name,
  181. ch_info->m_ch_id);
  182. ret = -CCCI_ERR_LOGIC_CH_HAS_REGISTERED;
  183. }
  184. spin_unlock_irqrestore(&ch_info->m_lock, flags);
  185. return ret;
  186. }
  187. int un_register_to_logic_ch(int md_id, int ch)
  188. {
  189. struct logic_channel_info_t *ch_info;
  190. unsigned long flags;
  191. struct logic_dispatch_ctl_block_t *ctl_b;
  192. if (unlikely(ch >= CCCI_MAX_CH_NUM)) {
  193. CCCI_MSG_INF(md_id, "cci", "%s fail: invalid logic ch%d\n",
  194. __func__, ch);
  195. return -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
  196. }
  197. ctl_b = logic_dispatch_ctlb[md_id];
  198. ch_info = &(ctl_b->m_logic_ch_table[ch]);
  199. spin_lock_irqsave(&ch_info->m_lock, flags);
  200. if (ch_info->m_register == 0)
  201. CCCI_MSG_INF(md_id, "cci", "ch%d not registered yet\n", ch);
  202. ch_info->m_call_back = NULL;
  203. ch_info->m_owner = NULL;
  204. ch_info->m_register = 0;
  205. spin_unlock_irqrestore(&ch_info->m_lock, flags);
  206. return 0;
  207. }
  208. int get_logic_ch_data(struct logic_channel_info_t *ch_info, struct ccci_msg_t *msg)
  209. {
  210. if (unlikely(ch_info == NULL)) {
  211. CCCI_MSG("%s fail: get invalid ch info\n", __func__);
  212. return -CCCI_ERR_GET_NULL_POINTER;
  213. }
  214. if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
  215. CCCI_MSG_INF(ch_info->m_md_id, "cci",
  216. "%s fail: %s(ch%d) is tx\n", __func__,
  217. ch_info->m_ch_name, msg->channel);
  218. return -CCCI_ERR_GET_RX_DATA_FROM_TX_CHANNEL;
  219. }
  220. /* check whether fifo is ready */
  221. if (unlikely(!ch_info->m_kfifo_ready)) {
  222. CCCI_MSG_INF(ch_info->m_md_id, "cci",
  223. "%s fail: %s(ch%d) kfifo not ready\n",
  224. __func__, ch_info->m_ch_name, msg->channel);
  225. return -CCCI_ERR_KFIFO_IS_NOT_READY;
  226. }
  227. /* Check fifo if has data */
  228. if (kfifo_is_empty(&ch_info->m_kfifo))
  229. return 0;
  230. /* Pop data */
  231. return kfifo_out(&ch_info->m_kfifo, msg, sizeof(struct ccif_msg_t));
  232. }
  233. int get_logic_ch_data_len(struct logic_channel_info_t *ch_info)
  234. {
  235. if (unlikely(ch_info == NULL)) {
  236. CCCI_MSG("%s get invalid ch info\n", __func__);
  237. return 0;
  238. }
  239. if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
  240. CCCI_MSG_INF(ch_info->m_md_id, "cci",
  241. "%s fail: %s(ch%d) is tx\n", __func__,
  242. ch_info->m_ch_name, ch_info->m_ch_id);
  243. return 0;
  244. }
  245. /* check whether fifo is ready */
  246. if (unlikely(!ch_info->m_kfifo_ready)) {
  247. CCCI_MSG_INF(ch_info->m_md_id, "cci",
  248. "%s fail: %s(ch%d) kfifo not ready\n",
  249. __func__, ch_info->m_ch_name,
  250. ch_info->m_ch_id);
  251. return 0;
  252. }
  253. /* Check fifo data length */
  254. return kfifo_len(&ch_info->m_kfifo);
  255. }
  256. struct logic_channel_info_t *get_logic_ch_info(int md_id, int ch_id)
  257. {
  258. struct logic_channel_info_t *ch_info;
  259. struct logic_dispatch_ctl_block_t *ctl_block;
  260. if (unlikely(ch_id >= CCCI_MAX_CH_NUM)) {
  261. CCCI_MSG_INF(md_id, "cci", "%s fail: invalid logic ch%d\n",
  262. __func__, ch_id);
  263. return NULL;
  264. }
  265. ctl_block = logic_dispatch_ctlb[md_id];
  266. ch_info = &(ctl_block->m_logic_ch_table[ch_id]);
  267. return ch_info;
  268. }
  269. static int __logic_dispatch_push(struct ccif_msg_t *msg, void *ctl_b)
  270. {
  271. struct logic_channel_info_t *ch_info;
  272. int ret = 0;
  273. struct logic_dispatch_ctl_block_t *ctl_block =
  274. (struct logic_dispatch_ctl_block_t *) ctl_b;
  275. int md_id = ctl_block->m_md_id;
  276. int drop = 1;
  277. if (unlikely(msg->channel >= CCCI_MAX_CH_NUM)) {
  278. CCCI_MSG_INF(md_id, "cci", "%s get invalid logic ch id:%d\n",
  279. __func__, msg->channel);
  280. ret = -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
  281. goto _out;
  282. }
  283. ch_info = &(ctl_block->m_logic_ch_table[msg->channel]);
  284. if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
  285. CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s is tx channel\n",
  286. __func__, msg->channel, ch_info->m_ch_name);
  287. ret = -CCCI_ERR_PUSH_RX_DATA_TO_TX_CHANNEL;
  288. goto _out;
  289. }
  290. /* check whether fifo is ready */
  291. if (!ch_info->m_kfifo_ready) {
  292. CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s's kfifo is not ready\n",
  293. __func__, msg->channel, ch_info->m_ch_name);
  294. ret = -CCCI_ERR_KFIFO_IS_NOT_READY;
  295. goto _out;
  296. }
  297. /* Check fifo free space */
  298. if (kfifo_is_full(&ch_info->m_kfifo)) {
  299. if (ch_info->m_attrs & L_CH_DROP_TOLERATED) {
  300. CCCI_CTL_MSG(md_id,
  301. "Drop (%08X %08X %02d %08X) is tolerated\n",
  302. msg->data[0], msg->data[1], msg->channel,
  303. msg->reserved);
  304. ret = sizeof(struct ccif_msg_t);
  305. } else {
  306. /* message should NOT be droped */
  307. CCCI_DBG_MSG(md_id, "cci",
  308. "kfifo full: ch:%s size:%d (%08X %08X %02d %08X)\n",
  309. ch_info->m_ch_name,
  310. kfifo_size(&ch_info->m_kfifo),
  311. msg->data[0], msg->data[1], msg->channel,
  312. msg->reserved);
  313. /* disalbe CCIF interrupt here???? */
  314. ret = 0; /* Fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
  315. }
  316. goto _out;
  317. }
  318. /* Push data */
  319. ret = kfifo_in(&ch_info->m_kfifo, msg, sizeof(struct ccif_msg_t));
  320. WARN_ON(ret != sizeof(struct ccif_msg_t));
  321. ctl_block->m_has_pending_data = 1;
  322. drop = 0;
  323. _out:
  324. add_logic_layer_record(md_id, (struct ccci_msg_t *) msg, drop);
  325. return ret;
  326. }
  327. static void __logic_layer_tasklet(unsigned long data)
  328. {
  329. struct logic_dispatch_ctl_block_t *logic_ctlb =
  330. (struct logic_dispatch_ctl_block_t *) data;
  331. struct logic_channel_info_t *ch_info;
  332. int i = 0;
  333. logic_ctlb->m_running = 1;
  334. while (logic_ctlb->m_has_pending_data) {
  335. logic_ctlb->m_has_pending_data = 0;
  336. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  337. ch_info = &logic_ctlb->m_logic_ch_table[i];
  338. if (!ch_info->m_kfifo_ready)
  339. continue;
  340. if (!kfifo_is_empty(&ch_info->m_kfifo)) {
  341. /* Note here, register call back should using spinlock_irqsave */
  342. spin_lock(&ch_info->m_lock);
  343. /* Has data to process */
  344. if (ch_info->m_call_back != NULL) {
  345. /* 1.Check if this channel is active
  346. has call back means this channel is active */
  347. ch_info->m_call_back(ch_info);
  348. } else if (ch_info->m_attrs &
  349. L_CH_MUST_RDY_FOR_BOOT) {
  350. /* 2.Important channel not ready, show waring message */
  351. CCCI_DBG_MSG(ch_info->m_md_id, "cci",
  352. "Has pending msg for ch:%d\n",
  353. ch_info->m_ch_id);
  354. }
  355. spin_unlock(&ch_info->m_lock);
  356. }
  357. }
  358. }
  359. logic_ctlb->m_running = 0;
  360. /* wake_lock_timeout(&logic_ctlb->m_wakeup_wake_lock, 3*HZ/2); */
  361. }
  362. static void __let_logic_dispatch_tasklet_run(void *ctl_b)
  363. {
  364. struct logic_dispatch_ctl_block_t *ctl_block =
  365. (struct logic_dispatch_ctl_block_t *) ctl_b;
  366. tasklet_schedule(&ctl_block->m_dispatch_tasklet);
  367. }
  368. void freeze_logic_layer_tx(int md_id)
  369. {
  370. struct logic_dispatch_ctl_block_t *ctl_b;
  371. ctl_b = logic_dispatch_ctlb[md_id];
  372. ctl_b->m_freezed = 1;
  373. }
  374. void freeze_all_logic_layer(int md_id)
  375. {
  376. struct logic_dispatch_ctl_block_t *ctl_b;
  377. struct ccif_t *ccif;
  378. ctl_b = logic_dispatch_ctlb[md_id];
  379. ccif = ctl_b->m_ccif;
  380. ccif->ccif_dis_intr(ccif);
  381. ctl_b->m_freezed = 1;
  382. }
  383. int logic_layer_reset(int md_id)
  384. {
  385. struct logic_dispatch_ctl_block_t *ctl_b;
  386. struct ccif_t *ccif;
  387. u64 ref_jiffies = get_jiffies_64();
  388. int i;
  389. ctl_b = logic_dispatch_ctlb[md_id];
  390. ccif = ctl_b->m_ccif;
  391. /* Check whether there is on-going isr/tasklet */
  392. while ((CCIF_TOP_HALF_RUNNING & ccif->m_status) || ctl_b->m_running
  393. || ctl_b->m_has_pending_data) {
  394. if ((get_jiffies_64() - ref_jiffies) > 2 * HZ) {
  395. CCCI_MSG_INF(ctl_b->m_md_id, "cci",
  396. "%s wait isr/tasklet more than 2 seconds\n",
  397. __func__);
  398. break;
  399. }
  400. }
  401. /* isr/tasklet done, then reset ccif and logic channel */
  402. ccif->ccif_reset(ccif);
  403. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  404. if (ctl_b->m_logic_ch_table[i].m_kfifo_ready)
  405. kfifo_reset(&(ctl_b->m_logic_ch_table[i].m_kfifo));
  406. }
  407. ctl_b->m_has_pending_data = 0;
  408. ctl_b->m_freezed = 0;
  409. ctl_b->m_running = 0;
  410. /* ctl_b->m_privilege = MD_BOOT_STAGE_0; */
  411. ctl_b->m_status_flag = 0;
  412. return 0;
  413. }
  414. /****************************************************************************/
  415. /* logical channel handle function */
  416. /* */
  417. /****************************************************************************/
  418. int bind_to_low_layer_notify(int md_id, void (*isr_func)(int),
  419. void (*send_func)(int, unsigned int))
  420. {
  421. struct logic_dispatch_ctl_block_t *ctl_b;
  422. struct ccif_t *ccif;
  423. int ret = 0;
  424. ctl_b = logic_dispatch_ctlb[md_id];
  425. /* Check whether call back function has been registered */
  426. if (NULL != ctl_b->m_send_notify_cb) {
  427. ret = -CCCI_ERR_MD_CB_HAS_REGISTER;
  428. return ret;
  429. }
  430. ctl_b->m_send_notify_cb = send_func;
  431. if (isr_func) {
  432. ccif = ctl_b->m_ccif;
  433. ret = ccif->register_isr_notify_func(ccif, isr_func);
  434. }
  435. return ret;
  436. }
  437. /* Support function for ccci char/tty/ccmni/fs/rpc/ipc/... */
  438. int ccci_message_send(int md_id, struct ccci_msg_t *msg, int retry_en)
  439. {
  440. struct logic_dispatch_ctl_block_t *ctl_b;
  441. struct ccif_t *ccif;
  442. int ret = 0;
  443. int args = 0;
  444. int drop = 0;
  445. unsigned long flags;
  446. int need_notify = 0;
  447. int md_stage = 0;
  448. ctl_b = logic_dispatch_ctlb[md_id];
  449. ccif = ctl_b->m_ccif;
  450. if (unlikely(ctl_b->m_freezed)) {
  451. CCCI_MSG_INF(md_id, "cci", "%s fail: ccci is freezed\n",
  452. __func__);
  453. ret = -CCCI_ERR_MD_NOT_READY;
  454. goto out;
  455. }
  456. if (unlikely(msg->channel >= CCCI_MAX_CH_NUM)) {
  457. if (msg->channel == CCCI_FORCE_ASSERT_CH) {
  458. ret =
  459. ccif->ccif_write_phy_ch_data(ccif,
  460. (unsigned int *)msg,
  461. retry_en);
  462. goto out;
  463. } else {
  464. CCCI_MSG_INF(md_id, "cci",
  465. "%s fail: invalid logic ch(%d)\n",
  466. __func__, msg->channel);
  467. ret = -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
  468. goto out;
  469. }
  470. }
  471. md_stage = get_curr_md_state(md_id);
  472. if (unlikely(md_stage == MD_BOOT_STAGE_0)) { /* PRIVILEGE 0 <-- */
  473. /* At ccci privilege mode, only privilege channel can send data to modem */
  474. if (ctl_b->
  475. m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG0) {
  476. ret =
  477. ccif->ccif_write_phy_ch_data(ccif,
  478. (unsigned int *)msg,
  479. retry_en);
  480. } else {
  481. ret = -ENODEV;
  482. }
  483. } else if (unlikely(md_stage == MD_BOOT_STAGE_1)) { /* PRIVILEGE 1 <-- */
  484. if (ctl_b->
  485. m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG1) {
  486. ret =
  487. ccif->ccif_write_phy_ch_data(ccif,
  488. (unsigned int *)msg,
  489. retry_en);
  490. } else {
  491. ret = -ENODEV;
  492. }
  493. } else if (unlikely(md_stage == MD_BOOT_STAGE_EXCEPTION)) { /* PRIVILEGE 2 <-- */
  494. if (ctl_b->
  495. m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG2) {
  496. ret =
  497. ccif->ccif_write_phy_ch_data(ccif,
  498. (unsigned int *)msg,
  499. retry_en);
  500. } else if (ctl_b->
  501. m_logic_ch_table[msg->
  502. channel].m_attrs &
  503. L_CH_ATTR_DUMMY_WRITE) {
  504. ret = sizeof(struct ccci_msg_t); /* Dummy write here, MD using polling */
  505. } else {
  506. ret = -ETXTBSY;
  507. }
  508. } else {
  509. ret =
  510. ccif->ccif_write_phy_ch_data(ccif, (unsigned int *)msg,
  511. retry_en);
  512. }
  513. out:
  514. spin_lock_irqsave(&ctl_b->m_lock, flags);
  515. if (ret == -CCCI_ERR_CCIF_NO_PHYSICAL_CHANNEL) {
  516. drop = 1;
  517. if ((get_debug_mode_flag() & (DBG_FLAG_JTAG | DBG_FLAG_DEBUG))
  518. == 0) {
  519. need_notify = 1;
  520. if ((ctl_b->m_status_flag & FIRST_PENDING) == 0) {
  521. ctl_b->m_status_flag |= FIRST_PENDING;
  522. ctl_b->m_last_send_ref_jiffies = get_jiffies_64(); /* Update jiffies; */
  523. } else {
  524. if (((get_jiffies_64() -
  525. ctl_b->m_last_send_ref_jiffies) > 5)
  526. && ((ctl_b->m_status_flag & PENDING_50MS) == 0)) { /* 50ms */
  527. /* Dump EE memory */
  528. args = 1;
  529. ctl_b->m_status_flag |= PENDING_50MS;
  530. } else if ((get_jiffies_64() - ctl_b->m_last_send_ref_jiffies) > 150) { /* 1500ms */
  531. /* Trigger EE */
  532. args = 2;
  533. /* ctl_b->m_status_flag |= PENDING_100MS; */
  534. ctl_b->m_status_flag |= PENDING_1500MS;
  535. }
  536. }
  537. }
  538. } else {
  539. ctl_b->m_status_flag = 0;
  540. }
  541. spin_unlock_irqrestore(&ctl_b->m_lock, flags);
  542. if ((NULL != ctl_b->m_send_notify_cb) && need_notify)
  543. ctl_b->m_send_notify_cb(md_id, args);
  544. add_logic_layer_record(md_id, msg, drop);
  545. return ret;
  546. }
  547. void ccci_disable_md_intr(int md_id)
  548. {
  549. struct ccif_t *ccif_obj;
  550. ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
  551. ccif_obj->ccif_dis_intr(ccif_obj);
  552. }
  553. void ccci_enable_md_intr(int md_id)
  554. {
  555. struct ccif_t *ccif_obj;
  556. ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
  557. ccif_obj->ccif_en_intr(ccif_obj);
  558. }
  559. void ccci_hal_reset(int md_id)
  560. {
  561. struct ccif_t *ccif_obj;
  562. ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
  563. ccif_obj->ccif_reset(ccif_obj);
  564. }
  565. void ccci_hal_irq_register(int md_id)
  566. {
  567. struct ccif_t *ccif_obj;
  568. ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
  569. ccif_obj->ccif_register_intr(ccif_obj);
  570. }
  571. int ccci_write_runtime_data(int md_id, unsigned char buf[], int len)
  572. {
  573. struct ccif_t *ccif_obj;
  574. int tmp;
  575. tmp = (int)buf;
  576. if ((tmp & (~0x3)) != tmp)
  577. return -CCCI_ERR_START_ADDR_NOT_4BYTES_ALIGN;
  578. if ((len & (~0x3)) != len)
  579. return -CCCI_ERR_NOT_DIVISIBLE_BY_4;
  580. ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
  581. return ccif_obj->ccif_write_runtime_data(ccif_obj, (unsigned int *)buf,
  582. len >> 2);
  583. }
  584. void ccci_dump_logic_layer_info(int md_id, unsigned int buf[], int len)
  585. {
  586. struct ccif_t *ccif;
  587. struct logic_dispatch_ctl_block_t *ctl_b;
  588. ctl_b = logic_dispatch_ctlb[md_id];
  589. if (ctl_b != NULL) {
  590. /* 1. Dump CCIF Info */
  591. ccif = ctl_b->m_ccif;
  592. ccif->ccif_dump_reg(ccif, buf, len);
  593. /* 2. Dump logic layer info */
  594. dump_logical_layer_tx_rx_histroy(md_id);
  595. }
  596. }
  597. void ccci_dump_hw_reg_val(int md_id, unsigned int buf[], int len)
  598. {
  599. struct ccif_t *ccif;
  600. struct logic_dispatch_ctl_block_t *ctl_b;
  601. ctl_b = logic_dispatch_ctlb[md_id];
  602. if (ctl_b != NULL) {
  603. /* 1. Dump CCIF Info */
  604. ccif = ctl_b->m_ccif;
  605. ccif->ccif_dump_reg(ccif, buf, len);
  606. }
  607. }
  608. /****************************************************************************/
  609. /* ccci logical layer initial */
  610. /* */
  611. /****************************************************************************/
  612. int ccci_logic_ctlb_init(int md_id)
  613. {
  614. int ret = 0;
  615. struct ccif_t *ccif;
  616. struct logic_channel_info_t *ch_info;
  617. int ch_id, ch_attr, i;
  618. struct logic_dispatch_ctl_block_t *ctl_b;
  619. struct ccif_hw_info_t ccif_hw_inf;
  620. CCCI_FUNC_ENTRY(md_id);
  621. /* Channel number check */
  622. if ((sizeof(logic_ch_static_info_tab) /
  623. sizeof(struct logic_channel_static_info_t)) != CCCI_MAX_CH_NUM) {
  624. CCCI_MSG_INF(md_id, "cci",
  625. "%s: channel max number mis-match fail\n",
  626. __func__);
  627. return -CCCI_ERR_CHANNEL_NUM_MIS_MATCH;
  628. }
  629. /* Allocate ctl block memory */
  630. ctl_b = (struct logic_dispatch_ctl_block_t *)
  631. kzalloc(sizeof(struct logic_dispatch_ctl_block_t), GFP_KERNEL);
  632. if (ctl_b == NULL) {
  633. CCCI_MSG_INF(md_id, "cci",
  634. "%s: alloc memory fail for logic_dispatch_ctlb\n",
  635. __func__);
  636. return -CCCI_ERR_ALLOCATE_MEMORY_FAIL;
  637. }
  638. logic_dispatch_ctlb[md_id] = ctl_b;
  639. /* Get CCIF HW info */
  640. if (get_ccif_hw_info(md_id, &ccif_hw_inf) < 0) {
  641. CCCI_MSG_INF(md_id, "cci", "%s: get ccif%d hw info fail\n",
  642. __func__, md_id + 1);
  643. ret = -CCCI_ERR_CCIF_GET_HW_INFO_FAIL;
  644. goto _ccif_instance_create_fail;
  645. }
  646. /* Create ccif instance */
  647. ccif = ccif_create_instance(&ccif_hw_inf, ctl_b, md_id);
  648. if (ccif == NULL) {
  649. CCCI_MSG_INF(md_id, "cci", "%s: create ccif instance fail\n",
  650. __func__);
  651. ret = -CCCI_ERR_CREATE_CCIF_INSTANCE_FAIL;
  652. goto _ccif_instance_create_fail;
  653. }
  654. ccif->ccif_init(ccif);
  655. ctl_b->m_ccif = ccif;
  656. /* Initialize logic channel and its kfifo */
  657. /* Step1, set all runtime channel id to CCCI_INVALID_CH_ID means default state */
  658. /* So, even if static channel table is out of order, we can make sure logic_dispatch_ctlb's channel */
  659. /* table is in order */
  660. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  661. ch_info = &ctl_b->m_logic_ch_table[i];
  662. ch_info->m_ch_id = CCCI_INVALID_CH_ID;
  663. }
  664. /* Step2, set all runtime channel info according to static channel info, make it in order */
  665. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  666. ch_id = logic_ch_static_info_tab[i].m_ch_id;
  667. ch_info = &ctl_b->m_logic_ch_table[ch_id];
  668. if (ch_info->m_ch_id != CCCI_INVALID_CH_ID) {
  669. CCCI_MSG_INF(md_id, "cci",
  670. "[Error]%s: ch%d has registered\n",
  671. __func__, ch_id);
  672. ret = -CCCI_ERR_REPEAT_CHANNEL_ID;
  673. goto _ccif_logic_channel_init_fail;
  674. } else {
  675. ch_info->m_ch_id = ch_id;
  676. ch_info->m_attrs = logic_ch_static_info_tab[i].m_attrs;
  677. ch_info->m_ch_name =
  678. logic_ch_static_info_tab[i].m_ch_name;
  679. ch_info->m_call_back = NULL;
  680. if (logic_ch_static_info_tab[i].m_kfifo_size) {
  681. if (0 !=
  682. kfifo_alloc(&ch_info->m_kfifo,
  683. sizeof(struct ccif_msg_t) *
  684. logic_ch_static_info_tab
  685. [i].m_kfifo_size, GFP_KERNEL)) {
  686. CCCI_MSG_INF(md_id, "cci",
  687. "%s: alloc kfifo fail for %s(ch%d)\n",
  688. __func__,
  689. ch_info->m_ch_name, ch_id);
  690. ch_info->m_kfifo_ready = 0;
  691. ret = CCCI_ERR_ALLOCATE_MEMORY_FAIL;
  692. goto _ccif_logic_channel_init_fail;
  693. } else {
  694. ch_info->m_kfifo_ready = 1;
  695. ch_info->m_md_id = md_id;
  696. }
  697. } else {
  698. ch_info->m_kfifo_ready = 0;
  699. }
  700. spin_lock_init(&ch_info->m_lock);
  701. }
  702. /* initial channel recording info */
  703. if (logic_ch_static_info_tab[i].m_attrs & L_CH_ATTR_TX)
  704. ch_attr = CCCI_LOG_TX;
  705. else
  706. ch_attr = CCCI_LOG_RX;
  707. statistics_init_ch_dir(md_id, ch_id, ch_attr,
  708. ch_info->m_ch_name);
  709. }
  710. /* Init logic_dispatch_ctlb */
  711. tasklet_init(&ctl_b->m_dispatch_tasklet, __logic_layer_tasklet,
  712. (unsigned long)ctl_b);
  713. ctl_b->m_has_pending_data = 0;
  714. ctl_b->m_freezed = 0;
  715. ctl_b->m_running = 0;
  716. /* ctl_b->m_privilege = MD_BOOT_STAGE_0; */
  717. ctl_b->m_md_id = md_id;
  718. snprintf(ctl_b->m_wakelock_name, sizeof(ctl_b->m_wakelock_name),
  719. "ccci%d_logic", (md_id + 1));
  720. wake_lock_init(&ctl_b->m_wakeup_wake_lock, WAKE_LOCK_SUSPEND,
  721. ctl_b->m_wakelock_name);
  722. ctl_b->m_send_notify_cb = NULL;
  723. spin_lock_init(&ctl_b->m_lock);
  724. /* Init CCIF now */
  725. ccif->register_call_back_func(ccif, __logic_dispatch_push,
  726. __let_logic_dispatch_tasklet_run);
  727. /* ccif->ccif_register_intr(ccif); */
  728. /* Init done */
  729. /* CCCI_DBG_MSG(md_id, "cci", "ccci_logic_ctlb_init success!\n"); */
  730. return ret;
  731. _ccif_logic_channel_init_fail:
  732. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  733. ch_info = &ctl_b->m_logic_ch_table[i];
  734. if (ch_info->m_kfifo_ready) {
  735. kfifo_free(&ch_info->m_kfifo);
  736. ch_info->m_kfifo_ready = 0;
  737. }
  738. }
  739. _ccif_instance_create_fail:
  740. kfree(ctl_b);
  741. logic_dispatch_ctlb[md_id] = NULL;
  742. return ret;
  743. }
  744. void ccci_logic_ctlb_deinit(int md_id)
  745. {
  746. struct ccif_t *ccif;
  747. struct logic_channel_info_t *ch_info;
  748. int i;
  749. struct logic_dispatch_ctl_block_t *ctl_b;
  750. ctl_b = logic_dispatch_ctlb[md_id];
  751. if (ctl_b != NULL) {
  752. /* Step 1, freeze ccci */
  753. ctl_b->m_freezed = 1;
  754. /* Step 2, de-init ccif */
  755. ccif = logic_dispatch_ctlb[md_id]->m_ccif;
  756. ccif->ccif_de_init(ccif);
  757. /* Step 3, kill ccci dispatch tasklet */
  758. tasklet_kill(&ctl_b->m_dispatch_tasklet);
  759. /* Step 4, free kfifo memory */
  760. for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
  761. ch_info = &ctl_b->m_logic_ch_table[i];
  762. if (ch_info->m_kfifo_ready) {
  763. kfifo_free(&ch_info->m_kfifo);
  764. ch_info->m_kfifo_ready = 0;
  765. }
  766. }
  767. /* Step 5, destroy wake lock */
  768. wake_lock_destroy(&ctl_b->m_wakeup_wake_lock);
  769. /* Step 6, free logic_dispatch_ctlb memory */
  770. kfree(ctl_b);
  771. logic_dispatch_ctlb[md_id] = NULL;
  772. }
  773. }
  774. int ccci_logic_layer_init(int md_id)
  775. {
  776. int ret = 0;
  777. ret = ccci_logic_ctlb_init(md_id);
  778. return ret;
  779. }
  780. void ccci_logic_layer_exit(int md_id)
  781. {
  782. ccci_logic_ctlb_deinit(md_id);
  783. }