1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
4 * - Michal Horn <hornmich@fel.cvut.cz>
6 * This document contains proprietary information belonging to Czech
7 * Technical University in Prague. Passing on and copying of this
8 * document, and communication of its contents is not permitted
9 * without prior written authorization.
11 * File : spi_resp_transl.c
14 * This module provides the capability to translate pure SPI response into human readable form.
16 * Some SPI peripherals provides simple responses, but some others provide responses depending
17 * on previous command, they have obtained.
19 * So we have a structure, that maps SPI peripheral names (spi port names) to arrays of another
20 * structure, that maps spi commands to responses field descriptors.
22 * Command to response field map consists of a command mask, command, pointer to field
23 * descriptor and number of fields in field descriptor.
25 * Each fields descriptor maps field name to field mask, that specifies the meaning of each
26 * bit or group of bits in the response.
29 #include "drv/digital_io.h"
31 #include "hal/spi_resp_transl.h"
34 static const spitr_field_desc_t din_glob_field_descs[DIN_NUM_GLOB_FD] = {
35 { .field_name = "Thermal flag\t", .mask = (1 << 23) },
36 { .field_name = "INT flag\t", .mask = (1 << 22) },
37 { .field_name = "SP0 - DIN0\t", .mask = (1 << 14) },
38 { .field_name = "SP1 - DIN1\t", .mask = (1 << 15) },
39 { .field_name = "SP2 - DIN2\t", .mask = (1 << 16) },
40 { .field_name = "SP3 - DIN3\t", .mask = (1 << 17) },
41 { .field_name = "SP4 - DIN4\t", .mask = (1 << 18) },
42 { .field_name = "SP5 - DIN5\t", .mask = (1 << 19) },
43 { .field_name = "SP6 - DIN6\t", .mask = (1 << 20) },
44 { .field_name = "SP7 - DIN7\t", .mask = (1 << 21) },
45 { .field_name = "SG0 - DIN8\t", .mask = (1 << 0) },
46 { .field_name = "SG1 - DIN9\t", .mask = (1 << 1) },
47 { .field_name = "SG2 - DIN10\t", .mask = (1 << 2) },
48 { .field_name = "SG3 - DIN11\t", .mask = (1 << 3) },
49 { .field_name = "SG4 - DIN12\t", .mask = (1 << 4) },
50 { .field_name = "SG5 - DIN13\t", .mask = (1 << 5) },
51 { .field_name = "SG6 - DIN14\t", .mask = (1 << 6) },
52 { .field_name = "SG7 - DIN15\t", .mask = (1 << 7) },
53 { .field_name = "SG8 - NA\t", .mask = (1 << 8) },
54 { .field_name = "SG9 - NA\t", .mask = (1 << 9) },
55 { .field_name = "SG10 - NA\t", .mask = (1 << 10) },
56 { .field_name = "SG11 - NA\t", .mask = (1 << 11) },
57 { .field_name = "SG12 - NA\t", .mask = (1 << 12) },
58 { .field_name = "SG13 - NA\t", .mask = (1 << 13) }
61 static const spitr_field_desc_t lout_glob_field_descs[LOUT_NUM_GLOB_FD] = {
62 { .field_name = "U401 VS PS M", .mask = (1 << 24) },
63 { .field_name = "U401 IN8 state", .mask = (1 << 27) },
64 { .field_name = "U401 IN7 state", .mask = (1 << 28) },
65 { .field_name = "U401 IN6 state", .mask = (1 << 29) },
66 { .field_name = "U401 IN5 state", .mask = (1 << 30) },
67 { .field_name = "U401 Driver 8 status", .mask = (uint32_t)(1 << 31) },
68 { .field_name = "U401 Driver 7 status", .mask = (1 << 16) },
69 { .field_name = "U401 Driver 6 status", .mask = (1 << 17) },
70 { .field_name = "U401 Driver 5 status", .mask = (1 << 18) },
71 { .field_name = "U401 Driver 4 status", .mask = (1 << 19) },
72 { .field_name = "U401 Driver 3 status", .mask = (1 << 20) },
73 { .field_name = "U401 Driver 2 status", .mask = (1 << 21) },
74 { .field_name = "U401 Driver 1 status", .mask = (1 << 22) },
75 { .field_name = "U401 Thermal warning", .mask = (1 << 23) },
76 { .field_name = "U404 VS PS M", .mask = (1 << 8) },
77 { .field_name = "U404 IN8 state", .mask = (1 << 11) },
78 { .field_name = "U404 IN7 state", .mask = (1 << 12) },
79 { .field_name = "U404 IN6 state", .mask = (1 << 13) },
80 { .field_name = "U404 IN5 state", .mask = (1 << 14) },
81 { .field_name = "U404 Driver 8 status", .mask = (1 << 15) },
82 { .field_name = "U404 Driver 7 status", .mask = (1 << 0) },
83 { .field_name = "U404 Driver 6 status", .mask = (1 << 1) },
84 { .field_name = "U404 Driver 5 status", .mask = (1 << 2) },
85 { .field_name = "U404 Driver 4 status", .mask = (1 << 3) },
86 { .field_name = "U404 Driver 3 status", .mask = (1 << 4) },
87 { .field_name = "U404 Driver 2 status", .mask = (1 << 5) },
88 { .field_name = "U404 Driver 1 status", .mask = (1 << 6) },
89 { .field_name = "U404 Thermal warning", .mask = (1 << 7) }
92 static const spitr_field_desc_t dac_glob_field_descs[DAC_NUM_GLOB_FD] = {
93 { .field_name = "Provides no informations", .mask = 0 }
96 static const spitr_field_desc_t fray_glob_field_descs[FRAY_NUM_GLOB_FD] = {
97 { .field_name = "Parity bit", .mask = (1 << 0) },
98 { .field_name = "SPI error", .mask = (1 << 5) },
99 { .field_name = "UVVIO", .mask = (1 << 6) },
100 { .field_name = "UVVCC", .mask = (1 << 7) },
101 { .field_name = "TXEN clamped", .mask = (1 << 8) },
102 { .field_name = "Temp high", .mask = (1 << 9) },
103 { .field_name = "Bus error", .mask = (1 << 10) },
104 { .field_name = "Pwon", .mask = (1 << 11) },
105 { .field_name = "BGE clamped", .mask = (1 << 12) },
106 { .field_name = "Transmiter enabled", .mask = (1 << 13) },
107 { .field_name = "Normal mode", .mask = (1 << 14) },
108 { .field_name = "Bus wake", .mask = (1 << 15) }
111 static const spitr_field_desc_t hbr_statreg0_field_descs[HBR_NUM_STATREG_FD] = {
112 { .field_name = "GL_ER", .mask = (1 << 15) },
113 { .field_name = "Frame Error", .mask = (1 << 14) },
114 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
115 { .field_name = "TSD", .mask = (1 << 12) },
116 { .field_name = "TW", .mask = (1 << 11) },
117 { .field_name = "UV", .mask = (1 << 10) },
118 { .field_name = "OV", .mask = (1 << 9) },
119 { .field_name = "WDTO", .mask = (1 << 8) },
120 { .field_name = "DS_MON_3", .mask = (1 << 7) },
121 { .field_name = "DS_MON_2", .mask = (1 << 6) },
122 { .field_name = "DS_MON_1", .mask = (1 << 5) },
123 { .field_name = "DS_MON_0", .mask = (1 << 4) },
124 { .field_name = "OT_EXT", .mask = (1 << 1) },
125 { .field_name = "CP_LOW", .mask = (1 << 0) }
128 static const spitr_field_desc_t hbr_applreg1_field_descs[HBR_NUM_APPLREG1_FD] = {
129 { .field_name = "GL_ER", .mask = (1 << 15) },
130 { .field_name = "Frame Error", .mask = (1 << 14) },
131 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
132 { .field_name = "TSD", .mask = (1 << 12) },
133 { .field_name = "TW", .mask = (1 << 11) },
134 { .field_name = "UV", .mask = (1 << 10) },
135 { .field_name = "OV", .mask = (1 << 9) },
136 { .field_name = "WDTO", .mask = (1 << 8) },
137 { .field_name = "RWD", .mask = (1 << 7) },
138 { .field_name = "FW_PAS", .mask = (1 << 6) },
139 { .field_name = "OFF_CAL", .mask = (1 << 5) },
140 { .field_name = "CLK_SPCTR", .mask = (1 << 4) },
141 { .field_name = "OVT", .mask = (1 << 3) },
142 { .field_name = "OV_UV_RD", .mask = (1 << 2) },
143 { .field_name = "DIAG", .mask = (3 << 0) }
146 static const spitr_field_desc_t hbr_applreg2_field_descs[HBR_NUM_APPLREG2_FD] = {
147 { .field_name = "GL_ER", .mask = (1 << 15) },
148 { .field_name = "Frame Error", .mask = (1 << 14) },
149 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
150 { .field_name = "TSD", .mask = (1 << 12) },
151 { .field_name = "TW", .mask = (1 << 11) },
152 { .field_name = "UV", .mask = (1 << 10) },
153 { .field_name = "OV", .mask = (1 << 9) },
154 { .field_name = "WDTO", .mask = (1 << 8) },
155 { .field_name = "RWD", .mask = (1 << 7) },
156 { .field_name = "COPT", .mask = (7 << 4) },
157 { .field_name = "FW", .mask = (1 << 3) },
158 { .field_name = "MCSA", .mask = (1 << 2) },
159 { .field_name = "GCSA", .mask = (3 << 0) }
162 static const spitr_field_desc_t hbr_applreg3_field_descs[HBR_NUM_APPLREG3_FD] = {
163 { .field_name = "GL_ER", .mask = (1 << 15) },
164 { .field_name = "Frame Error", .mask = (1 << 14) },
165 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
166 { .field_name = "TSD", .mask = (1 << 12) },
167 { .field_name = "TW", .mask = (1 << 11) },
168 { .field_name = "UV", .mask = (1 << 10) },
169 { .field_name = "OV", .mask = (1 << 9) },
170 { .field_name = "WDTO", .mask = (1 << 8) },
171 { .field_name = "RWD", .mask = (1 << 7) },
172 { .field_name = "EXT_TS", .mask = (1 << 6) },
173 { .field_name = "EXT_TH_5", .mask = (1 << 5) },
174 { .field_name = "EXT_TH_4", .mask = (1 << 4) },
175 { .field_name = "EXT_TH_3", .mask = (1 << 3) },
176 { .field_name = "EXT_TH_2", .mask = (1 << 2) },
177 { .field_name = "EXT_TH_1", .mask = (1 << 1) },
178 { .field_name = "EXT_TH_0", .mask = (1 << 0) }
181 static const spitr_field_desc_t hbr_diaddr0_field_descs[HBR_NUM_DIADDR0_FD] = {
182 { .field_name = "GL_ER", .mask = (1 << 15) },
183 { .field_name = "Frame Error", .mask = (1 << 14) },
184 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
185 { .field_name = "TSD", .mask = (1 << 12) },
186 { .field_name = "TW", .mask = (1 << 11) },
187 { .field_name = "UV", .mask = (1 << 10) },
188 { .field_name = "OV", .mask = (1 << 9) },
189 { .field_name = "WDTO", .mask = (1 << 8) },
190 { .field_name = "FAM", .mask = (3 << 6) },
191 { .field_name = "NR_PI", .mask = (0x3F << 0) }
194 static const spitr_field_desc_t hbr_diaddr1_field_descs[HBR_NUM_DIADDR1_FD] = {
195 { .field_name = "GL_ER", .mask = (1 << 15) },
196 { .field_name = "Frame Error", .mask = (1 << 14) },
197 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
198 { .field_name = "TSD", .mask = (1 << 12) },
199 { .field_name = "TW", .mask = (1 << 11) },
200 { .field_name = "UV", .mask = (1 << 10) },
201 { .field_name = "OV", .mask = (1 << 9) },
202 { .field_name = "WDTO", .mask = (1 << 8) },
203 { .field_name = "PRD_ID", .mask = (0xFF << 0) }
206 static const spitr_field_desc_t hbr_diaddr2_field_descs[HBR_NUM_DIADDR2_FD] = {
207 { .field_name = "GL_ER", .mask = (1 << 15) },
208 { .field_name = "Frame Error", .mask = (1 << 14) },
209 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
210 { .field_name = "TSD", .mask = (1 << 12) },
211 { .field_name = "TW", .mask = (1 << 11) },
212 { .field_name = "UV", .mask = (1 << 10) },
213 { .field_name = "OV", .mask = (1 << 9) },
214 { .field_name = "WDTO", .mask = (1 << 8) },
215 { .field_name = "PRD_ID", .mask = (0xFF << 0) }
218 static const spitr_field_desc_t hbr_diaddr3_field_descs[HBR_NUM_DIADDR3_FD] = {
219 { .field_name = "GL_ER", .mask = (1 << 15) },
220 { .field_name = "Frame Error", .mask = (1 << 14) },
221 { .field_name = "STK_RESET_Q", .mask = (1 << 13) },
222 { .field_name = "TSD", .mask = (1 << 12) },
223 { .field_name = "TW", .mask = (1 << 11) },
224 { .field_name = "UV", .mask = (1 << 10) },
225 { .field_name = "OV", .mask = (1 << 9) },
226 { .field_name = "WDTO", .mask = (1 << 8) },
227 { .field_name = "BR", .mask = (1 << 7) },
228 { .field_name = "AR5", .mask = (1 << 6) },
229 { .field_name = "AR4", .mask = (1 << 5) },
230 { .field_name = "AR3", .mask = (1 << 4) },
231 { .field_name = "32-bits", .mask = (1 << 3) },
232 { .field_name = "24-bits", .mask = (1 << 2) },
233 { .field_name = "16-bits", .mask = (1 << 1) },
234 { .field_name = "8-bits", .mask = (1 << 0) }
237 /* Map register descriptors to spi commands */
238 static const spitr_cmd_map_t din_cmd_map[DIN_NUM_CMD_D] = {
239 { .cmd_msk = 0, .command = 0, .field_desc = din_glob_field_descs, .num_fields = DIN_NUM_GLOB_FD}
242 static const spitr_cmd_map_t lout_cmd_map[LOUT_NUM_CMD_D] = {
243 { .cmd_msk = 0, .command = 0, .field_desc = lout_glob_field_descs, .num_fields = LOUT_NUM_GLOB_FD }
246 static const spitr_cmd_map_t dac_cmd_map[DAC_NUM_CMD_D] = {
247 { .cmd_msk = 0, .command = 0, .field_desc = dac_glob_field_descs, .num_fields = DAC_NUM_GLOB_FD }
250 static const spitr_cmd_map_t fray_cmd_map[FRAY_NUM_CMD_D] = {
251 { .cmd_msk = 0, .command = 0, .field_desc = fray_glob_field_descs, .num_fields = FRAY_NUM_GLOB_FD }
254 static const spitr_cmd_map_t hbr_cmd_map[HBR_NUM_CMD_D] = {
255 { .cmd_msk = 0x0000FF00, .command = 0xC000, .field_desc = hbr_diaddr0_field_descs, .num_fields = HBR_NUM_DIADDR0_FD },
256 { .cmd_msk = 0x0000FF00, .command = 0xC100, .field_desc = hbr_diaddr1_field_descs, .num_fields = HBR_NUM_DIADDR1_FD },
257 { .cmd_msk = 0x0000FF00, .command = 0xC200, .field_desc = hbr_diaddr2_field_descs, .num_fields = HBR_NUM_DIADDR2_FD },
258 { .cmd_msk = 0x0000FF00, .command = 0xC300, .field_desc = hbr_diaddr3_field_descs, .num_fields = HBR_NUM_DIADDR3_FD },
259 { .cmd_msk = 0x0000FF00, .command = 0x8000, .field_desc = hbr_statreg0_field_descs, .num_fields = HBR_NUM_STATREG_FD },
260 { .cmd_msk = 0x0000FF00, .command = 0x4000, .field_desc = hbr_statreg0_field_descs, .num_fields = HBR_NUM_STATREG_FD },
261 { .cmd_msk = 0x0000FF00, .command = 0x4100, .field_desc = hbr_applreg1_field_descs, .num_fields = HBR_NUM_APPLREG1_FD },
262 { .cmd_msk = 0x0000FF00, .command = 0x4200, .field_desc = hbr_applreg2_field_descs, .num_fields = HBR_NUM_APPLREG2_FD },
263 { .cmd_msk = 0x0000FF00, .command = 0x4300, .field_desc = hbr_applreg3_field_descs, .num_fields = HBR_NUM_APPLREG3_FD },
264 { .cmd_msk = 0x0000FF00, .command = 0x0100, .field_desc = hbr_applreg1_field_descs, .num_fields = HBR_NUM_APPLREG1_FD },
265 { .cmd_msk = 0x0000FF00, .command = 0x0200, .field_desc = hbr_applreg2_field_descs, .num_fields = HBR_NUM_APPLREG2_FD },
266 { .cmd_msk = 0x0000FF00, .command = 0x0300, .field_desc = hbr_applreg3_field_descs, .num_fields = HBR_NUM_APPLREG3_FD },
269 /* Map command maps to SPI peripheral name */
270 static const spitr_name_map_t spitr_map[NUM_SPI_DEVICES] = {
271 { .spi_name = DIO_PORT_NAME_DINSPI, .cmd_map = din_cmd_map, .num_cmd = DIN_NUM_CMD_D},
272 { .spi_name = DIO_PORT_NAME_LOUT, .cmd_map = lout_cmd_map, .num_cmd = LOUT_NUM_CMD_D },
273 { .spi_name = DIO_PORT_NAME_DAC1_2, .cmd_map = dac_cmd_map, .num_cmd = DAC_NUM_CMD_D },
274 { .spi_name = DIO_PORT_NAME_DAC3_4, .cmd_map = dac_cmd_map, .num_cmd = DAC_NUM_CMD_D },
275 { .spi_name = DIO_PORT_NAME_HBR, .cmd_map = hbr_cmd_map, .num_cmd = HBR_NUM_CMD_D },
276 { .spi_name = DIO_PORT_NAME_FRAY1, .cmd_map = fray_cmd_map, .num_cmd = FRAY_NUM_CMD_D },
277 { .spi_name = DIO_PORT_NAME_FRAY2, .cmd_map = fray_cmd_map, .num_cmd = FRAY_NUM_CMD_D }
283 * Get the map spi command to spi response.
284 * @param[in] spi_port_name String of the port name
285 * @param[in] len Length of the port name string, if terminated by '/0', then len = -1
286 * @param[out] num_cmdDesc returns number of command->fieldDesc fields assigned to the map
287 * @return command to field_desc map or NULL if not found
289 const spitr_cmd_map_t *get_spi_cmd_map(const char *spi_port_name, int len, uint32_t *num_cmdDesc)
292 const char *spi_port_name_ptr;
293 char port_name_term[32];
295 if (len != -1) { // port name not terminated by '\0'
296 strncpy(port_name_term, spi_port_name, len);
297 port_name_term[len] = '\0';
298 spi_port_name_ptr = port_name_term;
300 else spi_port_name_ptr = spi_port_name;
302 for (i = 0; i < NUM_SPI_DEVICES; i++) {
303 if (strcmp(spi_port_name_ptr, spitr_map[i].spi_name) == 0) {
304 *num_cmdDesc = spitr_map[i].num_cmd;
305 return spitr_map[i].cmd_map;
313 * Get fields descriptor according to the field descriptor map and command.
314 * @param[in] cmd_map pointer to structure, that maps commands to their field descriptors
315 * @param[in] num_cmd Number of fields in the cmd_map
316 * @param[in] cmd Command used as a key value in the cmd_map. We are searching for the field descriptors assigned to this command
317 * @param[out] num_fdDesc Number of fields in field descriptors structure, that was found
318 * @return pointer to the structure that maps field names to field masks or NULL, when not found
320 const spitr_field_desc_t *get_spi_field_desc(const spitr_cmd_map_t *cmd_map, uint32_t num_cmd, uint32_t cmd, uint32_t *num_fdDesc)
322 if (cmd_map == NULL) {
328 for (i = 0; i < num_cmd; i++) {
329 uint32_t mskcmd = cmd & cmd_map[i].cmd_msk;
330 uint32_t tmpCmd = cmd_map[i].command;
331 if (mskcmd == tmpCmd) {
332 *num_fdDesc = cmd_map[i].num_fields;
333 return cmd_map[i].field_desc;
336 *num_fdDesc = cmd_map[i].num_fields;
341 * Translate spi response into human readable form
342 * @param[in] fd Pointer to structure that maps Field names to field value masks
343 * @param[in] num_fields Number of fields in fd
344 * @param[in] value spi response to be traslated
345 * @param[out] table The result is stored in this table, where each row consists of the value name and the value
346 * @return number of rows in the translated table
348 int spitr_fill_tr_table(const spitr_field_desc_t *fd, uint32_t num_fields, uint32_t value, spitr_reg_translate_table_t *table)
352 for (i = 0; i < num_fields; i++) {
353 table->row[i].field_name = fd[i].field_name;
354 table->row[i].value = __mfld2val(fd[i].mask, value);
356 table->num_rows = num_fields;