Added support for oscar CAN interface.
authorppisa <ppisa>
Thu, 23 Sep 2004 23:06:51 +0000 (23:06 +0000)
committerppisa <ppisa>
Thu, 23 Sep 2004 23:06:51 +0000 (23:06 +0000)
It is SJA1000 based card connected to ARM LH7A400 SoC.
Support contributed by Michael Moedt  xemc _AT_ yahoo _DOT_ com

lincan/README
lincan/include/oscar.h [new file with mode: 0644]
lincan/src/Makefile.omk
lincan/src/Makefile.std
lincan/src/boardlist.c
lincan/src/oscar.c [new file with mode: 0644]

index 7ff2b91..4b6e4f1 100644 (file)
@@ -214,6 +214,7 @@ The hw argument can be one of:
 - unican-pci for Unicontrols PCAN-PCI card
 - unican-vme for Unicontrols VCAN card
 - ems_cpcpci for EMS CPC-PCI card
+- oscar for SJA1000 based card connected to ARM LH7A400 SoC
 - template, for yet unsupported hardware (you need to edit src/template.c)
 - virtual, CAN channel for testing of software and driver without CAN hardware
 
diff --git a/lincan/include/oscar.h b/lincan/include/oscar.h
new file mode 100644 (file)
index 0000000..50cca0c
--- /dev/null
@@ -0,0 +1,19 @@
+/* oscar.h
+ * Header file for the Linux CAN-bus 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
+ */
+
+int oscar_request_io(struct candevice_t *candev);
+int oscar_release_io(struct candevice_t *candev);
+int oscar_reset(struct candevice_t *candev); 
+int oscar_init_hw_data(struct candevice_t *candev);
+int oscar_init_chip_data(struct candevice_t *candev, int chipnr);
+int oscar_init_obj_data(struct canchip_t *chip, int objnr);
+void oscar_write_register(unsigned data, unsigned long address);
+unsigned oscar_read_register(unsigned long address);
+int oscar_program_irq(struct candevice_t *candev);
+
index f8bdb7b..863cfdc 100644 (file)
@@ -1,6 +1,6 @@
 lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 ems_cpcpci \
                pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan pikronisa \
-               kv_pcican msmcan unican virtual template
+               kv_pcican msmcan oscar unican virtual template
 
 default_CONFIG = CONFIG_OC_LINCAN=y CONFIG_OC_LINCANRTL=n CONFIG_OC_LINCANVME=n
 default_CONFIG += CONFIG_OC_LINCAN_PORTIO_ONLY=n CONFIG_OC_LINCAN_MEMIO_ONLY=n
index 52069e2..7d04da3 100644 (file)
@@ -63,7 +63,7 @@ endif
 SUPPORTED_CARDS = pip pccan smartcan nsi cc_can104 \
                  pc_i03 pcm3680 aim104 m437 pcccan ssv \
                  bfadcan pikronisa kv_pcican msmcan virtual template \
-                 unican unican_cl2 ems_cpcpci
+                 unican unican_cl2 ems_cpcpci oscar
 #                hms30c7202_can c_can c_can_irq
 #                pcan_dongle
 
index 2afcc17..21e589e 100644 (file)
@@ -12,6 +12,7 @@
 
 extern int template_register(struct hwspecops_t *hwspecops);
 extern int virtual_register(struct hwspecops_t *hwspecops);
+extern int oscar_register(struct hwspecops_t *hwspecops);
 extern int pip5_register(struct hwspecops_t *hwspecops);
 extern int pip6_register(struct hwspecops_t *hwspecops);
 extern int m437_register(struct hwspecops_t *hwspecops);
@@ -43,6 +44,9 @@ const struct boardtype_t can_boardtypes[]={
     #ifdef CONFIG_OC_LINCAN_CARD_template
        {"virtual", virtual_register, 0},
     #endif
+    #ifdef CONFIG_OC_LINCAN_CARD_oscar
+       {"oscar", oscar_register, 1},
+    #endif
     #ifdef CONFIG_OC_LINCAN_CARD_pip
        {"pip5", pip5_register, 1},
        {"pip6", pip6_register, 1},
diff --git a/lincan/src/oscar.c b/lincan/src/oscar.c
new file mode 100644 (file)
index 0000000..00f3616
--- /dev/null
@@ -0,0 +1,113 @@
+/* oscar.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
+
+ NOTE: Please see the template.c file for the comments relating to this code.
+       Herein is the modified copy of the functions
+
+ */ 
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/oscar.h"
+#include "../include/i82527.h"
+#include "../include/sja1000.h"
+
+#define IO_RANGE 0x80 // allow both basic CAN and PeliCAN modes for sja1000
+
+int oscar_request_io(struct candevice_t *candev)
+{
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
+               return -ENODEV;
+       }else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
+       }
+       return 0;
+}
+
+int oscar_release_io(struct candevice_t *candev)
+{
+       can_release_io_region(candev->io_addr,IO_RANGE);
+
+       return 0;
+}
+
+int oscar_reset(struct candevice_t *candev)
+{
+    DEBUGMSG("Cannot issue a hardware reset to the CAN chip.");
+    return -ENODEV;
+}
+
+int oscar_init_hw_data(struct candevice_t *candev) 
+{
+    candev->res_addr = 0x0; // RESET address?
+    candev->nr_82527_chips = 0;
+    candev->nr_sja1000_chips = 1; // We've got a SJA1000 variant
+    candev->nr_all_chips= 1;
+    candev->flags |= CANDEV_PROGRAMMABLE_IRQ;
+
+    return 0;
+}
+
+int oscar_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+    // i82527_fill_chipspecops(candev->chip[chipnr]);
+    sja1000_fill_chipspecops(candev->chip[chipnr]);
+    // sja1000p_fill_chipspecops(candev->chip[chipnr]);
+       
+    candev->chip[chipnr]->chip_base_addr = candev->io_addr;
+    candev->chip[chipnr]->clock = 12000000;
+    candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP;  // we use an external tranceiver
+    candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
+    // these three int_ registers are unused (we don't have this chip)
+    candev->chip[chipnr]->int_cpu_reg = 0;
+    candev->chip[chipnr]->int_clk_reg = 0;
+    candev->chip[chipnr]->int_bus_reg = 0;
+    
+    return 0;
+}
+
+int oscar_init_obj_data(struct canchip_t *chip, int objnr)
+{
+    chip->msgobj[objnr]->obj_base_addr = chip->chip_base_addr;
+    
+    return 0;
+}
+
+int oscar_program_irq(struct candevice_t *candev)
+{
+    // CAN_IRQ_L (active low) interrupt: PF2 / INT2 on our LH7A400 SoC
+    // This IRQ is set up already by the kernel.    
+
+    return 0;
+}
+
+void oscar_write_register(unsigned data, unsigned long address)
+{
+       outb(data,address);
+}
+
+unsigned oscar_read_register(unsigned long address)
+{
+       return inb(address);
+}
+
+/* !!! Don't change this function !!! */
+int oscar_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = oscar_request_io;
+       hwspecops->release_io = oscar_release_io;
+       hwspecops->reset = oscar_reset;
+       hwspecops->init_hw_data = oscar_init_hw_data;
+       hwspecops->init_chip_data = oscar_init_chip_data;
+       hwspecops->init_obj_data = oscar_init_obj_data;
+       hwspecops->write_register = oscar_write_register;
+       hwspecops->read_register = oscar_read_register;
+       hwspecops->program_irq = oscar_program_irq;
+       return 0;
+}