1
2
3
4
5
6
7
8
9
10
11#include <linux/io-64-nonatomic-lo-hi.h>
12#include <linux/platform_device.h>
13#include <asm/unaligned.h>
14#include <sound/soc.h>
15#include <sound/sof.h>
16#include "sof-priv.h"
17
18
19
20
21
22
23
24
25void sof_io_write(struct snd_sof_dev *sdev, void __iomem *addr, u32 value)
26{
27 writel(value, addr);
28}
29EXPORT_SYMBOL(sof_io_write);
30
31u32 sof_io_read(struct snd_sof_dev *sdev, void __iomem *addr)
32{
33 return readl(addr);
34}
35EXPORT_SYMBOL(sof_io_read);
36
37void sof_io_write64(struct snd_sof_dev *sdev, void __iomem *addr, u64 value)
38{
39 writeq(value, addr);
40}
41EXPORT_SYMBOL(sof_io_write64);
42
43u64 sof_io_read64(struct snd_sof_dev *sdev, void __iomem *addr)
44{
45 return readq(addr);
46}
47EXPORT_SYMBOL(sof_io_read64);
48
49
50
51
52
53void sof_mailbox_write(struct snd_sof_dev *sdev, u32 offset,
54 void *message, size_t bytes)
55{
56 void __iomem *dest = sdev->bar[sdev->mailbox_bar] + offset;
57
58 memcpy_toio(dest, message, bytes);
59}
60EXPORT_SYMBOL(sof_mailbox_write);
61
62void sof_mailbox_read(struct snd_sof_dev *sdev, u32 offset,
63 void *message, size_t bytes)
64{
65 void __iomem *src = sdev->bar[sdev->mailbox_bar] + offset;
66
67 memcpy_fromio(message, src, bytes);
68}
69EXPORT_SYMBOL(sof_mailbox_read);
70
71
72
73
74
75void sof_block_write(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *src,
76 size_t size)
77{
78 void __iomem *dest = sdev->bar[bar] + offset;
79 const u8 *src_byte = src;
80 u32 affected_mask;
81 u32 tmp;
82 int m, n;
83
84 m = size / 4;
85 n = size % 4;
86
87
88 __iowrite32_copy(dest, src, m);
89
90 if (n) {
91 affected_mask = (1 << (8 * n)) - 1;
92
93
94
95
96
97 tmp = ioread32(dest + m * 4);
98 tmp &= ~affected_mask;
99
100 tmp |= *(u32 *)(src_byte + m * 4) & affected_mask;
101 iowrite32(tmp, dest + m * 4);
102 }
103}
104EXPORT_SYMBOL(sof_block_write);
105
106void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest,
107 size_t size)
108{
109 void __iomem *src = sdev->bar[bar] + offset;
110
111 memcpy_fromio(dest, src, size);
112}
113EXPORT_SYMBOL(sof_block_read);
114
115
116
117
118
119
120
121
122int snd_sof_create_page_table(struct device *dev,
123 struct snd_dma_buffer *dmab,
124 unsigned char *page_table, size_t size)
125{
126 int i, pages;
127
128 pages = snd_sgbuf_aligned_pages(size);
129
130 dev_dbg(dev, "generating page table for %p size 0x%zx pages %d\n",
131 dmab->area, size, pages);
132
133 for (i = 0; i < pages; i++) {
134
135
136
137
138
139
140
141 u32 idx = (5 * i) >> 1;
142 u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
143 u8 *pg_table;
144
145 dev_vdbg(dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
146
147 pg_table = (u8 *)(page_table + idx);
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 if (i & 1)
164 put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4,
165 pg_table);
166 else
167 put_unaligned_le32(pfn, pg_table);
168 }
169
170 return pages;
171}
172EXPORT_SYMBOL(snd_sof_create_page_table);
173