gic-v3-its.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2019 Broadcom.
  4. */
  5. #include <common.h>
  6. #include <asm/gic.h>
  7. #include <asm/gic-v3.h>
  8. #include <asm/io.h>
  9. #include <linux/bitops.h>
  10. #include <linux/sizes.h>
  11. static u32 lpi_id_bits;
  12. #define LPI_NRBITS lpi_id_bits
  13. #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
  14. #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
  15. /*
  16. * Program the GIC LPI configuration tables for all
  17. * the re-distributors and enable the LPI table
  18. * base: Configuration table address
  19. * num_redist: number of redistributors
  20. */
  21. int gic_lpi_tables_init(u64 base, u32 num_redist)
  22. {
  23. u32 gicd_typer;
  24. u64 val;
  25. u64 tmp;
  26. int i;
  27. u64 redist_lpi_base;
  28. u64 pend_base = GICR_BASE + GICR_PENDBASER;
  29. gicd_typer = readl(GICD_BASE + GICD_TYPER);
  30. /* GIC support for Locality specific peripheral interrupts (LPI's) */
  31. if (!(gicd_typer & GICD_TYPER_LPIS)) {
  32. pr_err("GIC implementation does not support LPI's\n");
  33. return -EINVAL;
  34. }
  35. /*
  36. * Check for LPI is disabled for all the redistributors.
  37. * Once the LPI table is enabled, can not program the
  38. * LPI configuration tables again, unless the GIC is reset.
  39. */
  40. for (i = 0; i < num_redist; i++) {
  41. u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
  42. if ((readl((uintptr_t)(GICR_BASE + offset))) &
  43. GICR_CTLR_ENABLE_LPIS) {
  44. pr_err("Re-Distributor %d LPI is already enabled\n",
  45. i);
  46. return -EINVAL;
  47. }
  48. }
  49. /* lpi_id_bits to get LPI_PENDBASE_SZ and LPi_PROPBASE_SZ */
  50. lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gicd_typer),
  51. ITS_MAX_LPI_NRBITS);
  52. /* Set PropBase */
  53. val = (base |
  54. GICR_PROPBASER_INNERSHAREABLE |
  55. GICR_PROPBASER_RAWAWB |
  56. ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
  57. writeq(val, (GICR_BASE + GICR_PROPBASER));
  58. tmp = readl(GICR_BASE + GICR_PROPBASER);
  59. if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
  60. if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
  61. val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
  62. GICR_PROPBASER_CACHEABILITY_MASK);
  63. val |= GICR_PROPBASER_NC;
  64. writeq(val, (GICR_BASE + GICR_PROPBASER));
  65. }
  66. }
  67. redist_lpi_base = base + LPI_PROPBASE_SZ;
  68. for (i = 0; i < num_redist; i++) {
  69. u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
  70. val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) |
  71. GICR_PENDBASER_INNERSHAREABLE |
  72. GICR_PENDBASER_RAWAWB);
  73. writeq(val, (uintptr_t)(pend_base + offset));
  74. tmp = readq((uintptr_t)(pend_base + offset));
  75. if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
  76. val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
  77. GICR_PENDBASER_CACHEABILITY_MASK);
  78. val |= GICR_PENDBASER_NC;
  79. writeq(val, (uintptr_t)(pend_base + offset));
  80. }
  81. /* Enable LPI for the redistributor */
  82. writel(GICR_CTLR_ENABLE_LPIS, (uintptr_t)(GICR_BASE + offset));
  83. }
  84. return 0;
  85. }