1 /*
2 Copyright (c) 2018, MIPI Alliance, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * Neither the name of the copyright holder nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Contributors:
36 * Norbert Schulz (Intel Corporation) - Initial API and implementation
37 */
38 #include "mipi_syst.h"
39 #include "mipi_syst/message.h"
40 #include "mipi_syst/crc32.h"
41
42 #if defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE)
43
44 /** scatter write routine
45 *
46 * This function implements the scatter write algorithm that translates
47 * the logical SyS-T memory descriptor representation into output
48 * requests. The actual output routines are defined through
49 * the MIPI_SYST_OUTPUT_* definitions from the platform header file.
50 *
51 * @param systh used syst handle
52 * @param scatterprog message content write instructions
53 * @param pdesc pointer to memory area with message data
54 */
mipi_syst_scatter_write(struct mipi_syst_handle * systh,struct mipi_syst_scatter_prog * scatterprog,const void * pdesc)55 void mipi_syst_scatter_write(struct mipi_syst_handle* systh,
56 struct mipi_syst_scatter_prog *scatterprog, const void *pdesc)
57 {
58 unsigned int repeat;
59
60 /* Define an "any" size integer pointer to avoid casts and to simplify
61 * type based incrementing
62 */
63 union {
64 const void *vp;
65 const mipi_syst_u8 *bp;
66 const mipi_syst_u16 *hp;
67 const mipi_syst_u32 *wp;
68 const mipi_syst_u64 *dp;
69 } data;
70
71 #if defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM)
72 #define IFDO(a, b) { if (a) do { b; } while (0); }
73
74 mipi_syst_u32 crc;
75 int use_crc;
76
77 use_crc = systh->systh_tag.et_chksum;
78 crc = MIPI_SYST_CRC32_INIT(0);
79 #else
80
81 #define IFDO(a, b)
82 /* no checksump computation support */
83 #endif
84
85 /* Write the "always" present tag field as a time-stamped D32 */
86 MIPI_SYST_OUTPUT_D32TS(systh, *(mipi_syst_u32 *)pdesc);
87
88 IFDO(use_crc, MIPI_SYST_CRC32_U32(crc, *(mipi_syst_u32 *)pdesc));
89
90 /* Run the message scatter write program to dump the message contents
91 */
92 while (scatterprog->sso_opcode != MIPI_SYST_SCATTER_OP_END) {
93 repeat = scatterprog->sso_length;
94 data.vp = pdesc;
95 data.bp += scatterprog->sso_offset;
96
97 switch (scatterprog->sso_opcode) {
98 case MIPI_SYST_SCATTER_OP_8BIT:
99 do {
100 MIPI_SYST_OUTPUT_D8(systh, *data.bp);
101 IFDO(use_crc,
102 MIPI_SYST_CRC32_U8(crc, *data.bp));
103 ++data.bp;
104 } while (--repeat);
105 break;
106
107 case MIPI_SYST_SCATTER_OP_16BIT:
108 do {
109 MIPI_SYST_OUTPUT_D16(systh, *data.hp);
110 IFDO(use_crc,
111 MIPI_SYST_CRC32_U16(crc, *data.hp));
112 ++data.hp;
113 } while (--repeat);
114 break;
115
116 case MIPI_SYST_SCATTER_OP_32BIT:
117 do {
118 MIPI_SYST_OUTPUT_D32(systh, *data.wp);
119 IFDO(use_crc,
120 MIPI_SYST_CRC32_U32(crc, *data.wp));
121 ++data.wp;
122 } while (--repeat);
123 break;
124
125
126 case MIPI_SYST_SCATTER_OP_64BIT:
127 do {
128 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
129 MIPI_SYST_OUTPUT_D64(systh, *data.dp);
130 #else
131 #if defined(MIPI_SYST_BIG_ENDIAN)
132 MIPI_SYST_OUTPUT_D32(systh, data.wp[1]);
133 MIPI_SYST_OUTPUT_D32(systh, data.wp[0]);
134 #else
135 MIPI_SYST_OUTPUT_D32(systh, data.wp[0]);
136 MIPI_SYST_OUTPUT_D32(systh, data.wp[1]);
137 #endif
138
139 #endif /* ! defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) */
140 IFDO(use_crc,
141 MIPI_SYST_CRC32_U64(crc, *data.dp));
142 ++data.dp;
143 } while (--repeat);
144 break;
145
146 case MIPI_SYST_SCATTER_OP_BLOB:
147 /* data location is pointer to real data,
148 * not data itself
149 */
150 data.vp = *(void **)data.vp;
151
152 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
153
154 while (repeat >= sizeof(mipi_syst_u64)) {
155 mipi_syst_u64 v;
156 v = MIPI_SYST_HTOLE64(*data.dp);
157 MIPI_SYST_OUTPUT_D64(systh, v);
158 IFDO(use_crc,
159 MIPI_SYST_CRC32_U64(crc, v));
160 ++data.dp;
161 repeat -= sizeof(mipi_syst_u64);
162 }
163
164 if (repeat >= sizeof(mipi_syst_u32)) {
165 mipi_syst_u32 v;
166 v = MIPI_SYST_HTOLE32(*data.wp);
167 MIPI_SYST_OUTPUT_D32(systh, v);
168 IFDO(use_crc,
169 MIPI_SYST_CRC32_U32(crc,
170 *data.wp));
171 ++data.wp;
172 repeat -= sizeof(mipi_syst_u32);
173 }
174 #else
175 while (repeat >= sizeof(mipi_syst_u32)) {
176 mipi_syst_u32 v;
177 v = MIPI_SYST_HTOLE32(*data.wp);
178 MIPI_SYST_OUTPUT_D32(systh, v);
179
180 IFDO(use_crc,
181 MIPI_SYST_CRC32_U32(crc, v));
182 ++data.wp;
183 repeat -= sizeof(mipi_syst_u32);
184 }
185 #endif
186 if (repeat >= sizeof(mipi_syst_u16)) {
187 mipi_syst_u16 v;
188 v = MIPI_SYST_HTOLE16(*data.hp);
189 MIPI_SYST_OUTPUT_D16(systh, v);
190
191 IFDO(use_crc,
192 MIPI_SYST_CRC32_U16(crc, v));
193 ++data.hp;
194 repeat -= sizeof(mipi_syst_u16);
195 }
196
197 if (repeat) {
198 MIPI_SYST_OUTPUT_D8(systh,
199 *data.bp);
200 IFDO(use_crc,
201 MIPI_SYST_CRC32_U8(crc, *data.bp));
202 }
203 break;
204 }
205 ++scatterprog;
206 }
207
208 #if defined(MIPI_SYST_PCFG_ENABLE_CHECKSUM)
209 if (use_crc) {
210 crc = MIPI_SYST_CRC32_GET(crc);
211 MIPI_SYST_OUTPUT_D32(systh, crc);
212 }
213 #endif
214
215 /* EVENT end of record mark */
216 MIPI_SYST_OUTPUT_FLAG(systh);
217 }
218
219 #endif /* defined(MIPI_SYST_PCFG_ENABLE_DEFAULT_SCATTER_WRITE) */