-/* hcan2.c
- * Linux CAN-bus device driver.
- * This software is released under the GPL-License.
- */
+/**************************************************************************/
+/* File: hcan2.c - Renesas SH7760 HCAN2 controller support */
+/* */
+/* LinCAN - (Not only) Linux CAN bus driver */
+/* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
+/* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
+/* Copyright (C) 2007-2008 Martin Petera <peterm4@fel.cvut.cz> */
+/* Funded by OCERA and FRESCOR IST projects */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
+/* */
+/* LinCAN is free software; you can redistribute it and/or modify it */
+/* under terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2, or (at your option) any */
+/* later version. LinCAN is distributed in the hope that it will be */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* General Public License for more details. You should have received a */
+/* copy of the GNU General Public License along with LinCAN; see file */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
+/* Cambridge, MA 02139, USA. */
+/* */
+/* To allow use of LinCAN in the compact embedded systems firmware */
+/* and RT-executives (RTEMS for example), main authors agree with next */
+/* special exception: */
+/* */
+/* Including LinCAN header files in a file, instantiating LinCAN generics */
+/* or templates, or linking other files with LinCAN objects to produce */
+/* an application image/executable, does not by itself cause the */
+/* resulting application image/executable to be covered by */
+/* the GNU General Public License. */
+/* This exception does not however invalidate any other reasons */
+/* why the executable file might be covered by the GNU Public License. */
+/* Publication of enhanced or derived LinCAN files is required although. */
+/**************************************************************************/
#include "../include/can.h"
#include "../include/can_sysdep.h"
else
return -ENODEV;
- chip->chip_data = (void*)0; /* reset mbox number */
+ chip->chip_data = (void*)0; /* reset mbox number */
ctrl0 = ((code & 0x07ff) << 4);
lafm0 = ((mask & 0x07ff) << 4);
+ lafm0 |= 0x0003; /* ignore Ext ID 17:16 */
can_write_reg_w(chip, ctrl0, (int) obj->obj_base_addr + HCAN2_MB_CTRL0);
can_write_reg_w(chip, 0x0000, (int) obj->obj_base_addr + HCAN2_MB_CTRL1);
can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK);
can_write_reg_w(chip, 0xffff, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2);
- DEBUGMSG("Set standard_mask [id:0x%04x, m:0x%04x]\n", code, mask);
+ DEBUGMSG("MB%02d: Set standard_mask [id:0x%04x, m:0x%04x]\n", obj_idx, code, lafm0);
return 0;
}
can_write_reg_w(chip, lafm0, (int) obj->obj_base_addr + HCAN2_MB_MASK);
can_write_reg_w(chip, lafm1, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2);
- DEBUGMSG("Set extended_mask [id:0x%08x, m:0x%08x]\n", (uint32_t)code, (uint32_t)mask);
+ DEBUGMSG("MB%02d: Set extended_mask [id:0x%08x, m:0x%08x]\n", obj_idx, (uint32_t)code, (uint32_t)mask);
return 0;
}
/* Received message */
if (irq_reg & HCAN2_IRR_DFRI)
{
- rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
- can_read_reg_w(chip, HCAN2_RXPR0);
+ rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+ can_read_reg_w(chip, HCAN2_RXPR0);
- DEBUGMSG("Received message [0x%08x]\n", rxdf);
+ while(rxdf) {
+ DEBUGMSG("Received message [0x%08x]\n", rxdf);
- while (rxdf) {
/* find the message object */
- for (idx = 0; (idx < chip->max_objects) && !(rxdf & (1<<idx)); idx++) { }
-
- /* realy i got one? */
- if (idx < chip->max_objects) {
- hcan2_irq_read_handler(chip, chip->msgobj[idx]);
-
- /* clear RXPR flag for this msgobj */
- can_write_reg_w(chip, (1 << (idx % 16)), HCAN2_RXPR0 - 2*(idx / 16));
-
- rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+ for (idx = 0; (idx < chip->max_objects) && rxdf; idx++)
+ if ((rxdf & (1<<idx))) {
+ hcan2_irq_read_handler(chip, chip->msgobj[idx]);
+ /* RXPR flag for this msgobj is cleared during irq_read_handler*/
+ rxdf &= ~(1 << idx);
+ }
+
+
+ DEBUGMSG("Before reset flags [0x%08x]\n", rxdf);
+ rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
can_read_reg_w(chip, HCAN2_RXPR0);
- }
}
}
}
else
obj->rx_msg.id = (ctrl0 & HCAN2_MBCT0_STDID)>>4;
-
+
if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
for (i = 0; i < len; i++)
{
/* rcanqueue_ends_filt_conjuctionead 16bit data - two data bytes*/
data = can_read_reg_w(chip, (int) obj->obj_base_addr + HCAN2_MB_DATA1 + i);
- obj->rx_msg.data[i] = (data & 0xff00) >> 8;
- if (++i < len) obj->rx_msg.data[i] = data & 0x00ff;
+ obj->rx_msg.data[i] = (data & 0xff00) >> 8; // one data byte
+ if (++i < len) obj->rx_msg.data[i] = data & 0x00ff; // second data byte
}
/* Computes correct offset address of register from MSGBOX_IDX and RTR flag
* result is one of these:
* HCAN2_RXPR1, HCAN2_RXPR0, HCAN2_RFPR1, HCAN2_RFPR0
*/
- flag_addr = ((ctrl0 & HCAN2_MBCT0_RTR) << 3) + HCAN2_RXPR0 - ((obj->object - 1) / 16) * 2;
+ flag_addr = HCAN2_RXPR0 - (int)((obj->object - 1) / 16) * 2;
/* Reset flag by writing 1 to its position */
can_write_reg_w(chip, (1 << ((obj->object - 1) % 16)), flag_addr);