mbox-db5500.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
  4. * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
  5. * License terms: GNU General Public License (GPL), version 2.
  6. */
  7. /*
  8. * Mailbox nomenclature:
  9. *
  10. * APE MODEM
  11. * mbox pairX
  12. * ..........................
  13. * . .
  14. * . peer .
  15. * . send ---- .
  16. * . --> | | .
  17. * . | | .
  18. * . ---- .
  19. * . .
  20. * . local .
  21. * . rec ---- .
  22. * . | | <-- .
  23. * . | | .
  24. * . ---- .
  25. * .........................
  26. */
  27. #include <linux/init.h>
  28. #include <linux/module.h>
  29. #include <linux/device.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/spinlock.h>
  32. #include <linux/errno.h>
  33. #include <linux/io.h>
  34. #include <linux/irq.h>
  35. #include <linux/platform_device.h>
  36. #include <linux/debugfs.h>
  37. #include <linux/seq_file.h>
  38. #include <linux/completion.h>
  39. #include <mach/mbox-db5500.h>
  40. #define MBOX_NAME "mbox"
  41. #define MBOX_FIFO_DATA 0x000
  42. #define MBOX_FIFO_ADD 0x004
  43. #define MBOX_FIFO_REMOVE 0x008
  44. #define MBOX_FIFO_THRES_FREE 0x00C
  45. #define MBOX_FIFO_THRES_OCCUP 0x010
  46. #define MBOX_FIFO_STATUS 0x014
  47. #define MBOX_DISABLE_IRQ 0x4
  48. #define MBOX_ENABLE_IRQ 0x0
  49. #define MBOX_LATCH 1
  50. /* Global list of all mailboxes */
  51. static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
  52. static struct mbox *get_mbox_with_id(u8 id)
  53. {
  54. u8 i;
  55. struct list_head *pos = &mboxs;
  56. for (i = 0; i <= id; i++)
  57. pos = pos->next;
  58. return (struct mbox *) list_entry(pos, struct mbox, list);
  59. }
  60. int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
  61. {
  62. int res = 0;
  63. spin_lock(&mbox->lock);
  64. dev_dbg(&(mbox->pdev->dev),
  65. "About to buffer 0x%X to mailbox 0x%X."
  66. " ri = %d, wi = %d\n",
  67. mbox_msg, (u32)mbox, mbox->read_index,
  68. mbox->write_index);
  69. /* Check if write buffer is full */
  70. while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
  71. if (!block) {
  72. dev_dbg(&(mbox->pdev->dev),
  73. "Buffer full in non-blocking call! "
  74. "Returning -ENOMEM!\n");
  75. res = -ENOMEM;
  76. goto exit;
  77. }
  78. spin_unlock(&mbox->lock);
  79. dev_dbg(&(mbox->pdev->dev),
  80. "Buffer full in blocking call! Sleeping...\n");
  81. mbox->client_blocked = 1;
  82. wait_for_completion(&mbox->buffer_available);
  83. dev_dbg(&(mbox->pdev->dev),
  84. "Blocking send was woken up! Trying again...\n");
  85. spin_lock(&mbox->lock);
  86. }
  87. mbox->buffer[mbox->write_index] = mbox_msg;
  88. mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
  89. /*
  90. * Indicate that we want an IRQ as soon as there is a slot
  91. * in the FIFO
  92. */
  93. writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
  94. exit:
  95. spin_unlock(&mbox->lock);
  96. return res;
  97. }
  98. EXPORT_SYMBOL(mbox_send);
  99. #if defined(CONFIG_DEBUG_FS)
  100. /*
  101. * Expected input: <value> <nbr sends>
  102. * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
  103. */
  104. static ssize_t mbox_write_fifo(struct device *dev,
  105. struct device_attribute *attr,
  106. const char *buf,
  107. size_t count)
  108. {
  109. unsigned long mbox_mess;
  110. unsigned long nbr_sends;
  111. unsigned long i;
  112. char int_buf[16];
  113. char *token;
  114. char *val;
  115. struct mbox *mbox = (struct mbox *) dev->platform_data;
  116. strncpy((char *) &int_buf, buf, sizeof(int_buf));
  117. token = (char *) &int_buf;
  118. /* Parse message */
  119. val = strsep(&token, " ");
  120. if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
  121. mbox_mess = 0xDEADBEEF;
  122. val = strsep(&token, " ");
  123. if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
  124. nbr_sends = 1;
  125. dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
  126. mbox_mess, nbr_sends, (u32) mbox);
  127. for (i = 0; i < nbr_sends; i++)
  128. mbox_send(mbox, mbox_mess, true);
  129. return count;
  130. }
  131. static ssize_t mbox_read_fifo(struct device *dev,
  132. struct device_attribute *attr,
  133. char *buf)
  134. {
  135. int mbox_value;
  136. struct mbox *mbox = (struct mbox *) dev->platform_data;
  137. if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
  138. return sprintf(buf, "Mailbox is empty\n");
  139. mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
  140. writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
  141. return sprintf(buf, "0x%X\n", mbox_value);
  142. }
  143. static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
  144. static int mbox_show(struct seq_file *s, void *data)
  145. {
  146. struct list_head *pos;
  147. u8 mbox_index = 0;
  148. list_for_each(pos, &mboxs) {
  149. struct mbox *m =
  150. (struct mbox *) list_entry(pos, struct mbox, list);
  151. if (m == NULL) {
  152. seq_printf(s,
  153. "Unable to retrieve mailbox %d\n",
  154. mbox_index);
  155. continue;
  156. }
  157. spin_lock(&m->lock);
  158. if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
  159. seq_printf(s, "MAILBOX %d not setup or corrupt\n",
  160. mbox_index);
  161. spin_unlock(&m->lock);
  162. continue;
  163. }
  164. seq_printf(s,
  165. "===========================\n"
  166. " MAILBOX %d\n"
  167. " PEER MAILBOX DUMP\n"
  168. "---------------------------\n"
  169. "FIFO: 0x%X (%d)\n"
  170. "Free Threshold: 0x%.2X (%d)\n"
  171. "Occupied Threshold: 0x%.2X (%d)\n"
  172. "Status: 0x%.2X (%d)\n"
  173. " Free spaces (ot): %d (%d)\n"
  174. " Occup spaces (ot): %d (%d)\n"
  175. "===========================\n"
  176. " LOCAL MAILBOX DUMP\n"
  177. "---------------------------\n"
  178. "FIFO: 0x%.X (%d)\n"
  179. "Free Threshold: 0x%.2X (%d)\n"
  180. "Occupied Threshold: 0x%.2X (%d)\n"
  181. "Status: 0x%.2X (%d)\n"
  182. " Free spaces (ot): %d (%d)\n"
  183. " Occup spaces (ot): %d (%d)\n"
  184. "===========================\n"
  185. "write_index: %d\n"
  186. "read_index : %d\n"
  187. "===========================\n"
  188. "\n",
  189. mbox_index,
  190. readl(m->virtbase_peer + MBOX_FIFO_DATA),
  191. readl(m->virtbase_peer + MBOX_FIFO_DATA),
  192. readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
  193. readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
  194. readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
  195. readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
  196. readl(m->virtbase_peer + MBOX_FIFO_STATUS),
  197. readl(m->virtbase_peer + MBOX_FIFO_STATUS),
  198. (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
  199. (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
  200. (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
  201. (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
  202. readl(m->virtbase_local + MBOX_FIFO_DATA),
  203. readl(m->virtbase_local + MBOX_FIFO_DATA),
  204. readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
  205. readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
  206. readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
  207. readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
  208. readl(m->virtbase_local + MBOX_FIFO_STATUS),
  209. readl(m->virtbase_local + MBOX_FIFO_STATUS),
  210. (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
  211. (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
  212. (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
  213. (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
  214. m->write_index, m->read_index);
  215. mbox_index++;
  216. spin_unlock(&m->lock);
  217. }
  218. return 0;
  219. }
  220. static int mbox_open(struct inode *inode, struct file *file)
  221. {
  222. return single_open(file, mbox_show, NULL);
  223. }
  224. static const struct file_operations mbox_operations = {
  225. .owner = THIS_MODULE,
  226. .open = mbox_open,
  227. .read = seq_read,
  228. .llseek = seq_lseek,
  229. .release = single_release,
  230. };
  231. #endif
  232. static irqreturn_t mbox_irq(int irq, void *arg)
  233. {
  234. u32 mbox_value;
  235. int nbr_occup;
  236. int nbr_free;
  237. struct mbox *mbox = (struct mbox *) arg;
  238. spin_lock(&mbox->lock);
  239. dev_dbg(&(mbox->pdev->dev),
  240. "mbox IRQ [%d] received. ri = %d, wi = %d\n",
  241. irq, mbox->read_index, mbox->write_index);
  242. /*
  243. * Check if we have any outgoing messages, and if there is space for
  244. * them in the FIFO.
  245. */
  246. if (mbox->read_index != mbox->write_index) {
  247. /*
  248. * Check by reading FREE for LOCAL since that indicates
  249. * OCCUP for PEER
  250. */
  251. nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
  252. >> 4) & 0x7;
  253. dev_dbg(&(mbox->pdev->dev),
  254. "Status indicates %d empty spaces in the FIFO!\n",
  255. nbr_free);
  256. while ((nbr_free > 0) &&
  257. (mbox->read_index != mbox->write_index)) {
  258. /* Write the message and latch it into the FIFO */
  259. writel(mbox->buffer[mbox->read_index],
  260. (mbox->virtbase_peer + MBOX_FIFO_DATA));
  261. writel(MBOX_LATCH,
  262. (mbox->virtbase_peer + MBOX_FIFO_ADD));
  263. dev_dbg(&(mbox->pdev->dev),
  264. "Wrote message 0x%X to addr 0x%X\n",
  265. mbox->buffer[mbox->read_index],
  266. (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
  267. nbr_free--;
  268. mbox->read_index =
  269. (mbox->read_index + 1) % MBOX_BUF_SIZE;
  270. }
  271. /*
  272. * Check if we still want IRQ:s when there is free
  273. * space to send
  274. */
  275. if (mbox->read_index != mbox->write_index) {
  276. dev_dbg(&(mbox->pdev->dev),
  277. "Still have messages to send, but FIFO full. "
  278. "Request IRQ again!\n");
  279. writel(MBOX_ENABLE_IRQ,
  280. mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
  281. } else {
  282. dev_dbg(&(mbox->pdev->dev),
  283. "No more messages to send. "
  284. "Do not request IRQ again!\n");
  285. writel(MBOX_DISABLE_IRQ,
  286. mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
  287. }
  288. /*
  289. * Check if we can signal any blocked clients that it is OK to
  290. * start buffering again
  291. */
  292. if (mbox->client_blocked &&
  293. (((mbox->write_index + 1) % MBOX_BUF_SIZE)
  294. != mbox->read_index)) {
  295. dev_dbg(&(mbox->pdev->dev),
  296. "Waking up blocked client\n");
  297. complete(&mbox->buffer_available);
  298. mbox->client_blocked = 0;
  299. }
  300. }
  301. /* Check if we have any incoming messages */
  302. nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
  303. if (nbr_occup == 0)
  304. goto exit;
  305. if (mbox->cb == NULL) {
  306. dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
  307. "leaving %d incoming messages in fifo!\n", nbr_occup);
  308. goto exit;
  309. }
  310. /* Read and acknowledge the message */
  311. mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
  312. writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
  313. /* Notify consumer of new mailbox message */
  314. dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
  315. mbox_value);
  316. mbox->cb(mbox_value, mbox->client_data);
  317. exit:
  318. dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
  319. mbox->read_index, mbox->write_index);
  320. spin_unlock(&mbox->lock);
  321. return IRQ_HANDLED;
  322. }
  323. /* Setup is executed once for each mbox pair */
  324. struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
  325. {
  326. struct resource *resource;
  327. int irq;
  328. int res;
  329. struct mbox *mbox;
  330. mbox = get_mbox_with_id(mbox_id);
  331. if (mbox == NULL) {
  332. dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
  333. mbox_id);
  334. goto exit;
  335. }
  336. /*
  337. * Check if mailbox has been allocated to someone else,
  338. * otherwise allocate it
  339. */
  340. if (mbox->allocated) {
  341. dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
  342. mbox_id);
  343. mbox = NULL;
  344. goto exit;
  345. }
  346. mbox->allocated = true;
  347. dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
  348. mbox_id, (u32)mbox);
  349. mbox->client_data = priv;
  350. mbox->cb = mbox_cb;
  351. /* Get addr for peer mailbox and ioremap it */
  352. resource = platform_get_resource_byname(mbox->pdev,
  353. IORESOURCE_MEM,
  354. "mbox_peer");
  355. if (resource == NULL) {
  356. dev_err(&(mbox->pdev->dev),
  357. "Unable to retrieve mbox peer resource\n");
  358. mbox = NULL;
  359. goto exit;
  360. }
  361. dev_dbg(&(mbox->pdev->dev),
  362. "Resource name: %s start: 0x%X, end: 0x%X\n",
  363. resource->name, resource->start, resource->end);
  364. mbox->virtbase_peer = ioremap(resource->start, resource_size(resource));
  365. if (!mbox->virtbase_peer) {
  366. dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
  367. mbox = NULL;
  368. goto exit;
  369. }
  370. dev_dbg(&(mbox->pdev->dev),
  371. "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
  372. resource->start, resource->end, (u32) mbox->virtbase_peer);
  373. /* Get addr for local mailbox and ioremap it */
  374. resource = platform_get_resource_byname(mbox->pdev,
  375. IORESOURCE_MEM,
  376. "mbox_local");
  377. if (resource == NULL) {
  378. dev_err(&(mbox->pdev->dev),
  379. "Unable to retrieve mbox local resource\n");
  380. mbox = NULL;
  381. goto exit;
  382. }
  383. dev_dbg(&(mbox->pdev->dev),
  384. "Resource name: %s start: 0x%X, end: 0x%X\n",
  385. resource->name, resource->start, resource->end);
  386. mbox->virtbase_local = ioremap(resource->start, resource_size(resource));
  387. if (!mbox->virtbase_local) {
  388. dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
  389. mbox = NULL;
  390. goto exit;
  391. }
  392. dev_dbg(&(mbox->pdev->dev),
  393. "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
  394. resource->start, resource->end, (u32) mbox->virtbase_peer);
  395. init_completion(&mbox->buffer_available);
  396. mbox->client_blocked = 0;
  397. /* Get IRQ for mailbox and allocate it */
  398. irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
  399. if (irq < 0) {
  400. dev_err(&(mbox->pdev->dev),
  401. "Unable to retrieve mbox irq resource\n");
  402. mbox = NULL;
  403. goto exit;
  404. }
  405. dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
  406. res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
  407. if (res < 0) {
  408. dev_err(&(mbox->pdev->dev),
  409. "Unable to allocate mbox irq %d\n", irq);
  410. mbox = NULL;
  411. goto exit;
  412. }
  413. /* Set up mailbox to not launch IRQ on free space in mailbox */
  414. writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
  415. /*
  416. * Set up mailbox to launch IRQ on new message if we have
  417. * a callback set. If not, do not raise IRQ, but keep message
  418. * in FIFO for manual retrieval
  419. */
  420. if (mbox_cb != NULL)
  421. writel(MBOX_ENABLE_IRQ,
  422. mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
  423. else
  424. writel(MBOX_DISABLE_IRQ,
  425. mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
  426. #if defined(CONFIG_DEBUG_FS)
  427. res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
  428. if (res != 0)
  429. dev_warn(&(mbox->pdev->dev),
  430. "Unable to create mbox sysfs entry");
  431. (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
  432. NULL, &mbox_operations);
  433. #endif
  434. dev_info(&(mbox->pdev->dev),
  435. "Mailbox driver with index %d initiated!\n", mbox_id);
  436. exit:
  437. return mbox;
  438. }
  439. EXPORT_SYMBOL(mbox_setup);
  440. int __init mbox_probe(struct platform_device *pdev)
  441. {
  442. struct mbox local_mbox;
  443. struct mbox *mbox;
  444. int res = 0;
  445. dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
  446. memset(&local_mbox, 0x0, sizeof(struct mbox));
  447. /* Associate our mbox data with the platform device */
  448. res = platform_device_add_data(pdev,
  449. (void *) &local_mbox,
  450. sizeof(struct mbox));
  451. if (res != 0) {
  452. dev_err(&(pdev->dev),
  453. "Unable to allocate driver platform data!\n");
  454. goto exit;
  455. }
  456. mbox = (struct mbox *) pdev->dev.platform_data;
  457. mbox->pdev = pdev;
  458. mbox->write_index = 0;
  459. mbox->read_index = 0;
  460. INIT_LIST_HEAD(&(mbox->list));
  461. list_add_tail(&(mbox->list), &mboxs);
  462. sprintf(mbox->name, "%s", MBOX_NAME);
  463. spin_lock_init(&mbox->lock);
  464. dev_info(&(pdev->dev), "Mailbox driver loaded\n");
  465. exit:
  466. return res;
  467. }
  468. static struct platform_driver mbox_driver = {
  469. .driver = {
  470. .name = MBOX_NAME,
  471. .owner = THIS_MODULE,
  472. },
  473. };
  474. static int __init mbox_init(void)
  475. {
  476. return platform_driver_probe(&mbox_driver, mbox_probe);
  477. }
  478. module_init(mbox_init);
  479. void __exit mbox_exit(void)
  480. {
  481. platform_driver_unregister(&mbox_driver);
  482. }
  483. module_exit(mbox_exit);
  484. MODULE_LICENSE("GPL");
  485. MODULE_DESCRIPTION("MBOX driver");