]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/can.c
Make the RPP layer thread safe
[pes-rpp/rpp-lib.git] / rpp / src / rpp / can.c
1 /* Copyright (C) 2013-2015 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Carlos Jenkins <carlos@jenkins.co.cr>
5  *     - Karolína Burešová <karry@karryanna.cz>
6  *
7  * This document contains proprietary information belonging to Czech
8  * Technical University in Prague. Passing on and copying of this
9  * document, and communication of its contents is not permitted
10  * without prior written authorization.
11  *
12  * File : can.c
13  * Abstract:
14  *     CAN Bus Communication RPP API implementation file.
15  *
16  * References:
17  *     can.h
18  *     RPP API documentation.
19  */
20
21
22 #include "rpp/rpp.h"
23 #include <math.h>
24 #include "sys/ti_drv_dmm.h"
25 #include "rpp/mutex.h"
26
27 RPP_MUTEX_DEFINE(mutex_can);
28
29 static const struct rpp_can_config *can_config = NULL;
30
31 typedef volatile struct CANBase {
32         uint32_t CTL;               /**< 0x0000: Control Register                       */
33         uint32_t ES;                /**< 0x0004: Error and Status Register              */
34         uint32_t EERC;              /**< 0x0008: Error Counter Register                 */
35         uint32_t BTR;               /**< 0x000C: Bit Timing Register                    */
36         uint32_t INT;               /**< 0x0010: Interrupt Register                     */
37         uint32_t TEST;              /**< 0x0014: Test Register                          */
38         uint32_t      : 32U;        /**< 0x0018: Reserved                               */
39         uint32_t PERR;              /**< 0x001C: Parity/SECDED Error Code Register      */
40         uint32_t REL;               /**< 0x0020: Core Release Register                  */
41         uint32_t ECCDIAG;           /**< 0x0024: ECC Diagnostic Register                */
42         uint32_t ECCDIADSTAT;       /**< 0x0028: ECC Diagnostic Status Register         */
43         uint32_t      : 32U;        /**< 0x002C: Reserved                               */
44         uint32_t      : 32U;        /**< 0x0030: Reserved                               */
45         uint32_t      : 32U;        /**< 0x0034: Reserved                               */
46         uint32_t      : 32U;        /**< 0x0038: Reserved                               */
47         uint32_t      : 32U;        /**< 0x003C: Reserved                               */
48         uint32_t      : 32U;        /**< 0x0040: Reserved                               */
49         uint32_t      : 32U;        /**< 0x0044: Reserved                               */
50         uint32_t      : 32U;        /**< 0x0048: Reserved                               */
51         uint32_t      : 32U;        /**< 0x004C: Reserved                               */
52         uint32_t      : 32U;        /**< 0x0050: Reserved                               */
53         uint32_t      : 32U;        /**< 0x0054: Reserved                               */
54         uint32_t      : 32U;        /**< 0x0058: Reserved                               */
55         uint32_t      : 32U;        /**< 0x005C: Reserved                               */
56         uint32_t      : 32U;        /**< 0x0060: Reserved                               */
57         uint32_t      : 32U;        /**< 0x0064: Reserved                               */
58         uint32_t      : 32U;        /**< 0x0068: Reserved                               */
59         uint32_t      : 32U;        /**< 0x006C: Reserved                               */
60         uint32_t      : 32U;        /**< 0x0070: Reserved                               */
61         uint32_t      : 32U;        /**< 0x0074: Reserved                               */
62         uint32_t      : 32U;        /**< 0x0078: Reserved                               */
63         uint32_t      : 32U;        /**< 0x007C: Reserved                               */
64         uint32_t ABOTR;             /**< 0x0080: Auto Bus On Time Register              */
65         uint32_t TXRQX;             /**< 0x0084: Transmission Request X Register        */
66         uint32_t TXRQx[4U];         /**< 0x0088-0x0094: Transmission Request Registers  */
67         uint32_t NWDATX;            /**< 0x0098: New Data X Register                    */
68         uint32_t NWDATx[4U];        /**< 0x009C-0x00A8: New Data Registers              */
69         uint32_t INTPNDX;           /**< 0x00AC: Interrupt Pending X Register           */
70         uint32_t INTPNDx[4U];       /**< 0x00B0-0x00BC: Interrupt Pending Registers     */
71         uint32_t MSGVALX;           /**< 0x00C0: Message Valid X Register               */
72         uint32_t MSGVALx[4U];       /**< 0x00C4-0x00D0: Message Valid Registers         */
73         uint32_t      : 32U;        /**< 0x00D4: Reserved                               */
74         uint32_t INTMUXx[4U];       /**< 0x00D8-0x00E4: Interrupt Multiplexer Registers */
75         uint32_t      : 32U;        /**< 0x00E8: Reserved                               */
76         uint32_t      : 32U;        /**< 0x00EC: Reserved                               */
77         uint32_t      : 32U;        /**< 0x00F0: Reserved                               */
78         uint32_t      : 32U;        /**< 0x00F4: Reserved                               */
79         uint32_t      : 32U;        /**< 0x00F8: Reserved                               */
80         uint32_t      : 32U;        /**< 0x00FC: Reserved                               */
81 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
82         uint8_t IF1NO;              /**< 0x0100: IF1 Command Register, Msg Number       */
83         uint8_t IF1STAT;            /**< 0x0100: IF1 Command Register, Status           */
84         uint8_t IF1CMD;             /**< 0x0100: IF1 Command Register, Command          */
85         uint32_t      : 8U;         /**< 0x0100: IF1 Command Register, Reserved         */
86 #else
87         uint32_t      : 8U;         /**< 0x0100: IF1 Command Register, Reserved         */
88         uint8_t IF1CMD;             /**< 0x0100: IF1 Command Register, Command          */
89         uint8_t IF1STAT;            /**< 0x0100: IF1 Command Register, Status           */
90         uint8_t IF1NO;              /**< 0x0100: IF1 Command Register, Msg Number       */
91 #endif
92         uint32_t IF1MSK;            /**< 0x0104: IF1 Mask Register                      */
93         uint32_t IF1ARB;            /**< 0x0108: IF1 Arbitration Register               */
94         uint32_t IF1MCTL;           /**< 0x010C: IF1 Message Control Register           */
95         uint8_t IF1DATx[8U];        /**< 0x0110-0x0114: IF1 Data A and B Registers      */
96         uint32_t      : 32U;        /**< 0x0118: Reserved                               */
97         uint32_t      : 32U;        /**< 0x011C: Reserved                               */
98 #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
99         uint8_t IF2NO;              /**< 0x0120: IF2 Command Register, Msg No           */
100         uint8_t IF2STAT;            /**< 0x0120: IF2 Command Register, Status           */
101         uint8_t IF2CMD;             /**< 0x0120: IF2 Command Register, Command          */
102         uint32_t      : 8U;         /**< 0x0120: IF2 Command Register, Reserved         */
103 #else
104         uint32_t      : 8U;         /**< 0x0120: IF2 Command Register, Reserved         */
105         uint8_t IF2CMD;             /**< 0x0120: IF2 Command Register, Command          */
106         uint8_t IF2STAT;            /**< 0x0120: IF2 Command Register, Status           */
107         uint8_t IF2NO;              /**< 0x0120: IF2 Command Register, Msg Number       */
108 #endif
109         uint32_t IF2MSK;            /**< 0x0124: IF2 Mask Register                      */
110         uint32_t IF2ARB;            /**< 0x0128: IF2 Arbitration Register               */
111         uint32_t IF2MCTL;           /**< 0x012C: IF2 Message Control Register           */
112         uint8_t IF2DATx[8U];        /**< 0x0130-0x0134: IF2 Data A and B Registers      */
113         uint32_t      : 32U;        /**< 0x0138: Reserved                               */
114         uint32_t      : 32U;        /**< 0x013C: Reserved                               */
115         uint32_t IF3OBS;            /**< 0x0140: IF3 Observation Register               */
116         uint32_t IF3MSK;            /**< 0x0144: IF3 Mask Register                      */
117         uint32_t IF3ARB;            /**< 0x0148: IF3 Arbitration Register               */
118         uint32_t IF3MCTL;           /**< 0x014C: IF3 Message Control Register           */
119         uint8_t IF3DATx[8U];        /**< 0x0150-0x0154: IF3 Data A and B Registers      */
120         uint32_t      : 32U;        /**< 0x0158: Reserved                               */
121         uint32_t      : 32U;        /**< 0x015C: Reserved                               */
122         uint32_t IF3UEy[4U];        /**< 0x0160-0x016C: IF3 Update Enable Registers     */
123         uint32_t      : 32U;        /**< 0x0170: Reserved                               */
124         uint32_t      : 32U;        /**< 0x0174: Reserved                               */
125         uint32_t      : 32U;        /**< 0x0178: Reserved                               */
126         uint32_t      : 32U;        /**< 0x017C: Reserved                               */
127         uint32_t      : 32U;        /**< 0x0180: Reserved                               */
128         uint32_t      : 32U;        /**< 0x0184: Reserved                               */
129         uint32_t      : 32U;        /**< 0x0188: Reserved                               */
130         uint32_t      : 32U;        /**< 0x018C: Reserved                               */
131         uint32_t      : 32U;        /**< 0x0190: Reserved                               */
132         uint32_t      : 32U;        /**< 0x0194: Reserved                               */
133         uint32_t      : 32U;        /**< 0x0198: Reserved                               */
134         uint32_t      : 32U;        /**< 0x019C: Reserved                               */
135         uint32_t      : 32U;        /**< 0x01A0: Reserved                               */
136         uint32_t      : 32U;        /**< 0x01A4: Reserved                               */
137         uint32_t      : 32U;        /**< 0x01A8: Reserved                               */
138         uint32_t      : 32U;        /**< 0x01AC: Reserved                               */
139         uint32_t      : 32U;        /**< 0x01B0: Reserved                               */
140         uint32_t      : 32U;        /**< 0x01B4: Reserved                               */
141         uint32_t      : 32U;        /**< 0x01B8: Reserved                               */
142         uint32_t      : 32U;        /**< 0x01BC: Reserved                               */
143         uint32_t      : 32U;        /**< 0x01C0: Reserved                               */
144         uint32_t      : 32U;        /**< 0x01C4: Reserved                               */
145         uint32_t      : 32U;        /**< 0x01C8: Reserved                               */
146         uint32_t      : 32U;        /**< 0x01CC: Reserved                               */
147         uint32_t      : 32U;        /**< 0x01D0: Reserved                               */
148         uint32_t      : 32U;        /**< 0x01D4: Reserved                               */
149         uint32_t      : 32U;        /**< 0x01D8: Reserved                               */
150         uint32_t      : 32U;        /**< 0x01DC: Reserved                               */
151         uint32_t TIOC;              /**< 0x01E0: TX IO Control Register                 */
152         uint32_t RIOC;              /**< 0x01E4: RX IO Control Register                 */
153 } canBASE_t;
154
155 #define canREG1 ((canBASE_t *)0xFFF7DC00U)
156 #define canREG2 ((canBASE_t *)0xFFF7DE00U)
157 #define canREG3 ((canBASE_t *)0xFFF7E000U)
158
159 #ifndef __little_endian__
160 static const uint32_t s_can_byte_order[] = {3, 2, 1, 0, 7, 6, 5, 4};
161 #endif
162
163 static canBASE_t *can_base[3] = { canREG1, canREG2, canREG3 };
164
165 static inline canBASE_t *map_controller(uint8_t controller)
166 {
167         if (controller < 1 || controller > 3)
168                 return NULL;
169         return can_base[controller - 1];
170 }
171
172
173 static int8_t init_tx_box(struct rpp_can_tx_config cfg)
174 {
175         canBASE_t *controller;
176
177         if (!(controller = map_controller(cfg.controller)))
178                 return FAILURE;
179
180         // Wait until IF1 is ready to use
181         while (controller->IF1STAT & (1U << 7)) ;
182
183         /**
184          * 31 Set whether use of std/ext ID should have effect on acceptance filtering
185          */
186         switch (cfg.type) {
187         case RPP_CAN_STANDARD:
188                 controller->IF1MSK = 0U << 31;
189                 break;
190         case RPP_CAN_MIXED:
191                 controller->IF1MSK = 1U << 31;
192                 break;
193         case RPP_CAN_EXTENDED:
194                 controller->IF1MSK = 1U << 31;
195                 break;
196         }
197
198         /**
199          * 31 Message object is valid
200          * 30 Set whether to use extented identifier
201          * 29 Set direction as transmit
202          */
203         controller->IF1ARB = (1U << 31)
204                                                  | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
205                                                  | (1 << 29);
206
207         /**
208          *  7 End of buffer
209          * 4-1 Data length code
210          */
211         controller->IF1MCTL = (1 << 7)
212                                                   | 8;
213
214         /**
215          * Note that IF1CMD does not refer to whole CMD register
216          * (it refers to bits 23-16 of that register)
217          *  7 Transfer from IF to message object
218          *  5 Transfer arbitration bits
219          *  4 Transfer control bits
220          */
221         controller->IF1CMD = (1U << 7)
222                                                  | (1 << 5)
223                                                  | (1 << 4);
224
225         // Write MSG object number and enable transfer
226         controller->IF1NO = cfg.msg_obj;
227
228         return SUCCESS;
229 }
230
231 static int8_t init_rx_box(struct rpp_can_rx_config cfg)
232 {
233         canBASE_t *controller;
234
235         if (!(controller = map_controller(cfg.controller)))
236                 return FAILURE;
237
238         // Wait until IF2 is ready to use
239         while (controller->IF2STAT & (1U << 7)) ;
240
241         /**
242          * 31 Set whether use of std/ext ID should have effect on acceptance filtering
243          * 28-1 Set mask
244          */
245         switch (cfg.type) {
246         case RPP_CAN_STANDARD:
247                 controller->IF2MSK = (1U << 31) | (cfg.mask << 18);
248                 break;
249         case RPP_CAN_MIXED:
250                 controller->IF2MSK = (0U << 31) | cfg.mask;
251                 break;
252         case RPP_CAN_EXTENDED:
253                 controller->IF2MSK = (1U << 31) | cfg.mask;
254                 break;
255         }
256
257         /**
258          * 31 Message object is valid
259          * 30 Set whether extended ID should be used
260          * 29 Direction is read
261          * 28-18 / 28-1 Object ID
262          */
263         controller->IF2ARB = (1U << 31) // MsgVal
264                                                  | ((cfg.type == RPP_CAN_STANDARD ? 0 : 1) << 30)
265                                                  | (0 << 29)    // Dir
266                                                  | cfg.id << (cfg.type == RPP_CAN_STANDARD ? 18 : 0);
267         /**
268          * 12 Use mask for filtering
269          *  7 End of buffer
270          * 4-1 Data length code
271          */
272         controller->IF2MCTL = (1 << 12)
273                                                   | (1 << 7)
274                                                   | 8;
275
276         /**
277          * Note that IF2CMD does not refer to whole CMD register
278          * (it refers to bits 23-16 of that register)
279          *  7 Transfer from IF to message object
280          *  6 Transfer mask bits
281          *  5 Transfer arbitration bits
282          *  4 Transfer control bits
283          */
284         controller->IF2CMD = (1 << 7)
285                                                  | (1 << 6)
286                                                  | (1 << 5)
287                                                  | (1 << 4);
288
289         // Write MSG object number and enable transfer
290         controller->IF2NO = cfg.msg_obj;
291
292         return SUCCESS;
293 }
294
295
296
297 static int8_t can_reset(canBASE_t *controller)
298 {
299         /**
300          * 6 Request write access to config registers
301          * 0 Enter initialization mode
302          */
303         controller->CTL = 0
304                                           | (1 << 6)
305                                           | (1 << 0);
306
307         controller->ES;
308         controller->ABOTR = 0;
309
310         controller->TIOC = (0 << 0);
311         controller->RIOC = (0 << 0);
312
313         return SUCCESS;
314 }
315
316 static int8_t can_set_timing(canBASE_t *controller, const struct rpp_can_timing_cfg cfg)
317 {
318         controller->BTR = (((cfg.brp-1) >> 6) << 16)
319                                           | ((cfg.phase_seg2-1) << 12)
320                                           | (((cfg.phase_seg1+cfg.prop_seg)-1) << 8)
321                                           | ((cfg.sjw-1) << 6)
322                                           | ((cfg.brp-1) & 63);
323         return SUCCESS;
324 }
325
326 /* This code has been taken from can-calc-bit-timing.c */
327 /* can-calc-bit-timing.c: Calculate CAN bit timing parameters
328  *
329  * Derived from:
330  *   can_baud.c - CAN baudrate calculation
331  *   Code based on LinCAN sources and H8S2638 project
332  *   Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
333  *   Copyright 2005      Stanislav Marek
334  *   email:pisa@cmp.felk.cvut.cz
335  *
336  *   With permission from Pavel Pisa to distribute the code and
337  *   software under other license than GPL.
338  */
339 static int can_update_spt(int phase_seg2_min, int phase_seg2_max, int prop_seg_max, int phase_seg1_max,
340                                                   int sampl_pt, int tseg, int *tseg1, int *tseg2)
341 {
342         *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
343         if (*tseg2 < phase_seg2_min)
344                 *tseg2 = phase_seg2_min;
345         if (*tseg2 > phase_seg2_max)
346                 *tseg2 = phase_seg2_max;
347         *tseg1 = tseg - *tseg2;
348         if (*tseg1 > prop_seg_max + phase_seg1_max) {
349                 *tseg1 = prop_seg_max + phase_seg1_max;
350                 *tseg2 = tseg - *tseg1;
351         }
352         return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
353 }
354
355 /* This code has been taken from can-calc-bit-timing.c */
356 /* can-calc-bit-timing.c: Calculate CAN bit timing parameters
357  *
358  * Derived from:
359  *   can_baud.c - CAN baudrate calculation
360  *   Code based on LinCAN sources and H8S2638 project
361  *   Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
362  *   Copyright 2005      Stanislav Marek
363  *   email:pisa@cmp.felk.cvut.cz
364  *
365  *   With permission from Pavel Pisa to distribute the code and
366  *   software under other license than GPL.
367  */
368 static int8_t can_calculate_timing(const struct rpp_can_ctrl_config cfg, struct rpp_can_calculated_timing *timing)
369 {
370         static const int prop_seg_min = 1;
371         static const int prop_seg_max = 8;
372         static const int phase_seg1_min = 1;
373         static const int phase_seg1_max = 8;
374         static const int phase_seg2_min = 1;
375         static const int phase_seg2_max = 8;
376         static const int brp_min = 1;
377         static const int brp_max = 64;
378         static const int brp_inc = 1;
379
380         if (timing == NULL)
381                 return FAILURE;
382
383         int sampl_pt;
384         long best_error = 1000000000, error;
385         int best_tseg = 0, best_brp = 0, brp = 0;
386         int spt_error = 1000, spt = 0;
387         long rate = 0;
388         int tseg = 0, tseg1 = 0, tseg2 = 0;
389         uint64_t v64;
390
391         /* Use CIA recommended sample points */
392         if (cfg.baudrate > 800000)
393                 sampl_pt = 750;
394         else if (cfg.baudrate > 500000)
395                 sampl_pt = 800;
396         else
397                 sampl_pt = 875;
398
399         /* tseg even = round down, odd = round up */
400         for (tseg = (prop_seg_max + phase_seg1_max + phase_seg2_max) * 2 + 1;
401                  tseg >= (prop_seg_min + phase_seg1_min + phase_seg2_min) * 2;
402                  tseg--) {
403                 /* Compute all posibilities of tseg choices (tseg=tseg1+tseg2) */
404                 brp = cfg.clk / ((1 + tseg / 2) * cfg.baudrate) + tseg % 2;
405                 /* chose brp step which is possible in system */
406                 brp = (brp / brp_inc) * brp_inc;
407                 if ((brp < brp_min) || (brp > brp_max))
408                         continue;
409                 rate = cfg.clk / (brp * (1 + tseg / 2));
410                 error = cfg.baudrate - rate;
411                 /* tseg brp biterror */
412
413                 if (error < 0)
414                         error = -error;
415                 if (error > best_error)
416                         continue;
417                 best_error = error;
418                 if (error == 0) {
419                         spt = can_update_spt(phase_seg2_min, phase_seg2_max, prop_seg_max, phase_seg1_max, sampl_pt, tseg / 2, &tseg1, &tseg2);
420                         error = sampl_pt - spt;
421                         if (error < 0)
422                                 error = -error;
423                         if (error > spt_error)
424                                 continue;
425                         spt_error = error;
426                 }
427                 best_tseg = tseg / 2;
428                 best_brp = brp;
429                 if (error == 0)
430                         break;
431         }
432
433         if (best_error && (cfg.baudrate / best_error < 10))
434                 return -1;
435
436         tseg2 = best_tseg + 1 - (sampl_pt * (best_tseg + 1)) / 1000;
437         spt = can_update_spt(phase_seg2_min, phase_seg2_max, prop_seg_max, phase_seg1_max, sampl_pt, best_tseg, &tseg1, &tseg2);
438
439         if (tseg2 > tseg1)
440                 /* sample point < 50% */
441                 timing->timing_base_cfg.phase_seg1 = tseg1 / 2;
442         else
443                 /* keep phase_seg{1,2} equal around the sample point */
444                 timing->timing_base_cfg.phase_seg1 = tseg2;
445         timing->timing_base_cfg.prop_seg = tseg1 - timing->timing_base_cfg.phase_seg1;
446         /* Check prop_seg range if necessary */
447         if (prop_seg_min || prop_seg_max) {
448                 if (timing->timing_base_cfg.prop_seg < prop_seg_min)
449                         timing->timing_base_cfg.prop_seg = prop_seg_min;
450                 else if (timing->timing_base_cfg.prop_seg > prop_seg_max)
451                         timing->timing_base_cfg.prop_seg = prop_seg_max;
452                 timing->timing_base_cfg.phase_seg1 = tseg1 - timing->timing_base_cfg.prop_seg;
453         }
454         timing->timing_base_cfg.phase_seg2 = tseg2;
455         timing->timing_base_cfg.sjw = 1;
456         timing->timing_base_cfg.brp = best_brp;
457         timing->timing_info.error = best_error;
458         timing->timing_info.sampl_pt = spt;
459         v64 = (uint64_t)timing->timing_base_cfg.brp * 1000000000UL;
460         v64 /= cfg.clk;
461         timing->timing_info.tq = (int)v64;
462
463         return SUCCESS;
464 }
465
466 static int8_t can_configure(canBASE_t *controller, const struct rpp_can_ctrl_config cfg)
467 {
468         if (cfg.timing_calc_method == RPP_CAN_TIMING_CALC_AUTO) {
469                 struct rpp_can_calculated_timing timing_cfg;
470                 if (can_calculate_timing(cfg, &timing_cfg) == SUCCESS)
471                         return can_set_timing(controller, timing_cfg.timing_base_cfg);
472                 else
473                         return FAILURE;
474         }
475         else if (cfg.timing_calc_method == RPP_CAN_TIMING_CALC_MANUAL && cfg.timing_config != NULL)
476                 return can_set_timing(controller, *cfg.timing_config);
477         else
478                 return FAILURE;
479 }
480
481 static inline void can_leave_init(canBASE_t *controller)
482 {
483         controller->CTL &= ~( (1 << 6) | (1 << 0) );
484
485 }
486
487 static int8_t reset_box(canBASE_t *controller, uint32_t msg_obj)
488 {
489         // Wait until IF1 is ready
490         while (controller->IF1STAT & (1U << 7)) ;
491
492         controller->IF1MSK = 0;
493         controller->IF1ARB = 0;
494         controller->IF1MCTL = (1 << 7) | 8;
495         controller->IF1CMD = (1 << 7)
496                                                  | (1 << 6)
497                                                  | (1 << 5)
498                                                  | (1 << 4);
499         controller->IF1NO = msg_obj;
500
501         return SUCCESS;
502 }
503
504 static int8_t reset_boxes(void)
505 {
506         uint32_t i;
507
508         for (i = 1; i <= 64; i++) {
509                 reset_box(canREG1, i);
510         }
511
512         for (i = 1; i <= 64; i++) {
513                 reset_box(canREG2, i);
514         }
515
516         for (i = 1; i <= 32; i++) {
517                 reset_box(canREG3, i);
518         }
519
520         return SUCCESS;
521 }
522
523 int8_t can_setup_IF(canBASE_t *controller)
524 {
525         // Wait until IF1 is ready
526         while (controller->IF1STAT & (1U << 7)) ;
527
528         /**
529          * 7 Transfer from IF to message object
530          * 5 Transfer arbitration bits
531          * 4 Transfer control bits
532          * 2 Set TxRqst bit
533          * 1 Access data bytes 7-4
534          * 0 Access data bytes 3-0
535          */
536         controller->IF1CMD = (1 << 7)
537                                                  | (1 << 5)
538                                                  | (1 << 4)
539                                                  | (1 << 2)
540                                                  | (1 << 1)
541                                                  | (1 << 0);
542
543         // Wait until IF2 is ready
544         while (controller->IF2STAT & (1U << 7)) ;
545
546         /**
547          * 7 Transfer from message object to IF
548          * 5 Transfer arbitration bits
549          * 4 Transfer control bits
550          * 2 Clear NewDat bit
551          * 1 Access data bytes 7-4
552          * 0 Access data bytes 3-0
553          */
554         controller->IF2CMD = (0 << 7)
555                                                  | (1 << 5)
556                                                  | (1 << 4)
557                                                  | (1 << 2)
558                                                  | (1 << 1)
559                                                  | (1 << 0);
560
561         return SUCCESS;
562 }
563
564 int8_t rpp_can_init(const struct rpp_can_config *config)
565 {
566         uint16_t i;
567
568         if (!RPP_MUTEX_INIT(mutex_can))
569                 return FAILURE;
570
571 #ifdef TARGET_TMS570_RPP
572         dmmInit();
573
574         /*
575          * Reset the bus drivers to NORMAL MODE. CAN bus drivers control
576          * voltage regulators for big part of the board and NORMAL MODE
577          * prevents the board from going to sleep mode. Refer TJA1041A
578          * reference for more details about the states of the driver.
579          */
580         dmmREG->PC4 = 1<<13; // set CAN_NSTB
581         dmmREG->PC5 = 1<<15; // clr CAN_EN
582         dmmREG->PC5 = 1<<13; // clr CAN_NSTB
583         dmmREG->PC4 = 1<<13; // set CAN_NSTB
584         dmmREG->PC4 = 1<<15; // set CAN_EN
585 #endif
586
587         can_config = config;
588
589         if (can_reset(canREG1) == FAILURE)
590                 return FAILURE;
591         if (can_reset(canREG2) == FAILURE)
592                 return FAILURE;
593         if (can_reset(canREG3) == FAILURE)
594                 return FAILURE;
595
596         if (reset_boxes() == FAILURE)
597                 return FAILURE;
598
599         for (i = 0; i < config->num_tx_obj; i++) {
600                 if (init_tx_box(config->tx_config[i]) == FAILURE)
601                         return FAILURE;
602         }
603
604         for (i = 0; i < config->num_rx_obj; i++) {
605                 if (init_rx_box(config->rx_config[i]) == FAILURE)
606                         return FAILURE;
607         }
608
609         if (can_setup_IF(canREG1) == FAILURE)
610                 return FAILURE;
611         if (can_setup_IF(canREG2) == FAILURE)
612                 return FAILURE;
613         if (can_setup_IF(canREG3) == FAILURE)
614                 return FAILURE;
615
616         if (can_configure(canREG1, config->ctrl[0]) == FAILURE)
617                 return FAILURE;
618         if (can_configure(canREG2, config->ctrl[1]) == FAILURE)
619                 return FAILURE;
620         if (can_configure(canREG3, config->ctrl[2]) == FAILURE)
621                 return FAILURE;
622
623         can_leave_init(canREG1);
624         can_leave_init(canREG2);
625         can_leave_init(canREG3);
626
627         return SUCCESS;
628 }
629
630 int8_t rpp_can_write(rpp_can_hw_obj hw_obj, const struct rpp_can_pdu *pdu)
631 {
632         uint8_t i;
633         canBASE_t *controller;
634         struct rpp_can_tx_config *tx_cfg = &can_config->tx_config[hw_obj];
635
636         if (!(controller = map_controller(tx_cfg->controller)))
637                 return -RPP_EINVAL;
638
639         RPP_MUTEX_LOCK(mutex_can);
640
641         // Wait until IF1 is ready to use
642         while (controller->IF1STAT & (1U << 7)) ;
643
644         // Reset data length code
645         controller->IF1MCTL &= ~15;
646         controller->IF1MCTL |= pdu->dlc & 0xF;
647
648         /**
649          * 31 Message is valid
650          * 30 Whether std/ext ID should be used
651          * 29 Direction is transmit
652          * 28-18 / 28-0 Message ID
653          */
654         controller->IF1ARB = (1 << 31)
655                                                  | ((tx_cfg->type == RPP_CAN_STANDARD ? 0 : 1) << 30)
656                                                  | (1 << 29)
657                                                  | (pdu->id << (tx_cfg->type == RPP_CAN_STANDARD ? 18 : 0));
658
659         for (i = 0; i < pdu->dlc; i++) {
660 #ifdef __little_endian__
661                 controller->IF1DATx[i] = pdu->data[i];
662 #else
663                 controller->IF1DATx[s_can_byte_order[i]] = pdu->data[i];
664 #endif
665         }
666
667         // Copy TX data into message box
668         controller->IF1NO = tx_cfg->msg_obj;
669
670         RPP_MUTEX_UNLOCK(mutex_can);
671
672         return SUCCESS;
673 }
674
675
676 int8_t rpp_can_check_tx_pend(rpp_can_hw_obj hw_obj, bool *tx_pend)
677 {
678         uint32_t reg_index, bit_mask;
679         canBASE_t *controller;
680
681         if (!(controller = map_controller(can_config->tx_config[hw_obj].controller)))
682                 return FAILURE;
683
684         reg_index = can_config->tx_config[hw_obj].msg_obj >> 5;
685         bit_mask = 1 << ((can_config->tx_config[hw_obj].msg_obj - 1) & 0x1FU);
686
687         *tx_pend = controller->TXRQx[reg_index] & bit_mask;
688
689         return SUCCESS;
690 }
691
692 int8_t rpp_can_read(rpp_can_hw_obj hw_obj, struct rpp_can_pdu *pdu)
693 {
694         uint32_t reg_index, bit_mask;
695         uint32_t i;
696         canBASE_t *controller;
697
698         if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
699                 return -RPP_EINVAL;
700
701         reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
702         bit_mask = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
703
704         RPP_MUTEX_LOCK(mutex_can);
705
706         // FIXME: Check whether to abort if there are no new data
707         if (!(controller->NWDATx[reg_index] & bit_mask)) {
708                 RPP_MUTEX_UNLOCK(mutex_can);
709                 return -RPP_ENODATA;
710         }
711
712         // Wait until IF2 is ready to use
713         while (controller->IF2STAT & (1U << 7)) ;
714
715         // Copy data into IF2
716         controller->IF2NO = can_config->rx_config[hw_obj].msg_obj;
717
718         // Wait until IF2 is ready to use
719         while (controller->IF2STAT & (1U << 7)) ;
720
721         // Get length of data received
722         pdu->dlc = controller->IF2MCTL & 0xFU;
723
724         // Get message ID
725         if (controller->IF2ARB & (1 << 30))
726                 pdu->id = (controller->IF2ARB & 0x1FFFFFFF) | CAN_EFF_FLAG;
727         else
728                 pdu->id = (controller->IF2ARB & (0x7FF << 18)) >> 18;
729
730         // Copy RX data into pdu
731         for (i = 0; i < pdu->dlc; i++) {
732 #ifdef __little_endian__
733                 pdu->data[i] = controller->IF2DATx[i];
734 #else
735                 pdu->data[i] = controller->IF2DATx[s_can_byte_order[i]];
736 #endif
737         }
738
739         RPP_MUTEX_UNLOCK(mutex_can);
740
741         return SUCCESS;
742 }
743
744 int8_t rpp_can_check_rx_ind(rpp_can_hw_obj hw_obj, bool *rx_ind)
745 {
746         uint32_t reg_index, bit_mask;
747         canBASE_t *controller;
748
749         if (!(controller = map_controller(can_config->rx_config[hw_obj].controller)))
750                 return FAILURE;
751
752         reg_index = (can_config->rx_config[hw_obj].msg_obj - 1) >> 5;
753         bit_mask = 1 << ((can_config->rx_config[hw_obj].msg_obj - 1) & 0x1FU);
754
755         *rx_ind = controller->NWDATx[reg_index] & bit_mask;
756
757         return SUCCESS;
758 }