sdio_boot.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/mm.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/fs.h>
  18. #include <linux/sched.h>
  19. #include <linux/slab.h>
  20. #include <linux/mmc/core.h>
  21. #include <linux/mmc/card.h>
  22. #include <linux/mmc/sdio_func.h>
  23. #include <linux/firmware.h>
  24. #include "gdm_sdio.h"
  25. #include "sdio_boot.h"
  26. #define TYPE_A_HEADER_SIZE 4
  27. #define TYPE_A_LOOKAHEAD_SIZE 16
  28. #define YMEM0_SIZE 0x8000 /* 32kbytes */
  29. #define DOWNLOAD_SIZE (YMEM0_SIZE - TYPE_A_HEADER_SIZE)
  30. #define FW_DIR "gdm72xx/"
  31. #define FW_KRN "gdmskrn.bin"
  32. #define FW_RFS "gdmsrfs.bin"
  33. static u8 *tx_buf;
  34. static int ack_ready(struct sdio_func *func)
  35. {
  36. unsigned long wait = jiffies + HZ;
  37. u8 val;
  38. int ret;
  39. while (time_before(jiffies, wait)) {
  40. val = sdio_readb(func, 0x13, &ret);
  41. if (val & 0x01)
  42. return 1;
  43. schedule();
  44. }
  45. return 0;
  46. }
  47. static int download_image(struct sdio_func *func, const char *img_name)
  48. {
  49. int ret = 0, len, pno;
  50. u8 *buf = tx_buf;
  51. loff_t pos = 0;
  52. int img_len;
  53. const struct firmware *firm;
  54. ret = request_firmware(&firm, img_name, &func->dev);
  55. if (ret < 0) {
  56. dev_err(&func->dev,
  57. "requesting firmware %s failed with error %d\n",
  58. img_name, ret);
  59. return ret;
  60. }
  61. buf = kmalloc(DOWNLOAD_SIZE + TYPE_A_HEADER_SIZE, GFP_KERNEL);
  62. if (!buf)
  63. return -ENOMEM;
  64. img_len = firm->size;
  65. if (img_len <= 0) {
  66. ret = -1;
  67. goto out;
  68. }
  69. pno = 0;
  70. while (img_len > 0) {
  71. if (img_len > DOWNLOAD_SIZE) {
  72. len = DOWNLOAD_SIZE;
  73. buf[3] = 0;
  74. } else {
  75. len = img_len; /* the last packet */
  76. buf[3] = 2;
  77. }
  78. buf[0] = len & 0xff;
  79. buf[1] = (len >> 8) & 0xff;
  80. buf[2] = (len >> 16) & 0xff;
  81. memcpy(buf+TYPE_A_HEADER_SIZE, firm->data + pos, len);
  82. ret = sdio_memcpy_toio(func, 0, buf, len + TYPE_A_HEADER_SIZE);
  83. if (ret < 0) {
  84. dev_err(&func->dev,
  85. "send image error: packet number = %d ret = %d\n",
  86. pno, ret);
  87. goto out;
  88. }
  89. if (buf[3] == 2) /* The last packet */
  90. break;
  91. if (!ack_ready(func)) {
  92. ret = -EIO;
  93. dev_err(&func->dev, "Ack is not ready.\n");
  94. goto out;
  95. }
  96. ret = sdio_memcpy_fromio(func, buf, 0, TYPE_A_LOOKAHEAD_SIZE);
  97. if (ret < 0) {
  98. dev_err(&func->dev,
  99. "receive ack error: packet number = %d ret = %d\n",
  100. pno, ret);
  101. goto out;
  102. }
  103. sdio_writeb(func, 0x01, 0x13, &ret);
  104. sdio_writeb(func, 0x00, 0x10, &ret); /* PCRRT */
  105. img_len -= DOWNLOAD_SIZE;
  106. pos += DOWNLOAD_SIZE;
  107. pno++;
  108. }
  109. out:
  110. kfree(buf);
  111. return ret;
  112. }
  113. int sdio_boot(struct sdio_func *func)
  114. {
  115. int ret;
  116. const char *krn_name = FW_DIR FW_KRN;
  117. const char *rfs_name = FW_DIR FW_RFS;
  118. tx_buf = kmalloc(YMEM0_SIZE, GFP_KERNEL);
  119. if (!tx_buf)
  120. return -ENOMEM;
  121. ret = download_image(func, krn_name);
  122. if (ret)
  123. goto restore_fs;
  124. dev_info(&func->dev, "GCT: Kernel download success.\n");
  125. ret = download_image(func, rfs_name);
  126. if (ret)
  127. goto restore_fs;
  128. dev_info(&func->dev, "GCT: Filesystem download success.\n");
  129. restore_fs:
  130. kfree(tx_buf);
  131. return ret;
  132. }