]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/sja1000.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / sja1000.c
index d5f7b1557864a2d5e027eb854d696c6a1b5eaed8..507d911c81d0f6a187ff14bcf7f540a3fc1438ff 100644 (file)
@@ -1,21 +1,46 @@
-/* sja1000.c
- * Linux CAN-bus device driver.
- * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
- * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
- * email:pisa@cmp.felk.cvut.cz
- * This software is released under the GPL-License.
- * Version lincan-0.3  17 Jun 2004
- */
+/**************************************************************************/
+/* File: sja1000.c - Philips/NXP SJA1000 chip legacy mode (deprecated)    */
+/*                                                                        */
+/* 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>             */
+/* 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"
 #include "../include/main.h"
 #include "../include/sja1000.h"
 
-void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj);
-void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj);
+void sja1000_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj);
+void sja1000_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj);
 
-int sja1000_enable_configuration(struct chip_t *chip)
+int sja1000_enable_configuration(struct canchip_t *chip)
 {
        int i=0;
        unsigned flags;
@@ -39,7 +64,7 @@ int sja1000_enable_configuration(struct chip_t *chip)
        return 0;
 }
 
-int sja1000_disable_configuration(struct chip_t *chip)
+int sja1000_disable_configuration(struct canchip_t *chip)
 {
        int i=0;
        unsigned flags;
@@ -62,49 +87,49 @@ int sja1000_disable_configuration(struct chip_t *chip)
        return 0;
 }
 
-int sja1000_chip_config(struct chip_t *chip)
+int sja1000_chip_config(struct canchip_t *chip)
 {
        if (sja1000_enable_configuration(chip))
                return -ENODEV;
 
        /* Set mode, clock out, comparator */
-       can_write_reg(chip,chip->sja_cdr_reg,SJACDR); 
+       can_write_reg(chip,chip->sja_cdr_reg,SJACDR);
        /* Set driver output configuration */
-       can_write_reg(chip,chip->sja_ocr_reg,SJAOCR); 
+       can_write_reg(chip,chip->sja_ocr_reg,SJAOCR);
 
        if (sja1000_standard_mask(chip,0x0000, 0xffff))
                return -ENODEV;
-       
+
        if (!chip->baudrate)
                chip->baudrate=1000000;
        if (sja1000_baud_rate(chip,chip->baudrate,chip->clock,0,75,0))
                return -ENODEV;
 
        /* Enable hardware interrupts */
-       can_write_reg(chip,(sjaCR_RIE|sjaCR_TIE|sjaCR_EIE|sjaCR_OIE),SJACR); 
+       can_write_reg(chip,(sjaCR_RIE|sjaCR_TIE|sjaCR_EIE|sjaCR_OIE),SJACR);
 
        sja1000_disable_configuration(chip);
-       
+
        return 0;
 }
 
-int sja1000_standard_mask(struct chip_t *chip, unsigned short code, unsigned short mask)
+int sja1000_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask)
 {
        unsigned char write_code, write_mask;
 
        if (sja1000_enable_configuration(chip))
                return -ENODEV;
 
-       /* The acceptance code bits (SJAACR bits 0-7) and the eight most 
+       /* The acceptance code bits (SJAACR bits 0-7) and the eight most
         * significant bits of the message identifier (id.10 to id.3) must be
-        * equal to those bit positions which are marked relevant by the 
+        * equal to those bit positions which are marked relevant by the
         * acceptance mask bits (SJAAMR bits 0-7).
         * (id.10 to id.3) = (SJAACR.7 to SJAACR.0) v (SJAAMR.7 to SJAAMR.0)
         * (Taken from Philips sja1000 Data Sheet)
         */
        write_code = (unsigned char) code >> 3;
        write_mask = (unsigned char) mask >> 3;
-       
+
        can_write_reg(chip,write_code,SJAACR);
        can_write_reg(chip,write_mask,SJAAMR);
 
@@ -123,13 +148,13 @@ int sja1000_standard_mask(struct chip_t *chip, unsigned short code, unsigned sho
  * param sampl_pt sample point in % (0-100) sets (TSEG1+2)/(TSEG1+TSEG2+3) ratio
  * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP
  */
-int sja1000_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
+int sja1000_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
                                                        int sampl_pt, int flags)
 {
        int best_error = 1000000000, error;
        int best_tseg=0, best_brp=0, best_rate=0, brp=0;
        int tseg=0, tseg1=0, tseg2=0;
-       
+
        if (sja1000_enable_configuration(chip))
                return -ENODEV;
 
@@ -186,12 +211,12 @@ int sja1000_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
        return 0;
 }
 
-int sja1000_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
+int sja1000_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
 {
        int i;
-       
+
        i=can_read_reg(chip,SJASR);
-       
+
        if (!(i&sjaSR_RBS)) {
 //Temp
                for (i=0; i<0x20; i++)
@@ -201,7 +226,7 @@ int sja1000_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
        sja1000_start_chip(chip);
 
     // disable interrupts for a moment
-       can_write_reg(chip, 0, SJACR); 
+       can_write_reg(chip, 0, SJACR);
 
        sja1000_irq_read_handler(chip, obj);
 
@@ -214,7 +239,7 @@ int sja1000_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
 
 #define MAX_TRANSMIT_WAIT_LOOPS 10
 
-int sja1000_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
+int sja1000_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        int i=0, id=0;
@@ -223,11 +248,11 @@ int sja1000_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
        sja1000_start_chip(chip); //sja1000 goes automatically into reset mode on errors
 
        /* Wait until Transmit Buffer Status is released */
-       while ( !(can_read_reg(chip, SJASR) & sjaSR_TBS) && 
+       while ( !(can_read_reg(chip, SJASR) & sjaSR_TBS) &&
                                                i++<MAX_TRANSMIT_WAIT_LOOPS) {
                udelay(i);
        }
-       
+
        if (!(can_read_reg(chip, SJASR) & sjaSR_TBS)) {
                CANMSG("Transmit timed out, cancelling\n");
                can_write_reg(chip, sjaCMR_AT, SJACMR);
@@ -255,7 +280,7 @@ int sja1000_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
        return 0;
 }
 
-int sja1000_send_msg(struct chip_t *chip, struct msgobj_t *obj, 
+int sja1000_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        can_write_reg(chip, sjaCMR_TR, SJACMR);
@@ -263,7 +288,7 @@ int sja1000_send_msg(struct chip_t *chip, struct msgobj_t *obj,
        return 0;
 }
 
-int sja1000_check_tx_stat(struct chip_t *chip)
+int sja1000_check_tx_stat(struct canchip_t *chip)
 {
        if (can_read_reg(chip,SJASR) & sjaSR_TCS)
                return 0;
@@ -271,7 +296,7 @@ int sja1000_check_tx_stat(struct chip_t *chip)
                return 1;
 }
 
-int sja1000_set_btregs(struct chip_t *chip, unsigned short btr0, 
+int sja1000_set_btregs(struct canchip_t *chip, unsigned short btr0,
                                                        unsigned short btr1)
 {
        if (sja1000_enable_configuration(chip))
@@ -285,7 +310,7 @@ int sja1000_set_btregs(struct chip_t *chip, unsigned short btr0,
        return 0;
 }
 
-int sja1000_start_chip(struct chip_t *chip)
+int sja1000_start_chip(struct canchip_t *chip)
 {
        unsigned short flags = 0;
 
@@ -295,7 +320,7 @@ int sja1000_start_chip(struct chip_t *chip)
        return 0;
 }
 
-int sja1000_stop_chip(struct chip_t *chip)
+int sja1000_stop_chip(struct canchip_t *chip)
 {
        unsigned short flags = 0;
 
@@ -305,37 +330,50 @@ int sja1000_stop_chip(struct chip_t *chip)
        return 0;
 }
 
-int sja1000_remote_request(struct chip_t *chip, struct msgobj_t *obj)
+int sja1000_attach_to_chip(struct canchip_t *chip)
+{
+       return 0;
+}
+
+int sja1000_release_chip(struct canchip_t *chip)
+{
+       sja1000_stop_chip(chip);
+       can_write_reg(chip,sjaCR_RR,SJACR);
+
+       return 0;
+}
+
+int sja1000_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
 {
        CANMSG("sja1000_remote_request not implemented\n");
        return -ENOSYS;
 }
 
-int sja1000_extended_mask(struct chip_t *chip, unsigned long code,
+int sja1000_extended_mask(struct canchip_t *chip, unsigned long code,
                unsigned long mask)
 {
        CANMSG("sja1000_extended_mask not implemented\n");
        return -ENOSYS;
 }
 
-int sja1000_clear_objects(struct chip_t *chip)
+int sja1000_clear_objects(struct canchip_t *chip)
 {
        CANMSG("sja1000_clear_objects not implemented\n");
        return -ENOSYS;
 }
 
-int sja1000_config_irqs(struct chip_t *chip, short irqs)
+int sja1000_config_irqs(struct canchip_t *chip, short irqs)
 {
        CANMSG("sja1000_config_irqs not implemented\n");
        return -ENOSYS;
 }
 
 
-can_irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+int sja1000_irq_handler(int irq, struct canchip_t *chip)
 {
        unsigned irq_register;
-       struct chip_t *chip=(struct chip_t *)dev_id;
        struct msgobj_t *obj=chip->msgobj[0];
+       int loop_cnt=CHIP_MAX_IRQLOOP;
 
        irq_register=can_read_reg(chip, SJAIR);
 //     DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
@@ -343,43 +381,54 @@ can_irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 //                                     can_read_reg(chip, SJASR));
 
        if ((irq_register & (sjaIR_WUI|sjaIR_DOI|sjaIR_EI|sjaIR_TI|sjaIR_RI)) == 0)
-               return CAN_IRQ_NONE;
+               return CANCHIP_IRQ_NONE;
 
-       if ((irq_register & sjaIR_RI) != 0) 
-               sja1000_irq_read_handler(chip, obj);
+       do {
 
-       if ((irq_register & sjaIR_TI) != 0) { 
-               can_msgobj_set_fl(obj,TX_REQUEST);
-               while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
-                       can_msgobj_clear_fl(obj,TX_REQUEST);
+               if(!loop_cnt--) {
+                       CANMSG("sja1000_irq_handler IRQ %d stuck\n",irq);
+                       return CANCHIP_IRQ_STUCK;
+               }
 
-                       if (can_read_reg(chip, SJASR) & sjaSR_TBS)
-                               sja1000_irq_write_handler(chip, obj);
+               if ((irq_register & sjaIR_RI) != 0)
+                       sja1000_irq_read_handler(chip, obj);
 
-                       can_msgobj_clear_fl(obj,TX_LOCK);
-                       if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+               if ((irq_register & sjaIR_TI) != 0) {
+                       can_msgobj_set_fl(obj,TX_REQUEST);
+                       while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+                               can_msgobj_clear_fl(obj,TX_REQUEST);
+
+                               if (can_read_reg(chip, SJASR) & sjaSR_TBS)
+                                       sja1000_irq_write_handler(chip, obj);
+
+                               can_msgobj_clear_fl(obj,TX_LOCK);
+                               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+                       }
                }
-       }
 
-       if ((irq_register & (sjaIR_EI|sjaIR_DOI)) != 0) { 
-               // Some error happened
+               if ((irq_register & (sjaIR_EI|sjaIR_DOI)) != 0) {
+                       // Some error happened
 // FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
 // Reset flag set to 0 if chip is already off the bus. Full state report
-               CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
-                       can_read_reg(chip, SJASR), irq_register);
-               obj->ret=-1;
-
-               if(obj->tx_slot){
-                       canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
-                       /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
-                       obj->tx_slot=NULL;*/
+                       CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
+                               can_read_reg(chip, SJASR), irq_register);
+                       obj->ret=-1;
+
+                       if(obj->tx_slot){
+                               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
+                               /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+                               obj->tx_slot=NULL;*/
+                       }
                }
-       }
 
-       return CAN_IRQ_HANDLED;
+               irq_register=can_read_reg(chip, SJAIR);
+
+       } while(irq_register & (sjaIR_WUI|sjaIR_DOI|sjaIR_EI|sjaIR_TI|sjaIR_RI));
+
+       return CANCHIP_IRQ_HANDLED;
 }
 
-void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj)
+void sja1000_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
 {
        int i=0, id=0, len;
 
@@ -403,16 +452,16 @@ void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj)
        } while(can_read_reg(chip, SJASR) & sjaSR_RBS);
 }
 
-void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
+void sja1000_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
 {
        int cmd;
-       
+
        if(obj->tx_slot){
                /* Do local transmitted message distribution if enabled */
                if (processlocal){
                        /* fill CAN message timestamp */
                        can_filltimestamp(&obj->tx_slot->msg.timestamp);
-                       
+
                        obj->tx_slot->msg.flags |= MSG_LOCAL;
                        canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
                }
@@ -449,17 +498,17 @@ void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
  * Return Value: negative value reports error.
  * File: src/sja1000.c
  */
-int sja1000_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
+int sja1000_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
 {
        can_preempt_disable();
-       
+
        can_msgobj_set_fl(obj,TX_REQUEST);
        while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
                can_msgobj_clear_fl(obj,TX_REQUEST);
 
                if (can_read_reg(chip, SJASR) & sjaSR_TBS)
                        sja1000_irq_write_handler(chip, obj);
-       
+
                can_msgobj_clear_fl(obj,TX_LOCK);
                if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
        }
@@ -486,13 +535,16 @@ int sja1000_register(struct chipspecops_t *chipspecops)
        chipspecops->enable_configuration = sja1000_enable_configuration;
        chipspecops->disable_configuration = sja1000_disable_configuration;
        chipspecops->set_btregs = sja1000_set_btregs;
+       chipspecops->attach_to_chip=sja1000_attach_to_chip;
+       chipspecops->release_chip=sja1000_release_chip;
        chipspecops->start_chip = sja1000_start_chip;
        chipspecops->stop_chip = sja1000_stop_chip;
        chipspecops->irq_handler = sja1000_irq_handler;
+       chipspecops->irq_accept = NULL;
        return 0;
 }
 
-int sja1000_fill_chipspecops(struct chip_t *chip)
+int sja1000_fill_chipspecops(struct canchip_t *chip)
 {
        chip->chip_type="sja1000";
        chip->max_objects=1;