From: ppisa Date: Thu, 23 Sep 2004 23:06:51 +0000 (+0000) Subject: Added support for oscar CAN interface. X-Git-Tag: CLT_COMM_CAN-lincan-0_3~4 X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/commitdiff_plain/76d6542769a63f5779fe28f93d55d08535e649b8 Added support for oscar CAN interface. It is SJA1000 based card connected to ARM LH7A400 SoC. Support contributed by Michael Moedt xemc _AT_ yahoo _DOT_ com --- diff --git a/lincan/README b/lincan/README index 7ff2b91..4b6e4f1 100644 --- a/lincan/README +++ b/lincan/README @@ -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 index 0000000..50cca0c --- /dev/null +++ b/lincan/include/oscar.h @@ -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); + diff --git a/lincan/src/Makefile.omk b/lincan/src/Makefile.omk index f8bdb7b..863cfdc 100644 --- a/lincan/src/Makefile.omk +++ b/lincan/src/Makefile.omk @@ -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 diff --git a/lincan/src/Makefile.std b/lincan/src/Makefile.std index 52069e2..7d04da3 100644 --- a/lincan/src/Makefile.std +++ b/lincan/src/Makefile.std @@ -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 diff --git a/lincan/src/boardlist.c b/lincan/src/boardlist.c index 2afcc17..21e589e 100644 --- a/lincan/src/boardlist.c +++ b/lincan/src/boardlist.c @@ -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 index 0000000..00f3616 --- /dev/null +++ b/lincan/src/oscar.c @@ -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; +}