icid.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2018 NXP
  4. */
  5. #include <common.h>
  6. #include <linux/libfdt.h>
  7. #include <fdt_support.h>
  8. #include <asm/io.h>
  9. #include <asm/processor.h>
  10. #include <asm/arch-fsl-layerscape/fsl_icid.h>
  11. #include <fsl_fman.h>
  12. static void set_icid(struct icid_id_table *tbl, int size)
  13. {
  14. int i;
  15. for (i = 0; i < size; i++)
  16. if (tbl[i].le)
  17. out_le32((u32 *)(tbl[i].reg_addr), tbl[i].reg);
  18. else
  19. out_be32((u32 *)(tbl[i].reg_addr), tbl[i].reg);
  20. }
  21. #ifdef CONFIG_SYS_DPAA_FMAN
  22. void set_fman_icids(struct fman_icid_id_table *tbl, int size)
  23. {
  24. int i;
  25. ccsr_fman_t *fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
  26. for (i = 0; i < size; i++) {
  27. out_be32(&fm->fm_bmi_common.fmbm_ppid[tbl[i].port_id - 1],
  28. tbl[i].icid);
  29. }
  30. }
  31. #endif
  32. void set_icids(void)
  33. {
  34. /* setup general icid offsets */
  35. set_icid(icid_tbl, icid_tbl_sz);
  36. #ifdef CONFIG_SYS_DPAA_FMAN
  37. set_fman_icids(fman_icid_tbl, fman_icid_tbl_sz);
  38. #endif
  39. }
  40. int fdt_set_iommu_prop(void *blob, int off, int smmu_ph, u32 *ids, int num_ids)
  41. {
  42. int i, ret;
  43. u32 prop[8];
  44. /*
  45. * Note: The "iommus" property definition mentions Stream IDs while
  46. * this code handles ICIDs. The current implementation assumes that
  47. * ICIDs and Stream IDs are equal.
  48. */
  49. for (i = 0; i < num_ids; i++) {
  50. prop[i * 2] = cpu_to_fdt32(smmu_ph);
  51. prop[i * 2 + 1] = cpu_to_fdt32(ids[i]);
  52. }
  53. ret = fdt_setprop(blob, off, "iommus",
  54. prop, sizeof(u32) * num_ids * 2);
  55. if (ret) {
  56. printf("WARNING unable to set iommus: %s\n", fdt_strerror(ret));
  57. return ret;
  58. }
  59. return 0;
  60. }
  61. int fdt_fixup_icid_tbl(void *blob, int smmu_ph,
  62. struct icid_id_table *tbl, int size)
  63. {
  64. int i, err, off;
  65. for (i = 0; i < size; i++) {
  66. if (!tbl[i].compat)
  67. continue;
  68. off = fdt_node_offset_by_compat_reg(blob,
  69. tbl[i].compat,
  70. tbl[i].compat_addr);
  71. if (off > 0) {
  72. err = fdt_set_iommu_prop(blob, off, smmu_ph,
  73. &tbl[i].id, 1);
  74. if (err)
  75. return err;
  76. } else {
  77. printf("WARNING could not find node %s: %s.\n",
  78. tbl[i].compat, fdt_strerror(off));
  79. }
  80. }
  81. return 0;
  82. }
  83. #ifdef CONFIG_SYS_DPAA_FMAN
  84. int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl,
  85. const int size)
  86. {
  87. int i;
  88. for (i = 0; i < size; i++) {
  89. if (tbl[i].port_id == port_id)
  90. return tbl[i].icid;
  91. }
  92. return -1;
  93. }
  94. void fdt_fixup_fman_port_icid_by_compat(void *blob, int smmu_ph,
  95. const char *compat)
  96. {
  97. int noff, len, icid;
  98. const u32 *prop;
  99. noff = fdt_node_offset_by_compatible(blob, -1, compat);
  100. while (noff > 0) {
  101. prop = fdt_getprop(blob, noff, "cell-index", &len);
  102. if (!prop) {
  103. printf("WARNING missing cell-index for fman port\n");
  104. continue;
  105. }
  106. if (len != 4) {
  107. printf("WARNING bad cell-index size for fman port\n");
  108. continue;
  109. }
  110. icid = get_fman_port_icid(fdt32_to_cpu(*prop),
  111. fman_icid_tbl, fman_icid_tbl_sz);
  112. if (icid < 0) {
  113. printf("WARNING unknown ICID for fman port %d\n",
  114. *prop);
  115. continue;
  116. }
  117. fdt_set_iommu_prop(blob, noff, smmu_ph, (u32 *)&icid, 1);
  118. noff = fdt_node_offset_by_compatible(blob, noff, compat);
  119. }
  120. }
  121. void fdt_fixup_fman_icids(void *blob, int smmu_ph)
  122. {
  123. static const char * const compats[] = {
  124. "fsl,fman-v3-port-oh",
  125. "fsl,fman-v3-port-rx",
  126. "fsl,fman-v3-port-tx",
  127. };
  128. int i;
  129. for (i = 0; i < ARRAY_SIZE(compats); i++)
  130. fdt_fixup_fman_port_icid_by_compat(blob, smmu_ph, compats[i]);
  131. }
  132. #endif
  133. int fdt_get_smmu_phandle(void *blob)
  134. {
  135. int noff, smmu_ph;
  136. noff = fdt_node_offset_by_compatible(blob, -1, "arm,mmu-500");
  137. if (noff < 0) {
  138. printf("WARNING failed to get smmu node: %s\n",
  139. fdt_strerror(noff));
  140. return noff;
  141. }
  142. smmu_ph = fdt_get_phandle(blob, noff);
  143. if (!smmu_ph) {
  144. smmu_ph = fdt_create_phandle(blob, noff);
  145. if (!smmu_ph) {
  146. printf("WARNING failed to get smmu phandle\n");
  147. return -1;
  148. }
  149. }
  150. return smmu_ph;
  151. }
  152. void fdt_fixup_icid(void *blob)
  153. {
  154. int smmu_ph;
  155. smmu_ph = fdt_get_smmu_phandle(blob);
  156. if (smmu_ph < 0)
  157. return;
  158. fdt_fixup_icid_tbl(blob, smmu_ph, icid_tbl, icid_tbl_sz);
  159. #ifdef CONFIG_SYS_DPAA_FMAN
  160. fdt_fixup_fman_icids(blob, smmu_ph);
  161. #endif
  162. }