ioremap.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 <rtthread.h>
  11. #include <rthw.h>
  12. #ifdef RT_USING_USERSPACE
  13. #include <mmu.h>
  14. #include <lwp_mm_area.h>
  15. #endif
  16. #include <ioremap.h>
  17. #ifdef RT_USING_USERSPACE
  18. static struct lwp_avl_struct *k_map_area;
  19. extern rt_mmu_info mmu_info;
  20. static void _iounmap_range(void *addr, size_t size)
  21. {
  22. void *va = RT_NULL, *pa = RT_NULL;
  23. int i = 0;
  24. for (va = addr, i = 0; i < size; va = (void *)((char *)va + ARCH_PAGE_SIZE), i += ARCH_PAGE_SIZE)
  25. {
  26. pa = rt_hw_mmu_v2p(&mmu_info, va);
  27. if (pa)
  28. {
  29. rt_hw_mmu_unmap(&mmu_info, va, ARCH_PAGE_SIZE);
  30. }
  31. }
  32. }
  33. static void *_ioremap_type(void *p_addr, size_t size, int type)
  34. {
  35. rt_base_t level;
  36. void *v_addr = NULL;
  37. size_t attr;
  38. switch (type)
  39. {
  40. case MM_AREA_TYPE_PHY:
  41. attr = MMU_MAP_K_DEVICE;
  42. break;
  43. case MM_AREA_TYPE_PHY_CACHED:
  44. attr = MMU_MAP_K_RWCB;
  45. break;
  46. default:
  47. return v_addr;
  48. }
  49. level = rt_hw_interrupt_disable();
  50. v_addr = rt_hw_mmu_map(&mmu_info, 0, p_addr, size, attr);
  51. if (v_addr)
  52. {
  53. int ret = lwp_map_area_insert(&k_map_area, (size_t)v_addr, size, type);
  54. if (ret != 0)
  55. {
  56. _iounmap_range(v_addr, size);
  57. v_addr = NULL;
  58. }
  59. }
  60. rt_hw_interrupt_enable(level);
  61. return v_addr;
  62. }
  63. void *rt_ioremap(void *p_addr, size_t size)
  64. {
  65. return _ioremap_type(p_addr, size, MM_AREA_TYPE_PHY);
  66. }
  67. void *rt_ioremap_nocache(void *p_addr, size_t size)
  68. {
  69. return _ioremap_type(p_addr, size, MM_AREA_TYPE_PHY);
  70. }
  71. void *rt_ioremap_cached(void *p_addr, size_t size)
  72. {
  73. return _ioremap_type(p_addr, size, MM_AREA_TYPE_PHY_CACHED);
  74. }
  75. #else
  76. void *rt_ioremap(void *p_addr, size_t size)
  77. {
  78. return p_addr;
  79. }
  80. void *rt_ioremap_nocache(void *paddr, size_t size)
  81. {
  82. return p_addr;
  83. }
  84. void *rt_ioremap_cached(void *paddr, size_t size)
  85. {
  86. return p_addr;
  87. }
  88. #endif
  89. void rt_iounmap(volatile void *vaddr)
  90. {
  91. #ifdef RT_USING_USERSPACE
  92. rt_base_t level;
  93. struct lwp_avl_struct *ma_avl_node;
  94. level = rt_hw_interrupt_disable();
  95. ma_avl_node = lwp_map_find(k_map_area, (size_t)vaddr);
  96. if (ma_avl_node)
  97. {
  98. struct rt_mm_area_struct *ma = (struct rt_mm_area_struct *)ma_avl_node->data;
  99. _iounmap_range((void *)ma->addr, ma->size);
  100. lwp_map_area_remove(&k_map_area, (size_t)vaddr);
  101. }
  102. rt_hw_interrupt_enable(level);
  103. #endif
  104. }