ddr_parameter.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <string.h>
  7. #include <platform_def.h>
  8. #include <arch_helpers.h>
  9. #include <common/debug.h>
  10. #include <drivers/console.h>
  11. #include <drivers/delay_timer.h>
  12. #include <lib/mmio.h>
  13. #include <plat_private.h>
  14. #include <soc.h>
  15. #include "ddr_parameter.h"
  16. /*
  17. * The miniloader delivers the parameters about ddr usage info from address
  18. * 0x02000000 and the data format is defined as below figure. It tells ATF the
  19. * areas of ddr that are used by platform, we treat them as non-secure regions
  20. * by default. Then we should parse the other part regions and configurate them
  21. * as secure regions to avoid illegal access.
  22. *
  23. * [ddr usage info data format]
  24. * 0x02000000
  25. * -----------------------------------------------------------------------------
  26. * | <name> | <size> | <description> |
  27. * -----------------------------------------------------------------------------
  28. * | count | 4byte | the array numbers of the |
  29. * | | | 'addr_array' and 'size_array' |
  30. * -----------------------------------------------------------------------------
  31. * | reserved | 4byte | just for 'addr_array' 8byte aligned |
  32. * -----------------------------------------------------------------------------
  33. * | addr_array[count] | per 8byte | memory region base address |
  34. * -----------------------------------------------------------------------------
  35. * | size_array[count] | per 8byte | memory region size (byte) |
  36. * -----------------------------------------------------------------------------
  37. */
  38. /*
  39. * function: read parameters info(ns-regions) and try to parse s-regions info
  40. *
  41. * @addr: head address to the ddr usage struct from miniloader
  42. * @max_mb: the max ddr capacity(MB) that the platform support
  43. */
  44. struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb)
  45. {
  46. uint64_t base, top;
  47. uint32_t i, addr_offset, size_offset;
  48. struct param_ddr_usage p;
  49. memset(&p, 0, sizeof(p));
  50. /* read how many blocks of ns-regions, read from offset: 0x0 */
  51. p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET);
  52. if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) {
  53. ERROR("over or zero region, nr=%d, max=%d\n",
  54. p.ns_nr, DDR_REGION_NR_MAX);
  55. return p;
  56. }
  57. /* whole ddr regions boundary, it will be used when parse s-regions */
  58. p.boundary = max_mb;
  59. /* calculate ns-region base addr and size offset */
  60. addr_offset = REGION_ADDR_OFFSET;
  61. size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES;
  62. /* read all ns-regions base and top address */
  63. for (i = 0; i < p.ns_nr; i++) {
  64. base = mmio_read_64(addr + addr_offset);
  65. top = base + mmio_read_64(addr + size_offset);
  66. /*
  67. * translate byte to MB and store info,
  68. * Miniloader will promise every ns-region is MB aligned.
  69. */
  70. p.ns_base[i] = RG_SIZE_MB(base);
  71. p.ns_top[i] = RG_SIZE_MB(top);
  72. addr_offset += REGION_DATA_PER_BYTES;
  73. size_offset += REGION_DATA_PER_BYTES;
  74. }
  75. /*
  76. * a s-region's base starts from previous ns-region's top, and a
  77. * s-region's top ends with next ns-region's base. maybe like this:
  78. *
  79. * case1: ns-regison start from 0MB
  80. * -----------------------------------------------
  81. * | ns0 | S0 | ns1 | S1 | ns2 |
  82. * 0----------------------------------------------- max_mb
  83. *
  84. *
  85. * case2: ns-regison not start from 0MB
  86. * -----------------------------------------------
  87. * | S0 | ns0 | ns1 | ns2 | S1 |
  88. * 0----------------------------------------------- max_mb
  89. */
  90. /* like above case2 figure, ns-region is not start from 0MB */
  91. if (p.ns_base[0] != 0) {
  92. p.s_base[p.s_nr] = 0;
  93. p.s_top[p.s_nr] = p.ns_base[0];
  94. p.s_nr++;
  95. }
  96. /*
  97. * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0
  98. */
  99. for (i = 0; i < p.ns_nr; i++) {
  100. /*
  101. * if current ns-regions top covers boundary,
  102. * that means s-regions are all parsed yet, so finsh.
  103. */
  104. if (p.ns_top[i] == p.boundary)
  105. goto out;
  106. /* s-region's base starts from previous ns-region's top */
  107. p.s_base[p.s_nr] = p.ns_top[i];
  108. /* s-region's top ends with next ns-region's base */
  109. if (i + 1 < p.ns_nr)
  110. p.s_top[p.s_nr] = p.ns_base[i + 1];
  111. else
  112. p.s_top[p.s_nr] = p.boundary;
  113. p.s_nr++;
  114. }
  115. out:
  116. return p;
  117. }