]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/hal/spi_resp_transl.c
e09555370a522fc63f1aa8770c6277fbc210b2fc
[pes-rpp/rpp-lib.git] / rpp / src / hal / spi_resp_transl.c
1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn <hornmich@fel.cvut.cz>
5  *
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.
10  *
11  * File : spi_resp_transl.c
12  *
13  * Abstract:
14  *          This module provides the capability to translate pure SPI response into human readable form.
15  *
16  *      Some SPI peripherals provides simple responses, but some others provide responses depending
17  *      on previous command, they have obtained.
18  *
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.
21  *
22  *      Command to response field map consists of a command mask, command, pointer to field
23  *      descriptor and number of fields in field descriptor.
24  *
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.
27  */
28
29 #include "hal/hal.h"
30 #include "hal/spi.h"
31 #include "hal/spi_resp_transl.h"
32
33 // Field descriptors
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) }
59 };
60
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) }
90 };
91
92 static const spitr_field_desc_t dac_glob_field_descs[DAC_NUM_GLOB_FD] = {
93         { .field_name = "Provides no informations", .mask = 0 }
94 };
95
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) }
109 };
110
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) }
126 };
127
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) }
144 };
145
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) }
160 };
161
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) }
179 };
180
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) }
192 };
193
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) }
204 };
205
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) }
216 };
217
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) }
235 };
236
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}
240 };
241
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 }
244 };
245
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 }
248 };
249
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 }
252 };
253
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 },
267 };
268
269 /* Map command maps to SPI peripheral name */
270 static const spitr_name_map_t spitr_map[NUM_SPI_DEVICES] = {
271         { .spi_name = PORT_NAME_DINSPI,     .cmd_map = din_cmd_map,     .num_cmd = DIN_NUM_CMD_D},
272         { .spi_name = PORT_NAME_LOUT,       .cmd_map = lout_cmd_map,    .num_cmd = LOUT_NUM_CMD_D },
273         { .spi_name = PORT_NAME_DAC1_2,     .cmd_map = dac_cmd_map,     .num_cmd = DAC_NUM_CMD_D },
274         { .spi_name = PORT_NAME_DAC3_4,     .cmd_map = dac_cmd_map,     .num_cmd = DAC_NUM_CMD_D },
275         { .spi_name = PORT_NAME_HBR,        .cmd_map = hbr_cmd_map,     .num_cmd = HBR_NUM_CMD_D },
276         { .spi_name = PORT_NAME_FRAY1,      .cmd_map = fray_cmd_map,    .num_cmd = FRAY_NUM_CMD_D },
277         { .spi_name = PORT_NAME_FRAY2,      .cmd_map = fray_cmd_map,    .num_cmd = FRAY_NUM_CMD_D }
278 };
279
280
281
282 /**
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
288  */
289 const spitr_cmd_map_t *get_spi_cmd_map(const char *spi_port_name, int len, uint32_t *num_cmdDesc)
290 {
291         uint32_t i;
292         const char *spi_port_name_ptr;
293         char port_name_term[32];
294
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;
299         }
300         else spi_port_name_ptr = spi_port_name;
301
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;
306                 }
307         }
308         *num_cmdDesc = 0;
309         return NULL;
310 }
311
312 /**
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
319  */
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)
321 {
322         if (cmd_map == NULL) {
323                 *num_fdDesc = 0;
324                 return NULL;
325         }
326
327         uint32_t i;
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;
334                 }
335         }
336         *num_fdDesc = cmd_map[i].num_fields;
337         return NULL;
338 }
339
340 /**
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
347  */
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)
349 {
350         uint32_t i;
351
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);
355         }
356         table->num_rows = num_fields;
357         return i;
358 }