From 4ccebe5b45857eca673615b5ac8b1901a6d29d8f Mon Sep 17 00:00:00 2001 From: ppisa Date: Sat, 8 May 2004 01:06:34 +0000 Subject: [PATCH] New file for EMS CPC-PCI card added. This card requires more changes and documentation to get work. --- lincan/src/Makefile.omk | 6 +- lincan/src/boardlist.c | 4 + lincan/src/ems_cpcpci.c | 277 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 lincan/src/ems_cpcpci.c diff --git a/lincan/src/Makefile.omk b/lincan/src/Makefile.omk index 1629610..f8bdb7b 100644 --- a/lincan/src/Makefile.omk +++ b/lincan/src/Makefile.omk @@ -1,6 +1,6 @@ -lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 \ - pc_i03 pcm3680 aim104 m437 pcccan ssv \ - bfadcan pikronisa kv_pcican msmcan unican virtual template +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 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/boardlist.c b/lincan/src/boardlist.c index 38fbd3c..629097f 100644 --- a/lincan/src/boardlist.c +++ b/lincan/src/boardlist.c @@ -20,6 +20,7 @@ extern int pccanf_register(struct hwspecops_t *hwspecops); extern int pccand_register(struct hwspecops_t *hwspecops); extern int pccanq_register(struct hwspecops_t *hwspecops); extern int kv_pcican_register(struct hwspecops_t *hwspecops); +extern int ems_cpcpci_register(struct hwspecops_t *hwspecops); extern int nsi_register(struct hwspecops_t *hwspecops); extern int cc104_register(struct hwspecops_t *hwspecops); extern int pci03_register(struct hwspecops_t *hwspecops); @@ -74,6 +75,9 @@ const struct boardtype_t can_boardtypes[]={ {"pcican-d", kv_pcican_register, 0}, {"pcican-q", kv_pcican_register, 0}, #endif + #if defined(CONFIG_OC_LINCAN_CARD_ems_cpcpci)&&defined(CAN_ENABLE_PCI_SUPPORT) + {"ems_cpcpci", ems_cpcpci_register, 0}, + #endif #ifdef CONFIG_OC_LINCAN_CARD_m437 {"m437", m437_register, 1}, #endif diff --git a/lincan/src/ems_cpcpci.c b/lincan/src/ems_cpcpci.c new file mode 100644 index 0000000..69d855f --- /dev/null +++ b/lincan/src/ems_cpcpci.c @@ -0,0 +1,277 @@ +/* ems_cpcpci.c - support for EMS-WUENSCHE CPC-PCI card + * Linux CAN-bus device driver. + * The card support added by Paolo Grisleri + * This software is released under the GPL-License. + * Version lincan-0.2 9 Jul 2003 + */ + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/main.h" +#include "../include/sja1000p.h" + +#ifdef CAN_ENABLE_PCI_SUPPORT + + +/* the only one supported: EMS CPC-PCI */ +// PGX: check identifiers name +# define EMS_CPCPCI_PCICAN_VENDOR 0x110a +# define EMS_CPCPCI_PCICAN_ID 0x2104 + +/*AMCC 5920*/ +#define S5920_OMB 0x0C +#define S5920_IMB 0x1C +#define S5920_MBEF 0x34 +#define S5920_INTCSR 0x38 +#define S5920_RCR 0x3C +#define S5920_PTCR 0x60 + +#define INTCSR_ADDON_INTENABLE_M 0x2000 +#define INTCSR_INTERRUPT_ASSERTED_M 0x800000 + +#define EMS_CPCPCI_BYTES_PER_CIRCUIT 0x200 +/* Each CPC register occupies 4 bytes */ +#define EMS_CPCPCI_BYTES_PER_REG 0x4 + +// Standard value: Pushpull (OCTP1|OCTN1|OCTP0|OCTN0|OCM1) +#define EMS_CPCPCI_OCR_DEFAULT_STD 0xDA +// For Galathea piggyback. +#define EMS_CPCPCI_OCR_DEFAULT_GAL 0xDB + +/* + +You need to know the following: +" RX1 is connected to ground. +" TX1 is not connected. +" CLKO is not connected. +" Setting the OCR register to 0xDA is a good idea. + This means normal output mode , push-pull and the correct polarity. +" In the CDR register, you should set CBP to 1. + You will probably also want to set the clock divider value to 0 (meaning divide-by-2), + the Pelican bit, and the clock-off bit (you have no need for CLKOUT anyway.) + +*/ + + + +void ems_cpcpci_disconnect_irq(struct candevice_t *candev) +{ + unsigned long tmp; + /* Disable interrupts from card */ + tmp = inl(candev->dev_base_addr + S5920_INTCSR); + tmp &= ~INTCSR_ADDON_INTENABLE_M; + outl(tmp, candev->dev_base_addr + S5920_INTCSR); +} + +void ems_cpcpci_connect_irq(struct candevice_t *candev) +{ + unsigned long tmp; + /* Enable interrupts from card */ + tmp = inl(candev->dev_base_addr + S5920_INTCSR); + tmp |= INTCSR_ADDON_INTENABLE_M; + outl(tmp, candev->dev_base_addr + S5920_INTCSR); +} + + +int ems_cpcpci_request_io(struct candevice_t *candev) +{ + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) + if(pci_request_region(candev->sysdevptr.pcidev, 0, "ems_cpcpci_s5920") != 0){ + CANMSG("Request of ems_cpcpci_s5920 range failed\n"); + return -ENODEV; + }else if(pci_request_region(candev->sysdevptr.pcidev, 1, "ems_cpcpci_io") != 0){ + CANMSG("Request of ems_cpcpci_io range failed\n"); + goto error_io; + }else if(pci_request_region(candev->sysdevptr.pcidev, 2, "ems_cpcpci_xilinx") != 0){ + CANMSG("Request of ems_cpcpci_xilinx range failed\n"); + goto error_xilinx; + } + #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + if(pci_request_regions(candev->sysdevptr.pcidev, "EMS_CPCPCI") != 0){ + CANMSG("Request of ems_cpcpci_s5920 regions failed\n"); + return -ENODEV; + } + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + + ems_cpcpci_disconnect_irq(candev); + + return 0; + + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) + error_xilinx: + pci_release_region(candev->sysdevptr.pcidev, 1); + error_io: + pci_release_region(candev->sysdevptr.pcidev, 0); + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + + return -ENODEV; +} + +int ems_cpcpci_release_io(struct candevice_t *candev) +{ + ems_cpcpci_disconnect_irq(candev); + + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) + pci_release_region(candev->sysdevptr.pcidev, 2); + pci_release_region(candev->sysdevptr.pcidev, 1); + pci_release_region(candev->sysdevptr.pcidev, 0); + #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + pci_release_regions(candev->sysdevptr.pcidev); + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + + return 0; +} + + +void ems_cpcpci_write_register(unsigned char data, unsigned long address) +{ + address += ((address&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1)) + *(EMS_CPCPCI_BYTES_PER_REG-1)); + readb(data,address); +} + +unsigned ems_cpcpci_read_register(unsigned long address) +{ + address += ((address&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1)) + *(EMS_CPCPCI_BYTES_PER_REG-1)); + return inb(address); +} + +int ems_cpcpci_reset(struct candevice_t *candev) +{ + int i=0,chip_nr; + struct chip_t *chip; + unsigned cdr; + + DEBUGMSG("Resetting EMS_CPCPCI hardware ...\n"); + + /* Assert PTADR# - we're in passive mode so the other bits are not important */ + outl(0x80808080L, candev->dev_base_addr + S5920_PTCR); + + ems_cpcpci_disconnect_irq(candev); + + for(chip_nr=0;chip_nrnr_all_chips;chip_nr++){ + if(!candev->chip[chip_nr]) continue; + chip=candev->chip[chip_nr]; + + ems_cpcpci_write_register(MOD_RM, chip->chip_base_addr+SJAMOD); + udelay(1000); + + cdr=ems_cpcpci_read_register(chip->chip_base_addr+SJACDR); + ems_cpcpci_write_register(cdr|CDR_PELICAN, chip->chip_base_addr+SJACDR); + + ems_cpcpci_write_register(0, chip->chip_base_addr+SJAIER); + + i=20; + ems_cpcpci_write_register(0, chip->chip_base_addr+SJAMOD); + while (ems_cpcpci_read_register(chip->chip_base_addr+SJAMOD)&MOD_RM){ + if(!i--) return -ENODEV; + udelay(1000); + ems_cpcpci_write_register(0, chip->chip_base_addr+SJAMOD); + } + + cdr=ems_cpcpci_read_register(chip->chip_base_addr+SJACDR); + ems_cpcpci_write_register(cdr|CDR_PELICAN, chip->chip_base_addr+SJACDR); + + ems_cpcpci_write_register(0, chip->chip_base_addr+SJAIER); + + ems_cpcpci_read_register(chip->chip_base_addr+SJAIR); + } + + + ems_cpcpci_connect_irq(candev); + + return 0; +} + +int ems_cpcpci_init_hw_data(struct candevice_t *candev) +{ + struct pci_dev *pcidev = NULL; + int i; + + pcidev = pci_find_device(EMS_CPCPCI_PCICAN_VENDOR, EMS_CPCPCI_PCICAN_ID, pcidev); + if(pcidev == NULL) return -ENODEV; + + if (pci_enable_device (pcidev)){ + printk(KERN_CRIT "Setup of EMS_CPCPCI failed\n"); + return -EIO; + } + candev->sysdevptr.pcidev=pcidev; + + for(i=0;i<2;i++){ + if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){ + printk(KERN_CRIT "EMS_CPCPCI region %d is not memory\n",i); + return -EIO; + } + } + candev->dev_base_addr=pci_resource_start(pcidev,0); /*S5920*/ + /* some control registers */ + candev->io_addr=pci_resource_start(pcidev,1); + /* 0 more EMS control registers + * 0x400 the first SJA1000 + * 0x600 the second SJA1000 + * each register occupies 4 bytes + */ + + /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/ + + if (!strcmp(candev->hwname,"ems_cpcpci")) { + candev->nr_82527_chips=0; + candev->nr_sja1000_chips=2; + candev->nr_all_chips=2; + } + + return 0; +} + +int ems_cpcpci_init_chip_data(struct candevice_t *candev, int chipnr) +{ + + if(candev->sysdevptr.pcidev==NULL) + return -ENODEV; + + candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq; + + candev->chip[chipnr]->chip_type="sja1000p"; + candev->chip[chipnr]->chip_base_addr = candev->io_addr+ + 0x400 + chipnr*EMS_CPCPCI_BYTES_PER_CIRCUIT; + candev->chip[chipnr]->flags = 0; + candev->chip[chipnr]->int_cpu_reg = 0; + candev->chip[chipnr]->int_clk_reg = 0; + candev->chip[chipnr]->int_bus_reg = 0; + candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF; + candev->chip[chipnr]->sja_ocr_reg = EMS_CPCPCI_OCR_DEFAULT_STD; + candev->chip[chipnr]->clock = 8000000; + candev->chip[chipnr]->flags |= CHIP_IRQ_PCI; + + return 0; +} + +int ems_cpcpci_init_obj_data(struct chip_t *chip, int objnr) +{ + chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; + return 0; +} + +int ems_cpcpci_program_irq(struct candevice_t *candev) +{ + + return 0; +} + +int ems_cpcpci_register(struct hwspecops_t *hwspecops) +{ + hwspecops->request_io = ems_cpcpci_request_io; + hwspecops->release_io = ems_cpcpci_release_io; + hwspecops->reset = ems_cpcpci_reset; + hwspecops->init_hw_data = ems_cpcpci_init_hw_data; + hwspecops->init_chip_data = ems_cpcpci_init_chip_data; + hwspecops->init_obj_data = ems_cpcpci_init_obj_data; + hwspecops->write_register = ems_cpcpci_write_register; + hwspecops->read_register = ems_cpcpci_read_register; + hwspecops->program_irq = ems_cpcpci_program_irq; + return 0; +} + + +#endif /*CAN_ENABLE_PCI_SUPPORT*/ -- 2.39.2