sps_map.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2011-2013, 2015, 2017-2019, 2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. /**
  7. * Connection mapping table management for SPS device driver.
  8. */
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/memory.h>
  12. #include "spsi.h"
  13. /* Module state */
  14. struct sps_map_state {
  15. const struct sps_map *maps;
  16. u32 num_maps;
  17. u32 options;
  18. };
  19. static struct sps_map_state sps_maps;
  20. /**
  21. * Initialize connection mapping module
  22. *
  23. */
  24. int sps_map_init(const struct sps_map *map_props, u32 options)
  25. {
  26. const struct sps_map *maps;
  27. /* Are there any connection mappings? */
  28. memset(&sps_maps, 0, sizeof(sps_maps));
  29. if (map_props == NULL)
  30. return 0;
  31. /* Init the module state */
  32. sps_maps.maps = map_props;
  33. sps_maps.options = options;
  34. for (maps = sps_maps.maps;; maps++, sps_maps.num_maps++)
  35. if (maps->src.periph_class == SPS_CLASS_INVALID &&
  36. maps->src.periph_phy_addr == SPS_ADDR_INVALID)
  37. break;
  38. SPS_DBG(sps, "sps: %d mappings\n", sps_maps.num_maps);
  39. return 0;
  40. }
  41. /**
  42. * De-initialize connection mapping module
  43. *
  44. */
  45. void sps_map_de_init(void)
  46. {
  47. memset(&sps_maps, 0, sizeof(sps_maps));
  48. }
  49. /**
  50. * Find matching connection mapping
  51. *
  52. */
  53. int sps_map_find(struct sps_connect *connect)
  54. {
  55. const struct sps_map *map;
  56. u32 i;
  57. void *desc;
  58. void *data;
  59. /* Are there any connection mappings? */
  60. if (sps_maps.num_maps == 0)
  61. return SPS_ERROR;
  62. /* Search the mapping table for a match to the specified connection */
  63. for (i = sps_maps.num_maps, map = sps_maps.maps;
  64. i > 0; i--, map++)
  65. if (map->src.periph_class == (u32) connect->source &&
  66. map->dest.periph_class == (u32) connect->destination
  67. && map->config == (u32) connect->config)
  68. break;
  69. if (i == 0)
  70. return SPS_ERROR;
  71. /*
  72. * Before modifying client parameter struct, perform all
  73. * operations that might fail
  74. */
  75. desc = spsi_get_mem_ptr(map->desc_base);
  76. if (desc == NULL) {
  77. SPS_ERR(sps,
  78. "sps:Cannot get virt addr for I/O buffer: %pa\n",
  79. &map->desc_base);
  80. return SPS_ERROR;
  81. }
  82. if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
  83. data = spsi_get_mem_ptr(map->data_base);
  84. if (data == NULL) {
  85. SPS_ERR(sps,
  86. "sps:Can't get virt addr for I/O buffer: %pa\n",
  87. &map->data_base);
  88. return SPS_ERROR;
  89. }
  90. } else {
  91. data = NULL;
  92. }
  93. /* Copy mapping values to client parameter struct */
  94. if (connect->source != SPS_DEV_HANDLE_MEM)
  95. connect->src_pipe_index = map->src.pipe_index;
  96. if (connect->destination != SPS_DEV_HANDLE_MEM)
  97. connect->dest_pipe_index = map->dest.pipe_index;
  98. if (connect->mode == SPS_MODE_SRC)
  99. connect->event_thresh = map->src.event_thresh;
  100. else
  101. connect->event_thresh = map->dest.event_thresh;
  102. connect->desc.size = map->desc_size;
  103. connect->desc.phys_base = map->desc_base;
  104. connect->desc.base = desc;
  105. if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
  106. connect->data.size = map->data_size;
  107. connect->data.phys_base = map->data_base;
  108. connect->data.base = data;
  109. }
  110. return 0;
  111. }