ipa_reg.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  3. * Copyright (C) 2019-2022 Linaro Ltd.
  4. */
  5. #include <linux/io.h>
  6. #include "ipa.h"
  7. #include "ipa_reg.h"
  8. /* Is this register valid and defined for the current IPA version? */
  9. static bool ipa_reg_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
  10. {
  11. enum ipa_version version = ipa->version;
  12. bool valid;
  13. /* Check for bogus (out of range) register IDs */
  14. if ((u32)reg_id >= ipa->regs->reg_count)
  15. return false;
  16. switch (reg_id) {
  17. case IPA_BCR:
  18. case COUNTER_CFG:
  19. valid = version < IPA_VERSION_4_5;
  20. break;
  21. case IPA_TX_CFG:
  22. case FLAVOR_0:
  23. case IDLE_INDICATION_CFG:
  24. valid = version >= IPA_VERSION_3_5;
  25. break;
  26. case QTIME_TIMESTAMP_CFG:
  27. case TIMERS_XO_CLK_DIV_CFG:
  28. case TIMERS_PULSE_GRAN_CFG:
  29. valid = version >= IPA_VERSION_4_5;
  30. break;
  31. case SRC_RSRC_GRP_45_RSRC_TYPE:
  32. case DST_RSRC_GRP_45_RSRC_TYPE:
  33. valid = version <= IPA_VERSION_3_1 ||
  34. version == IPA_VERSION_4_5;
  35. break;
  36. case SRC_RSRC_GRP_67_RSRC_TYPE:
  37. case DST_RSRC_GRP_67_RSRC_TYPE:
  38. valid = version <= IPA_VERSION_3_1;
  39. break;
  40. case ENDP_FILTER_ROUTER_HSH_CFG:
  41. valid = version != IPA_VERSION_4_2;
  42. break;
  43. case IRQ_SUSPEND_EN:
  44. case IRQ_SUSPEND_CLR:
  45. valid = version >= IPA_VERSION_3_1;
  46. break;
  47. default:
  48. valid = true; /* Others should be defined for all versions */
  49. break;
  50. }
  51. /* To be valid, it must be defined */
  52. return valid && ipa->regs->reg[reg_id];
  53. }
  54. const struct ipa_reg *ipa_reg(struct ipa *ipa, enum ipa_reg_id reg_id)
  55. {
  56. if (WARN_ON(!ipa_reg_valid(ipa, reg_id)))
  57. return NULL;
  58. return ipa->regs->reg[reg_id];
  59. }
  60. static const struct ipa_regs *ipa_regs(enum ipa_version version)
  61. {
  62. switch (version) {
  63. case IPA_VERSION_3_1:
  64. return &ipa_regs_v3_1;
  65. case IPA_VERSION_3_5_1:
  66. return &ipa_regs_v3_5_1;
  67. case IPA_VERSION_4_2:
  68. return &ipa_regs_v4_2;
  69. case IPA_VERSION_4_5:
  70. return &ipa_regs_v4_5;
  71. case IPA_VERSION_4_9:
  72. return &ipa_regs_v4_9;
  73. case IPA_VERSION_4_11:
  74. return &ipa_regs_v4_11;
  75. default:
  76. return NULL;
  77. }
  78. }
  79. int ipa_reg_init(struct ipa *ipa)
  80. {
  81. struct device *dev = &ipa->pdev->dev;
  82. const struct ipa_regs *regs;
  83. struct resource *res;
  84. regs = ipa_regs(ipa->version);
  85. if (!regs)
  86. return -EINVAL;
  87. if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT))
  88. return -EINVAL;
  89. /* Setup IPA register memory */
  90. res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM,
  91. "ipa-reg");
  92. if (!res) {
  93. dev_err(dev, "DT error getting \"ipa-reg\" memory property\n");
  94. return -ENODEV;
  95. }
  96. ipa->reg_virt = ioremap(res->start, resource_size(res));
  97. if (!ipa->reg_virt) {
  98. dev_err(dev, "unable to remap \"ipa-reg\" memory\n");
  99. return -ENOMEM;
  100. }
  101. ipa->reg_addr = res->start;
  102. ipa->regs = regs;
  103. return 0;
  104. }
  105. void ipa_reg_exit(struct ipa *ipa)
  106. {
  107. iounmap(ipa->reg_virt);
  108. }