ccci_tty.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*****************************************************************************
  2. *
  3. * Filename:
  4. * ---------
  5. * ccci_tty.c
  6. *
  7. * Project:
  8. * --------
  9. * ALPS
  10. *
  11. * Description:
  12. * ------------
  13. * MT65XX CCCI Virtual TTY Driver
  14. *
  15. ****************************************************************************/
  16. #include <linux/sched.h>
  17. #include <linux/module.h>
  18. #include <linux/device.h>
  19. #include <linux/wakelock.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/delay.h>
  22. #include <linux/wait.h>
  23. #include <linux/poll.h>
  24. #include <linux/tty.h>
  25. #include <linux/tty_driver.h>
  26. #include <linux/tty_flip.h>
  27. #include <linux/dma-mapping.h>
  28. #include <ccci.h>
  29. #include <ccci_tty.h>
  30. struct tty_instance_t {
  31. int m_md_id;
  32. int count;
  33. int ready;
  34. int need_reset;
  35. int reset_handle;
  36. int channel;
  37. int uart_tx;
  38. int uart_rx_ack;
  39. int idx;
  40. struct wake_lock wake_lock;
  41. char wakelock_name[16];
  42. wait_queue_head_t write_waitq;
  43. wait_queue_head_t read_waitq;
  44. wait_queue_head_t poll_waitq_r;
  45. wait_queue_head_t poll_waitq_w;
  46. spinlock_t poll_lock;
  47. struct shared_mem_tty_t *shared_mem;
  48. struct mutex ccci_tty_mutex;
  49. int has_pending_read;
  50. rwlock_t ccci_tty_rwlock;
  51. struct timer_list timer;
  52. struct tasklet_struct ccci_tty_tasklet;
  53. };
  54. struct tty_ctl_block_t {
  55. int m_md_id;
  56. struct tty_instance_t ccci_tty_modem;
  57. struct tty_instance_t ccci_tty_meta;
  58. struct tty_instance_t ccci_tty_ipc;
  59. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  60. struct tty_instance_t ccci_tty_icusb;
  61. #endif
  62. struct shared_mem_tty_t *uart1_shared_mem;
  63. struct shared_mem_tty_t *uart2_shared_mem;
  64. struct shared_mem_tty_t *uart3_shared_mem;
  65. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  66. struct shared_mem_tty_t *uart4_shared_mem;
  67. #endif
  68. int tty_buf_size;
  69. struct MD_CALL_BACK_QUEUE tty_notifier;
  70. char drv_name[32];
  71. char node_name[16];
  72. struct cdev ccci_tty_dev;
  73. int major;
  74. int minor;
  75. };
  76. static struct tty_ctl_block_t *tty_ctlb[MAX_MD_NUM];
  77. unsigned int tty_debug_enable[MAX_MD_NUM] = { 0 };
  78. /* 1UL<<0, tty_modem; 1UL<<1, tty_meta; 1UL<<2, tty_rpc */
  79. static int ccci_tty_readable(struct tty_instance_t *tty_instance)
  80. {
  81. int read, write, size;
  82. read = tty_instance->shared_mem->rx_control.read;
  83. write = tty_instance->shared_mem->rx_control.write;
  84. size = write - read;
  85. if (size < 0)
  86. size += tty_instance->shared_mem->rx_control.length;
  87. return size;
  88. }
  89. static int ccci_tty_writeable(struct tty_instance_t *tty_instance)
  90. {
  91. int read, write, size, length;
  92. read = tty_instance->shared_mem->tx_control.read;
  93. write = tty_instance->shared_mem->tx_control.write;
  94. length = tty_instance->shared_mem->tx_control.length;
  95. if (read == write) {
  96. size = length - 1;
  97. } else if (read < write) {
  98. size = length - write;
  99. size += read;
  100. } else {
  101. size = read - write - 1;
  102. }
  103. if ((size <= 0) || (length <= 0)) {
  104. CCCI_MSG_INF(tty_instance->m_md_id, "tty",
  105. "writeable: read=%d,write=%d,length=%d,size=%d\n",
  106. read, write, length, size);
  107. }
  108. return size;
  109. }
  110. /* will be called when modem sends us something. */
  111. /* we will then copy it to the tty's buffer. */
  112. /* this is essentially the "read" fops. */
  113. static void ccci_tty_callback(void *private)
  114. {
  115. struct logic_channel_info_t *ch_info = (struct logic_channel_info_t *) private;
  116. struct ccci_msg_t msg;
  117. struct tty_ctl_block_t *ctlb = (struct tty_ctl_block_t *) ch_info->m_owner;
  118. while (get_logic_ch_data(ch_info, &msg)) {
  119. switch (msg.channel) {
  120. case CCCI_UART1_TX_ACK:
  121. /* this should be in an interrupt, */
  122. /* so no locking required... */
  123. if (ccci_tty_writeable(&ctlb->ccci_tty_meta)) {
  124. wake_up_interruptible(&ctlb->
  125. ccci_tty_meta.write_waitq);
  126. wake_up_interruptible_poll(&ctlb->
  127. ccci_tty_meta.poll_waitq_w,
  128. POLLOUT);
  129. }
  130. break;
  131. case CCCI_UART1_RX:
  132. if (ccci_tty_readable(&ctlb->ccci_tty_meta)) {
  133. wake_up_interruptible(&ctlb->
  134. ccci_tty_meta.read_waitq);
  135. wake_up_interruptible_poll(&ctlb->
  136. ccci_tty_meta.poll_waitq_r,
  137. POLLIN);
  138. wake_lock_timeout(&ctlb->
  139. ccci_tty_meta.wake_lock,
  140. HZ / 2);
  141. }
  142. break;
  143. case CCCI_UART2_TX_ACK:
  144. /* this should be in an interrupt, */
  145. /* so no locking required... */
  146. if (ccci_tty_writeable(&ctlb->ccci_tty_modem)) {
  147. wake_up_interruptible(&ctlb->
  148. ccci_tty_modem.write_waitq);
  149. wake_up_interruptible_poll
  150. (&ctlb->ccci_tty_modem.poll_waitq_w,
  151. POLLOUT);
  152. }
  153. break;
  154. case CCCI_UART2_RX:
  155. if (ccci_tty_readable(&ctlb->ccci_tty_modem)) {
  156. ctlb->ccci_tty_modem.has_pending_read = 1;
  157. wake_up_interruptible(&ctlb->
  158. ccci_tty_modem.read_waitq);
  159. wake_up_interruptible_poll
  160. (&ctlb->ccci_tty_modem.poll_waitq_r,
  161. POLLIN);
  162. wake_lock_timeout(&ctlb->
  163. ccci_tty_modem.wake_lock,
  164. HZ / 2);
  165. }
  166. break;
  167. case CCCI_IPC_UART_TX_ACK:
  168. if (ccci_tty_writeable(&ctlb->ccci_tty_ipc)) {
  169. wake_up_interruptible(&ctlb->
  170. ccci_tty_ipc.write_waitq);
  171. wake_up_interruptible_poll(&ctlb->
  172. ccci_tty_ipc.poll_waitq_w,
  173. POLLOUT);
  174. }
  175. break;
  176. case CCCI_IPC_UART_RX:
  177. if (ccci_tty_readable(&ctlb->ccci_tty_ipc)) {
  178. wake_up_interruptible(&ctlb->
  179. ccci_tty_ipc.read_waitq);
  180. wake_up_interruptible_poll(&ctlb->
  181. ccci_tty_ipc.poll_waitq_r,
  182. POLLIN);
  183. wake_lock_timeout(&ctlb->ccci_tty_ipc.wake_lock,
  184. HZ / 2);
  185. }
  186. break;
  187. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  188. case CCCI_ICUSB_TX_ACK:
  189. if (ccci_tty_writeable(&ctlb->ccci_tty_icusb)) {
  190. wake_up_interruptible(&ctlb->
  191. ccci_tty_icusb.write_waitq);
  192. wake_up_interruptible_poll
  193. (&ctlb->ccci_tty_icusb.poll_waitq_w,
  194. POLLOUT);
  195. }
  196. break;
  197. case CCCI_ICUSB_RX:
  198. if (ccci_tty_readable(&ctlb->ccci_tty_icusb)) {
  199. wake_up_interruptible(&ctlb->
  200. ccci_tty_icusb.read_waitq);
  201. wake_up_interruptible_poll
  202. (&ctlb->ccci_tty_icusb.poll_waitq_r,
  203. POLLIN);
  204. wake_lock_timeout(&ctlb->
  205. ccci_tty_icusb.wake_lock,
  206. HZ / 2);
  207. }
  208. break;
  209. #endif
  210. default:
  211. break;
  212. }
  213. }
  214. }
  215. static ssize_t ccci_tty_read(struct file *file, char *buf, size_t count,
  216. loff_t *ppos)
  217. {
  218. struct tty_instance_t *tty_instance = (struct tty_instance_t *) file->private_data;
  219. int part, size, ret = 0;
  220. int value;
  221. unsigned read, write, length;
  222. struct ccci_msg_t msg;
  223. char *rx_buffer;
  224. int md_id = tty_instance->m_md_id;
  225. int data_be_read;
  226. char *u_buf = buf;
  227. read = tty_instance->shared_mem->rx_control.read;
  228. write = tty_instance->shared_mem->rx_control.write;
  229. rx_buffer = tty_instance->shared_mem->buffer;
  230. length = tty_instance->shared_mem->rx_control.length;
  231. do {
  232. size = ccci_tty_readable(tty_instance);
  233. if (size == 0) {
  234. if (file->f_flags & O_NONBLOCK) {
  235. ret = -EAGAIN;
  236. goto out;
  237. } else {
  238. /* Block read */
  239. value =
  240. wait_event_interruptible
  241. (tty_instance->read_waitq,
  242. ccci_tty_readable(tty_instance));
  243. if (value == -ERESTARTSYS) {
  244. CCCI_TTY_MSG(md_id,
  245. "Interrupted syscall.signal_pend=0x%llx\n",
  246. *(long long *)
  247. current->pending.signal.
  248. sig);
  249. ret = -EINTR;
  250. goto out;
  251. }
  252. }
  253. } else
  254. break;
  255. } while (size == 0);
  256. data_be_read = (int)count;
  257. if (tty_debug_enable[md_id] & (1UL << tty_instance->idx))
  258. CCCI_DBG_MSG(md_id, "tty",
  259. "[RX](Before) tty%d read_request=%d write=%04d read=%4d\n",
  260. tty_instance->idx, data_be_read,
  261. tty_instance->shared_mem->rx_control.write, read);
  262. if (data_be_read > size)
  263. data_be_read = size;
  264. /* copy_to_user may be scheduled, */
  265. /* So add 0.5s wake lock to make sure ccci user can be running. */
  266. wake_lock_timeout(&tty_instance->wake_lock, HZ / 2);
  267. if ((read + data_be_read) >= length) {
  268. /* Need read twice */
  269. /* Copy first part */
  270. part = length - read;
  271. if (copy_to_user(u_buf, &rx_buffer[read], part)) {
  272. CCCI_MSG_INF(md_id, "tty",
  273. "read: copy_to_user fail:u_buf=%08x,rx_buffer=0x%08x,read=%d,size=%d ret=%d line=%d\n",
  274. (unsigned int)u_buf,
  275. (unsigned int)rx_buffer, read, part, ret,
  276. __LINE__);
  277. ret = -EFAULT;
  278. goto out;
  279. }
  280. /* Copy second part */
  281. if (copy_to_user(&u_buf[part], rx_buffer, data_be_read - part)) {
  282. CCCI_MSG_INF(md_id, "tty",
  283. "read: copy_to_user fail:u_buf=%08x,rx_buffer=0x%08x,read=%d,size=%d ret=%d line=%d\n",
  284. (unsigned int)u_buf,
  285. (unsigned int)rx_buffer, read,
  286. data_be_read - part, ret, __LINE__);
  287. ret = -EFAULT;
  288. goto out;
  289. }
  290. } else {
  291. /* Just need read once */
  292. if (copy_to_user(u_buf, &rx_buffer[read], data_be_read)) {
  293. CCCI_MSG_INF(md_id, "tty",
  294. "read: copy_to_user fail:u_buf=%08x,rx_buffer=0x%08x,read=%d,size=%d ret=%d line=%d\n",
  295. (unsigned int)u_buf,
  296. (unsigned int)rx_buffer, read,
  297. data_be_read, ret, __LINE__);
  298. ret = -EFAULT;
  299. goto out;
  300. }
  301. }
  302. /* Update read pointer */
  303. read += data_be_read;
  304. if (read >= length)
  305. read -= length;
  306. tty_instance->shared_mem->rx_control.read = read;
  307. /* Ack to MD */
  308. msg.magic = 0xFFFFFFFF;
  309. msg.id = tty_instance->channel;
  310. msg.channel = tty_instance->uart_rx_ack;
  311. msg.reserved = 0;
  312. /*wait memory updated*/
  313. mb();
  314. ret = ccci_message_send(md_id, &msg, 1);
  315. if (ret != sizeof(msg)) {
  316. CCCI_DBG_MSG(md_id, "tty",
  317. "ccci_write_mailbox for %d fail: %d\n",
  318. tty_instance->channel, ret);
  319. /* mod_timer(&tty_instance->timer,jiffies + msecs_to_jiffies(10)); */
  320. } else {
  321. /* del_timer(&tty_instance->timer): */
  322. }
  323. ret = data_be_read;
  324. out:
  325. if (tty_debug_enable[md_id] & (1UL << tty_instance->idx))
  326. CCCI_DBG_MSG(md_id, "tty",
  327. "[RX](after) tty%d read_len=%d write=%04d read=%4d\n",
  328. tty_instance->idx, ret,
  329. tty_instance->shared_mem->rx_control.write,
  330. tty_instance->shared_mem->rx_control.read);
  331. return ret;
  332. }
  333. static ssize_t ccci_tty_write(struct file *file, const char __user *buf,
  334. size_t count, loff_t *ppos)
  335. {
  336. struct tty_instance_t *tty_instance = (struct tty_instance_t *) file->private_data;
  337. int ret = 0, part;
  338. int data_be_write, size, value;
  339. unsigned read, write, length;
  340. int xmit_retry = 0;
  341. struct ccci_msg_t msg;
  342. char *tx_buffer;
  343. int md_id = tty_instance->m_md_id;
  344. if (count == 0)
  345. return 0;
  346. mutex_lock(&tty_instance->ccci_tty_mutex);
  347. data_be_write = (int)count;
  348. if (tty_debug_enable[md_id] & (1UL << tty_instance->idx))
  349. CCCI_DBG_MSG(md_id, "tty",
  350. "[TX] (Before) tty%d write_request=%d write=%04d read=%4d\n",
  351. tty_instance->idx, data_be_write,
  352. tty_instance->shared_mem->tx_control.write,
  353. tty_instance->shared_mem->tx_control.read);
  354. size = 0;
  355. /* Check free space */
  356. read = tty_instance->shared_mem->tx_control.read;
  357. write = tty_instance->shared_mem->tx_control.write;
  358. length = tty_instance->shared_mem->tx_control.length;
  359. tx_buffer = tty_instance->shared_mem->buffer + length;
  360. do {
  361. size = ccci_tty_writeable(tty_instance);
  362. if (size == 0) {
  363. if (file->f_flags & O_NONBLOCK) {
  364. ret = -EAGAIN;
  365. goto out;
  366. } else {
  367. /* Block write */
  368. value =
  369. wait_event_interruptible
  370. (tty_instance->write_waitq,
  371. ccci_tty_writeable(tty_instance));
  372. if (value == -ERESTARTSYS) {
  373. CCCI_TTY_MSG(md_id,
  374. "(W)Interrupted syscall.signal_pend=0x%llx\n",
  375. *(long long *)
  376. current->pending.signal.
  377. sig);
  378. ret = -EINTR;
  379. goto out;
  380. }
  381. }
  382. } else
  383. break;
  384. } while (size == 0);
  385. /* Calculate write size */
  386. if (data_be_write >= size)
  387. data_be_write = size;
  388. if ((size <= 0) || (length <= 0) || (length - write <= 0)
  389. || (data_be_write <= 0)) {
  390. CCCI_MSG_INF(md_id, "tty",
  391. "write: length=%d,size=%d,write=%d,data_be_write=%d,count=%d\n",
  392. length, size, write, data_be_write, count);
  393. }
  394. if ((write + data_be_write) >= length) {
  395. /* Write twice */
  396. /* 1st write */
  397. part = length - write;
  398. ret = copy_from_user(&tx_buffer[write], buf, part);
  399. if (ret) {
  400. CCCI_MSG_INF(md_id, "tty",
  401. "write: copy from user fail:tx_buffer=0x%08x,write=%d, buf=%08x, part=%d ret=%d line=%d\n",
  402. (unsigned int)tx_buffer, write,
  403. (unsigned int)buf, part, ret, __LINE__);
  404. ret = -EFAULT;
  405. goto out;
  406. }
  407. /* 2nd write */
  408. ret =
  409. copy_from_user(tx_buffer, &buf[part], data_be_write - part);
  410. if (ret) {
  411. CCCI_MSG_INF(md_id, "tty",
  412. "write: copy from user fail:tx_buffer=0x%08x,buf=%08x,part=%d,data_be_write-part=%d ret=%d line=%d\n",
  413. (unsigned int)tx_buffer, (unsigned int)buf,
  414. part, data_be_write - part, ret, __LINE__);
  415. ret = -EFAULT;
  416. goto out;
  417. }
  418. } else {
  419. /* Write once is OK */
  420. ret = copy_from_user(&tx_buffer[write], buf, data_be_write);
  421. if (ret) {
  422. CCCI_MSG_INF(md_id, "tty",
  423. "write: copy from user fail:tx_buffer=0x%08x,write=%d,buf=%08x,data_be_write=%d ret=%d line=%d\n",
  424. (unsigned int)tx_buffer, write,
  425. (unsigned int)buf, data_be_write, ret,
  426. __LINE__);
  427. ret = -EFAULT;
  428. goto out;
  429. }
  430. }
  431. /* Updata read pointer */
  432. write += data_be_write;
  433. if (write >= length)
  434. write -= length;
  435. tty_instance->shared_mem->tx_control.write = write;
  436. /*wait memory updated*/
  437. mb();
  438. msg.addr = 0;
  439. msg.len = data_be_write;
  440. msg.channel = tty_instance->uart_tx;
  441. msg.reserved = 0;
  442. /*wait memory updated*/
  443. mb();
  444. do {
  445. ret = ccci_message_send(md_id, &msg, 1);
  446. if (ret == sizeof(msg))
  447. break;
  448. if (ret == -CCCI_ERR_CCIF_NO_PHYSICAL_CHANNEL) {
  449. xmit_retry++;
  450. msleep(20);
  451. } else
  452. break;
  453. } while (1);
  454. if (ret != sizeof(struct ccci_msg_t)) {
  455. tty_instance->ready = 1;
  456. if (ret == CCCI_MD_NOT_READY) {
  457. CCCI_DBG_MSG(md_id, "tty",
  458. "ttyC%d write fail when Modem not ready\n",
  459. tty_instance->channel);
  460. }
  461. } else {
  462. ret = data_be_write;
  463. }
  464. out:
  465. if (tty_debug_enable[md_id] & (1UL << tty_instance->idx))
  466. CCCI_DBG_MSG(md_id, "tty",
  467. "[TX] (After) tty%d write_request=%d write=%04d read=%4d\n",
  468. tty_instance->idx, ret,
  469. tty_instance->shared_mem->tx_control.write,
  470. tty_instance->shared_mem->tx_control.read);
  471. mutex_unlock(&tty_instance->ccci_tty_mutex);
  472. return ret;
  473. }
  474. static long ccci_tty_ioctl(struct file *file, unsigned int cmd,
  475. unsigned long arg)
  476. {
  477. int ret = 0;
  478. switch (cmd) {
  479. default:
  480. ret = 0;
  481. break;
  482. }
  483. return ret;
  484. }
  485. static unsigned int ccci_tty_poll(struct file *file, poll_table *wait)
  486. {
  487. struct tty_instance_t *tty_instance = (struct tty_instance_t *) file->private_data;
  488. int ret = 0;
  489. unsigned long flags;
  490. poll_wait(file, &tty_instance->poll_waitq_r, wait);
  491. poll_wait(file, &tty_instance->poll_waitq_w, wait);
  492. spin_lock_irqsave(&tty_instance->poll_lock, flags);
  493. if (ccci_tty_readable(tty_instance))
  494. ret |= POLLIN | POLLRDNORM;
  495. if (ccci_tty_writeable(tty_instance))
  496. ret |= POLLOUT | POLLWRNORM;
  497. spin_unlock_irqrestore(&tty_instance->poll_lock, flags);
  498. return ret;
  499. }
  500. static int ccci_tty_open(struct inode *inode, struct file *file)
  501. {
  502. int minor = iminor(inode);
  503. int major = imajor(inode);
  504. int index, minor_start;
  505. int md_id;
  506. int ret = 0;
  507. char *name;
  508. struct tty_ctl_block_t *ctlb;
  509. struct tty_instance_t *tty_instance = NULL;
  510. md_id = get_md_id_by_dev_major(major);
  511. if (md_id < 0) {
  512. CCCI_MSG_INF(md_id, "tty", "get_md_id_by_dev_major(%d)=%d\n",
  513. major, md_id);
  514. return -ENODEV;
  515. }
  516. ret = get_dev_id_by_md_id(md_id, "tty", NULL, &minor_start);
  517. if (ret < 0) {
  518. CCCI_MSG_INF(md_id, "tty", "get minor start fail(%d)\n", ret);
  519. return -ENODEV;
  520. }
  521. index = minor - minor_start;
  522. ctlb = tty_ctlb[md_id];
  523. switch (index) {
  524. case CCCI_TTY_MODEM:
  525. name = "ccci_modem";
  526. tty_instance = &ctlb->ccci_tty_modem;
  527. break;
  528. case CCCI_TTY_META:
  529. name = "ccci_meta";
  530. tty_instance = &ctlb->ccci_tty_meta;
  531. break;
  532. case CCCI_TTY_IPC:
  533. name = "ccci_ipc";
  534. tty_instance = &ctlb->ccci_tty_ipc;
  535. break;
  536. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  537. case CCCI_TTY_ICUSB:
  538. name = "ccci_icusb";
  539. tty_instance = &ctlb->ccci_tty_icusb;
  540. break;
  541. #endif
  542. default:
  543. return -ENODEV;
  544. }
  545. mutex_lock(&tty_instance->ccci_tty_mutex);
  546. tty_instance->count++;
  547. tty_instance->m_md_id = md_id;
  548. if (tty_instance->count > 1) {
  549. CCCI_MSG_INF(md_id, "tty",
  550. "[tty_open]Multi-Open! %s open %s%d, %s, count:%d\n",
  551. current->comm, ctlb->node_name, index, name,
  552. tty_instance->count);
  553. mutex_unlock(&tty_instance->ccci_tty_mutex);
  554. return -EMFILE;
  555. }
  556. CCCI_MSG_INF(md_id, "tty",
  557. "[tty_open]%s open %s%d, %s, nb_flag:%x\n",
  558. current->comm, ctlb->node_name, index, name,
  559. file->f_flags & O_NONBLOCK);
  560. write_lock_bh(&tty_instance->ccci_tty_rwlock);
  561. tty_instance->ready = 1;
  562. write_unlock_bh(&tty_instance->ccci_tty_rwlock);
  563. file->private_data = tty_instance;
  564. nonseekable_open(inode, file);
  565. mutex_unlock(&tty_instance->ccci_tty_mutex);
  566. /* Note: reset handle must be set after make sure open tty instance successfully */
  567. if (tty_instance->need_reset) {
  568. /* CCCI_MSG("<tty>%s opening ttyC%d, %s\n", current->comm, index, name); */
  569. tty_instance->reset_handle =
  570. ccci_reset_register(md_id, name);
  571. if (tty_instance->reset_handle < 0)
  572. CCCI_ERR_INF(md_id, "fs ", "tty_instance->reset_handle %d< 0\n",
  573. tty_instance->reset_handle);
  574. }
  575. return ret;
  576. }
  577. static int ccci_tty_release(struct inode *inode, struct file *file)
  578. {
  579. struct tty_instance_t *tty_instance = (struct tty_instance_t *) file->private_data;
  580. int md_id;
  581. struct tty_ctl_block_t *ctlb = NULL;
  582. md_id = tty_instance->m_md_id;
  583. ctlb = tty_ctlb[md_id];
  584. mutex_lock(&tty_instance->ccci_tty_mutex);
  585. tty_instance->count--;
  586. CCCI_MSG_INF(md_id, "tty", "[tty_close]Port%d count %d\n",
  587. tty_instance->idx, tty_instance->count);
  588. if (tty_instance->count == 0) {
  589. /* keep tty_instance->tty cannot be used by ccci_tty_read() */
  590. write_lock_bh(&tty_instance->ccci_tty_rwlock);
  591. tty_instance->ready = 0;
  592. write_unlock_bh(&tty_instance->ccci_tty_rwlock);
  593. ccci_reset_buffers(tty_instance->shared_mem,
  594. ctlb->tty_buf_size);
  595. if (tty_instance->need_reset) {
  596. if (tty_instance->reset_handle >= 0) {
  597. ccci_user_ready_to_reset(md_id,
  598. tty_instance->reset_handle);
  599. } else {
  600. CCCI_MSG_INF(md_id, "tty",
  601. "[tty_close] fail, Invalid reset handle(port%d): %d\n",
  602. tty_instance->idx,
  603. tty_instance->reset_handle);
  604. }
  605. }
  606. }
  607. mutex_unlock(&tty_instance->ccci_tty_mutex);
  608. return 0;
  609. }
  610. void ccci_reset_buffers(struct shared_mem_tty_t *shared_mem, int size)
  611. {
  612. shared_mem->tx_control.length = size;
  613. shared_mem->tx_control.read = 0;
  614. shared_mem->tx_control.write = 0;
  615. shared_mem->rx_control.length = size;
  616. shared_mem->rx_control.read = 0;
  617. shared_mem->rx_control.write = 0;
  618. memset(shared_mem->buffer, 0, size * 2);
  619. }
  620. int ccci_uart_ipo_h_restore(int md_id)
  621. {
  622. struct tty_ctl_block_t *ctlb = NULL;
  623. ctlb = tty_ctlb[md_id];
  624. ccci_reset_buffers(ctlb->uart1_shared_mem, ctlb->tty_buf_size);
  625. ccci_reset_buffers(ctlb->uart2_shared_mem, ctlb->tty_buf_size);
  626. ccci_reset_buffers(ctlb->uart3_shared_mem, ctlb->tty_buf_size);
  627. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  628. ccci_reset_buffers(ctlb->uart4_shared_mem, ctlb->tty_buf_size);
  629. #endif
  630. return 0;
  631. }
  632. static void tty_call_back_func(struct MD_CALL_BACK_QUEUE *notifier,
  633. unsigned long data)
  634. {
  635. struct tty_ctl_block_t *ctl_b =
  636. container_of(notifier, struct tty_ctl_block_t, tty_notifier);
  637. int md_id = ctl_b->m_md_id;
  638. switch (data) {
  639. case CCCI_MD_RESET:
  640. CCCI_TTY_MSG(md_id, "tty_call_back_func: reset tty buffers\n");
  641. ccci_reset_buffers(ctl_b->ccci_tty_meta.shared_mem,
  642. ctl_b->tty_buf_size);
  643. ccci_reset_buffers(ctl_b->ccci_tty_modem.shared_mem,
  644. ctl_b->tty_buf_size);
  645. ccci_reset_buffers(ctl_b->ccci_tty_ipc.shared_mem,
  646. ctl_b->tty_buf_size);
  647. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  648. ccci_reset_buffers(ctl_b->ccci_tty_icusb.shared_mem,
  649. ctl_b->tty_buf_size);
  650. #endif
  651. break;
  652. default:
  653. break;
  654. }
  655. }
  656. static const struct file_operations ccci_tty_ops = {
  657. .owner = THIS_MODULE,
  658. .open = ccci_tty_open,
  659. .read = ccci_tty_read,
  660. .write = ccci_tty_write,
  661. .release = ccci_tty_release,
  662. .unlocked_ioctl = ccci_tty_ioctl,
  663. .poll = ccci_tty_poll,
  664. };
  665. void tty_timer_func(unsigned long data)
  666. {
  667. #if 0
  668. struct tty_instance_t *tty_instance = (struct tty_instance_t *) data;
  669. struct tty_ctl_block_t *ctlb = NULL;
  670. int md_id = tty_instance->m_md_id;
  671. CCCI_DBG_MSG(md_id, "tty", "timer func running\n");
  672. switch (tty_instance->idx) {
  673. case CCCI_TTY_MODEM:
  674. ctlb =
  675. container_of(tty_instance, struct tty_ctl_block_t, ccci_tty_modem);
  676. tasklet_schedule(&ctlb->ccci_tty_modem_read_tasklet);
  677. break;
  678. case CCCI_TTY_META:
  679. CCCI_DBG_MSG(md_id, "tty", "timer: META\n");
  680. ctlb =
  681. container_of(tty_instance, struct tty_ctl_block_t, ccci_tty_meta);
  682. tasklet_schedule(&ctlb->ccci_tty_meta_read_tasklet);
  683. break;
  684. case CCCI_TTY_IPC:
  685. ctlb =
  686. container_of(tty_instance, struct tty_ctl_block_t, ccci_tty_ipc);
  687. tasklet_schedule(&ctlb->ccci_tty_ipc_read_tasklet);
  688. break;
  689. }
  690. #endif
  691. }
  692. #define CCCI_TTY_NAME "ccci_tty_drv"
  693. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  694. #define CCCI_TTY_DEV_NUM (4)
  695. #else
  696. #define CCCI_TTY_DEV_NUM (3)
  697. #endif
  698. void ccci_tty_instance_init(struct tty_instance_t *instance)
  699. {
  700. rwlock_init(&instance->ccci_tty_rwlock);
  701. spin_lock_init(&instance->poll_lock);
  702. wake_lock_init(&instance->wake_lock, WAKE_LOCK_SUSPEND,
  703. instance->wakelock_name);
  704. /* setup_timer(&instance->timer, tty_timer_func, instance); */
  705. mutex_init(&instance->ccci_tty_mutex);
  706. init_waitqueue_head(&instance->read_waitq);
  707. init_waitqueue_head(&instance->write_waitq);
  708. init_waitqueue_head(&instance->poll_waitq_r);
  709. init_waitqueue_head(&instance->poll_waitq_w);
  710. /* tasklet_init(&instance->ccci_tty_tasklet, ccci_tty_read, instance); */
  711. }
  712. int ccci_tty_init(int md_id)
  713. {
  714. int ret = 0;
  715. int smem_phy = 0;
  716. int smem_size = 0;
  717. int tty_buf_len;
  718. int major, minor;
  719. struct tty_ctl_block_t *ctlb;
  720. char name[16];
  721. /* Create control block structure */
  722. ctlb = kmalloc(sizeof(struct tty_ctl_block_t), GFP_KERNEL);
  723. if (ctlb == NULL)
  724. return -CCCI_ERR_GET_MEM_FAIL;
  725. memset(ctlb, 0, sizeof(struct tty_ctl_block_t));
  726. tty_ctlb[md_id] = ctlb;
  727. /* Init ctlb */
  728. ctlb->m_md_id = md_id;
  729. ctlb->tty_notifier.call = tty_call_back_func;
  730. ctlb->tty_notifier.next = NULL;
  731. ret = md_register_call_chain(md_id, &ctlb->tty_notifier);
  732. if (ret) {
  733. CCCI_MSG_INF(md_id, "tty", "md_register_call_chain fail: %d\n",
  734. ret);
  735. goto _RELEASE_CTL_MEMORY;
  736. }
  737. ret = get_dev_id_by_md_id(md_id, "tty", &major, &minor);
  738. if (ret < 0)
  739. goto _RELEASE_CTL_MEMORY;
  740. snprintf(name, 16, "%s%d", CCCI_TTY_NAME, md_id);
  741. if (register_chrdev_region(MKDEV(major, minor), CCCI_TTY_DEV_NUM, name)
  742. != 0) {
  743. CCCI_MSG_INF(md_id, "tty", "regsiter CCCI_TTY fail\n");
  744. ret = -1;
  745. goto _RELEASE_CTL_MEMORY;
  746. }
  747. cdev_init(&ctlb->ccci_tty_dev, &ccci_tty_ops);
  748. ctlb->ccci_tty_dev.owner = THIS_MODULE;
  749. ret =
  750. cdev_add(&ctlb->ccci_tty_dev, MKDEV(major, minor),
  751. CCCI_TTY_DEV_NUM);
  752. if (ret) {
  753. CCCI_MSG_INF(md_id, "tty", "cdev_add fail\n");
  754. goto _DEL_TTY_DRV;
  755. }
  756. snprintf(ctlb->drv_name, 32, CCCI_TTY_NAME "_%d", md_id);
  757. if (md_id == MD_SYS1)
  758. snprintf(ctlb->node_name, 16, "ttyC");
  759. else if (md_id == MD_SYS2)
  760. snprintf(ctlb->node_name, 16, "ccci%d_tty", md_id + 1);
  761. ccci_uart_base_req(md_id, 0, (int *)&ctlb->uart1_shared_mem, &smem_phy, &smem_size);
  762. /* CCCI_DBG_MSG(md_id, "tty", "TTY0 %x:%x:%d\n", (unsigned int)ctlb->uart1_shared_mem, */
  763. /* (unsigned int)smem_phy, smem_size); */
  764. /* Get tty config information */
  765. ccci_get_sub_module_cfg(md_id, "tty", (char *)&tty_buf_len, sizeof(int));
  766. tty_buf_len = (tty_buf_len - sizeof(struct shared_mem_tty_t)) / 2;
  767. ctlb->tty_buf_size = tty_buf_len;
  768. /* Meta section */
  769. ctlb->uart1_shared_mem->tx_control.length = tty_buf_len;
  770. ctlb->uart1_shared_mem->tx_control.read = 0;
  771. ctlb->uart1_shared_mem->tx_control.write = 0;
  772. ctlb->uart1_shared_mem->rx_control.length = tty_buf_len;
  773. ctlb->uart1_shared_mem->rx_control.read = 0;
  774. ctlb->uart1_shared_mem->rx_control.write = 0;
  775. /* meta related channel register */
  776. register_to_logic_ch(md_id, CCCI_UART1_RX, ccci_tty_callback, ctlb);
  777. register_to_logic_ch(md_id, CCCI_UART1_TX_ACK, ccci_tty_callback, ctlb);
  778. ctlb->ccci_tty_meta.need_reset = 0;
  779. ctlb->ccci_tty_meta.reset_handle = -1;
  780. ctlb->ccci_tty_meta.count = 0;
  781. ctlb->ccci_tty_meta.channel = 0;
  782. ctlb->ccci_tty_meta.shared_mem = ctlb->uart1_shared_mem;
  783. ctlb->ccci_tty_meta.uart_tx = CCCI_UART1_TX;
  784. ctlb->ccci_tty_meta.uart_rx_ack = CCCI_UART1_RX_ACK;
  785. ctlb->ccci_tty_meta.ready = 1;
  786. ctlb->ccci_tty_meta.idx = 1;
  787. snprintf(ctlb->ccci_tty_meta.wakelock_name,
  788. sizeof(ctlb->ccci_tty_meta.wakelock_name), "%s%d", "ccci_meta",
  789. (md_id + 1));
  790. ccci_tty_instance_init(&ctlb->ccci_tty_meta);
  791. /* MUX section */
  792. ccci_uart_base_req(md_id, 1, (int *)&ctlb->uart2_shared_mem, &smem_phy, &smem_size);
  793. /* CCCI_DBG_MSG(md_id, "tty", "TTY1 %x:%x:%d\n", (unsigned int)ctlb->uart2_shared_mem, */
  794. /* (unsigned int)smem_phy, smem_size); */
  795. ctlb->uart2_shared_mem->tx_control.length = tty_buf_len;
  796. ctlb->uart2_shared_mem->tx_control.read = 0;
  797. ctlb->uart2_shared_mem->tx_control.write = 0;
  798. ctlb->uart2_shared_mem->rx_control.length = tty_buf_len;
  799. ctlb->uart2_shared_mem->rx_control.read = 0;
  800. ctlb->uart2_shared_mem->rx_control.write = 0;
  801. /* modem related channel registration. */
  802. register_to_logic_ch(md_id, CCCI_UART2_RX, ccci_tty_callback, ctlb);
  803. register_to_logic_ch(md_id, CCCI_UART2_TX_ACK, ccci_tty_callback, ctlb);
  804. /* modem reset registration. */
  805. ctlb->ccci_tty_modem.need_reset = 1;
  806. ctlb->ccci_tty_modem.reset_handle = -1;
  807. ctlb->ccci_tty_modem.count = 0;
  808. ctlb->ccci_tty_modem.channel = 1;
  809. ctlb->ccci_tty_modem.shared_mem = ctlb->uart2_shared_mem;
  810. ctlb->ccci_tty_modem.uart_tx = CCCI_UART2_TX;
  811. ctlb->ccci_tty_modem.uart_rx_ack = CCCI_UART2_RX_ACK;
  812. ctlb->ccci_tty_modem.ready = 1;
  813. ctlb->ccci_tty_modem.idx = 0;
  814. snprintf(ctlb->ccci_tty_modem.wakelock_name,
  815. sizeof(ctlb->ccci_tty_modem.wakelock_name), "%s%d",
  816. "ccci_modem", (md_id + 1));
  817. ccci_tty_instance_init(&ctlb->ccci_tty_modem);
  818. /* for IPC uart */
  819. ccci_uart_base_req(md_id, 5, (int *)&ctlb->uart3_shared_mem, &smem_phy, &smem_size);
  820. /* CCCI_DBG_MSG(md_id, "tty", "TTY2 %x:%x:%d\n", (unsigned int)ctlb->uart3_shared_mem, */
  821. /* (unsigned int)smem_phy, smem_size); */
  822. ctlb->uart3_shared_mem->tx_control.length = tty_buf_len;
  823. ctlb->uart3_shared_mem->tx_control.read = 0;
  824. ctlb->uart3_shared_mem->tx_control.write = 0;
  825. ctlb->uart3_shared_mem->rx_control.length = tty_buf_len;
  826. ctlb->uart3_shared_mem->rx_control.read = 0;
  827. ctlb->uart3_shared_mem->rx_control.write = 0;
  828. /* IPC related channel register */
  829. register_to_logic_ch(md_id, CCCI_IPC_UART_RX, ccci_tty_callback, ctlb);
  830. register_to_logic_ch(md_id, CCCI_IPC_UART_TX_ACK, ccci_tty_callback, ctlb);
  831. /* IPC reset register */
  832. ctlb->ccci_tty_ipc.need_reset = 0;
  833. ctlb->ccci_tty_ipc.reset_handle = -1;
  834. ctlb->ccci_tty_ipc.count = 0;
  835. ctlb->ccci_tty_ipc.channel = 1;
  836. ctlb->ccci_tty_ipc.shared_mem = ctlb->uart3_shared_mem;
  837. ctlb->ccci_tty_ipc.uart_tx = CCCI_IPC_UART_TX;
  838. ctlb->ccci_tty_ipc.uart_rx_ack = CCCI_IPC_UART_RX_ACK;
  839. ctlb->ccci_tty_ipc.ready = 1;
  840. ctlb->ccci_tty_ipc.idx = 2;
  841. snprintf(ctlb->ccci_tty_ipc.wakelock_name,
  842. sizeof(ctlb->ccci_tty_ipc.wakelock_name), "%s%d", "ccci_ipc",
  843. (md_id + 1));
  844. ccci_tty_instance_init(&ctlb->ccci_tty_ipc);
  845. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  846. /* for ICUSB uart */
  847. ccci_uart_base_req(md_id, 6, (int *)&ctlb->uart4_shared_mem, &smem_phy, &smem_size);
  848. /* CCCI_DBG_MSG(md_id, "tty", "TTY2 %x:%x:%d\n", (unsigned int)ctlb->uart3_shared_mem, */
  849. /* (unsigned int)smem_phy, smem_size); */
  850. ctlb->uart4_shared_mem->tx_control.length = tty_buf_len;
  851. ctlb->uart4_shared_mem->tx_control.read = 0;
  852. ctlb->uart4_shared_mem->tx_control.write = 0;
  853. ctlb->uart4_shared_mem->rx_control.length = tty_buf_len;
  854. ctlb->uart4_shared_mem->rx_control.read = 0;
  855. ctlb->uart4_shared_mem->rx_control.write = 0;
  856. /* IPC related channel register */
  857. register_to_logic_ch(md_id, CCCI_ICUSB_RX, ccci_tty_callback, ctlb);
  858. register_to_logic_ch(md_id, CCCI_ICUSB_TX_ACK, ccci_tty_callback, ctlb);
  859. /* IPC reset register */
  860. ctlb->ccci_tty_icusb.need_reset = 0;
  861. ctlb->ccci_tty_icusb.reset_handle = -1;
  862. ctlb->ccci_tty_icusb.count = 0;
  863. ctlb->ccci_tty_icusb.channel = 1;
  864. ctlb->ccci_tty_icusb.shared_mem = ctlb->uart4_shared_mem;
  865. ctlb->ccci_tty_icusb.uart_tx = CCCI_ICUSB_TX;
  866. ctlb->ccci_tty_icusb.uart_rx_ack = CCCI_ICUSB_RX_ACK;
  867. ctlb->ccci_tty_icusb.ready = 1;
  868. ctlb->ccci_tty_icusb.idx = 3;
  869. snprintf(ctlb->ccci_tty_icusb.wakelock_name,
  870. sizeof(ctlb->ccci_tty_icusb.wakelock_name), "%s%d",
  871. "ccci_icusb", (md_id + 1));
  872. ccci_tty_instance_init(&ctlb->ccci_tty_icusb);
  873. #endif
  874. return 0;
  875. _DEL_TTY_DRV:
  876. unregister_chrdev_region(MKDEV(major, minor), CCCI_TTY_DEV_NUM);
  877. _RELEASE_CTL_MEMORY:
  878. kfree(ctlb);
  879. tty_ctlb[md_id] = NULL;
  880. return ret;
  881. }
  882. void __exit ccci_tty_exit(int md_id)
  883. {
  884. struct tty_ctl_block_t *ctlb = tty_ctlb[md_id];
  885. if (ctlb != NULL) {
  886. unregister_chrdev_region(MKDEV(ctlb->major, ctlb->minor),
  887. CCCI_TTY_DEV_NUM);
  888. cdev_del(&ctlb->ccci_tty_dev);
  889. un_register_to_logic_ch(md_id, CCCI_UART1_RX);
  890. /* ccci_unregister(CCCI_UART1_RX_ACK); */
  891. /* ccci_unregister(CCCI_UART1_TX); */
  892. un_register_to_logic_ch(md_id, CCCI_UART1_TX_ACK);
  893. un_register_to_logic_ch(md_id, CCCI_UART2_RX);
  894. /* ccci_unregister(CCCI_UART2_RX_ACK); */
  895. /* ccci_unregister(CCCI_UART2_TX); */
  896. un_register_to_logic_ch(md_id, CCCI_UART2_TX_ACK);
  897. un_register_to_logic_ch(md_id, CCCI_IPC_UART_RX);
  898. /* ccci_unregister(CCCI_IPC_UART_RX_ACK); */
  899. /* ccci_unregister(CCCI_IPC_UART_TX); */
  900. un_register_to_logic_ch(md_id, CCCI_IPC_UART_TX_ACK);
  901. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  902. un_register_to_logic_ch(md_id, CCCI_ICUSB_RX);
  903. un_register_to_logic_ch(md_id, CCCI_ICUSB_TX_ACK);
  904. #endif
  905. ctlb->uart1_shared_mem = NULL;
  906. ctlb->uart2_shared_mem = NULL;
  907. ctlb->uart3_shared_mem = NULL;
  908. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  909. ctlb->uart4_shared_mem = NULL;
  910. #endif
  911. wake_lock_destroy(&ctlb->ccci_tty_modem.wake_lock);
  912. wake_lock_destroy(&ctlb->ccci_tty_meta.wake_lock);
  913. wake_lock_destroy(&ctlb->ccci_tty_ipc.wake_lock);
  914. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  915. wake_lock_destroy(&ctlb->ccci_tty_icusb.wake_lock);
  916. #endif
  917. kfree(ctlb);
  918. tty_ctlb[md_id] = NULL;
  919. }
  920. }