X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/831ccb1f14f7472962fc2d185f32e18105209bd7..50e9e47fc21191ea9ea758fea1e7f2bd5a275e98:/lincan/src/hcan2.c diff --git a/lincan/src/hcan2.c b/lincan/src/hcan2.c index e960685..279a4e9 100644 --- a/lincan/src/hcan2.c +++ b/lincan/src/hcan2.c @@ -1,7 +1,37 @@ -/* 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 */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Copyright (C) 2007-2008 Martin Petera */ +/* Funded by OCERA and FRESCOR IST projects */ +/* Based on CAN driver code by Arnaud Westenberg */ +/* */ +/* 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" @@ -46,7 +76,7 @@ uint16_t IRQs = ~(HCAN2_IRR_DFRI + HCAN2_IRR_MBEI + HCAN2_IRR_BOI + HCAN2_IRR_EP int hcan2_chip_config(struct canchip_t *chip) { DEBUGMSG("Configuring chip...\n"); - + if (hcan2_enable_configuration(chip)) return -ENODEV; @@ -206,7 +236,7 @@ int hcan2_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, int sa bcr1 = (((tseg1 - 1) & 0x000f) << 12) + (((tseg2 - 1) & 0x0007) << 8) + ((sjw & 0x0003) << 4); bcr0 = (best_brp - 1) & 0x00ff; - hcan2_set_btregs(chip, bcr0, bcr1); + hcan2_set_btregs(chip, bcr0, bcr1); hcan2_disable_configuration(chip); @@ -224,7 +254,7 @@ int hcan2_set_btregs(struct canchip_t *chip, unsigned short bcr0, unsigned short can_write_reg_w(chip, bcr1, HCAN2_BCR1); can_write_reg_w(chip, bcr0, HCAN2_BCR0); - + /* DEBUGMSG("BCR0 and BCR1 successfully set.\n"); */ return 0; } @@ -259,8 +289,8 @@ int hcan2_stop_chip(struct canchip_t *chip) int hcan2_attach_to_chip(struct canchip_t *chip) { /* DEBUGMSG("Attaching to chip %d.\n", chip->chip_idx); */ - - /* initialize chip */ + + /* initialize chip */ if (hcan2_enable_configuration(chip)) return -ENODEV; @@ -288,9 +318,9 @@ int hcan2_release_chip(struct canchip_t *chip) { hcan2_stop_chip(chip); can_disable_irq(chip->chip_irq); - + hcan2_clear_objects(chip); - + DEBUGMSG("Chip released [%02d]\n", chip->chip_idx); return 0; } @@ -302,10 +332,10 @@ int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned sh struct msgobj_t * obj; int obj_idx = (int) (chip->chip_data); - if (code & 0x1ffff800) + if (code & 0x1ffff800) return hcan2_extended_mask(chip, code, mask); - + if (obj_idx > 0 && obj_idx <= 32) obj = chip->msgobj[obj_idx - 1]; else @@ -317,7 +347,7 @@ int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned sh 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); @@ -334,7 +364,7 @@ int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned lon struct msgobj_t * obj; int obj_idx = (int) (chip->chip_data); - + if (obj_idx > 0 && obj_idx <= 32) obj = chip->msgobj[obj_idx - 1]; else @@ -350,14 +380,14 @@ int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned lon lafm0 = ((mask & 0x1ffc0000) >> 14); lafm0 |=((mask & 0x00030000) >> 16); lafm1 = (mask & 0x0000ffff); - + can_write_reg_w(chip, ctrl0, (int) obj->obj_base_addr + HCAN2_MB_CTRL0); can_write_reg_w(chip, ctrl1, (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, lafm1, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2); - + DEBUGMSG("MB%02d: Set extended_mask [id:0x%08x, m:0x%08x]\n", obj_idx, (uint32_t)code, (uint32_t)mask); - + return 0; } @@ -370,7 +400,7 @@ int hcan2_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj) /* clears mailbox and setup LFA to accept all Exted Messages */ hcan2_setup_mbox4read(obj); - + hcan2_disable_configuration(chip); return 0; @@ -380,15 +410,15 @@ int hcan2_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct { DEBUGMSG("Pre write config\n"); - /* change Mailbox header only if neccessary */ + /* change Mailbox header only if neccessary */ /* otherwise change only data */ if (hcan2_compare_msg(obj, msg)) { if (hcan2_enable_configuration(chip)) return -ENODEV; - + hcan2_setup_mbox4write(obj, msg); - + if (hcan2_disable_configuration(chip)) return -ENODEV; } @@ -401,10 +431,10 @@ int hcan2_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct int hcan2_send_msg(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg) { unsigned obj_bit; - int b_addr = ((obj->object - 1) / 16) * (-2); + int b_addr = ((obj->object - 1) / 16) * (-2); obj_bit = (1 << ((obj->object - 1) % 16)); - + /* CANMSG("Sending message [obj: %d]\n", obj->object - 1); */ can_write_reg_w(chip, obj_bit, b_addr + HCAN2_TXPR0); @@ -503,7 +533,7 @@ int hcan2_irq_handler(int irq, struct canchip_t *chip) CANMSG("Warning: entering ERROR PASSIVE state\nTEC: %d REC: %d\n", (uint16_t)((tecrec >> 8) & 0x00ff), (uint16_t)(tecrec & 0x00ff)); - + /* Show warning only */ /* reset flag - by writing '1' */ @@ -511,17 +541,17 @@ int hcan2_irq_handler(int irq, struct canchip_t *chip) } /* Message Overrun/Overwritten */ - if (irq_reg & HCAN2_IRR_MOOI) { + if (irq_reg & HCAN2_IRR_MOOI) { /* put get Unread Message Status Register */ rxdf = (can_read_reg_w(chip, HCAN2_UMSR1) << 16) + can_read_reg_w(chip, HCAN2_UMSR0); /* find the message object */ for (idx = 0; (idx < chip->max_objects) && !(rxdf & (1<max_objects) + if (idx < chip->max_objects) hcan2_notifyRXends(chip->msgobj[idx], CANQUEUE_NOTIFY_ERROR); /* reset flag */ @@ -543,12 +573,12 @@ int hcan2_irq_handler(int irq, struct canchip_t *chip) can_write_reg_w(chip, 0xffff, HCAN2_ABACK0); can_write_reg_w(chip, 0xffff, HCAN2_ABACK1); return CANCHIP_IRQ_HANDLED; - } + } - /* Clear TXACK flag */ + /* Clear TXACK flag */ can_write_reg_w(chip, 1 << (idx % 16), HCAN2_TXACK0 - 2 * (idx / 16)); - /* sends message */ + /* sends message */ hcan2_wakeup_tx(chip, chip->msgobj[idx]); } @@ -569,11 +599,11 @@ int hcan2_config_irqs(struct canchip_t *chip, short irqs) hcan2_clear_irq_flags(chip); can_write_reg_w(chip, irqs, HCAN2_IMR); - + /* allow all mailboxes to generate IRQ */ can_write_reg_w(chip, 0, HCAN2_MBIMR0); can_write_reg_w(chip, 0, HCAN2_MBIMR1); - + /* CANMSG("IRQ Mask set [0x%02x]\n", irqs); */ return 0; } @@ -603,7 +633,7 @@ int hcan2_check_tx_stat(struct canchip_t *chip) int hcan2_check_MB_tx_stat(struct canchip_t *chip, struct msgobj_t *obj) { /* Transmition is complete return 0 - no error */ - + /* MB1-MB15 are in CANTXPR0 and MB16-MB31 are in CANTXPR1 CANTXPR0 = CANTXPR1 + 0x0002 MB0 - receive only */ @@ -618,9 +648,9 @@ int hcan2_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) if (obj->object == 1) /* msgbox 0 cant transmit only receive ! */ return -ENODEV; - + can_preempt_disable(); - + can_msgobj_set_fl(obj,TX_REQUEST); if(!can_msgobj_test_and_set_fl(obj,TX_LOCK) && !hcan2_check_MB_tx_stat(chip, obj)) @@ -628,7 +658,7 @@ int hcan2_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) can_msgobj_clear_fl(obj,TX_REQUEST); hcan2_irq_write_handler(chip, obj); - + can_msgobj_clear_fl(obj,TX_LOCK); } else @@ -657,7 +687,9 @@ int hcan2_filtch_rq(struct canchip_t *chip, struct msgobj_t * obj) /* HCAN2 uses oposite logic for LAFM: 1-ignore bit, 0-use bit as mask */ +#if myDEBUG DEBUGMSG("CNT: %d ID: 0x%08x MASK: 0x%08x\n", num, (uint32_t) (filter.id) & 0x1fffffff, (uint32_t) (~filter.mask) & 0x1fffffff); +#endif if (filter.flags & MSG_EXT) /* Extended ID */ return hcan2_extended_mask(chip, filter.id, ~filter.mask); @@ -672,7 +704,7 @@ void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) unsigned ctrl0, ctrl2, data; unsigned long flag_addr; uint16_t mb_offset; - + mb_offset = (int ) obj->obj_base_addr; @@ -684,7 +716,7 @@ void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) obj->rx_msg.length = len = ctrl2 & HCAN2_MBCT2_DLC; obj->rx_msg.flags = (ctrl0 & HCAN2_MBCT0_RTR) ? MSG_RTR : 0; obj->rx_msg.cob = obj->object - 1; - + /* get ID of received message */ if (ctrl0 & HCAN2_MBCT0_IDE) { @@ -711,7 +743,7 @@ void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) * HCAN2_RXPR1, HCAN2_RXPR0, HCAN2_RFPR1, HCAN2_RFPR0 */ 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); @@ -800,7 +832,7 @@ int hcan2_fill_chipspecops(struct canchip_t *chip) chip->max_objects = 32; chip->write_register = chip->hostdevice->hwspecops->write_register; chip->read_register = chip->hostdevice->hwspecops->read_register; - + /* chip->flags; chip->baudrate; @@ -832,7 +864,7 @@ int hcan2_reset_chip(struct canchip_t *chip) * 11 recessive bits to join CAN bus activity */ - int i; + int i; unsigned gsr_reset; DEBUGMSG("Resetting HCAN2 chip %d...\n", chip->chip_idx); @@ -840,7 +872,7 @@ int hcan2_reset_chip(struct canchip_t *chip) /* send Reset Request */ can_write_reg_w(chip, HCAN2_MCR_RESET, HCAN2_MCR ); - /* Check hardware reset status */ + /* Check hardware reset status */ i = 0; gsr_reset = can_read_reg_w(chip, HCAN2_GSR) & HCAN2_GSR_RESET; while (!(gsr_reset) && ((i++) <= MAX_SETTING_WAIT_LOOPS)) @@ -947,14 +979,14 @@ void hcan2_clear_mbox(struct canchip_t *chip, int msgobj_idx) void hcan2_setup_mbox4write(struct msgobj_t * obj, struct canmsg_t * msg) { int mb_offset; - uint16_t ctrl0, ctrl1, ctrl2; + uint16_t ctrl0, ctrl1, ctrl2; struct canchip_t * chip = obj->hostchip; DEBUGMSG("Change Header\n"); mb_offset = (int) obj->obj_base_addr; - + hcan2_setup_ctrl_regs(msg, &ctrl0, &ctrl1, &ctrl2); can_write_reg_w(chip, ctrl0, mb_offset + HCAN2_MB_CTRL0); @@ -968,17 +1000,17 @@ void hcan2_setup_mbox4write(struct msgobj_t * obj, struct canmsg_t * msg) void hcan2_setup_mbox4write_data(struct msgobj_t * obj, struct canmsg_t * msg) { int len,i, mb_offset; - uint16_t data; - + uint16_t data; + struct canchip_t * chip = obj->hostchip; DEBUGMSG("Change Data\n"); mb_offset = (int) obj->obj_base_addr; - + len = msg->length; if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH; - + for (i = 0; i < len; i+=2) { data = (msg->data[i] << 8) + (i+1 < len ? msg->data[i+1] : 0); @@ -989,7 +1021,7 @@ void hcan2_setup_mbox4write_data(struct msgobj_t * obj, struct canmsg_t * msg) void hcan2_setup_mbox4read(struct msgobj_t * obj) { struct canchip_t * chip = obj->hostchip; - + hcan2_clear_mbox(chip, obj->object - 1); // in structure chip->chip_data is Mailbox number @@ -1034,7 +1066,7 @@ int hcan2_compare_msg(struct msgobj_t * obj, struct canmsg_t * msg) uint16_t ctrl0, ctrl1, ctrl2; uint16_t mb_offset; uint16_t c0,c1,c2; - + struct canchip_t * chip = obj->hostchip; mb_offset = (int) obj->obj_base_addr; @@ -1048,7 +1080,7 @@ int hcan2_compare_msg(struct msgobj_t * obj, struct canmsg_t * msg) /* if using EXT ID conpare also ctrl1 */ if (msg->flags & MSG_EXT && ctrl1 ^ c1) return 1; - + DEBUGMSG("C0 0x%04x HW: 0x%04x\n", ctrl0, c0); DEBUGMSG("C1 0x%04x HW: 0x%04x\n", ctrl1, c1);