emmc_generic_inter.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <stdint.h>
  32. #include <printf.h>
  33. #include <malloc.h>
  34. #include <string.h>
  35. #ifdef MTK_GPT_SCHEME_SUPPORT
  36. #include <platform/partition.h>
  37. #else
  38. #include <mt_partition.h>
  39. #endif
  40. #include <part_interface.h>
  41. #include <platform/errno.h>
  42. #include <debug.h>
  43. #include <kernel/mutex.h>
  44. /* alignment handler
  45. * MSDC HW dma does not need to make alignment
  46. * MSDC PIO mode needs to be 4 byte align */
  47. #define DMA_BUF_ALIGN_SIZE 1
  48. #define PIO_BUF_ALIGN_SIZE 4
  49. #define MAX(a,b) (((a)>(b))?(a):(b))
  50. #define PART_BUF_ALIGN_SIZE MAX(DMA_BUF_ALIGN_SIZE,PIO_BUF_ALIGN_SIZE)
  51. static part_dev_t *mt_part_dev;
  52. static uchar *mt_part_buf;
  53. static mutex_t g_part_lock;
  54. static ulong mt_part_alloc_buffer_align(uchar** buf_alloc, ulong item_cnt, int item_size) {
  55. ulong blkcnt_buf = item_cnt;
  56. *buf_alloc = NULL;
  57. while (blkcnt_buf > 0) {
  58. *buf_alloc = (uchar*)memalign(PART_BUF_ALIGN_SIZE, blkcnt_buf * item_size);
  59. if (*buf_alloc != NULL) {
  60. break;
  61. } else {
  62. blkcnt_buf = blkcnt_buf >> 1;
  63. }
  64. }
  65. if (*buf_alloc == NULL) {
  66. dprintf(CRITICAL, "[%s:%d] allocate %lu bytes buffer for alignment handler fail\n", __FUNCTION__, __LINE__, blkcnt_buf * item_size);
  67. *buf_alloc = (uchar *) &mt_part_buf[0];
  68. blkcnt_buf = 1;
  69. }
  70. dprintf(INFO, "[%s:%d] allocate %lu bytes buffer for alignment handler, addr:%x\n", __FUNCTION__, __LINE__, blkcnt_buf * item_size, (u32)*buf_alloc);
  71. return blkcnt_buf;
  72. }
  73. static int mt_part_generic_read(part_dev_t *dev, u64 src, uchar *dst, int size)
  74. {
  75. int dev_id = dev->id;
  76. uchar *buf;
  77. block_dev_desc_t *blkdev = dev->blkdev;
  78. u64 end, part_start, part_end, part_len, aligned_start, aligned_end;
  79. u32 dst_start;
  80. ulong blknr, blkcnt, blkcnt_buf;
  81. if (!blkdev) {
  82. dprintf(CRITICAL,"No block device registered\n");
  83. return -ENODEV;
  84. }
  85. if (size == 0) {
  86. return 0;
  87. }
  88. end = src + size;
  89. part_start = src & ((u64)blkdev->blksz - 1);
  90. part_end = end & ((u64)blkdev->blksz - 1);
  91. aligned_start = src & ~((u64)blkdev->blksz - 1);
  92. aligned_end = end & ~((u64)blkdev->blksz - 1);
  93. mutex_acquire(&g_part_lock);
  94. if (part_start) {
  95. buf = (uchar *) &mt_part_buf[0];
  96. blknr = aligned_start >> (blkdev->blk_bits);
  97. part_len = blkdev->blksz - part_start;
  98. if (part_len > (u64)size) {
  99. part_len = size;
  100. }
  101. if ((blkdev->block_read(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  102. mutex_release(&g_part_lock);
  103. return -EIO;
  104. }
  105. memcpy(dst, buf + part_start, part_len);
  106. dst += part_len;
  107. src += part_len;
  108. }
  109. aligned_start = src & ~((u64)blkdev->blksz - 1);
  110. blknr = aligned_start >> (blkdev->blk_bits);
  111. blkcnt = (aligned_end - aligned_start) >> (blkdev->blk_bits);
  112. dst_start = (u32)dst & (PART_BUF_ALIGN_SIZE - 1); // dst buffer alignment
  113. if (blkcnt > 0) {
  114. if (dst_start) {
  115. //dprintf(INFO,"[%s:%d] %llx, %x, %d, %lu, %lu, %d\n", __FUNCTION__, __LINE__, src, (u32)dst, dst_start, blknr, blkcnt, PART_BUF_ALIGN_SIZE);
  116. blkcnt_buf = mt_part_alloc_buffer_align(&buf, blkcnt, blkdev->blksz);
  117. while (blkcnt >= blkcnt_buf) {
  118. if ((blkdev->block_read(dev_id, blknr, blkcnt_buf, (unsigned long *)buf)) != blkcnt_buf) {
  119. mutex_release(&g_part_lock);
  120. if (buf)
  121. free(buf);
  122. return -EIO;
  123. }
  124. memcpy(dst, buf, blkcnt_buf * blkdev->blksz);
  125. blknr += blkcnt_buf;
  126. blkcnt -= blkcnt_buf;
  127. src += (blkcnt_buf << blkdev->blk_bits);
  128. dst += (blkcnt_buf << blkdev->blk_bits);
  129. }
  130. //dprintf(INFO, "[%s:%d] remain blkcnt: %lu\n", __FUNCTION__, __LINE__, blkcnt);
  131. if (blkcnt > 0) {
  132. if ((blkdev->block_read(dev_id, blknr, blkcnt, (unsigned long *)buf)) != blkcnt) {
  133. mutex_release(&g_part_lock);
  134. if (buf)
  135. free(buf);
  136. return -EIO;
  137. }
  138. memcpy(dst, buf, blkcnt * blkdev->blksz);
  139. blknr += blkcnt;
  140. blkcnt = 0;
  141. src += (blkcnt << blkdev->blk_bits);
  142. dst += (blkcnt << blkdev->blk_bits);
  143. }
  144. if (buf)
  145. free(buf);
  146. } else {
  147. if ((blkdev->block_read(dev_id, blknr, blkcnt, (unsigned long *)(dst))) != blkcnt) {
  148. mutex_release(&g_part_lock);
  149. return -EIO;
  150. }
  151. src += (blkcnt << (blkdev->blk_bits));
  152. dst += (blkcnt << (blkdev->blk_bits));
  153. }
  154. }
  155. if (part_end && src < end) {
  156. buf = (uchar *) &mt_part_buf[0];
  157. blknr = aligned_end >> (blkdev->blk_bits);
  158. if ((blkdev->block_read(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  159. mutex_release(&g_part_lock);
  160. return -EIO;
  161. }
  162. memcpy(dst, buf, part_end);
  163. }
  164. mutex_release(&g_part_lock);
  165. return size;
  166. }
  167. static int mt_part_generic_write(part_dev_t *dev, uchar *src, u64 dst, int size)
  168. {
  169. int dev_id = dev->id;
  170. uchar *buf;
  171. block_dev_desc_t *blkdev = dev->blkdev;
  172. u64 end, part_start, part_end, part_len, aligned_start, aligned_end;
  173. u32 src_start;
  174. ulong blknr, blkcnt, blkcnt_buf;
  175. //dprintf(INFO,"[%s:%d] %x, %llx, %d, %d, align: %d\n", __FUNCTION__, __LINE__, (u32)src, dst, size, part_id, PART_BUF_ALIGN_SIZE);
  176. if (!blkdev) {
  177. dprintf(CRITICAL,"No block device registered\n");
  178. return -ENODEV;
  179. }
  180. if (size == 0) {
  181. return 0;
  182. }
  183. end = dst + size;
  184. part_start = dst & ((u64)blkdev->blksz - 1);
  185. part_end = end & ((u64)blkdev->blksz - 1);
  186. aligned_start = dst & ~((u64)blkdev->blksz - 1);
  187. aligned_end = end & ~((u64)blkdev->blksz - 1);
  188. mutex_acquire(&g_part_lock);
  189. if (part_start) {
  190. buf = (uchar *) &mt_part_buf[0];
  191. blknr = aligned_start >> (blkdev->blk_bits);
  192. part_len = blkdev->blksz - part_start;
  193. if (part_len > (u64)size) {
  194. part_len = size;
  195. }
  196. if ((blkdev->block_read(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  197. mutex_release(&g_part_lock);
  198. return -EIO;
  199. }
  200. memcpy(buf + part_start, src, part_len);
  201. if ((blkdev->block_write(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  202. mutex_release(&g_part_lock);
  203. return -EIO;
  204. }
  205. dst += part_len;
  206. src += part_len;
  207. }
  208. aligned_start = dst & ~((u64)blkdev->blksz - 1);
  209. blknr = aligned_start >> (blkdev->blk_bits);
  210. blkcnt = (aligned_end - aligned_start) >> (blkdev->blk_bits);
  211. src_start = (u32)src & (PART_BUF_ALIGN_SIZE - 1); // src buffer alignment
  212. //dprintf(INFO,"[%s:%d] %x, %llx, %x, %lu, %lu\n", __FUNCTION__, __LINE__, (u32)src, dst, src_start, blknr, blkcnt);
  213. if (blkcnt > 0) {
  214. if (src_start) {
  215. blkcnt_buf = mt_part_alloc_buffer_align(&buf, blkcnt, blkdev->blksz);
  216. while (blkcnt >= blkcnt_buf) {
  217. memcpy(buf, src, blkcnt_buf * blkdev->blksz);
  218. if ((blkdev->block_write(dev_id, blknr, blkcnt_buf, (unsigned long *)buf)) != blkcnt_buf) {
  219. mutex_release(&g_part_lock);
  220. if (buf)
  221. free(buf);
  222. return -EIO;
  223. }
  224. blknr += blkcnt_buf;
  225. blkcnt -= blkcnt_buf;
  226. src += (blkcnt_buf << blkdev->blk_bits);
  227. dst += (blkcnt_buf << blkdev->blk_bits);
  228. }
  229. //dprintf(INFO, "[%s:%d] remain blkcnt: %lu\n", __FUNCTION__, __LINE__, blkcnt);
  230. if (blkcnt > 0) {
  231. memcpy(buf, src, blkcnt * blkdev->blksz);
  232. if ((blkdev->block_write(dev_id, blknr, blkcnt, (unsigned long *)buf)) != blkcnt) {
  233. mutex_release(&g_part_lock);
  234. if (buf)
  235. free(buf);
  236. return -EIO;
  237. }
  238. blknr += blkcnt;
  239. blkcnt = 0;
  240. src += (blkcnt << blkdev->blk_bits);
  241. dst += (blkcnt << blkdev->blk_bits);
  242. }
  243. if (buf)
  244. free(buf);
  245. } else {
  246. if ((blkdev->block_write(dev_id, blknr, blkcnt, (unsigned long *)(src))) != blkcnt) {
  247. mutex_release(&g_part_lock);
  248. return -EIO;
  249. }
  250. src += (blkcnt << blkdev->blk_bits);
  251. dst += (blkcnt << blkdev->blk_bits);
  252. }
  253. }
  254. if (part_end && dst < end) {
  255. buf = (uchar *) &mt_part_buf[0];
  256. blknr = aligned_end >> (blkdev->blk_bits);
  257. if ((blkdev->block_read(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  258. mutex_release(&g_part_lock);
  259. return -EIO;
  260. }
  261. memcpy(buf, src, part_end);
  262. if ((blkdev->block_write(dev_id, blknr, 1, (unsigned long*)buf)) != 1) {
  263. mutex_release(&g_part_lock);
  264. return -EIO;
  265. }
  266. }
  267. //dprintf(INFO,"[%s:%d] ret %d\n", __FUNCTION__, __LINE__, size);
  268. return size;
  269. }
  270. static int mt_part_generic_erase(int dev_num,u64 start_addr,u64 len)
  271. {
  272. return -1;
  273. }
  274. int mt_part_register_device(part_dev_t *dev)
  275. {
  276. dprintf(CRITICAL,"[mt_part_register_device]\n");
  277. if (!mt_part_dev) {
  278. if (!dev->read) {
  279. dev->read = mt_part_generic_read;
  280. }
  281. if (!dev->write) {
  282. dev->write = mt_part_generic_write;
  283. }
  284. if (!dev->erase) {
  285. dev->erase = mt_part_generic_erase;
  286. }
  287. mt_part_dev = dev;
  288. mutex_init(&g_part_lock);
  289. mt_part_buf = (uchar*)memalign(PART_BUF_ALIGN_SIZE, dev->blkdev->blksz * 2);
  290. if (mt_part_buf == NULL) {
  291. dprintf(CRITICAL, "allocate %lu buffer fail!\n", dev->blkdev->blksz * 2);
  292. }
  293. if (part_init(dev)) {
  294. dprintf(CRITICAL,"partition init error!\n");
  295. }
  296. }
  297. return 0;
  298. }
  299. part_dev_t *mt_part_get_device(void)
  300. {
  301. if (mt_part_dev && !mt_part_dev->init && mt_part_dev->init_dev) {
  302. mt_part_dev->init_dev(mt_part_dev->id);
  303. mt_part_dev->init = 1;
  304. }
  305. return mt_part_dev;
  306. }