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