ioremap.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-05-06 Jesven first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <mmu.h>
  13. #include <mm_aspace.h>
  14. #include <ioremap.h>
  15. void *rt_ioremap_start;
  16. size_t rt_ioremap_size;
  17. #ifdef RT_USING_SMART
  18. #include <lwp_mm.h>
  19. #endif
  20. #define DBG_TAG "mm.ioremap"
  21. #define DBG_LVL DBG_LOG
  22. #include <rtdbg.h>
  23. enum ioremap_type
  24. {
  25. MM_AREA_TYPE_PHY,
  26. MM_AREA_TYPE_PHY_WT,
  27. MM_AREA_TYPE_PHY_CACHED
  28. };
  29. static void *_ioremap_type(void *paddr, size_t size, enum ioremap_type type)
  30. {
  31. char *v_addr = NULL;
  32. size_t attr;
  33. size_t lo_off;
  34. int err;
  35. size_t pa_off = (rt_ubase_t)paddr & ~(RT_PAGE_AFFINITY_BLOCK_SIZE - 1);
  36. lo_off = (rt_ubase_t)paddr - pa_off;
  37. pa_off = MM_PA_TO_OFF(pa_off);
  38. struct rt_mm_va_hint hint = {
  39. .prefer = RT_NULL,
  40. .map_size = RT_ALIGN(size + lo_off, RT_PAGE_AFFINITY_BLOCK_SIZE),
  41. .flags = MMF_CREATE(0, RT_PAGE_AFFINITY_BLOCK_SIZE),
  42. .limit_start = rt_ioremap_start,
  43. .limit_range_size = rt_ioremap_size,
  44. };
  45. switch (type)
  46. {
  47. case MM_AREA_TYPE_PHY:
  48. attr = MMU_MAP_K_DEVICE;
  49. break;
  50. case MM_AREA_TYPE_PHY_WT:
  51. attr = MMU_MAP_K_RW;
  52. break;
  53. case MM_AREA_TYPE_PHY_CACHED:
  54. attr = MMU_MAP_K_RWCB;
  55. break;
  56. default:
  57. return v_addr;
  58. }
  59. err = rt_aspace_map_phy(&rt_kernel_space, &hint, attr, pa_off, (void **)&v_addr);
  60. if (err)
  61. {
  62. LOG_W("IOREMAP 0x%lx failed %d\n", paddr, err);
  63. v_addr = NULL;
  64. }
  65. else
  66. {
  67. v_addr = v_addr + lo_off;
  68. }
  69. return v_addr;
  70. }
  71. rt_weak void *rt_ioremap_early(void *paddr, size_t size)
  72. {
  73. if (!size)
  74. {
  75. return RT_NULL;
  76. }
  77. return paddr;
  78. }
  79. void *rt_ioremap(void *paddr, size_t size)
  80. {
  81. return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY);
  82. }
  83. void *rt_ioremap_nocache(void *paddr, size_t size)
  84. {
  85. return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY);
  86. }
  87. void *rt_ioremap_wt(void *paddr, size_t size)
  88. {
  89. return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY_WT);
  90. }
  91. void *rt_ioremap_cached(void *paddr, size_t size)
  92. {
  93. return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY_CACHED);
  94. }
  95. void rt_iounmap(volatile void *vaddr)
  96. {
  97. rt_aspace_unmap(&rt_kernel_space, (void *)vaddr);
  98. }