io_addr_dec.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (C) 2016 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <common/debug.h>
  8. #include <lib/mmio.h>
  9. #include <io_addr_dec.h>
  10. #include <plat_marvell.h>
  11. #define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
  12. (win) * (off))
  13. #define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
  14. (win) * (off) + 0x4)
  15. #define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
  16. (win) * (off) + 0x8)
  17. #define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16)
  18. #define MVEBU_DEC_WIN_ENABLE (0x1)
  19. #define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8)
  20. #define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4)
  21. #define MVEBU_DEC_WIN_CTRL_EN_OFF (0)
  22. #define MVEBU_DEC_WIN_BASE_OFF (16)
  23. #define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000)
  24. /* There are up to 14 IO unit which need address decode in Armada-3700 */
  25. #define IO_UNIT_NUM_MAX (14)
  26. #define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL)
  27. static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
  28. uintptr_t win_size,
  29. struct dec_win_config *dec_win)
  30. {
  31. uint32_t ctrl = 0;
  32. uint32_t base = 0;
  33. /* set size */
  34. ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
  35. MVEBU_DEC_WIN_CTRL_SIZE_OFF;
  36. /* set attr according to IO decode window */
  37. ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
  38. /* set target */
  39. ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
  40. /* set base */
  41. base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
  42. MVEBU_DEC_WIN_BASE_OFF;
  43. /* set base address*/
  44. mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
  45. win_id, dec_win->win_offset),
  46. base);
  47. /* set remap window, some unit does not have remap window */
  48. if (win_id < dec_win->max_remap)
  49. mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
  50. win_id, dec_win->win_offset), base);
  51. /* set control register */
  52. mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
  53. win_id, dec_win->win_offset), ctrl);
  54. /* enable the address decode window at last to make it effective */
  55. ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
  56. mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
  57. win_id, dec_win->win_offset), ctrl);
  58. INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
  59. win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
  60. win_id, dec_win->win_offset)),
  61. mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
  62. win_id, dec_win->win_offset)),
  63. (win_id < dec_win->max_remap) ?
  64. mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
  65. win_id, dec_win->win_offset)) : 0);
  66. }
  67. /* Set io decode window */
  68. static int set_io_addr_dec(struct dram_win_map *win_map,
  69. struct dec_win_config *dec_win)
  70. {
  71. struct dram_win *win;
  72. int id;
  73. /* disable all windows first */
  74. for (id = 0; id < dec_win->max_dram_win; id++)
  75. mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
  76. dec_win->win_offset), 0);
  77. /* configure IO decode windows for DRAM, inheritate DRAM size,
  78. * base and target from CPU-DRAM decode window and others
  79. * from hard coded IO decode window settings array.
  80. */
  81. if (win_map->dram_win_num > dec_win->max_dram_win) {
  82. /*
  83. * If cpu dram windows number exceeds the io decode windows
  84. * max number, then fill the first io decode window
  85. * with base(0) and size(4GB).
  86. */
  87. set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
  88. return 0;
  89. }
  90. for (id = 0; id < win_map->dram_win_num; id++, win++) {
  91. win = &win_map->dram_windows[id];
  92. set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
  93. }
  94. return 0;
  95. }
  96. /*
  97. * init_io_addr_dec
  98. *
  99. * This function initializes io address decoder windows by
  100. * cpu dram window mapping information
  101. *
  102. * @input: N/A
  103. * - dram_wins_map: cpu dram windows mapping
  104. * - io_dec_config: io address decoder windows configuration
  105. * - io_unit_num: io address decoder unit number
  106. * @output: N/A
  107. *
  108. * @return: 0 on success and others on failure
  109. */
  110. int init_io_addr_dec(struct dram_win_map *dram_wins_map,
  111. struct dec_win_config *io_dec_config, uint32_t io_unit_num)
  112. {
  113. int32_t index;
  114. struct dec_win_config *io_dec_win;
  115. int32_t ret;
  116. INFO("Initializing IO address decode windows\n");
  117. if (io_dec_config == NULL || io_unit_num == 0) {
  118. ERROR("No IO address decoder windows configurations!\n");
  119. return -1;
  120. }
  121. if (io_unit_num > IO_UNIT_NUM_MAX) {
  122. ERROR("IO address decoder windows number %d is over max %d\n",
  123. io_unit_num, IO_UNIT_NUM_MAX);
  124. return -1;
  125. }
  126. if (dram_wins_map == NULL) {
  127. ERROR("No cpu dram decoder windows map!\n");
  128. return -1;
  129. }
  130. for (index = 0; index < dram_wins_map->dram_win_num; index++)
  131. INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
  132. index, dram_wins_map->dram_windows[index].base_addr,
  133. dram_wins_map->dram_windows[index].win_size);
  134. /* Set address decode window for each IO */
  135. for (index = 0; index < io_unit_num; index++) {
  136. io_dec_win = io_dec_config + index;
  137. ret = set_io_addr_dec(dram_wins_map, io_dec_win);
  138. if (ret) {
  139. ERROR("Failed to set IO address decode\n");
  140. return -1;
  141. }
  142. INFO("Set IO decode window successfully, base(0x%x)"
  143. " win_attr(%x) max_dram_win(%d) max_remap(%d)"
  144. " win_offset(%d)\n", io_dec_win->dec_reg_base,
  145. io_dec_win->win_attr, io_dec_win->max_dram_win,
  146. io_dec_win->max_remap, io_dec_win->win_offset);
  147. }
  148. return 0;
  149. }