utils.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2018 Intel Corporation. All rights reserved.
  7. //
  8. // Author: Keyon Jie <yang.jie@linux.intel.com>
  9. //
  10. #include <linux/io-64-nonatomic-lo-hi.h>
  11. #include <linux/platform_device.h>
  12. #include <asm/unaligned.h>
  13. #include <sound/soc.h>
  14. #include <sound/sof.h>
  15. #include "sof-priv.h"
  16. /*
  17. * Register IO
  18. *
  19. * The sof_io_xyz() wrappers are typically referenced in snd_sof_dsp_ops
  20. * structures and cannot be inlined.
  21. */
  22. void sof_io_write(struct snd_sof_dev *sdev, void __iomem *addr, u32 value)
  23. {
  24. writel(value, addr);
  25. }
  26. EXPORT_SYMBOL(sof_io_write);
  27. u32 sof_io_read(struct snd_sof_dev *sdev, void __iomem *addr)
  28. {
  29. return readl(addr);
  30. }
  31. EXPORT_SYMBOL(sof_io_read);
  32. void sof_io_write64(struct snd_sof_dev *sdev, void __iomem *addr, u64 value)
  33. {
  34. writeq(value, addr);
  35. }
  36. EXPORT_SYMBOL(sof_io_write64);
  37. u64 sof_io_read64(struct snd_sof_dev *sdev, void __iomem *addr)
  38. {
  39. return readq(addr);
  40. }
  41. EXPORT_SYMBOL(sof_io_read64);
  42. /*
  43. * IPC Mailbox IO
  44. */
  45. void sof_mailbox_write(struct snd_sof_dev *sdev, u32 offset,
  46. void *message, size_t bytes)
  47. {
  48. void __iomem *dest = sdev->bar[sdev->mailbox_bar] + offset;
  49. memcpy_toio(dest, message, bytes);
  50. }
  51. EXPORT_SYMBOL(sof_mailbox_write);
  52. void sof_mailbox_read(struct snd_sof_dev *sdev, u32 offset,
  53. void *message, size_t bytes)
  54. {
  55. void __iomem *src = sdev->bar[sdev->mailbox_bar] + offset;
  56. memcpy_fromio(message, src, bytes);
  57. }
  58. EXPORT_SYMBOL(sof_mailbox_read);
  59. /*
  60. * Memory copy.
  61. */
  62. void sof_block_write(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *src,
  63. size_t size)
  64. {
  65. void __iomem *dest = sdev->bar[bar] + offset;
  66. const u8 *src_byte = src;
  67. u32 affected_mask;
  68. u32 tmp;
  69. int m, n;
  70. m = size / 4;
  71. n = size % 4;
  72. /* __iowrite32_copy use 32bit size values so divide by 4 */
  73. __iowrite32_copy(dest, src, m);
  74. if (n) {
  75. affected_mask = (1 << (8 * n)) - 1;
  76. /* first read the 32bit data of dest, then change affected
  77. * bytes, and write back to dest. For unaffected bytes, it
  78. * should not be changed
  79. */
  80. tmp = ioread32(dest + m * 4);
  81. tmp &= ~affected_mask;
  82. tmp |= *(u32 *)(src_byte + m * 4) & affected_mask;
  83. iowrite32(tmp, dest + m * 4);
  84. }
  85. }
  86. EXPORT_SYMBOL(sof_block_write);
  87. void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest,
  88. size_t size)
  89. {
  90. void __iomem *src = sdev->bar[bar] + offset;
  91. memcpy_fromio(dest, src, size);
  92. }
  93. EXPORT_SYMBOL(sof_block_read);
  94. /*
  95. * Generic buffer page table creation.
  96. * Take the each physical page address and drop the least significant unused
  97. * bits from each (based on PAGE_SIZE). Then pack valid page address bits
  98. * into compressed page table.
  99. */
  100. int snd_sof_create_page_table(struct device *dev,
  101. struct snd_dma_buffer *dmab,
  102. unsigned char *page_table, size_t size)
  103. {
  104. int i, pages;
  105. pages = snd_sgbuf_aligned_pages(size);
  106. dev_dbg(dev, "generating page table for %p size 0x%zx pages %d\n",
  107. dmab->area, size, pages);
  108. for (i = 0; i < pages; i++) {
  109. /*
  110. * The number of valid address bits for each page is 20.
  111. * idx determines the byte position within page_table
  112. * where the current page's address is stored
  113. * in the compressed page_table.
  114. * This can be calculated by multiplying the page number by 2.5.
  115. */
  116. u32 idx = (5 * i) >> 1;
  117. u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
  118. u8 *pg_table;
  119. dev_vdbg(dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
  120. pg_table = (u8 *)(page_table + idx);
  121. /*
  122. * pagetable compression:
  123. * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5
  124. * ___________pfn 0__________ __________pfn 1___________ _pfn 2...
  125. * .... .... .... .... .... .... .... .... .... .... ....
  126. * It is created by:
  127. * 1. set current location to 0, PFN index i to 0
  128. * 2. put pfn[i] at current location in Little Endian byte order
  129. * 3. calculate an intermediate value as
  130. * x = (pfn[i+1] << 4) | (pfn[i] & 0xf)
  131. * 4. put x at offset (current location + 2) in LE byte order
  132. * 5. increment current location by 5 bytes, increment i by 2
  133. * 6. continue to (2)
  134. */
  135. if (i & 1)
  136. put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4,
  137. pg_table);
  138. else
  139. put_unaligned_le32(pfn, pg_table);
  140. }
  141. return pages;
  142. }
  143. EXPORT_SYMBOL(snd_sof_create_page_table);