http://www.embeddedarm.com/
contributed support for TS-CAN1 and TS-7KV
+Manuel Bessler, m.bessler@gmx.net
+http://projects.varxec.net/can_pci-200
+ contributed support for ESD Electronics CAN/PCI-200 card
+
========================================
List of companies and subjects
who donated hardware to LinCAN project
# Generic directory or leaf node makefile for OCERA make framework
ifndef MAKERULES_DIR
-MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
endif
ifeq ($(MAKERULES_DIR),)
all : default
.DEFAULT::
@echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
-else
+else
include $(MAKERULES_DIR)/Makefile.rules
endif
-SUBDIRS = src utils
+SUBDIRS = src
- pcm3680, for the PCM-3680 PC/104 card by Advantech
- m437, for the M436 PC/104 card by SECO
- bfadcan for sja1000 CAN embedded card made by BFAD GmbH
+- gensja1000io for many sja1000 I/O mapped cards (PCAN-PC/104 for example).
- pikronisa for ISA memory mapped sja1000 CAN card made by PiKRON Ltd.
- pimx1 for MX1_DIS1 extension board for PiMX1 ARM based BCC
- msmcan for MICROSPACE IO space indexed i82527
- tscan1 for Technologic Systems' TS-CAN1 single SJA1000 based board
- ts7kv for Technologic Systems' TS-7KV Multi-function board with SJA1000
both these cards require CONFIG_OC_LINCAN_CARD_tscan1=y
+- pcan_pci for PEAK System PCAN-PCI single, double or quad SJA1000 based board
+- esdpci200 for the CAN/PCI-200 card by ESD Electronics board
- template, for yet unsupported hardware (you need to edit src/template.c)
- virtual, CAN channel for testing of software and driver without CAN hardware
- extended=[1|0], configures the driver to use extended message format.
- pelican=[1|0], configures the driver to set the CAN chips into pelican mode.
- baudrate=<nr>, sets the baudrate of the device(s)
-- clock_freq=<nr>, the frequency of the CAN quartz
+- clockfreq=<nr>, the frequency of the CAN quartz
- stdmask=<nr>, sets the standard mask of the device
- extmask=<nr>, sets the extended mask of the device
- mo15mask=<nr>, sets the mask for message object 15 (i82527 only)
int aim104_init_hw_data(struct candevice_t *candev);
int aim104_init_chip_data(struct candevice_t *candev, int chipnr);
int aim104_init_obj_data(struct canchip_t *chip, int objnr);
-void aim104_write_register(unsigned data, unsigned long address);
-unsigned aim104_read_register(unsigned long address);
+void aim104_write_register(unsigned data, can_ioptr_t address);
+unsigned aim104_read_register(can_ioptr_t address);
int aim104_program_irq(struct candevice_t *candev);
*/
extern inline void c_can_write_reg_w(const struct canchip_t *pchip, u16 data, unsigned reg)
{
- u32 address = pchip->chip_base_addr + reg;
+ can_ioptr_t address = pchip->chip_base_addr + reg;
#ifndef CONFIG_OC_LINCAN_DYNAMICIO
writew(data,address);
#else /*CONFIG_OC_LINCAN_DYNAMICIO*/
extern inline u16 c_can_read_reg_w(const struct canchip_t *pchip, unsigned reg)
{
- u32 address = pchip->chip_base_addr + reg;
+ can_ioptr_t address = pchip->chip_base_addr + reg;
#ifndef CONFIG_OC_LINCAN_DYNAMICIO
return readw(address);
#else /*CONFIG_OC_LINCAN_DYNAMICIO*/
#else /* __KERNEL__ */
+#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#define CAN_IRQ_HANDLED IRQ_HANDLED
#define CAN_IRQ_RETVAL IRQ_RETVAL
#endif /* <=2.5.67 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+ int irq_number, void *dev_id, struct pt_regs *regs
+#else /* < 2.6.19 */
+ #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+ int irq_number, void *dev_id
+#endif /* < 2.6.19 */
#else /*CAN_WITH_RTL*/
typedef int can_irqreturn_t;
#define CAN_IRQ_NONE 0
#define CAN_IRQ_HANDLED 1
#define CAN_IRQ_RETVAL(x) ((x) != 0)
+ #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+ int irq_number, void *dev_id, struct pt_regs *regs
#endif /*CAN_WITH_RTL*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,33))
#define del_timer_sync del_timer
#endif /* <2.4.0 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
+ typedef unsigned long can_ioptr_t;
+ #define can_ioptr2ulong(ioaddr) ((unsigned long)(ioaddr))
+ #define can_ulong2ioptr(addr) ((unsigned long)(addr))
+ #define can_inb(ioaddr) inb(ioaddr)
+ #define can_outb(data,ioaddr) outb(data,ioaddr)
+ #define can_inw(ioaddr) inb(ioaddr)
+ #define can_outw(data,ioaddr) outb(data,ioaddr)
+ #define can_inl(ioaddr) inb(ioaddr)
+ #define can_outl(data,ioaddr) outb(data,ioaddr)
+#else /* >=2.6.9 */
+ typedef void __iomem * can_ioptr_t;
+ #define can_ioptr2ulong(ioaddr) ((unsigned long __force)(ioaddr))
+ #define can_ulong2ioptr(addr) ((can_ioptr_t)(addr))
+ #define can_inb(ioaddr) inb(can_ioptr2ulong(ioaddr))
+ #define can_outb(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+ #define can_inw(ioaddr) inb(can_ioptr2ulong(ioaddr))
+ #define can_outw(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+ #define can_inl(ioaddr) inb(can_ioptr2ulong(ioaddr))
+ #define can_outl(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+#endif
+
+#define can_readb readb
+#define can_writeb writeb
+#define can_readw readw
+#define can_writew writew
+#define can_readl readl
+#define can_writel writel
+
+#define can_ioport2ioptr can_ulong2ioptr
+
#ifdef __HAVE_ARCH_CMPXCHG
#define CAN_HAVE_ARCH_CMPXCHG
#endif
#define CAN_DEFINE_SPINLOCK DEFINE_SPINLOCK
#endif /*DEFINE_SPINLOCK*/
-#if defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+#if !defined(CONFIG_PREEMPT_RT) && ( defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) )
#define can_preempt_disable preempt_disable
#define can_preempt_enable preempt_enable
#else /*CONFIG_PREEMPT*/
#else /* __KERNEL__ */
+#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
int cc104_init_hw_data(struct candevice_t *candev);
int cc104_init_chip_data(struct candevice_t *candev, int chipnr);
int cc104_init_obj_data(struct canchip_t *chip, int objnr);
-void cc104_write_register(unsigned data, unsigned long address);
-unsigned cc104_read_register(unsigned long address);
+void cc104_write_register(unsigned data, can_ioptr_t address);
+unsigned cc104_read_register(can_ioptr_t address);
int cc104_program_irq(struct candevice_t *candev);
int eb8245_init_chip_data(struct candevice_t *candev, int chipnr);
int eb8245_init_obj_data(struct canchip_t *chip, int objnr);
int eb8245_program_irq(struct candevice_t *candev);
-void eb8245_write_register(unsigned data, unsigned long address);
-unsigned eb8245_read_register(unsigned long address);
+void eb8245_write_register(unsigned data, can_ioptr_t address);
+unsigned eb8245_read_register(can_ioptr_t address);
--- /dev/null
+/* gensja1000io.h
+ * Header file for the Linux CAN-bus driver.
+ * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Added by Pavel Pisa pisa@cmp.felk.cvut.cz
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.3 17 Jun 2004
+ *
+ * Support for PiKRON Ltd ISA CAN card using
+ * memory mapped SJA1000 controller
+ */
+
+int gensja1000io_request_io(struct candevice_t *candev);
+int gensja1000io_release_io(struct candevice_t *candev);
+int gensja1000io_reset(struct candevice_t *candev);
+int gensja1000io_init_hw_data(struct candevice_t *candev);
+int gensja1000io_init_chip_data(struct candevice_t *candev, int chipnr);
+int gensja1000io_init_obj_data(struct canchip_t *chip, int objnr);
+int gensja1000io_program_irq(struct candevice_t *candev);
+void gensja1000io_write_register(unsigned data, can_ioptr_t address);
+unsigned gensja1000io_read_register(can_ioptr_t address);
+
--- /dev/null
+/* hcan2.h
+* Header file for the Linux CAN-bus driver.
+* This software is released under the GPL-License.
+*/
+
+int hcan2_chip_config(struct canchip_t *chip);
+int hcan2_enable_configuration(struct canchip_t *chip);
+int hcan2_disable_configuration(struct canchip_t *chip);
+
+int hcan2_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, int sampl_pt, int flags);
+int hcan2_set_btregs(struct canchip_t *chip, unsigned short btr0, unsigned short btr1);
+
+int hcan2_start_chip(struct canchip_t *chip);
+int hcan2_stop_chip(struct canchip_t *chip);
+int hcan2_attach_to_chip(struct canchip_t *chip);
+int hcan2_release_chip(struct canchip_t *chip);
+
+int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask);
+int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask);
+int hcan2_message15_mask(int irq, struct canchip_t *chip);
+
+int hcan2_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj);
+int hcan2_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg);
+int hcan2_send_msg(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg);
+int hcan2_remote_request(struct canchip_t *chip, struct msgobj_t *obj);
+
+int hcan2_irq_handler(int irq, struct canchip_t *chip);
+int hcan2_irq_accept(int irq, struct canchip_t *chip);
+int hcan2_config_irqs(struct canchip_t *chip, short irqs);
+
+int hcan2_clear_objects(struct canchip_t *chip);
+int hcan2_check_tx_stat(struct canchip_t *chip);
+int hcan2_check_MB_tx_stat(struct canchip_t *chip, struct msgobj_t *obj);
+int hcan2_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj);
+int hcan2_filtch_rq(struct canchip_t *chip, struct msgobj_t * obj);
+
+int hcan2_register(struct chipspecops_t *chipspecops);
+int hcan2_fill_chipspecops(struct canchip_t *chip);
+
+int hcan2_reset_chip(struct canchip_t *chip);
+
+
+extern inline void can_write_reg_w(const struct canchip_t *pchip, uint16_t data, unsigned reg)
+{
+ can_ioptr_t address = pchip->chip_base_addr + reg;
+ #ifndef CONFIG_OC_LINCAN_DYNAMICIO
+ writew(data,address);
+ #else /*CONFIG_OC_LINCAN_DYNAMICIO*/
+ pchip->write_register(data, address);
+ #endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
+}
+
+extern inline uint16_t can_read_reg_w(const struct canchip_t *pchip, unsigned reg)
+{
+ can_ioptr_t address = pchip->chip_base_addr + reg;
+ #ifndef CONFIG_OC_LINCAN_DYNAMICIO
+ return readw(address);
+ #else /*CONFIG_OC_LINCAN_DYNAMICIO*/
+ return pchip->read_register(address);
+ #endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
+}
+
+
+/* BasicCAN mode address map */
+#define HCAN2_MCR 0x00000000 /* Master control register */
+#define HCAN2_GSR 0x00000002 /* General status register */
+#define HCAN2_BCR1 0x00000004 /* Bit configuration register 1 */
+#define HCAN2_BCR0 0x00000006 /* Bit configuration register 0 */
+#define HCAN2_IRR 0x00000008 /* Interrupt request register */
+#define HCAN2_IMR 0x0000000a /* Interrupt mask register */
+#define HCAN2_TECREC 0x0000000c /* 15:8 Transmit error counter 7:0 Receive error counter */
+#define HCAN2_TXPR1 0x00000020 /* Transmit pending request register 1 */
+#define HCAN2_TXPR0 0x00000022 /* Transmit pending request register 0 */
+#define HCAN2_TXCR1 0x00000028 /* Transmit cancel register 1 */
+#define HCAN2_TXCR0 0x0000002a /* Transmit cancel register 0 */
+#define HCAN2_TXACK1 0x00000030 /* Transmit acknowledge register 1 */
+#define HCAN2_TXACK0 0x00000032 /* Transmit acknowledge register 0 */
+#define HCAN2_ABACK1 0x00000038 /* Abort acknowledge register 1 */
+#define HCAN2_ABACK0 0x0000003a /* Abort acknowledge register 0 */
+#define HCAN2_RXPR1 0x00000040 /* Receive data frame pending register 1 */
+#define HCAN2_RXPR0 0x00000042 /* Receive data frame pending register 0 */
+#define HCAN2_RFPR1 0x00000048 /* Remote frame request pending register 1 */
+#define HCAN2_RFPR0 0x0000004a /* Remote frame request pending register 0 */
+#define HCAN2_MBIMR1 0x00000050 /* Mailbox interrupt mask register 1 */
+#define HCAN2_MBIMR0 0x00000052 /* Mailbox interrupt mask register 0 */
+#define HCAN2_UMSR1 0x00000058 /* Unread message status register 1 */
+#define HCAN2_UMSR0 0x0000005a /* Unread message status register 0 */
+#define HCAN2_TCNTR 0x00000080 /* Timer counter register */
+#define HCAN2_TCR 0x00000082 /* Timer control register */
+#define HCAN2_TCMR 0x00000084 /* Timer Compare Match register */
+#define HCAN2_TDCR 0x00000086
+#define HCAN2_LOSR 0x00000088
+#define HCAN2_ICR1 0x0000008e
+#define HCAN2_TCMR0 0x00000090 /* Timer compare match register */
+#define HCAN2_TCMR1 0x00000092
+#define HCAN2_TCMR2 0x00000094
+#define HCAN2_CCR 0x00000096
+#define HCAN2_CMAX 0x00000098
+#define HCAN2_TMR 0x0000009a
+
+/* BaudRate minimal and maximal TSEG values */
+#define TSEG_MIN 8
+#define TSEG_MAX 25
+#define TSEG1_MIN 4
+#define TSEG1_MAX 16
+#define TSEG2_MIN 2
+#define TSEG2_MAX 8
+
+enum hcan2_mcr {
+ /* bits 15 to 8 are used for test mode */
+ HCAN2_MCR_AWAKE = 1 << 7, /* Auto Wake Mode */
+ HCAN2_MCR_SLEEP = 1 << 5, /* Sleep Mode */
+ HCAN2_MCR_TXP = 1 << 2, /* Transmition Priority 0-message ID number priority, 1-mailbox number piority*/
+ HCAN2_MCR_HALT = 1 << 1, /* Halt Request */
+ HCAN2_MCR_RESET = 1 << 0, /* Reset Request */
+};
+
+enum hcan2_gsr {
+ HCAN2_GSR_EPS = 1 << 5, /* Error Passive Status */
+ HCAN2_GSR_HSS = 1 << 4, /* Halt/Sleep Status */
+ HCAN2_GSR_RESET = 1 << 3, /* Reset Status */
+ HCAN2_GSR_TXC = 1 << 2, /* Message Transmission Complete Flag */
+ HCAN2_GSR_TXRXW = 1 << 1, /* Transmit/Receive Warning Flag */
+ HCAN2_GSR_BOFF = 1 << 0, /* Buss Off Flag */
+};
+
+/* IRR and IMR register */
+enum hcan2_irr {
+ HCAN2_IRR_TCMI = 1 << 14, /* Time Compare Match Register */
+ HCAN2_IRR_TOI = 1 << 13, /* Time Overrun Interrupt */
+ HCAN2_IRR_WUBA = 1 << 12, /* Wake-up on Bus Activity */
+ HCAN2_IRR_MOOI = 1 << 9, /* Message Overrun/Overwrite Interrupt Flag */
+ HCAN2_IRR_MBEI = 1 << 8, /* Messagebox Empty Interrupt Flag */
+ HCAN2_IRR_OF = 1 << 7, /* Overload Frame */
+ HCAN2_IRR_BOI = 1 << 6, /* Bus Off Interrupt Flag */
+ HCAN2_IRR_EPI = 1 << 5, /* Error Passive Interrupt Flag */
+ HCAN2_IRR_ROWI = 1 << 4, /* Receive Overload Warning Interrupt Flag */
+ HCAN2_IRR_TOWI = 1 << 3, /* Transmit Overload Warining Interrupt Flag */
+ HCAN2_IRR_RFRI = 1 << 2, /* Remote Frame Request Interrupt Flag */
+ HCAN2_IRR_DFRI = 1 << 1, /* Data Frame Received Interrupt Flag */
+ HCAN2_IRR_RHSI = 1 << 0, /* Reset/Halt/Sleep Interrupt Flag */
+};
+
+/* Message box 0-31 */
+#define HCAN2_MB0 0x00000100 /* RECEIVE ONLY */
+#define HCAN2_MB_OFFSET 0x00000020
+
+/* Message box structure offsets */
+#define HCAN2_MB_CTRL0 0x00000000 /* Control 0 */
+#define HCAN2_MB_CTRL1 0x00000002 /* Control 1 */
+#define HCAN2_MB_CTRL2 0x00000004 /* Control 2 */
+#define HCAN2_MB_TSTP 0x00000006 /* Time stamp */
+#define HCAN2_MB_DATA0 0x00000009 /* Data 0 */
+#define HCAN2_MB_DATA1 0x00000008 /* Data 1 */
+#define HCAN2_MB_DATA2 0x0000000b /* Data 2 */
+#define HCAN2_MB_DATA3 0x0000000a /* Data 3 */
+#define HCAN2_MB_DATA4 0x0000000d /* Data 4 */
+#define HCAN2_MB_DATA5 0x0000000c /* Data 5 */
+#define HCAN2_MB_DATA6 0x0000000f /* Data 6 */
+#define HCAN2_MB_DATA7 0x0000000e /* Data 7 */
+#define HCAN2_MB_MASK 0x00000010 /* Acceptance filter mask 4 bytes */
+
+/* Control register 0 */
+enum hcan2_mb_ctrl0{
+ HCAN2_MBCT0_STDID = 0x7ff0, /* STD ID */
+ HCAN2_MBCT0_RTR = 0x0008, /* Remote transmition request 0-DataFrame 1-RemoteFrame */
+ HCAN2_MBCT0_IDE = 0x0004, /* Identifier extension 0-Standard 1-Extended */
+ HCAN2_MBCT0_EXTID = 0x0003 /* EXTID 17:16 */
+};
+
+/* Control register 1 */
+/* whole register is EXTD ID 15:0 */
+
+/* Control register 2 */
+enum hcan2_mb_ctrl2{
+ HCAN2_MBCT2_NMC = 1<<13, /* New message control */
+ HCAN2_MBCT2_ATX = 1<<12, /* Automatic transmition of data frame */
+ HCAN2_MBCT2_DART = 1<<11, /* Disable automatic re-transmition */
+ HCAN2_MBCT2_MBC = 7<<8, /* Mailbox configuration */
+ HCAN2_MBCT2_CBE = 1<<5, /* CAN bus error */
+ HCAN2_MBCT2_DLC = 0xf /* Data length code */
+};
+
+/* MessageBox modes */
+enum hcan2_mb_mode{
+ HCAN2_MBMOD_TXDR = 0, /* Transmit Data and Remote Frame */
+ HCAN2_MBMOD_TXDR_RXR = 1, /* Transmit Data and Remote Frame, Receive Remote Frame */
+ HCAN2_MBMOD_RXDR = 2, /* Receive Data and Remote Frame */
+ HCAN2_MBMOD_RXD = 3, /* Receive Data Frame */
+ HCAN2_MBMOD_TXR_RXDR = 4, /* Transmit Remote Frame, Receive Data and Remove Frame */
+ HCAN2_MBMOD_TXR_RXD = 5, /* Transmit Remote Frame, Receive Data Frame */
+ /* 6 is not used and prohibited */
+ HCAN2_MBMOD_INNACTIVE = 7, /* Mailboc Innactive */
+};
int hms30c7202_request_io(struct candevice_t *candev);\r
int hms30c7202_release_io(struct candevice_t *candev);\r
int hms30c7202_reset( struct candevice_t *candev);\r
-void hms30c7202_write_register(unsigned data, unsigned long address);\r
-unsigned hms30c7202_read_register(unsigned long address);\r
+void hms30c7202_write_register(unsigned data, can_ioptr_t address);\r
+unsigned hms30c7202_read_register(can_ioptr_t address);\r
\r
\r
\r
* Version lincan-0.3 17 Jun 2004
*/
+#include "../include/can_sysdep.h"
#include "../include/kthread.h"
/* PCI device identification */
/* BCI queue info */
struct bci_queue_t {
- int idx; /* points to the active record in buffer */
- unsigned long addr; /* start address of the message queue */
+ int idx; /* points to the active record in buffer */
+ can_ioptr_t addr; /* start address of the message queue */
};
/* ipci165 chip data */
#ifndef _KTHREAD_H
#define _KTHREAD_H
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
- #include <linux/config.h>
-#endif
#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+#include <linux/config.h>
+#endif
#include <linux/kernel.h>
#include <linux/sched.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
#include <linux/tqueue.h>
#define tasklet_struct tq_struct
-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
- #include <linux/devfs_fs_kernel.h>
+#else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+ #include <linux/devfs_fs_kernel.h>
+ #endif
#endif
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <asm/unistd.h>
-#include <asm/semaphore.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
+ #include <asm/semaphore.h>
+#else
+ #include <linux/semaphore.h>
+#endif
/* a structure to store all information we need
for our thread */
int m437_init_hw_data(struct candevice_t *candev);
int m437_init_chip_data(struct candevice_t *candev, int chipnr);
int m437_init_obj_data(struct canchip_t *chip, int objnr);
-void m437_write_register(unsigned data, unsigned long address);
-unsigned m437_read_register(unsigned long address);
+void m437_write_register(unsigned data, can_ioptr_t address);
+unsigned m437_read_register(can_ioptr_t address);
int m437_program_irq(struct candevice_t *candev);
int m437_register(struct hwspecops_t *hwspecops);
#include "./can_queue.h"
#ifdef CAN_DEBUG
- #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "can.o (debug): " fmt,\
+ #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "lincan (debug): " fmt,\
##args)
#else
#define DEBUGMSG(fmt,args...)
#endif
-#define CANMSG(fmt,args...) can_printk(KERN_ERR "can.o: " fmt,##args)
+#define CANMSG(fmt,args...) can_printk(KERN_ERR "lincan: " fmt,##args)
extern can_spinlock_t canuser_manipulation_lock;
int candev_idx; /* board index in canhardware_t.candevice[] */
unsigned long io_addr; /* IO/physical MEM address */
unsigned long res_addr; /* optional reset register port */
- unsigned long dev_base_addr; /* CPU translated IO/virtual MEM address */
+ can_ioptr_t dev_base_addr; /* CPU translated IO/virtual MEM address */
+ can_ioptr_t aux_base_addr; /* CPU translated IO/virtual MEM address */
unsigned int flags;
int nr_all_chips;
int nr_82527_chips;
char *chip_type;
int chip_idx; /* chip index in candevice_t.chip[] */
int chip_irq;
- unsigned long chip_base_addr;
+ can_ioptr_t chip_base_addr;
unsigned int flags;
long clock; /* Chip clock in Hz */
long baudrate;
- void (*write_register)(unsigned data,unsigned long address);
- unsigned (*read_register)(unsigned long address);
+ void (*write_register)(unsigned data, can_ioptr_t address);
+ unsigned (*read_register)(can_ioptr_t address);
void *chip_data;
* that reuse same object for TX
*/
struct msgobj_t {
- unsigned long obj_base_addr;
+ can_ioptr_t obj_base_addr;
unsigned int minor; /* associated device minor number */
unsigned int object; /* object number in canchip_t +1 for debug printk */
unsigned long obj_flags;
int (*init_chip_data)(struct candevice_t *candev, int chipnr);
int (*init_obj_data)(struct canchip_t *chip, int objnr);
int (*program_irq)(struct candevice_t *candev);
- void (*write_register)(unsigned data,unsigned long address);
- unsigned (*read_register)(unsigned long address);
+ void (*write_register)(unsigned data, can_ioptr_t address);
+ unsigned (*read_register)(can_ioptr_t address);
};
/**
extern int minor[MAX_TOT_CHIPS];
extern int extended;
extern int baudrate[MAX_TOT_CHIPS];
-extern char *hw[MAX_HW_CARDS];
extern int irq[MAX_IRQ];
+extern char *hw[MAX_HW_CARDS];
extern unsigned long io[MAX_HW_CARDS];
+extern long clockfreq[MAX_HW_CARDS];
extern int processlocal;
extern struct canhardware_t *hardware_p;
#if defined(CONFIG_OC_LINCAN_PORTIO_ONLY)
-extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
{
- outb(data, chip->chip_base_addr+address);
+ can_outb(data, chip->chip_base_addr+reg_offs);
}
-extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
{
- return inb(chip->chip_base_addr+address);
+ return can_inb(chip->chip_base_addr+reg_offs);
}
extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned char data, unsigned address)
+ unsigned char data, unsigned reg_offs)
{
- outb(data, obj->obj_base_addr+address);
+ can_outb(data, obj->obj_base_addr+reg_offs);
}
extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned address)
+ unsigned reg_offs)
{
- return inb(obj->obj_base_addr+address);
+ return can_inb(obj->obj_base_addr+reg_offs);
}
#elif defined(CONFIG_OC_LINCAN_MEMIO_ONLY)
-extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
{
- writeb(data, chip->chip_base_addr+address);
+ can_writeb(data, chip->chip_base_addr+reg_offs);
}
-extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
{
- return readb(chip->chip_base_addr+address);
+ return can_readb(chip->chip_base_addr+reg_offs);
}
extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned char data, unsigned address)
+ unsigned char data, unsigned reg_offs)
{
- writeb(data, obj->obj_base_addr+address);
+ can_writeb(data, obj->obj_base_addr+reg_offs);
}
extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned address)
+ unsigned reg_offs)
{
- return readb(obj->obj_base_addr+address);
+ return can_readb(obj->obj_base_addr+reg_offs);
}
#else /*CONFIG_OC_LINCAN_DYNAMICIO*/
#define CONFIG_OC_LINCAN_DYNAMICIO
#endif
-/* Inline function to write to the hardware registers. The argument address is
- * relative to the memory map of the chip and not the absolute memory address.
+/* Inline function to write to the hardware registers. The argument reg_offs is
+ * relative to the memory map of the chip and not the absolute memory reg_offs.
*/
-extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
{
- unsigned long address_to_write;
- address_to_write = chip->chip_base_addr+address;
+ can_ioptr_t address_to_write;
+ address_to_write = chip->chip_base_addr+reg_offs;
chip->write_register(data, address_to_write);
}
-extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
{
- unsigned long address_to_read;
- address_to_read = chip->chip_base_addr+address;
+ can_ioptr_t address_to_read;
+ address_to_read = chip->chip_base_addr+reg_offs;
return chip->read_register(address_to_read);
}
extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned char data, unsigned address)
+ unsigned char data, unsigned reg_offs)
{
- unsigned long address_to_write;
- address_to_write = obj->obj_base_addr+address;
+ can_ioptr_t address_to_write;
+ address_to_write = obj->obj_base_addr+reg_offs;
chip->write_register(data, address_to_write);
}
extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
- unsigned address)
+ unsigned reg_offs)
{
- unsigned long address_to_read;
- address_to_read = obj->obj_base_addr+address;
+ can_ioptr_t address_to_read;
+ address_to_read = obj->obj_base_addr+reg_offs;
return chip->read_register(address_to_read);
}
#endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
-int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base);
+int can_base_addr_fixup(struct candevice_t *candev, can_ioptr_t new_base);
int can_request_io_region(unsigned long start, unsigned long n, const char *name);
void can_release_io_region(unsigned long start, unsigned long n);
int can_request_mem_region(unsigned long start, unsigned long n, const char *name);
int msmcan_init_hw_data(struct candevice_t *candev);
int msmcan_init_chip_data(struct candevice_t *candev, int chipnr);
int msmcan_init_obj_data(struct canchip_t *chip, int objnr);
-void msmcan_write_register(unsigned data, unsigned long address);
-unsigned msmcan_read_register(unsigned long address);
+void msmcan_write_register(unsigned data, can_ioptr_t address);
+unsigned msmcan_read_register(can_ioptr_t address);
int msmcan_program_irq(struct candevice_t *candev);
int ns_dev_request_io(struct candevice_t *candev);
int ns_dev_release_io(struct candevice_t *candev);
int ns_dev_reset(struct candevice_t *candev);
-void ns_dev_write_register(unsigned data, unsigned long address);
-unsigned ns_dev_read_register(unsigned long address);
+void ns_dev_write_register(unsigned data, can_ioptr_t address);
+unsigned ns_dev_read_register(can_ioptr_t address);
int ns_dev_init_obj_data(struct canchip_t *chip, int objnr);
int ns_dev_program_irq(struct candevice_t *candev);
int nsi_init_hw_data(struct candevice_t *candev);
int nsi_init_chip_data(struct candevice_t *candev, int chipnr);
int nsi_init_obj_data(struct canchip_t *chip, int objnr);
-void nsi_write_register(unsigned data, unsigned long address);
-unsigned nsi_read_register(unsigned long address);
+void nsi_write_register(unsigned data, can_ioptr_t address);
+unsigned nsi_read_register(can_ioptr_t address);
int nsi_program_irq(struct candevice_t *candev);
int nsi_canpci_init_hw_data(struct candevice_t *candev);
int nsi_canpci_init_chip_data(struct candevice_t *candev, int chipnr);
int nsi_canpci_init_obj_data(struct canchip_t *chip, int objnr);
-void nsi_canpci_write_register(unsigned data, unsigned long address);
-unsigned nsi_canpci_read_register(unsigned long address);
+void nsi_canpci_write_register(unsigned data, can_ioptr_t address);
+unsigned nsi_canpci_read_register(can_ioptr_t address);
int nsi_canpci_program_irq(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);
+void oscar_write_register(unsigned data, can_ioptr_t address);
+unsigned oscar_read_register(can_ioptr_t address);
int oscar_program_irq(struct candevice_t *candev);
int pci03_init_hw_data(struct candevice_t *candev);
int pci03_init_chip_data(struct candevice_t *candev, int chipnr);
int pci03_init_obj_data(struct canchip_t *chip, int objnr);
-void pci03_write_register(unsigned data, unsigned long address);
-unsigned pci03_read_register(unsigned long address);
+void pci03_write_register(unsigned data, can_ioptr_t address);
+unsigned pci03_read_register(can_ioptr_t address);
int pci03_program_irq(struct candevice_t *candev);
int pcan_dongle_init_hw_data(struct candevice_t *candev);
int pcan_dongle_init_chip_data(struct candevice_t *candev, int chipnr);
int pcan_dongle_init_obj_data(struct canchip_t *chip, int objnr);
-void pcan_dongle_write_register(unsigned data, unsigned long address);
-unsigned pcan_dongle_read_register(unsigned long address);
+void pcan_dongle_write_register(unsigned data, can_ioptr_t address);
+unsigned pcan_dongle_read_register(can_ioptr_t address);
int pcan_dongle_program_irq(struct candevice_t *candev);
#endif // __PCAN_DONGLE_H__
int pccan_init_hw_data(struct candevice_t *candev);
int pccan_init_chip_data(struct candevice_t *candev, int chipnr);
int pccan_init_obj_data(struct canchip_t *chip, int objnr);
-void pccan_write_register(unsigned data, unsigned long address);
-unsigned pccan_read_register(unsigned long address);
+void pccan_write_register(unsigned data, can_ioptr_t address);
+unsigned pccan_read_register(can_ioptr_t address);
int pccan_program_irq(struct candevice_t *candev);
int pcccan_init_hw_data(struct candevice_t *candev);
int pcccan_init_chip_data(struct candevice_t *candev, int chipnr);
int pcccan_init_obj_data(struct canchip_t *chip, int objnr);
-void pcccan_write_register(unsigned data, unsigned long address);
-unsigned pcccan_read_register(unsigned long address);
+void pcccan_write_register(unsigned data, can_ioptr_t address);
+unsigned pcccan_read_register(can_ioptr_t address);
int pcccan_program_irq(struct candevice_t *candev);
int pcm3680_init_hw_data(struct candevice_t *candev);
int pcm3680_init_chip_data(struct candevice_t *candev, int chipnr);
int pcm3680_init_obj_data(struct canchip_t *chip, int objnr);
-void pcm3680_write_register(unsigned data, unsigned long address);
-unsigned pcm3680_read_register(unsigned long address);
+void pcm3680_write_register(unsigned data, can_ioptr_t address);
+unsigned pcm3680_read_register(can_ioptr_t address);
int pcm3680_program_irq(struct candevice_t *candev);
int pikronisa_init_chip_data(struct candevice_t *candev, int chipnr);
int pikronisa_init_obj_data(struct canchip_t *chip, int objnr);
int pikronisa_program_irq(struct candevice_t *candev);
-void pikronisa_write_register(unsigned data, unsigned long address);
-unsigned pikronisa_read_register(unsigned long address);
+void pikronisa_write_register(unsigned data, can_ioptr_t address);
+unsigned pikronisa_read_register(can_ioptr_t address);
int pip_init_hw_data(struct candevice_t *candev);
int pip_init_chip_data(struct candevice_t *candev, int chipnr);
int pip_init_obj_data(struct canchip_t *chip, int objnr);
-void pip_write_register(unsigned data, unsigned long address);
-unsigned pip_read_register(unsigned long address);
+void pip_write_register(unsigned data, can_ioptr_t address);
+unsigned pip_read_register(can_ioptr_t address);
int pip_program_irq(struct candevice_t *candev);
--- /dev/null
+/* sh7760.h
+ * Header file for the Linux CAN-bus driver.
+ * This software is released under the GPL-License.
+ */
+
+#define NR_82527 0
+#define NR_SJA1000 0
+#define NR_ALL 2
+
+#define SH7760_CAN_IRQ 56
+#define SH7760_CAN_CHIP_OFFSET 0x10000
+#define SH7760_CAN_CLOCK 33333330 /* 33.3 MHz */
+
+#define IO_RANGE 0x10000
+
+/* static CAN_DEFINE_SPINLOCK(sh7760_port_lock); */
+
+
+
+int sh7760_request_io(struct candevice_t *candev);
+int sh7760_release_io(struct candevice_t *candev);
+int sh7760_reset(struct candevice_t *candev);
+int sh7760_init_hw_data(struct candevice_t *candev);
+int sh7760_init_chip_data(struct candevice_t *candev, int chipnr);
+int sh7760_init_obj_data(struct canchip_t *chip, int objnr);
+int sh7760_program_irq(struct candevice_t *candev);
+void sh7760_write_register(unsigned data, can_ioptr_t address);
+unsigned sh7760_read_register(can_ioptr_t address);
+
int smartcan_init_hw_data(struct candevice_t *candev);
int smartcan_init_chip_data(struct candevice_t *candev, int chipnr);
int smartcan_init_obj_data(struct canchip_t *chip, int objnr);
-void smartcan_write_register(unsigned data, unsigned long address);
-unsigned smartcan_read_register(unsigned long address);
+void smartcan_write_register(unsigned data, can_ioptr_t address);
+unsigned smartcan_read_register(can_ioptr_t address);
int ssv_init_hw_data(struct candevice_t *candev);
int ssv_init_chip_data(struct candevice_t *candev, int chipnr);
int ssv_init_obj_data(struct canchip_t *chip, int objnr);
-void ssv_write_register(unsigned data, unsigned long address);
-unsigned ssv_read_register(unsigned long address);
+void ssv_write_register(unsigned data, can_ioptr_t address);
+unsigned ssv_read_register(can_ioptr_t address);
int ssv_program_irq(struct candevice_t *candev);
int template_init_hw_data(struct candevice_t *candev);
int template_init_chip_data(struct candevice_t *candev, int chipnr);
int template_init_obj_data(struct canchip_t *chip, int objnr);
-void template_write_register(unsigned data, unsigned long address);
-unsigned template_read_register(unsigned long address);
+void template_write_register(unsigned data, can_ioptr_t address);
+unsigned template_read_register(can_ioptr_t address);
int template_program_irq(struct candevice_t *candev);
int tscan1_init_hw_data(struct candevice_t *candev);
int tscan1_init_chip_data(struct candevice_t *candev, int chipnr);
int tscan1_init_obj_data(struct canchip_t *chip, int objnr);
-void tscan1_write_register(unsigned data, unsigned long address);
-unsigned tscan1_read_register(unsigned long address);
+void tscan1_write_register(unsigned data, can_ioptr_t address);
+unsigned tscan1_read_register(can_ioptr_t address);
int tscan1_program_irq(struct candevice_t *candev);
unsigned long tscan1_getmappedaddr(unsigned long address);
# Generic directory or leaf node makefile for OCERA make framework
ifndef MAKERULES_DIR
-MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
endif
ifeq ($(MAKERULES_DIR),)
all : default
.DEFAULT::
@echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
-else
+else
include $(MAKERULES_DIR)/Makefile.rules
endif
lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 ems_cpcpci \
- pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan pikronisa eb8245 \
- kv_pcican msmcan oscar adlink7841 unican virtual template usbcan
+ pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan gensja1000io pikronisa eb8245 \
+ kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican usbcan virtual template
-lincan_morecards_NAMES = hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 nsi_canpci
+lincan_morecards_NAMES = hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 nsi_canpci sh7760
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
rtlinux_INCLUDES = -I $(srcdir)/../include -I .
kernel_INCLUDES = -I $(srcdir)/../include -I .
#kernel_INCLUDES += -DCAN_DEBUG
-kernel_INCLUDES += -DWITH_DEVFS_FS -DKBUILD_MODNAME
+kernel_INCLUDES += -DWITH_DEVFS_FS
lincan_cards_SOURCES = $(lincan_cards_SELECTED:%=%.c)
lincan_cards_SOURCES += ipci165_fw.c kthread.c
endif
+ifeq ($(CONFIG_OC_LINCAN_CARD_sh7760),y)
+lincan_cards_SOURCES += sh7760.c
+endif
+
ifeq ($(CONFIG_OC_LINCAN_CARD_usbcan),y)
lincan_cards_SOURCES += kthread.c
endif
lincan_SOURCES = can_queue.c can_quekern.c main.c modparms.c \
devcommon.c setup.c finish.c irq.c sysdep_lnx.c boardlist.c \
- sja1000p.c sja1000.c i82527.c \
+ sja1000p.c sja1000.c i82527.c hcan2.c \
open.c close.c read.c write.c ioctl.c select.c fasync.c \
proc.c ioctl_query.c ioctl_remote.c \
$(lincan_cards_SOURCES) $(lincan_rtl_SOURCES)
#KERNEL_LOCATION=/usr/src/linux-2.2.19
#KERNEL_LOCATION=/usr/src/linux-2.2.22
#KERNEL_LOCATION=/usr/src/linux-2.6.0
+#KERNEL_LOCATION=/usr/src/linux-2.6.18-rc4/_build/arm
#KERNEL_LOCATION=/home/cvs/ocera/ocera-build/kernel/linux
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 adlink7841 oscar
+ unican unican_cl2 ems_cpcpci adlink7841 oscar \
+ pcan_pci esdpci200
# hms30c7202_can c_can c_can_irq tscan1
# pcan_dongle
KERNEL_VERSION := $(shell awk -F\" '/REL/ {print $$2}' \
$(KERNEL_LOCATION)/include/linux/version.h | awk -F\- '{print $$1}')
+ifeq ($(KERNEL_VERSION),)
+KERNEL_VERSION=$(shell grep UTS_RELEASE ${KERNEL_LOCATION}/include/linux/utsrelease.h | \
+ sed 's/[^"]*"\(.*\)\{1\}"/\1/')
+endif
+
+#$(warning KERNEL_VERSION = $(KERNEL_VERSION))
+
PROC_FS := $(shell awk -F\ '/PROC_FS/ {print $$3}' \
$(KERNEL_LOCATION)/include/linux/autoconf.h)
}
-void adlink7841_write_register(unsigned data, unsigned long address)
+void adlink7841_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
-unsigned adlink7841_read_register(unsigned long address)
+unsigned adlink7841_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
int adlink7841_reset(struct candevice_t *candev)
sja1000p_fill_chipspecops(candev->chip[chipnr]);
candev->chip[chipnr]->chip_base_addr=
- candev->io_addr+chipnr*ADLINK7841_BYTES_PER_CIRCUIT;
+ can_ioport2ioptr(candev->io_addr+chipnr*ADLINK7841_BYTES_PER_CIRCUIT);
candev->chip[chipnr]->flags = 0;
candev->chip[chipnr]->int_cpu_reg = 0;
candev->chip[chipnr]->int_clk_reg = 0;
int aim104_init_chip_data(struct candevice_t *candev, int chipnr)
{
sja1000_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->flags = 0;
candev->chip[chipnr]->sja_cdr_reg = 0x08;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void aim104_write_register(unsigned data, unsigned long address)
+void aim104_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned aim104_read_register(unsigned long address)
+unsigned aim104_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
/* !!! Don't change this function !!! */
#define __NO_VERSION__
#include <linux/module.h>
-long clock_freq;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-MODULE_PARM(clock_freq,"i");
-#else
-module_param(clock_freq,int,0);
-#endif
+#define CAN_BFAD_CLOCKFREQ 20000000
/* cli and sti are not allowed in 2.5.5x SMP kernels */
#ifdef WINDOWED_ACCESS
#define IO_RANGE 0x100
#endif
-unsigned bfadcan_read_register(unsigned long address);
-void bfadcan_write_register(unsigned data, unsigned long address);
+unsigned bfadcan_read_register(can_ioptr_t address);
+void bfadcan_write_register(unsigned data, can_ioptr_t address);
/**
{
unsigned int id1, id2;
sja1000p_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
- candev->chip[chipnr]->clock = clock_freq;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
+ if(candev->chip[chipnr]->clock<=0)
+ candev->chip[chipnr]->clock = CAN_BFAD_CLOCKFREQ;
candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
- id1 = inb(0xe284);
- id2 = inb(0xe285);
+ id1 = can_inb(0xe284);
+ id2 = can_inb(0xe285);
CANMSG("can driver ver lincan-0.3, at %04lx, CPLD v%d.%d.%d.%d\n",
- candev->chip[chipnr]->chip_base_addr,
- id1>>4, id1&0x0f, id2>>4, id2&0x0f);
+ can_ioptr2ulong(candev->chip[chipnr]->chip_base_addr),
+ id1>>4, id1&0x0f, id2>>4, id2&0x0f);
return 0;
* Return Value: The function does not return a value
* File: src/bfadcan.c
*/
-void bfadcan_write_register(unsigned data, unsigned long address)
+void bfadcan_write_register(unsigned data, can_ioptr_t address)
{
#ifdef WINDOWED_ACCESS
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&bfadcan_win_lock,flags);
- outb(address&0x00ff,0x200);
- outb(data, 0x201);
+ can_outb(can_ioptr2ulong(address)&0x00ff,0x200);
+ can_outb(data, 0x201);
can_spin_unlock_irqrestore(&bfadcan_win_lock,flags);
#else
- outb(data,address);
+ can_outb(data,address);
#endif
}
* Return Value: The function returns the value stored in @address
* File: src/bfadcan.c
*/
-unsigned bfadcan_read_register(unsigned long address)
+unsigned bfadcan_read_register(can_ioptr_t address)
{
#ifdef WINDOWED_ACCESS
can_spin_irqflags_t flags;
int ret;
can_spin_lock_irqsave(&bfadcan_win_lock,flags);
- outb(address&0x00ff,0x200);
- ret = inb(0x201);
+ can_outb(can_ioptr2ulong(address)&0x00ff,0x200);
+ ret = can_inb(0x201);
can_spin_unlock_irqrestore(&bfadcan_win_lock,flags);
return ret;
#else
- return inb(address);
+ return can_inb(address);
#endif
}
extern int ssv_register(struct hwspecops_t *hwspecops);
extern int bfadcan_register(struct hwspecops_t *hwspecops);
extern int pikronisa_register(struct hwspecops_t *hwspecops);
+extern int gensja1000io_register(struct hwspecops_t *hwspecops);
extern int pimx1_register(struct hwspecops_t *hwspecops);
extern int msmcan_register(struct hwspecops_t *hwspecops);
extern int unican_register(struct hwspecops_t *hwspecops);
extern int hms30c7202_register(struct hwspecops_t *hwspecops);
extern int nsi_canpci_register(struct hwspecops_t *hwspecops);
extern int usbcan_register(struct hwspecops_t *hwspecops);
+extern int pcan_pci_register(struct hwspecops_t *hwspecops);
+extern int esdpci200_register(struct hwspecops_t *hwspecops);
+extern int sh7760_register(struct hwspecops_t *hwspecops);
const struct boardtype_t can_boardtypes[]={
#ifdef CONFIG_OC_LINCAN_CARD_template
#ifdef CONFIG_OC_LINCAN_CARD_pikronisa
{"pikronisa", pikronisa_register, 1},
#endif
+ #ifdef CONFIG_OC_LINCAN_CARD_gensja1000io
+ {"gensja1000io", gensja1000io_register, 1},
+ #endif
#ifdef CONFIG_OC_LINCAN_CARD_pimx1
{"pimx1", pimx1_register, 0},
#endif
#if defined(CONFIG_OC_LINCAN_CARD_adlink7841)
{"adlink7841", adlink7841_register, 0},
#endif
+ #if defined(CONFIG_OC_LINCAN_CARD_esdpci200)
+ {"esdpci200", esdpci200_register, 0},
+ #endif
#if defined(CONFIG_OC_LINCAN_CARD_tscan1)
{"tscan1", tscan1_register, 1},
{"ts7kv", ts7kv_register, 1},
#if defined(CONFIG_OC_LINCAN_CARD_ns_dev_can)
{"ns_dev", ns_dev_register, 1},
#endif
+ #if defined(CONFIG_OC_LINCAN_CARD_sh7760)
+ {"sh7760", sh7760_register, 2},
+ #endif
#if defined(CONFIG_OC_LINCAN_CARD_hms30c7202_can)
{"hms30c7202", hms30c7202_register, 1},
#endif
#if defined(CONFIG_OC_LINCAN_CARD_nsi_canpci)&&defined(CAN_ENABLE_PCI_SUPPORT)
{"nsicanpci", nsi_canpci_register, 1},
#endif
+ #if defined(CONFIG_OC_LINCAN_CARD_pcan_pci)&&defined(CAN_ENABLE_PCI_SUPPORT)
+ {"pcan_pci", pcan_pci_register, 0},
+ #endif
#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
{"usbcan", usbcan_register, 0},
#endif
return -1;
if (pchip->baudrate == 0)
- pchip->baudrate = 1000;
+ pchip->baudrate = 1000000;
if (c_can_baud_rate
- (pchip, pchip->baudrate * 1000, pchip->clock, 0, 75, 0)) {
+ (pchip, pchip->baudrate, pchip->clock, 0, 75, 0)) {
CANMSG("Error configuring baud rate\n");
return -ENODEV;
}
unsigned short comreg = 0;
comreg = c_can_read_reg_w(pchip, CCIF1CR);
- while ((comreg & IFXCR_BUSY) && (i <= 10)) {
- udelay(100); //100 microseconds
+ while ((comreg & IFXCR_BUSY) && (i <= 100)) {
+ udelay(1); //1 microseconds
i++;
comreg = c_can_read_reg_w(pchip, CCIF1CR);
}
unsigned short comreg = 0;
comreg = c_can_read_reg_w(pchip, CCIF2CR);
- while ((comreg & IFXCR_BUSY) && (i <= 10)) {
- udelay(100); //100 microseconds
+ while ((comreg & IFXCR_BUSY) && (i <= 100)) {
+ udelay(1); //1 microseconds
i++;
comreg = c_can_read_reg_w(pchip, CCIF2CR);
}
if (c_can_if1_busycheck(pmsgobj->hostchip))
return -ENODEV;
+ //set indication, that mask is used
+ tempreg = c_can_read_reg_w(pmsgobj->hostchip, CCIF1DMC);
+ c_can_write_reg_w(pmsgobj->hostchip, tempreg | IFXMC_UMASK,
+ CCIF1DMC);
+
//writing acceptance mask for extended or standart mode
if (can_msgobj_test_fl(pmsgobj, RX_MODE_EXT)) {
if (usedirbit)
((mask << 2) & 0x1FFC), CCIF1M2);
c_can_write_reg_w(pmsgobj->hostchip, 0, CCIF1M1);
}
+
//seting Message Valid Bit to one
tempreg = c_can_read_reg_w(pmsgobj->hostchip, CCIF1A2);
c_can_write_reg_w(pmsgobj->hostchip, tempreg | IFXARB2_MVAL, CCIF1A2);
if (c_can_if1_busycheck(pchip)) ;
if (c_can_read_reg_w(pchip, CCIF1A2) &
IFXARB2_DIR) {
+ DEBUGMSG("c_can_irq_write_handler idxobj=%d, msgid=%d\n",idxobj,msgid);
spin_unlock(&c_can_if1lock);
c_can_irq_write_handler(pchip, idxobj);
int cc104_init_chip_data(struct candevice_t *candev, int chipnr)
{
sja1000_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->flags = 0;
candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void cc104_write_register(unsigned data, unsigned long address)
+void cc104_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned cc104_read_register(unsigned long address)
+unsigned cc104_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
/* !!! Don't change this function !!! */
*/
int eb8245_request_io(struct candevice_t *candev)
{
- int remap_addr;
+ can_ioptr_t remap_addr;
if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - eb8245")) {
CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
return -ENODEV;
}
- if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return -ENODEV;
* Return Value: The function does not return a value
* File: src/eb8245.c
*/
-void eb8245_write_register(unsigned data, unsigned long address)
+void eb8245_write_register(unsigned data, can_ioptr_t address)
{
/*DEBUGMSG("eb8245_write_register: addr=0x%lx data=0x%x",
address,data);*/
- writeb(data,address);
+ can_writeb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/eb8245.c
*/
-unsigned eb8245_read_register(unsigned long address)
+unsigned eb8245_read_register(can_ioptr_t address)
{
- return readb(address);
+ return can_readb(address);
}
/* !!! Don't change this function !!! */
void ems_cpcpci_disconnect_irq(struct candevice_t *candev)
{
/* Disable interrupts from card */
- writel(0, candev->dev_base_addr + PITA2_ICR);
+ can_writel(0, candev->aux_base_addr + PITA2_ICR);
}
void ems_cpcpci_connect_irq(struct candevice_t *candev)
{
/* Enable interrupts from card */
- writel(PITA2_ICR_INT0_En, candev->dev_base_addr + PITA2_ICR);
+ can_writel(PITA2_ICR_INT0_En, candev->aux_base_addr + PITA2_ICR);
}
#endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
pita2_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
- if (!(candev->dev_base_addr = (long) ioremap(pita2_addr,
+ if (!(candev->aux_base_addr = ioremap(pita2_addr,
pci_resource_len(candev->sysdevptr.pcidev,0)))) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", pita2_addr);
goto error_ioremap_pita2;
}
io_addr=pci_resource_start(candev->sysdevptr.pcidev,1);;
- if (!(candev->io_addr = (long) ioremap(io_addr,
+ if (!(candev->dev_base_addr = ioremap(io_addr,
pci_resource_len(candev->sysdevptr.pcidev,1)))) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
goto error_ioremap_io;
}
- candev->res_addr=candev->io_addr;
+ candev->io_addr=io_addr;
+ candev->res_addr=pita2_addr;
/*
* this is redundant with chip initialization, but remap address
for(i=0;i<candev->nr_all_chips;i++) {
struct canchip_t *chip=candev->chip[i];
if(!chip) continue;
- chip->chip_base_addr = candev->io_addr+
+ chip->chip_base_addr = candev->dev_base_addr+
0x400 + i*EMS_CPCPCI_BYTES_PER_CIRCUIT;
if(!chip->msgobj[0]) continue;
chip->msgobj[0]->obj_base_addr=chip->chip_base_addr;
}
/* Configure PITA-2 parallel interface */
- writel(PITA2_MISC_CONFIG, candev->dev_base_addr + PITA2_MISC);
+ can_writel(PITA2_MISC_CONFIG, candev->aux_base_addr + PITA2_MISC);
ems_cpcpci_disconnect_irq(candev);
return 0;
error_ioremap_io:
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->aux_base_addr);
error_ioremap_pita2:
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 1);
{
ems_cpcpci_disconnect_irq(candev);
- iounmap((void*)candev->io_addr);
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
+ iounmap(candev->aux_base_addr);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 1);
pci_release_region(candev->sysdevptr.pcidev, 0);
}
-void ems_cpcpci_write_register(unsigned data, unsigned long address)
+void ems_cpcpci_write_register(unsigned data, can_ioptr_t address)
{
- address += ((address&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1))
- *(EMS_CPCPCI_BYTES_PER_REG-1));
- writeb(data,address);
+ address += ((can_ioptr2ulong(address)&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1))
+ *(EMS_CPCPCI_BYTES_PER_REG-1));
+ can_writeb(data,address);
}
-unsigned ems_cpcpci_read_register(unsigned long address)
+unsigned ems_cpcpci_read_register(can_ioptr_t address)
{
- address += ((address&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1))
- *(EMS_CPCPCI_BYTES_PER_REG-1));
- return readb(address);
+ address += ((can_ioptr2ulong(address)&(EMS_CPCPCI_BYTES_PER_CIRCUIT-1))
+ *(EMS_CPCPCI_BYTES_PER_REG-1));
+ return can_readb(address);
}
int ems_cpcpci_irq_handler(int irq, struct canchip_t *chip)
unsigned long icr;
int test_irq_again;
- icr=readl(candev->dev_base_addr + PITA2_ICR);
+ icr=can_readl(candev->aux_base_addr + PITA2_ICR);
if(!(icr & PITA2_ICR_INT0)) return CANCHIP_IRQ_NONE;
/* correct way to handle interrupts from all chips connected to the one PITA-2 */
do {
- writel(PITA2_ICR_INT0_En | PITA2_ICR_INT0, candev->dev_base_addr + PITA2_ICR);
+ can_writel(PITA2_ICR_INT0_En | PITA2_ICR_INT0, candev->aux_base_addr + PITA2_ICR);
test_irq_again=0;
for(i=0;i<candev->nr_all_chips;i++){
chip=candev->chip[i];
if(sja1000p_irq_handler(irq, chip))
test_irq_again=1;
}
- icr=readl(candev->dev_base_addr + PITA2_ICR);
+ icr=can_readl(candev->aux_base_addr + PITA2_ICR);
} while((icr & PITA2_ICR_INT0)||test_irq_again);
return CANCHIP_IRQ_HANDLED;
}
if(ems_cpcpci_request_io(candev)<0)
return -ENODEV;
- /*** candev->dev_base_addr=pci_resource_start(pcidev,0); ***/
+ /*** candev->aux_base_addr=pci_resource_start(pcidev,0); ***/
/* some control registers */
- /*** candev->io_addr=pci_resource_start(pcidev,1); ***/
+ /*** candev->dev_base_addr=pci_resource_start(pcidev,1); ***/
/* 0 more EMS control registers
* 0x400 the first SJA1000
* 0x600 the second SJA1000
for(l=0,i=0;i<4;i++){
l<<=8;
- l|=readb(candev->io_addr + i*4);
+ l|=can_readb(candev->dev_base_addr + i*4);
}
- i=readb(candev->io_addr + i*5);
+ i=can_readb(candev->dev_base_addr + i*5);
CANMSG("EMS CPC-PCI check value %04lx, ID %d\n", l, i);
candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
- candev->chip[chipnr]->chip_base_addr = candev->io_addr+
+ candev->chip[chipnr]->chip_base_addr = candev->dev_base_addr+
0x400 + chipnr*EMS_CPCPCI_BYTES_PER_CIRCUIT;
candev->chip[chipnr]->flags = 0;
candev->chip[chipnr]->int_cpu_reg = 0;
--- /dev/null
+/* esdpci200.c - support for ESD Electronics' CAN/PCI-200 cards
+ * Linux CAN-bus device driver.
+ * The card support was added by Manuel Bessler <m.bessler@gmx.net>
+ * Based on adlink7841.c and nsi_canpci.c
+ * This software is released under the GPL-License.
+ * Version lincan-0.3.3
+ */
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/sja1000p.h"
+
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+ #define ioread32 can_readl
+ #define iowrite32 can_writel
+ #define ioread8 can_readb
+ #define iowrite8 can_writeb
+ #define wmb()
+ #define rmb()
+#else
+#endif
+
+#define ESDPCI200_PCI_VENDOR_ID 0x10B5
+#define ESDPCI200_PCI_PRODUCT_ID 0x9050
+
+/* PCI to local bus bridge PLX9052 */
+
+#define PLX9052_INTCSR 0x4c /* interrupt control register */
+#define PLX9052_CNTRL 0x50 /* control register, for software reset */
+
+/* The ESD PCI/200 uses (per default) just LINTi1 (Local Interrupt 1)
+ * on the PLX. This means that both CAN channels' (SJA1000's) /INT pins
+ * are OR'ed to the LINTi1 pin (actually ANDed in the 74HC08 since both
+ * the SJA1000's /INT pins and the LINTi1 pin are active low).
+ *
+ * The board does have an option to route the 2nd channel to LINTi2,
+ * apparently just one or two resistors need to be added.
+ *
+ * LINTi2 is floating per default, so don't set its interrupt enable flag
+ * 'PLX9052_INTCSR_LI2EN', it'll just interrupt all the time.
+ */
+#define PLX9052_INTCSR_LI1EN 0x00000001 /* Local Interrupt 1 enable */
+#define PLX9052_INTCSR_LI1S 0x00000004 /* Local Interrupt 1 status */
+#define PLX9052_INTCSR_LI2EN 0x00000008 /* Local Interrupt 2 enable */
+#define PLX9052_INTCSR_LI2S 0x00000020 /* Local Interrupt 2 status */
+#define PLX9052_INTCSR_PIEN 0x00000040 /* PCI Interrupt enable */
+
+#define PLX9052_CNTRL_SWRESET 0x40000000 /* PCI Adapter Software Reset to Local Bus */
+
+#define IO_RANGE 0x100
+
+// Standard value: Pushpull (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1)
+#define ESDPCI200_OCR_DEFAULT_STD 0xFA
+/* Setting the OCR register to 0xFA is a good idea.
+ This means normal output mode , push-pull and the correct polarity. */
+
+
+void esdpci200_pci_soft_reset(struct candevice_t *candev)
+{
+ unsigned long reg_reset;
+ reg_reset = inl( candev->res_addr+PLX9052_CNTRL);
+ reg_reset &= ~(PLX9052_CNTRL_SWRESET);
+ rmb();
+ /* PCI Adapter Software Reset plus reset local bus */
+ outl( (reg_reset | PLX9052_CNTRL_SWRESET ), candev->res_addr+PLX9052_CNTRL);
+ wmb();
+ udelay(2500);
+ outl(reg_reset, candev->res_addr+PLX9052_CNTRL);
+ wmb();
+ udelay(2500);
+}
+
+void esdpci200_disconnect_irq(struct candevice_t *candev)
+{
+ /* writing 0x0 into the PLX's INTCSR register disables interrupts */
+ /* 0x0 is also the value in the register after a power-on reset */
+ outl(0x0, candev->res_addr + PLX9052_INTCSR);
+ DEBUGMSG("disabled interrupts on the PLX\n");
+}
+
+void esdpci200_connect_irq(struct candevice_t *candev)
+{
+ /* enable interrupts for the SJA1000's, enable PCI interrupts */
+ outl( PLX9052_INTCSR_LI1EN | PLX9052_INTCSR_PIEN,
+ candev->res_addr+PLX9052_INTCSR);
+ DEBUGMSG("enabled interrupts on the PLX\n");
+}
+
+int esdpci200_irq_handler(int irq, struct canchip_t *chip)
+{
+ int retcode;
+ unsigned long it_reg;
+ struct candevice_t *candev;
+ candev = chip->hostdevice;
+ retcode = CANCHIP_IRQ_NONE;
+ //DEBUGMSG("Starting to handle an IRQ\n");
+ it_reg = inl(candev->res_addr+PLX9052_INTCSR);
+ rmb();
+ if((it_reg & (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) )
+ == (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) )
+ { /*interrupt enabled and active */
+ int chipnum;
+ for(chipnum=0; chipnum < candev->nr_sja1000_chips; chipnum++)
+ {
+ if(sja1000p_irq_handler(irq, candev->chip[chipnum]) == CANCHIP_IRQ_NONE)
+ { /* since both chips use the same IRQ and the same LINTi on the PLX,
+ we need manually do 'interrupt sharing' on the boardlevel
+ by checking all chips one-by-one */
+ continue;
+ }
+ else
+ {
+ retcode=CANCHIP_IRQ_HANDLED;
+ }
+ }
+ if( retcode != CANCHIP_IRQ_HANDLED )
+ {/* None of the chips felt they were responsible for this IRQ...
+ so it appears we have problems with the IRQ */
+ it_reg &= ~(PLX9052_INTCSR_LI1EN);
+ //Either we have a problem with IRQ malfunctions, or our IRQ is shared with some other device.
+ //
+ //not actually disabled, unless outl() below is uncommented
+ //outl(it_reg,(void*)(candev->res_addr+PLX9052_INTCSR));
+ //CANMSG("CAN Interrupt disabled due to malfunction\n");
+ }
+ }
+ return retcode;
+}
+
+int esdpci200_request_io(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_ioptr_t remap_addr;
+ unsigned long bar2_addr;
+
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ if(pci_request_region(pcidev, 0, "esdpci200_plx9050") != 0){
+ CANMSG("Request of esdpci200_plx9050 range failed\n");
+ return -ENODEV;
+ }else if(pci_request_region(pcidev, 1, "esdpci200_io") != 0){
+ CANMSG("Request of esdpci200_io range failed\n");
+ pci_release_region(pcidev, 0);
+ return -ENODEV;
+ }else if(pci_request_region(pcidev, 2, "esdpci200_sja") != 0){
+ CANMSG("Request of esdpci200_sja range failed\n");
+ pci_release_region(pcidev, 1);
+ pci_release_region(pcidev, 0);
+ return -ENODEV;
+ }
+ #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ if(pci_request_regions(pcidev, "esdpci200") != 0){
+ CANMSG("Request of esdpci200_plx9050 regions failed\n");
+ return -ENODEV;
+ }
+ #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+
+
+ /* ioports, PLX local configuration registers */
+ candev->res_addr=pci_resource_start(pcidev,1);
+ /*MEM window for SJA1000 chips*/
+ bar2_addr = pci_resource_start(pcidev,2);
+ candev->io_addr = bar2_addr;
+ if( ! (remap_addr=ioremap(bar2_addr,
+ pci_resource_len(pcidev,2)))) /*MEM window for SJA1000 chips*/
+ {
+ CANMSG("Unable to access I/O memory at: 0x%lx\n", (unsigned long)bar2_addr);
+ goto ioremap_error;
+ }
+
+ can_base_addr_fixup(candev, remap_addr);
+ CANMSG("esdpci200_sja IO-memory: 0x%lx - 0x%lx (VMA 0x%lx)\n",
+ (unsigned long) bar2_addr,
+ (unsigned long) bar2_addr + pci_resource_len(pcidev,2) - 1,
+ (long) remap_addr);
+
+ return 0;
+
+ ioremap_error:
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ pci_release_region(pcidev, 2);
+ pci_release_region(pcidev, 1);
+ pci_release_region(pcidev, 0);
+#else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ pci_release_regions(pcidev);
+#endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ return -ENODEV;
+}
+
+int esdpci200_release_io(struct candevice_t *candev)
+{
+ esdpci200_disconnect_irq(candev);
+ esdpci200_pci_soft_reset(candev);
+
+ iounmap(candev->dev_base_addr);
+ #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 esdpci200_write_register(unsigned data, can_ioptr_t address)
+{
+ iowrite8((u8)data,(void*)address);
+ wmb();
+}
+
+unsigned esdpci200_read_register(can_ioptr_t address)
+{
+ return ioread8((void*)address);
+}
+
+int esdpci200_reset(struct candevice_t *candev)
+{
+ int i=0,chip_nr;
+ struct canchip_t *chip;
+ unsigned cdr;
+ DEBUGMSG("Resetting esdpci200 hardware ...\n");
+
+ esdpci200_disconnect_irq(candev);
+ esdpci200_pci_soft_reset(candev);
+
+ for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
+ if(!candev->chip[chip_nr]) continue;
+ chip=candev->chip[chip_nr];
+
+ esdpci200_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
+ udelay(1000);
+
+ cdr=esdpci200_read_register(chip->chip_base_addr+SJACDR);
+ esdpci200_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ esdpci200_write_register(0, chip->chip_base_addr+SJAIER);
+
+ i=20;
+ esdpci200_write_register(0, chip->chip_base_addr+SJAMOD);
+ while (esdpci200_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
+ if(!i--) return -ENODEV;
+ udelay(1000);
+ esdpci200_write_register(0, chip->chip_base_addr+SJAMOD);
+ }
+
+ cdr=esdpci200_read_register(chip->chip_base_addr+SJACDR);
+ esdpci200_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ esdpci200_write_register(0, chip->chip_base_addr+SJAIER);
+
+ esdpci200_read_register(chip->chip_base_addr+SJAIR);
+ }
+
+
+ esdpci200_connect_irq(candev);
+
+ return 0;
+}
+
+int esdpci200_init_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = NULL;
+
+ do {
+ pcidev = pci_find_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID, pcidev);
+ if(pcidev == NULL) return -ENODEV;
+ } while(can_check_dev_taken(pcidev));
+
+ if (pci_enable_device (pcidev)){
+ printk(KERN_CRIT "Setup of ESDPCI200 failed\n");
+ return -EIO;
+ }
+ candev->sysdevptr.pcidev=pcidev;
+
+ can_spin_lock_init(&candev->device_lock);
+
+ if(!(pci_resource_flags(pcidev, 0)&IORESOURCE_MEM))
+ {
+ printk(KERN_CRIT "PCI200 region %d is not MEM\n",0);
+ return -EIO;
+ }
+ if(!(pci_resource_flags(pcidev, 1)&IORESOURCE_IO))
+ {
+ printk(KERN_CRIT "PCI200 region %d is not IO\n",1);
+ return -EIO;
+ }
+
+ if(!(pci_resource_flags(pcidev,2)&IORESOURCE_MEM))
+ {
+ printk(KERN_CRIT "PCI200 region %d is not MEM\n",2);
+ return -EIO;
+ }
+
+ /* Reset/control field - used to store port of PLX9052 control region */
+ candev->res_addr = pci_resource_start(pcidev,1);;
+
+ /* Physical address of SJA1000 window, stored for debugging only */
+ candev->io_addr = pci_resource_start(pcidev,2);
+
+ candev->aux_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
+ candev->dev_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
+ /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
+
+ candev->nr_82527_chips=0;
+ candev->nr_sja1000_chips=2;
+ candev->nr_all_chips=2;
+
+ return 0;
+}
+
+int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+
+ if(candev->sysdevptr.pcidev==NULL)
+ return -ENODEV;
+
+ CANMSG("initializing esdpci200 chip operations\n");
+
+
+ sja1000p_fill_chipspecops(candev->chip[chipnr]);
+ candev->chip[chipnr]->chip_base_addr=candev->dev_base_addr + chipnr * IO_RANGE;
+
+ candev->chip[chipnr]->chipspecops->irq_handler=esdpci200_irq_handler;
+
+ candev->chip[chipnr]->flags = 0;
+ candev->chip[chipnr]->int_cpu_reg = 0; /* i82527 specific */
+ candev->chip[chipnr]->int_clk_reg = 0; /* i82527 specific */
+ candev->chip[chipnr]->int_bus_reg = 0; /* i82527 specific */
+ candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF; /* hardware specific options for the Clock Divider register */
+ candev->chip[chipnr]->sja_ocr_reg = ESDPCI200_OCR_DEFAULT_STD; /* hardware specific options for the Output Control register */
+ candev->chip[chipnr]->clock = 16000000;
+ candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
+ candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
+ if( chipnr > 0 ) /* only one IRQ used for both channels.
+ CHIP_IRQ_CUSTOM req'd for RTAI, since
+ registering two handlers for the same IRQ
+ returns an error */
+ candev->chip[chipnr]->flags |= CHIP_IRQ_CUSTOM;
+
+ return 0;
+}
+
+int esdpci200_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+ return 0;
+}
+
+int esdpci200_program_irq(struct candevice_t *candev)
+{
+
+ return 0;
+}
+
+int esdpci200_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = esdpci200_request_io;
+ hwspecops->release_io = esdpci200_release_io;
+ hwspecops->reset = esdpci200_reset;
+ hwspecops->init_hw_data = esdpci200_init_hw_data;
+ hwspecops->init_chip_data = esdpci200_init_chip_data;
+ hwspecops->init_obj_data = esdpci200_init_obj_data;
+ hwspecops->write_register = esdpci200_write_register;
+ hwspecops->read_register = esdpci200_read_register;
+ hwspecops->program_irq = esdpci200_program_irq;
+ return 0;
+}
+
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
--- /dev/null
+/* gensja1000io.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
+ */
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/gensja1000io.h"
+#include "../include/sja1000p.h"
+
+/*
+ * IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ */
+#define IO_RANGE 0x20
+
+/**
+ * gensja1000io_request_io: - reserve io or memory range for can board
+ * @candev: pointer to candevice/board which asks for io. Field @io_addr
+ * of @candev is used in most cases to define start of the range
+ *
+ * The function gensja1000io_request_io() is used to reserve the io-memory. If your
+ * hardware uses a dedicated memory range as hardware control registers you
+ * will have to add the code to reserve this memory as well.
+ * %IO_RANGE is the io-memory range that gets reserved, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_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;
+}
+
+/**
+ * gensja1000io_elease_io - free reserved io memory range
+ * @candev: pointer to candevice/board which releases io
+ *
+ * The function gensja1000io_release_io() is used to free reserved io-memory.
+ * In case you have reserved more io memory, don't forget to free it here.
+ * IO_RANGE is the io-memory range that gets released, please adjust according
+ * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
+ * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
+ * Return Value: The function always returns zero
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_release_io(struct candevice_t *candev)
+{
+ can_release_io_region(candev->io_addr,IO_RANGE);
+
+ return 0;
+}
+
+/**
+ * gensja1000io_reset - hardware reset routine
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function gensja1000io_reset() is used to give a hardware reset. This is
+ * rather hardware specific so I haven't included example code. Don't forget to
+ * check the reset status of the chip before returning.
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_reset(struct candevice_t *candev)
+{
+ int i;
+ struct canchip_t *chip=candev->chip[0];
+ unsigned cdr;
+
+ gensja1000io_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
+ udelay(1000);
+
+ cdr=gensja1000io_read_register(chip->chip_base_addr+SJACDR);
+ gensja1000io_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ gensja1000io_write_register(0, chip->chip_base_addr+SJAIER);
+
+ i=20;
+ gensja1000io_write_register(0, chip->chip_base_addr+SJAMOD);
+ while (gensja1000io_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
+ if(!i--) return -ENODEV;
+ udelay(1000);
+ gensja1000io_write_register(0, chip->chip_base_addr+SJAMOD);
+ }
+
+ cdr=gensja1000io_read_register(chip->chip_base_addr+SJACDR);
+ gensja1000io_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ gensja1000io_write_register(0, chip->chip_base_addr+SJAIER);
+
+ return 0;
+}
+
+#define RESET_ADDR 0x0
+#define NR_82527 0
+#define NR_SJA1000 1
+
+/**
+ * gensja1000io_init_hw_data - Initialize hardware cards
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function gensja1000io_init_hw_data() is used to initialize the hardware
+ * structure containing information about the installed CAN-board.
+ * %RESET_ADDR represents the io-address of the hardware reset register.
+ * %NR_82527 represents the number of intel 82527 chips on the board.
+ * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
+ * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
+ * the hardware uses programmable interrupts.
+ * Return Value: The function always returns zero
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_init_hw_data(struct candevice_t *candev)
+{
+ candev->res_addr=RESET_ADDR;
+ candev->nr_82527_chips=0;
+ candev->nr_sja1000_chips=1;
+ candev->nr_all_chips=1;
+ candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
+
+ return 0;
+}
+
+/**
+ * gensja1000io_init_chip_data - Initialize chips
+ * @candev: Pointer to candevice/board structure
+ * @chipnr: Number of the CAN chip on the hardware card
+ *
+ * The function gensja1000io_init_chip_data() is used to initialize the hardware
+ * structure containing information about the CAN chips.
+ * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
+ * "sja1000".
+ * The @chip_base_addr entry represents the start of the 'official' memory map
+ * of the installed chip. It's likely that this is the same as the @io_addr
+ * argument supplied at module loading time.
+ * The @clock entry holds the chip clock value in Hz.
+ * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
+ * register. Options defined in the %sja1000.h file:
+ * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
+ * The entry @sja_ocr_reg holds hardware specific options for the Output Control
+ * register. Options defined in the %sja1000.h file:
+ * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
+ * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
+ * The entry @int_clk_reg holds hardware specific options for the Clock Out
+ * register. Options defined in the %i82527.h file:
+ * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
+ * The entry @int_bus_reg holds hardware specific options for the Bus
+ * Configuration register. Options defined in the %i82527.h file:
+ * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
+ * The entry @int_cpu_reg holds hardware specific options for the cpu interface
+ * register. Options defined in the %i82527.h file:
+ * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
+ * Return Value: The function always returns zero
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+ /*sja1000_fill_chipspecops(candev->chip[chipnr]);*/
+ sja1000p_fill_chipspecops(candev->chip[chipnr]);
+
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
+ if(candev->chip[chipnr]->clock<=0)
+ candev->chip[chipnr]->clock = 16000000;
+ candev->chip[chipnr]->int_clk_reg = 0x0;
+ candev->chip[chipnr]->int_bus_reg = 0x0;
+ candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
+ candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
+
+ return 0;
+}
+
+/**
+ * gensja1000io_init_obj_data - Initialize message buffers
+ * @chip: Pointer to chip specific structure
+ * @objnr: Number of the message buffer
+ *
+ * The function gensja1000io_init_obj_data() is used to initialize the hardware
+ * structure containing information about the different message objects on the
+ * CAN chip. In case of the sja1000 there's only one message object but on the
+ * i82527 chip there are 15.
+ * The code below is for a i82527 chip and initializes the object base addresses
+ * The entry @obj_base_addr represents the first memory address of the message
+ * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
+ * base address.
+ * Unless the hardware uses a segmented memory map, flags can be set zero.
+ * Return Value: The function always returns zero
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+ return 0;
+}
+
+/**
+ * gensja1000io_program_irq - program interrupts
+ * @candev: Pointer to candevice/board structure
+ *
+ * The function gensja1000io_program_irq() is used for hardware that uses
+ * programmable interrupts. If your hardware doesn't use programmable interrupts
+ * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
+ * leave this function unedited. Again this function is hardware specific so
+ * there's no example code.
+ * Return value: The function returns zero on success or %-ENODEV on failure
+ * File: src/gensja1000io.c
+ */
+int gensja1000io_program_irq(struct candevice_t *candev)
+{
+ return 0;
+}
+
+/**
+ * gensja1000io_write_register - Low level write register routine
+ * @data: data to be written
+ * @address: memory address to write to
+ *
+ * The function gensja1000io_write_register() is used to write to hardware registers
+ * on the CAN chip. You should only have to edit this function if your hardware
+ * uses some specific write process.
+ * Return Value: The function does not return a value
+ * File: src/gensja1000io.c
+ */
+void gensja1000io_write_register(unsigned data, can_ioptr_t address)
+{
+ /*DEBUGMSG("gensja1000io_write_register: addr=0x%lx data=0x%x",
+ address,data);*/
+ can_outb(data,address);
+}
+
+/**
+ * gensja1000io_read_register - Low level read register routine
+ * @address: memory address to read from
+ *
+ * The function gensja1000io_read_register() is used to read from hardware registers
+ * on the CAN chip. You should only have to edit this function if your hardware
+ * uses some specific read process.
+ * Return Value: The function returns the value stored in @address
+ * File: src/gensja1000io.c
+ */
+unsigned gensja1000io_read_register(can_ioptr_t address)
+{
+ return can_inb(address);
+}
+
+/* !!! Don't change this function !!! */
+int gensja1000io_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = gensja1000io_request_io;
+ hwspecops->release_io = gensja1000io_release_io;
+ hwspecops->reset = gensja1000io_reset;
+ hwspecops->init_hw_data = gensja1000io_init_hw_data;
+ hwspecops->init_chip_data = gensja1000io_init_chip_data;
+ hwspecops->init_obj_data = gensja1000io_init_obj_data;
+ hwspecops->write_register = gensja1000io_write_register;
+ hwspecops->read_register = gensja1000io_read_register;
+ hwspecops->program_irq = gensja1000io_program_irq;
+ return 0;
+}
--- /dev/null
+/* hcan2.c
+ * Linux CAN-bus device driver.
+ * This software is released under the GPL-License.
+ */
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/hcan2.h"
+
+#define myDEBUG 0
+
+#if myDEBUG
+ #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "lincan (debug): " fmt,##args)
+#endif
+
+
+#define MAX_TRANSMIT_WAIT_LOOPS 20
+#define MAX_SETTING_WAIT_LOOPS 25 /* maximal loop count while checking Chip reply to action */
+#define MAX_IRQ_WAIT_LOOPS 25
+
+void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj);
+void hcan2_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj);
+
+void hcan2_clear_irq_flags(struct canchip_t *chip);
+void hcan2_clear_mbox(struct canchip_t *chip, int msgobj_idx);
+
+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);
+void hcan2_setup_mbox4read(struct msgobj_t * obj);
+
+void hcan2_setup_ctrl_regs(struct canmsg_t * msg, uint16_t * ctrl0, uint16_t * ctrl1, uint16_t * ctrl2);
+
+int hcan2_compare_msg(struct msgobj_t * obj, struct canmsg_t * msg);
+void hcan2_notifyRXends(struct msgobj_t * obj, int what);
+/* Enable folowing IRQs
+ * HCAN2_IRR_DFRI = Data Frame Received Interrupt Flag
+ * HCAN2_IRR_MBEI = Mailbox Empty Interrupt Flag
+ *
+ * and Errors:
+ * Bus Off, Error Passive, Message Overrun/Overwrite
+ */
+uint16_t IRQs = ~(HCAN2_IRR_DFRI + HCAN2_IRR_MBEI + HCAN2_IRR_BOI + HCAN2_IRR_EPI + HCAN2_IRR_MOOI);
+/* 1 - mask interrupt, 0 - interrupt not masked */
+
+int hcan2_chip_config(struct canchip_t *chip)
+{
+ DEBUGMSG("Configuring chip...\n");
+
+ if (hcan2_enable_configuration(chip))
+ return -ENODEV;
+
+ if (!chip->baudrate)
+ chip->baudrate=1000000;
+ if (hcan2_baud_rate(chip, chip->baudrate,chip->clock,0,75,0))
+ return -ENODEV;
+
+ hcan2_config_irqs(chip, IRQs);
+
+ if (hcan2_disable_configuration(chip))
+ return -ENODEV;
+
+/* DEBUGMSG("Chip configured\n"); */
+ return 0;
+}
+
+int hcan2_enable_configuration(struct canchip_t *chip)
+{
+ int i = 0;
+ uint16_t gsr;
+
+ DEBUGMSG("Enabling configuration...\n");
+
+ /* Disable interrupt */
+ can_disable_irq(chip->chip_irq);
+
+ /* Halt mode - disable CAN activity after completing current operation */
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+ if (gsr & (HCAN2_GSR_BOFF | HCAN2_GSR_RESET)) /* chip is already in config mode */
+ return 0;
+
+ can_write_reg_w(chip, HCAN2_MCR_HALT, HCAN2_MCR);
+
+ /* Waits until chip enters Halt mode - finishes current TX/RX operation */
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+ while ( !(gsr & HCAN2_GSR_HSS) && ((i++) <= MAX_SETTING_WAIT_LOOPS) ) {
+ udelay(200);
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+ }
+
+ if (i >= MAX_SETTING_WAIT_LOOPS) {
+ CANMSG("Error entering HALT mode (enable configuration) \n");
+ can_enable_irq(chip->chip_irq);
+ return -ENODEV;
+ }
+
+/* DEBUGMSG("Configuration mode is ENABLED\n"); */
+ return 0;
+}
+
+int hcan2_disable_configuration(struct canchip_t *chip)
+{
+ int i = 0;
+ uint16_t gsr, mcr;
+
+ DEBUGMSG("Disabling configuration mode...\n");
+
+ /* Halt mode - disable CAN activity after completing current operation */
+ mcr = can_read_reg_w(chip, HCAN2_MCR);
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+
+ /* if configuration already disabled */
+ if (!(gsr & HCAN2_GSR_HSS) && !(mcr & HCAN2_MCR_HALT))
+ return 0;
+
+ can_write_reg_w(chip, mcr & ~HCAN2_MCR_HALT, HCAN2_MCR);
+
+ /* Waits until chip leaves Halt mode */
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+ while ( (gsr & HCAN2_GSR_BOFF) && ((i++) <= MAX_SETTING_WAIT_LOOPS) ) {
+ udelay(200);
+ gsr = can_read_reg_w(chip, HCAN2_GSR);
+ }
+
+ if (i >= MAX_SETTING_WAIT_LOOPS) {
+ CANMSG("Error leaving HALT mode (enable configuration) \n");
+ return -ENODEV;
+ }
+
+ /* Enable interrupt */
+ can_enable_irq(chip->chip_irq);
+
+/* DEBUGMSG("Configuration mode is DISABLED\n"); */
+ return 0;
+}
+
+/* ********************************************* */
+int hcan2_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, int sampl_pt, int flags)
+{
+ /* Set communication parameters.
+ * param rate baud rate in Hz
+ * param clock frequency of hcan2 clock in Hz (on sh7760 most probably 27.5MHz)
+ * param sjw synchronization jump width (0-3) prescaled clock cycles
+ * param sampl_pt sample point in % (0-100) sets (TSEG1 + 1)/(TSEG1 + TSEG2 + 1) ration
+ * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP
+ */
+
+
+ /* rate = clock / ((tseg1 + tseg2 + 1) * brp ) */
+
+ int best_error = 1000000000, error;
+ int best_tseg = 0, best_brp = 0, best_rate = 0, brp = 0;
+ int tseg, tseg1 = 0, tseg2 = 0; /* tseg = TSEG1 + TSEG2 + 1*/
+ uint16_t bcr0 = 0, bcr1 = 0;
+
+ DEBUGMSG("Seting Baud rate...\n");
+
+ for (tseg = TSEG_MIN; tseg <= TSEG_MAX; tseg++)
+ {
+ brp = 10 * clock/(tseg * rate);
+ brp = brp % 10 > 4 ? brp / 10 + 1: brp / 10; /* round */
+
+ if (brp == 0 || brp > 256)
+ continue;
+
+ error = rate - clock/(brp * tseg);
+ if (error < 0)
+ error = -error;
+ if (error <= best_error) {
+ best_error = error;
+ best_tseg = tseg;
+ best_brp = brp;
+ best_rate = clock/(brp * tseg);
+ }
+ }
+
+ tseg2 = best_tseg - (sampl_pt * best_tseg)/100;
+ if (tseg2 < TSEG2_MIN) /* tseg2 <= sjw +1 , TSEG2_MIN = 4 */
+ tseg2 = TSEG2_MIN;
+ if (tseg2 > TSEG2_MAX)
+ tseg2 = TSEG2_MAX;
+ tseg1 = best_tseg - tseg2 - 1;
+ if (tseg1 > TSEG1_MAX) {
+ tseg1 = TSEG1_MAX;
+ tseg2 = best_tseg - tseg1 - 1;
+ }
+
+ if (best_error && (rate/best_error < 10)) {
+ CANMSG("baud rate %d is not possible with %d Hz clock\n",
+ rate, clock);
+ CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
+ best_rate, best_brp, best_tseg, tseg1, tseg2);
+ return -EINVAL;
+ }
+
+ DEBUGMSG("Setting %d bps.\n", best_rate);
+/* DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
+ best_brp, best_tseg, tseg1, tseg2,
+ (100 * tseg1 / best_tseg));
+*/
+ /*
+ * EG = 0b0 - Resynchronization at falling edge
+ * BSP = 0b00 - bit sampling at one point (end of TSEG1)
+ */
+
+ bcr1 = (((tseg1 - 1) & 0x000f) << 12) + (((tseg2 - 1) & 0x0007) << 8) + ((sjw & 0x0003) << 4);
+ bcr0 = (best_brp - 1) & 0x00ff;
+
+ hcan2_set_btregs(chip, bcr0, bcr1);
+
+ hcan2_disable_configuration(chip);
+
+/* DEBUGMSG("Baud rate set successfully\n"); */
+ return 0;
+}
+
+int hcan2_set_btregs(struct canchip_t *chip, unsigned short bcr0, unsigned short bcr1)
+{
+/* DEBUGMSG("Seting BCR0 and BCR1.\n"); */
+
+ /* masks words to correct format */
+ bcr0 &= 0x00ff;
+ bcr1 &= 0xf733;
+
+ 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;
+}
+
+/* ********************************************* */
+int hcan2_start_chip(struct canchip_t *chip)
+{
+/* DEBUGMSG("Starting chip %d...\n", chip->chip_idx); */
+
+ /* Stop chip turns chip to HALT mode - traffic on CAN bus is ignored after completing curent operation.
+ * Start chip only turn chip back from HALT state - using disable_config
+ */
+ hcan2_disable_configuration(chip);
+
+ DEBUGMSG("Chip [%d] started\n", chip->chip_idx);
+ return 0;
+}
+
+int hcan2_stop_chip(struct canchip_t *chip)
+{
+/* DEBUGMSG("Stopping chip %d...\n", chip->chip_idx); */
+
+ /* Stop chip turns chip to HALT mode - traffic on CAN bus is ignored after completing curent operation.
+ * - using enable_config
+ */
+ hcan2_enable_configuration(chip);
+
+ DEBUGMSG("Chip [%d] stopped\n", chip->chip_idx);
+ return 0;
+}
+
+int hcan2_attach_to_chip(struct canchip_t *chip)
+{
+/* DEBUGMSG("Attaching to chip %d.\n", chip->chip_idx); */
+
+ /* initialize chip */
+
+ if (hcan2_enable_configuration(chip))
+ return -ENODEV;
+
+ /* Clear all Mailboxes */
+ if (hcan2_clear_objects(chip))
+ return -ENODEV;
+
+ /* set Baudrate and Interrupts */
+ if (hcan2_chip_config(chip))
+ return -ENODEV;
+
+ if (hcan2_disable_configuration(chip))
+ return -ENODEV;
+
+ /* Enable interrupt */
+ can_enable_irq(chip->chip_irq);
+ can_enable_irq(chip->chip_irq);
+
+ CANMSG("Successfully attached to chip [%02d].\n", chip->chip_idx);
+ return 0;
+}
+
+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;
+}
+
+/* ********************************************* */
+int hcan2_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask)
+{
+ uint16_t ctrl0, lafm0;
+ struct msgobj_t * obj;
+ int obj_idx = (int) (chip->chip_data);
+
+ if (code & 0x1ffff800)
+ return hcan2_extended_mask(chip, code, mask);
+
+
+ if (obj_idx > 0 && obj_idx <= 32)
+ obj = chip->msgobj[obj_idx - 1];
+ else
+ return -ENODEV;
+
+ chip->chip_data = (void*)0; /* reset mbox number */
+
+
+ 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);
+ can_write_reg_w(chip, 0xffff, (int) obj->obj_base_addr + HCAN2_MB_MASK + 2);
+
+ DEBUGMSG("MB%02d: Set standard_mask [id:0x%04x, m:0x%04x]\n", obj_idx, code, lafm0);
+ return 0;
+}
+
+int hcan2_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
+{
+ uint16_t ctrl0, ctrl1, lafm0, lafm1;
+
+ 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
+ return -ENODEV;
+
+ chip->chip_data = (void*)0; /* reset mbox number */
+
+ ctrl0 = ((code & 0x1ffc0000) >> 14);
+ ctrl0 |=((code & 0x00030000) >> 16);
+ ctrl0 |= HCAN2_MBCT0_IDE; /* set IDE flag */
+ ctrl1 = (code & 0x0000ffff);
+
+ 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;
+}
+
+/* ********************************************* */
+int hcan2_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
+{
+ DEBUGMSG("Pre read config\n");
+
+ hcan2_enable_configuration(chip);
+
+ /* clears mailbox and setup LFA to accept all Exted Messages */
+ hcan2_setup_mbox4read(obj);
+
+ hcan2_disable_configuration(chip);
+
+ return 0;
+}
+
+int hcan2_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg)
+{
+ DEBUGMSG("Pre write config\n");
+
+ /* 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;
+ }
+ else
+ hcan2_setup_mbox4write_data(obj, msg);
+
+ return 0;
+}
+
+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);
+
+ 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);
+
+/* CANMSG("Message sent [obj: %d]\n", obj->object - 1); */
+ return 0;
+}
+
+int hcan2_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
+{
+ CANMSG("hcan2_remote_request not implemented\n");
+ return -ENOSYS;
+}
+
+/* ********************************************* */
+int hcan2_irq_handler(int irq, struct canchip_t *chip)
+{
+ uint16_t irq_reg, idx;
+ short loop_cnt = MAX_IRQ_WAIT_LOOPS;
+ uint32_t rxdf, txdf;
+
+/*
+ HCAN2_IRR_TCMI - Time Compare Match Register
+ HCAN2_IRR_TOI - Time Overrun Interrupt
+ HCAN2_IRR_WUBA - Wake-up on Bus Activity
+ HCAN2_IRR_MOOI - Message Overrun/Overwrite Interrupt Flag
+ HCAN2_IRR_MBEI - Messagebox Empty Interrupt Flag
+ HCAN2_IRR_OF - Overload Frame
+ HCAN2_IRR_BOI - Bus Off Interrupt Flag
+ HCAN2_IRR_EPI - Error Passive Interrupt Flag
+ HCAN2_IRR_ROWI - Receive Overload Warning Interrupt Flag
+ HCAN2_IRR_TOWI - Transmit Overload Warining Interrupt Flag
+ HCAN2_IRR_RFRI - Remote Frame Request Interrupt Flag
+ HCAN2_IRR_DFRI - Data Frame Received Interrupt Flag
+ HCAN2_IRR_RHSI - Reset/Halt/Sleep Interrupt Flag */
+
+ irq_reg = can_read_reg_w(chip, HCAN2_IRR);
+ DEBUGMSG("irq: %d, chip base addr: 0x%08x\n", irq, (uint32_t)chip->chip_base_addr);
+ DEBUGMSG("IRQ Handler: HCAN2_IRR: 0x%04x\n", irq_reg); //*/
+
+ do {
+
+ if(!loop_cnt--) {
+ CANMSG("hcan2_irq_handler IRQ %d stuck\n", irq);
+ return CANCHIP_IRQ_STUCK;
+ }
+
+ /* Received message */
+ if (irq_reg & HCAN2_IRR_DFRI)
+ {
+ rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+ can_read_reg_w(chip, HCAN2_RXPR0);
+
+ while(rxdf) {
+ DEBUGMSG("Received message [0x%08x]\n", rxdf);
+
+ /* find the message object */
+ for (idx = 0; (idx < chip->max_objects) && rxdf; idx++)
+ if ((rxdf & (1<<idx))) {
+ hcan2_irq_read_handler(chip, chip->msgobj[idx]);
+ /* RXPR flag for this msgobj is cleared during irq_read_handler*/
+ rxdf &= ~(1 << idx);
+ }
+
+
+ DEBUGMSG("Before reset flags [0x%08x]\n", rxdf);
+ rxdf = (can_read_reg_w(chip, HCAN2_RXPR1) << 16) +
+ can_read_reg_w(chip, HCAN2_RXPR0);
+ }
+ }
+
+ /* Error: Bus Off */
+ if (irq_reg & HCAN2_IRR_BOI) {
+ CANMSG("Error: entering BUS OFF state\nstatus register: 0x%02x irq register: 0x%02x\n",
+ can_read_reg_w(chip, HCAN2_GSR), irq_reg);
+
+ /* notify all RX/TX ends */
+ for (idx = 0; idx < chip->max_objects; idx++) {
+ /* notify TX */
+ chip->msgobj[idx]->ret=-1;
+ if(chip->msgobj[idx]->tx_slot)
+ canque_notify_inends(chip->msgobj[idx]->tx_qedge,
+ CANQUEUE_NOTIFY_ERROR);
+ /* notify RX */
+ hcan2_notifyRXends(chip->msgobj[idx], CANQUEUE_NOTIFY_ERROR);
+ }
+
+ /* reset flag - by writing '1' */
+ can_write_reg_w(chip, HCAN2_IRR_BOI, HCAN2_IRR);
+ }
+
+ /* Warning: Error Passive */
+ if (irq_reg & HCAN2_IRR_EPI) {
+ uint16_t tecrec;
+ tecrec = can_read_reg_w(chip, HCAN2_TECREC);
+
+ 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' */
+ can_write_reg_w(chip, HCAN2_IRR_EPI, HCAN2_IRR);
+ }
+
+ /* Message Overrun/Overwritten */
+ 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<<idx)); idx++) { }
+
+ CANMSG("Error: MESSAGE OVERRUN/OVERWRITTEN [MB: %d]\n",idx);
+
+ /* notify only injured RXqueue-end */
+ if (idx < chip->max_objects)
+ hcan2_notifyRXends(chip->msgobj[idx], CANQUEUE_NOTIFY_ERROR);
+
+ /* reset flag */
+ can_write_reg_w(chip, (1 << (idx % 16)), HCAN2_UMSR0 - 2 * (idx / 16));
+ }
+
+ /* Mailbox empty - after message was sent */
+ if (irq_reg & HCAN2_IRR_MBEI)
+ {
+ txdf = (can_read_reg_w(chip, HCAN2_TXACK1) << 16) +
+ can_read_reg_w(chip, HCAN2_TXACK0);
+
+ /* find the message object */
+ for (idx = 0; (idx < chip->max_objects) && !(txdf & (1<<idx)); idx++) { }
+
+ /* realy i got one? */
+ if (idx >= chip->max_objects) {
+ /* IRQ is caused by Aborted transmition */
+ can_write_reg_w(chip, 0xffff, HCAN2_ABACK0);
+ can_write_reg_w(chip, 0xffff, HCAN2_ABACK1);
+ return CANCHIP_IRQ_HANDLED;
+ }
+
+ /* Clear TXACK flag */
+ can_write_reg_w(chip, 1 << (idx % 16), HCAN2_TXACK0 - 2 * (idx / 16));
+
+ /* sends message */
+ hcan2_wakeup_tx(chip, chip->msgobj[idx]);
+ }
+
+ irq_reg = can_read_reg_w(chip, HCAN2_IRR);
+ } while(irq_reg & ~IRQs);
+
+ return CANCHIP_IRQ_HANDLED;
+}
+
+int hcan2_irq_accept(int irq, struct canchip_t *chip)
+{
+ CANMSG("hcan2_irq_accept NOT IMPLEMENTED\n");
+ return -ENOSYS;
+}
+
+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;
+}
+
+
+/* ********************************************* */
+int hcan2_clear_objects(struct canchip_t *chip)
+{
+ int i;
+ for (i = 0; i < chip->max_objects; i++)
+ hcan2_clear_mbox(chip, i);
+
+ return 0;
+}
+
+int hcan2_check_tx_stat(struct canchip_t *chip)
+{
+/* DEBUGMSG("Check TX stat\n"); */
+ /* If Transmition is complete return 0 - no error */
+ if (can_read_reg_w(chip, HCAN2_GSR) & HCAN2_GSR_TXC)
+ return 0;
+ else
+ return 1;
+}
+
+/* Note: this checks TX status of concrete messagebox */
+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 */
+
+ char id = obj->object - 1;
+ return (can_read_reg_w(chip, HCAN2_TXPR0 - 2 * (id / 16)) & (1 << (id & 0x00ff)));
+}
+
+int hcan2_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
+{
+ DEBUGMSG("WakeUP TX\n");
+
+ 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))
+ { /* enable transmition only if MB is empty */
+ can_msgobj_clear_fl(obj,TX_REQUEST);
+
+ hcan2_irq_write_handler(chip, obj);
+
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ }
+ else
+ can_msgobj_clear_fl(obj,TX_REQUEST);
+
+
+ can_preempt_enable();
+
+/* DEBUGMSG("WakeUP TX - END\n"); */
+ return 0;
+}
+
+int hcan2_filtch_rq(struct canchip_t *chip, struct msgobj_t * obj)
+{
+ struct canfilt_t filter;
+
+
+#if myDEBUG
+ int num = canqueue_ends_filt_conjuction(obj->qends, &filter);
+#else
+ canqueue_ends_filt_conjuction(obj->qends, &filter);
+#endif
+
+ /* in structure chip->chip_data is Mailbox number */
+ chip->chip_data = (void*)(obj->object);
+
+ /* HCAN2 uses oposite logic for LAFM: 1-ignore bit, 0-use bit as mask */
+
+ DEBUGMSG("CNT: %d ID: 0x%08x MASK: 0x%08x\n", num, (uint32_t) (filter.id) & 0x1fffffff, (uint32_t) (~filter.mask) & 0x1fffffff);
+
+ if (filter.flags & MSG_EXT) /* Extended ID */
+ return hcan2_extended_mask(chip, filter.id, ~filter.mask);
+ else /* Standard ID */
+ return hcan2_standard_mask(chip, filter.id, ~filter.mask);
+}
+
+/* ********************************************* */
+void hcan2_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj)
+{
+ int i, len;
+ unsigned ctrl0, ctrl2, data;
+ unsigned long flag_addr;
+ uint16_t mb_offset;
+
+
+ mb_offset = (int ) obj->obj_base_addr;
+
+/* DEBUGMSG("------IRQ Read Handler\n"); */
+
+ ctrl0 = can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL0);
+ ctrl2 = can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL2);
+
+ 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)
+ {
+ DEBUGMSG("EXTENDED ID\n");
+ obj->rx_msg.id = (ctrl0 & HCAN2_MBCT0_STDID) << (18 - 4);
+ obj->rx_msg.id |= can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL1);
+ obj->rx_msg.id |= ((ctrl0 & HCAN2_MBCT0_EXTID) << 16);
+ }
+ else
+ obj->rx_msg.id = (ctrl0 & HCAN2_MBCT0_STDID)>>4;
+
+
+ if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+ for (i = 0; i < len; i++)
+ {
+ /* rcanqueue_ends_filt_conjuctionead 16bit data - two data bytes*/
+ data = can_read_reg_w(chip, (int) obj->obj_base_addr + HCAN2_MB_DATA1 + i);
+ obj->rx_msg.data[i] = (data & 0xff00) >> 8; // one data byte
+ if (++i < len) obj->rx_msg.data[i] = data & 0x00ff; // second data byte
+ }
+
+ /* Computes correct offset address of register from MSGBOX_IDX and RTR flag
+ * result is one of these:
+ * 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);
+
+ /* fill CAN message timestamp */
+ can_filltimestamp(&obj->rx_msg.timestamp);
+
+ canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+}
+
+void hcan2_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);
+ }
+ /* Free transmitted slot */
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot=NULL;
+ }
+
+ cmd = canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+ if(cmd < 0)
+ return;
+
+ if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+ obj->ret = -1;
+ canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot = NULL;
+ return;
+ }
+ if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+ obj->ret = -1;
+ canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ obj->tx_slot = NULL;
+ return;
+ }
+}
+
+/* ********************************************* */
+int hcan2_register(struct chipspecops_t *chipspecops)
+{
+ chipspecops->chip_config = hcan2_chip_config;
+ chipspecops->enable_configuration = hcan2_enable_configuration;
+ chipspecops->disable_configuration = hcan2_disable_configuration;
+
+ chipspecops->baud_rate = hcan2_baud_rate;
+ chipspecops->set_btregs = hcan2_set_btregs;
+
+ chipspecops->start_chip = hcan2_start_chip;
+ chipspecops->stop_chip = hcan2_stop_chip;
+ chipspecops->attach_to_chip = hcan2_attach_to_chip;
+ chipspecops->release_chip = hcan2_release_chip;
+
+ chipspecops->standard_mask = hcan2_standard_mask;
+ chipspecops->extended_mask = hcan2_extended_mask;
+ chipspecops->message15_mask = NULL; /* hcan2_message15_mask; */
+
+ chipspecops->pre_read_config = hcan2_pre_read_config;
+ chipspecops->pre_write_config = hcan2_pre_write_config;
+ chipspecops->send_msg = hcan2_send_msg;
+ chipspecops->remote_request = hcan2_remote_request;
+
+ chipspecops->irq_handler = hcan2_irq_handler;
+ chipspecops->irq_accept = NULL; /* hcan2_irq_accept; */
+ chipspecops->config_irqs = hcan2_config_irqs;
+
+ chipspecops->clear_objects = hcan2_clear_objects;
+ chipspecops->check_tx_stat = hcan2_check_tx_stat;
+ chipspecops->wakeup_tx = hcan2_wakeup_tx;
+ chipspecops->filtch_rq = hcan2_filtch_rq;
+ return 0;
+}
+
+int hcan2_fill_chipspecops(struct canchip_t *chip)
+{
+ chip->chip_type = "hcan2";
+ chip->max_objects = 32;
+ chip->write_register = chip->hostdevice->hwspecops->write_register;
+ chip->read_register = chip->hostdevice->hwspecops->read_register;
+
+ /*
+ chip->flags;
+ chip->baudrate;
+ chip->msgobj;
+ chip->chip_data;
+ chip->chip_lock;
+
+ chip->sja_cdr_reg;
+ chip->sja_ocr_reg;
+ chip->int_cpu_reg;
+ chip->int_clk_reg;
+ chip->int_bus_reg;
+
+ #ifdef CAN_WITH_RTL
+ chip->worker_thread;
+ chip->pend_flags;
+ #endif
+ */
+
+ hcan2_register(chip->chipspecops);
+ return 0;
+}
+
+
+/* ********************************************* */
+int hcan2_reset_chip(struct canchip_t *chip)
+{
+ /* After reset and reconfig (start_chip) Chip waits for
+ * 11 recessive bits to join CAN bus activity
+ */
+
+ int i;
+ unsigned gsr_reset;
+
+ DEBUGMSG("Resetting HCAN2 chip %d...\n", chip->chip_idx);
+
+ /* send Reset Request */
+ can_write_reg_w(chip, HCAN2_MCR_RESET, HCAN2_MCR );
+
+ /* 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))
+ {
+ udelay(10000);
+ gsr_reset = can_read_reg_w(chip, HCAN2_GSR) & HCAN2_GSR_RESET;
+ }
+
+ if (i >= MAX_SETTING_WAIT_LOOPS) {
+ CANMSG("Reset status timeout! (enter Reset Mode)\n");
+ return -ENODEV;
+ }
+
+ /* Clear Reset request flag */
+ can_write_reg_w(chip, can_read_reg_w(chip, HCAN2_MCR) & (~HCAN2_MCR_RESET), HCAN2_MCR);
+
+
+ /* Clear Reset Interrupt Flag IRR 0 */
+ can_write_reg_w(chip, HCAN2_IRR_RHSI, HCAN2_IRR);
+
+/* DEBUGMSG("Chips reset status ok.\n"); */
+
+ return 0;
+}
+
+/* !!! Functions below doesn't call enable/disable chip config !!! */
+/* !!! Usable only in block, where enable/diable config is called explicitly !!! */
+void hcan2_clear_irq_flags(struct canchip_t *chip)
+{
+ uint16_t irr;
+ DEBUGMSG("Clearing IRQ flags...\n");
+ DEBUGMSG("IRR: %04x\n",can_read_reg_w(chip, HCAN2_IRR));
+
+ irr = HCAN2_IRR_TCMI | HCAN2_IRR_TOI | HCAN2_IRR_WUBA |
+ HCAN2_IRR_OF | HCAN2_IRR_BOI | HCAN2_IRR_EPI |
+ HCAN2_IRR_ROWI | HCAN2_IRR_TOWI | HCAN2_IRR_RHSI;
+ can_write_reg_w(chip, irr, HCAN2_IRR);
+
+ /* Other IRQ flags are cleared through other registers - see below */
+
+ /* Meseage Overrun/Overwrite interrupt */
+ can_write_reg_w(chip, 0, HCAN2_UMSR0);
+ can_write_reg_w(chip, 0, HCAN2_UMSR1);
+
+ /* Mailbox Empty Interrupt */
+ can_write_reg_w(chip, 0, HCAN2_TXACK0);
+ can_write_reg_w(chip, 0, HCAN2_TXACK1);
+ can_write_reg_w(chip, 0, HCAN2_ABACK0);
+ can_write_reg_w(chip, 0, HCAN2_ABACK1);
+
+ /* Remote Frame Request Interrupt */
+ can_write_reg_w(chip, 0, HCAN2_RFPR0);
+ can_write_reg_w(chip, 0, HCAN2_RFPR1);
+
+ /* Data Frame Received Interupt Flag */
+ can_write_reg_w(chip, 0, HCAN2_RXPR0);
+ can_write_reg_w(chip, 0, HCAN2_RXPR1);
+
+ DEBUGMSG("clear_irq_flags - OK\n");
+}
+
+void hcan2_clear_mbox(struct canchip_t *chip, int msgobj_idx)
+{
+ unsigned long mb_start_addr = HCAN2_MB0 + msgobj_idx * HCAN2_MB_OFFSET;
+
+/* DEBUGMSG("Clearing message object %d\n", msgobj_idx); */
+
+ /* STDID = 0
+ * Standard Identifier format (0)
+ * Data Frame (0)
+ * EXTID{17,16} = 0
+ */
+ can_write_reg_w(chip, 0, mb_start_addr + HCAN2_MB_CTRL0);
+
+ /* EXTID {15:0} = 0 */
+ can_write_reg_w(chip, 0, mb_start_addr + HCAN2_MB_CTRL1);
+
+ /* NMC: overwrite stored message (1)
+ * ATDF: No message is transmited after receiving Remote Frame (0)
+ * DARTX: disable Automatic Retransmition: yes (1)
+ * MBC = 111 - not used: HCAN2_MBCT2_MBC default value correspond to 'Not Used'
+ * CAN Bus error - 0
+ * Data Length = 0
+ */
+ can_write_reg_w(chip, (uint16_t) (HCAN2_MBCT2_NMC | HCAN2_MBCT2_DART | HCAN2_MBCT2_MBC), mb_start_addr + HCAN2_MB_CTRL2);
+
+ /* TimeStamp */
+ can_write_reg_w(chip, 0, mb_start_addr + HCAN2_MB_TSTP);
+
+ /* Data: all bytes 0xff */
+ can_write_reg_w(chip, (uint16_t) 0xffff, mb_start_addr + HCAN2_MB_DATA0);
+ can_write_reg_w(chip, (uint16_t) 0xffff, mb_start_addr + HCAN2_MB_DATA2);
+ can_write_reg_w(chip, (uint16_t) 0xffff, mb_start_addr + HCAN2_MB_DATA4);
+ can_write_reg_w(chip, (uint16_t) 0xffff, mb_start_addr + HCAN2_MB_DATA6);
+
+ /* Local Acceptance Filter Mask - all bits of STDID and EXTID must match values set in mailbox */
+ can_write_reg_w(chip, 0, mb_start_addr + HCAN2_MB_MASK);
+ can_write_reg_w(chip, 0, mb_start_addr + HCAN2_MB_MASK + 2); /* Mask is 4 bytes */
+
+
+ DEBUGMSG("Mailbox [%d] cleared.\n", msgobj_idx);
+}
+
+void hcan2_setup_mbox4write(struct msgobj_t * obj, struct canmsg_t * msg)
+{
+ int mb_offset;
+ 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);
+ can_write_reg_w(chip, ctrl1, mb_offset + HCAN2_MB_CTRL1); /* set 0 if not using EXT format */
+ can_write_reg_w(chip, ctrl2, mb_offset + HCAN2_MB_CTRL2);
+
+ /* data */
+ hcan2_setup_mbox4write_data(obj, msg);
+}
+
+void hcan2_setup_mbox4write_data(struct msgobj_t * obj, struct canmsg_t * msg)
+{
+ int len,i, mb_offset;
+ 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);
+ can_write_reg_w(chip, data, mb_offset + HCAN2_MB_DATA1 + i);
+ }
+}
+
+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
+ chip->chip_data = (void*)(obj->object);
+ hcan2_extended_mask(chip, 2048, 0x1fffffff); /* accept all */
+
+ can_write_reg_w(chip, HCAN2_MBCT2_DART + (HCAN2_MBMOD_RXDR << 8),
+ (int) obj->obj_base_addr + HCAN2_MB_CTRL2);
+}
+
+void hcan2_setup_ctrl_regs(struct canmsg_t * msg, uint16_t * ctrl0, uint16_t * ctrl1, uint16_t * ctrl2)
+{
+ uint8_t len;
+ uint32_t id = msg->id;
+
+ len = msg->length;
+ if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
+
+ *ctrl0 = (msg->flags & MSG_RTR ? HCAN2_MBCT0_RTR : 0);
+
+ if (msg->flags & MSG_EXT)
+ {
+ /* Extended ID */
+ *ctrl0 |= ((id & 0x1ffc0000) << 14);
+ *ctrl0 |= ((id & 0x00030000) >> 16) | HCAN2_MBCT0_IDE; /* get bits {17:16} from EXTID */
+ *ctrl1 = (id & 0x0000ffff);
+ }
+ else
+ {
+ /* Standard ID */
+ *ctrl0 |= ((id & 0x01ff) << 4);
+ *ctrl1 = 0;
+ }
+
+ *ctrl2 = HCAN2_MBCT2_DART + HCAN2_MBMOD_TXDR + (len & HCAN2_MBCT2_DLC);
+}
+
+int hcan2_compare_msg(struct msgobj_t * obj, struct canmsg_t * msg)
+{
+ /* Check if mailbox header content change is neccessary */
+ /* Comparing only Control regs */
+ 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;
+
+ c0 = can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL0);
+ c1 = can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL1);
+ c2 = can_read_reg_w(chip, mb_offset + HCAN2_MB_CTRL2);
+
+ hcan2_setup_ctrl_regs(msg, &ctrl0, &ctrl1, &ctrl2);
+
+ /* 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);
+ DEBUGMSG("C2 0x%04x HW: 0x%04x\n", ctrl2, c2);
+
+ return ((ctrl0 ^ c0) || (ctrl2 ^ c2));
+}
+
+void hcan2_notifyRXends(struct msgobj_t * obj, int what){
+ struct canque_edge_t * edge;
+ canque_for_each_inedge(obj->qends, edge){
+ canque_notify_outends(edge, what);
+ }
+}
(unsigned long)candev->io_addr );
}
- if (!( candev->dev_base_addr = (long)ioremap( candev->io_addr, IO_RANGE ))) {
+ if (!( candev->dev_base_addr = ioremap( candev->io_addr, IO_RANGE ))) {
DEBUGMSG( "Failed to map IO-memory: 0x%lx - 0x%lx, mapped to 0x%lx\n",
(unsigned long)candev->io_addr,
(unsigned long)candev->io_addr + IO_RANGE - 1,
candev->chip[0]->chipspecops->stop_chip(candev->chip[0]);
// release I/O memory mapping
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
// Release the memory region
can_release_mem_region(candev->io_addr, IO_RANGE);
/*( struct canchip_t *pchip, u16 chip_nr, u16 startminor, u32 baseaddr, u8 irq )*/
{
// u32 intCntrVAddr = 0;
- u32 gpioVAddr = 0;
+ can_ioptr_t gpioVAddr = 0;
u32 tempReg = 0;
u32 baseaddr=candev->io_addr;
- // if ( (!( intCntrVAddr = (u32)ioremap( 0x80024000, 0xCD ) ))
- // & (! ( gpioVAddr = (u32)ioremap( 0x80023000, 0xAD ) ))) {
+ // if ( (!( intCntrVAddr = ioremap( 0x80024000, 0xCD ) ))
+ // & (! ( gpioVAddr = ioremap( 0x80023000, 0xAD ) ))) {
// DEBUGMSG("Failed to map Int and GPIO memory\n");
// return -EIO;
// }
- if ( ! ( gpioVAddr = (u32)ioremap( 0x80023000, 0xAD ) )) {
+ if ( ! ( gpioVAddr = ioremap( 0x80023000, 0xAD ) )) {
DEBUGMSG("Failed to map GPIO memory\n");
return -EIO;
} else {
}
if (baseaddr == 0x8002f000) {
- // tempReg = readl(intCntrVAddr);
+ // tempReg = can_readl(intCntrVAddr);
// DEBUGMSG("Read Interrupt Enable Register : 0x%.4lx\n",(long)tempReg);
// DEBUGMSG("Trying to activate CAN0 Interrupt (Bit 18)\n");
- // writel((tempReg | (1<<18)), intCntrVAddr);
- // tempReg = readl(intCntrVAddr);
+ // can_writel((tempReg | (1<<18)), intCntrVAddr);
+ // tempReg = can_readl(intCntrVAddr);
// DEBUGMSG("Read changed Interrupt Enable Register : 0x%.4lx\n",(long)tempReg);
- tempReg = readl(gpioVAddr + 0x5C);
+ tempReg = can_readl(gpioVAddr + 0x5C);
DEBUGMSG("Read GPIO-C Enable Register : 0x%.4lx\n",(long)tempReg);
DEBUGMSG("Trying to activate CAN0 (Bit 1 = 0 for CANTx0, Bit 2 = 0 for CANRx0,)\n");
- writel(tempReg & ~0x6, gpioVAddr + 0x5C);
- tempReg = readl(gpioVAddr + 0x5C);
+ can_writel(tempReg & ~0x6, gpioVAddr + 0x5C);
+ tempReg = can_readl(gpioVAddr + 0x5C);
DEBUGMSG("Read changed GPIO-C Enable Register : 0x%.4lx\n",(long)tempReg);
- tempReg = readl(gpioVAddr + 0x44);
+ tempReg = can_readl(gpioVAddr + 0x44);
DEBUGMSG("Read GPIO-C Direction Register : 0x%.4lx\n",(long)tempReg);
DEBUGMSG("Trying to set CAN0 directions (Bit 1 = 0 for CANTx0 as OUT, Bit 2 = 1 for CANRx0 as IN,)\n");
- writel((tempReg & ~0x2) | 0x4, gpioVAddr + 0x44);
- tempReg = readl(gpioVAddr + 0x44);
+ can_writel((tempReg & ~0x2) | 0x4, gpioVAddr + 0x44);
+ tempReg = can_readl(gpioVAddr + 0x44);
DEBUGMSG("Read changed GPIO-C Direction Register : 0x%.4lx\n",(long)tempReg);
}
else if (baseaddr == 0x80030000) {
- // tempReg = readl(intCntrVAddr);
- // writel((tempReg | (1<<19)), intCntrVAddr);
- tempReg = readl(gpioVAddr + 0x9C);
+ // tempReg = can_readl(intCntrVAddr);
+ // can_writel((tempReg | (1<<19)), intCntrVAddr);
+ tempReg = can_readl(gpioVAddr + 0x9C);
DEBUGMSG("Read GPIO-E Enable Register : 0x%.8lx\n",(long)tempReg);
DEBUGMSG("Trying to activate CAN1 (Bit 22 = 0 for CANRx1, Bit 23 = 0 for CANTx1,)\n");
- writel(tempReg & 0xFF3FFFFF, gpioVAddr + 0x9C);
- tempReg = readl(gpioVAddr + 0x9C);
+ can_writel(tempReg & 0xFF3FFFFF, gpioVAddr + 0x9C);
+ tempReg = can_readl(gpioVAddr + 0x9C);
DEBUGMSG("Read changed GPIO-E Enable Register : 0x%.8lx\n",(long)tempReg);
- tempReg = readl(gpioVAddr + 0x84);
+ tempReg = can_readl(gpioVAddr + 0x84);
DEBUGMSG("Read GPIO-E Direction Register : 0x%.8lx\n",(long)tempReg);
DEBUGMSG("Trying to set CAN1 directions (Bit 22 = 1 for CANRx1 as IN, Bit 23 = 0 for CANTx1 as OUT,)\n");
- writel((tempReg & ~(1<<23)) | 1<<22, gpioVAddr + 0x84);
- tempReg = readl(gpioVAddr + 0x84);
+ can_writel((tempReg & ~(1<<23)) | 1<<22, gpioVAddr + 0x84);
+ tempReg = can_readl(gpioVAddr + 0x84);
DEBUGMSG("Read changed GPIO-E Direction Register : 0x%.8lx\n",(long)tempReg);
}
//DEBUGMSG("Current Interrupt Status Register (ISR): 0x%4.4lx\n",
- // (long)readl(intCntrVAddr + 4));
+ // (long)can_readl(intCntrVAddr + 4));
//DEBUGMSG("Current Interrupt ID: %d\n",
- // (int)(readl(intCntrVAddr + 0x90) & 0xF));
+ // (int)(can_readl(intCntrVAddr + 0x90) & 0xF));
// iounmap( (void*)intCntrVAddr);
- iounmap( (void*)gpioVAddr );
+ iounmap( gpioVAddr );
// DEBUGMSG( "Unmapped Interrupt Controller IO-memory: 0x%lx\n",
// (unsigned long)intCntrVAddr);
DEBUGMSG( "Unmapped GPIO IO-memory: 0x%lx\n",
* File: src/template.c
*/
-void hms30c7202_write_register(unsigned data, unsigned long address)
+void hms30c7202_write_register(unsigned data, can_ioptr_t address)
{
+ unsigned long addr=can_ioptr2ulong(address);
int i;
//unsigned long usecs = 1;
- address = ((address & C_CAN_REGOFFS_MASK) << 1) |
- (address & ~C_CAN_REGOFFS_MASK);
+ address = can_ulong2ioptr(((addr & C_CAN_REGOFFS_MASK) << 1) |
+ (addr & ~C_CAN_REGOFFS_MASK));
//DEBUGMSG("Trying to write 0x%u16x to address 0x%lx\n",data,address);
- writew(data,address);
+ can_writew(data,address);
//udelay( usecs );
for (i=0; i<5; i++);
}
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned hms30c7202_read_register(unsigned long address)
+unsigned hms30c7202_read_register(can_ioptr_t address)
{
+ unsigned long addr=can_ioptr2ulong(address);
u16 value, i;
- address = ((address & C_CAN_REGOFFS_MASK) << 1) |
- (address & ~C_CAN_REGOFFS_MASK);
+ address = can_ulong2ioptr(((addr & C_CAN_REGOFFS_MASK) << 1) |
+ (addr & ~C_CAN_REGOFFS_MASK));
//DEBUGMSG("Trying to read from address 0x%lx :",address);
- value = readw(address);
+ value = can_readw(address);
//udelay( usecs );
for (i=0;i<5;i++);
- value = readw(address);
+ value = can_readw(address);
//udelay( usecs );
for (i=0;i<5;i++);
i82527_pre_read_config(chip, obj);
- CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",obj->obj_base_addr);
+ CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",
+ can_ioptr2ulong(obj->obj_base_addr));
}
}
#include <ctype.h>
-can_irqreturn_t ipci165_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif /*IRQF_SHARED*/
+
+can_irqreturn_t ipci165_irq_handler(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id));
int ipci165_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
int sampl_pt, int flags);
int ipci165_set_btregs(struct canchip_t *chip, unsigned short btr0,
*/
void ipci165_generate_irq(struct candevice_t *candev)
{
- unsigned long crm_addr = candev->io_addr;
- writeb(readb(crm_addr + CRM_UCR) & 0xFB, crm_addr + CRM_UCR);
- writeb(readb(crm_addr + CRM_UCR) | 0x04, crm_addr + CRM_UCR);
+ can_ioptr_t crm_addr = candev->aux_base_addr;
+ can_writeb(can_readb(crm_addr + CRM_UCR) & 0xFB, crm_addr + CRM_UCR);
+ can_writeb(can_readb(crm_addr + CRM_UCR) | 0x04, crm_addr + CRM_UCR);
}
/**
*/
int bci_command(struct candevice_t *candev, char cmd, int size, char *data)
{
- unsigned long dpram_addr = candev->dev_base_addr;
+ can_ioptr_t dpram_addr = candev->dev_base_addr;
DEBUGMSG ("ipci165_bci_command\n");
can_spin_lock(&candev->device_lock);
// check command buffer status
- if (readb(dpram_addr + OF_BCI_SYNC) != 0)
+ if (can_readb(dpram_addr + OF_BCI_SYNC) != 0)
{
/* something went wrong ... */
can_spin_unlock(&candev->device_lock);
}
// prepare command
- writeb(cmd, dpram_addr + OF_BCI_CMD);
- writeb(size + 1, dpram_addr + OF_BCI_NUM);
+ can_writeb(cmd, dpram_addr + OF_BCI_CMD);
+ can_writeb(size + 1, dpram_addr + OF_BCI_NUM);
memcpy_toio(dpram_addr + OF_BCI_DATA, data, size);
// set flag for firmware
- writeb(1, dpram_addr + OF_BCI_SYNC);
+ can_writeb(1, dpram_addr + OF_BCI_SYNC);
// generate interrupt to microcontroller
ipci165_generate_irq (candev);
*/
int bci_response(struct candevice_t *candev, char cmd, int *size, char *data)
{
- unsigned long dpram_addr = candev->dev_base_addr;
+ can_ioptr_t dpram_addr = candev->dev_base_addr;
char tmp;
int delay;
DEBUGMSG ("ipci165_bci_response\n");
delay = 1000;
- while (readb(dpram_addr + OF_BCI_SYNC) != 2)
+ while (can_readb(dpram_addr + OF_BCI_SYNC) != 2)
{
/* wait 1 ms */
/* ipci165_delay(1); */
}
/* we will not copy the command filed, so decrement the size by 1 */
- tmp = readb(dpram_addr + OF_BCI_NUM) - 1;
+ tmp = can_readb(dpram_addr + OF_BCI_NUM) - 1;
if (*size > tmp) *size = tmp;
- if (readb(dpram_addr + OF_BCI_CMD) != cmd)
+ if (can_readb(dpram_addr + OF_BCI_CMD) != cmd)
{
/* release the buffer */
- writeb(0, dpram_addr + OF_BCI_SYNC);
+ can_writeb(0, dpram_addr + OF_BCI_SYNC);
/* unlock the access */
can_spin_unlock(&candev->device_lock);
memcpy_fromio(data, dpram_addr + OF_BCI_DATA, *size);
/* release the buffer */
- writeb(0, dpram_addr + OF_BCI_SYNC);
+ can_writeb(0, dpram_addr + OF_BCI_SYNC);
/* unlock the access */
can_spin_unlock(&candev->device_lock);
return 0;
for (i = 0; i< BCI_QUEUE_SIZE; i++)
{
- writeb(BCI_MSG_STATUS_FREE, chip_data->rx_queue.addr + msg_ofs);
- writeb(BCI_MSG_STATUS_FREE, chip_data->tx_queue.addr + msg_ofs);
+ can_writeb(BCI_MSG_STATUS_FREE, chip_data->rx_queue.addr + msg_ofs);
+ can_writeb(BCI_MSG_STATUS_FREE, chip_data->tx_queue.addr + msg_ofs);
msg_ofs += BCI_MSG_SIZE;
}
*/
int ipci165_connect_irq(struct candevice_t *candev)
{
- unsigned long crm_addr = candev->io_addr;
+ can_ioptr_t crm_addr = candev->aux_base_addr;
unsigned char icr;
DEBUGMSG ("ipci165_connect_irq\n");
/* install interrupt routine */
if (request_irq(candev->sysdevptr.pcidev->irq,
ipci165_irq_handler,
- SA_SHIRQ,
+ IRQF_SHARED,
DEVICE_NAME,
candev))
return -ENODEV;
// Enable interrupt to PC
- writeb(readb(crm_addr + CRM_ICR) | 0x40, crm_addr + CRM_ICR);
+ can_writeb(can_readb(crm_addr + CRM_ICR) | 0x40, crm_addr + CRM_ICR);
udelay (100);
- icr = readb(crm_addr + CRM_ICR);
+ icr = can_readb(crm_addr + CRM_ICR);
return 0;
}
*/
void ipci165_disconnect_irq(struct candevice_t *candev)
{
- unsigned long crm_addr = candev->io_addr;
+ can_ioptr_t crm_addr = candev->aux_base_addr;
unsigned char icr;
DEBUGMSG ("ipci165_disconnect_irq\n");
// Enable interrupt to PC
- writeb(readb(crm_addr + CRM_ICR) & ~0x40, crm_addr + CRM_ICR);
+ can_writeb(can_readb(crm_addr + CRM_ICR) & ~0x40, crm_addr + CRM_ICR);
udelay (100);
- icr = readb(crm_addr + CRM_ICR);
+ icr = can_readb(crm_addr + CRM_ICR);
/* deinstall interrupt routine */
free_irq(candev->sysdevptr.pcidev->irq, candev);
}
{
struct ipci165_chip_t *chip_data = (struct ipci165_chip_t *)chip->chip_data;
struct bci_queue_t *queue = &(chip_data)->rx_queue;
- unsigned long queue_addr = queue->addr;
- unsigned long msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
+ can_ioptr_t queue_addr = queue->addr;
+ can_ioptr_t msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
int len;
unsigned char frame_info;
do {
dump_mem(msg_addr, BCI_MSG_SIZE);
- if (readb(msg_addr + BCI_MSG_TYPE) == BCI_MSG_TYPE_CAN)
+ if (can_readb(msg_addr + BCI_MSG_TYPE) == BCI_MSG_TYPE_CAN)
{
#if 0
- printk("ST(0)=%x, ST(1)=%x\n",readw(chip->chip_base_addr+OF_CAN1_STATUS),
- readw(chip->chip_base_addr+OF_CAN2_STATUS));
+ printk("ST(0)=%x, ST(1)=%x\n",can_readw(chip->chip_base_addr+OF_CAN1_STATUS),
+ can_readw(chip->chip_base_addr+OF_CAN2_STATUS));
for (tmp16 = 0 ; tmp16 < BCI_QUEUE_SIZE ; tmp16 ++)
- printk ("MSG_ST(%i)=%x\n",tmp16,readb(chip->chip_base_addr + OF_CH2_TX_QUEUE + tmp16*BCI_MSG_SIZE + BCI_MSG_STATUS));
+ printk ("MSG_ST(%i)=%x\n",tmp16,can_readb(chip->chip_base_addr + OF_CH2_TX_QUEUE + tmp16*BCI_MSG_SIZE + BCI_MSG_STATUS));
/* this is a can message */
DEBUGMSG ("ipci165_irq_read_handler[%i]: message in buffer\n",chip->chip_idx);
#endif
- frame_info = readb(msg_addr + BCI_MSG_FRAME);
+ frame_info = can_readb(msg_addr + BCI_MSG_FRAME);
len = frame_info & 0x0f;
if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
obj->rx_msg.length = len;
obj->rx_msg.cob = 0;
obj->rx_msg.timestamp.tv_sec = 0;
obj->rx_msg.timestamp.tv_usec =
- BCI_TIMESTAMP_RES * readl(msg_addr + BCI_MSG_TIMESTAMP);
- /* BCI_TIMESTAMP_RES * le32_to_cpu(readl(msg_addr + BCI_MSG_TIMESTAMP)); */
+ BCI_TIMESTAMP_RES * can_readl(msg_addr + BCI_MSG_TIMESTAMP);
+ /* BCI_TIMESTAMP_RES * le32_to_cpu(can_readl(msg_addr + BCI_MSG_TIMESTAMP)); */
/* fill CAN message timestamp */
/* can_filltimestamp(&obj->rx_msg.timestamp); */
/* extended frame - 29 bit identifier */
obj->rx_msg.flags |= MSG_EXT;
/* the ID is stored in motorola format (big endian), left justified */
- /* obj->rx_msg.id = be32_to_cpu(readl(msg_addr + BCI_MSG_ID) >> 3); */
+ /* obj->rx_msg.id = be32_to_cpu(can_readl(msg_addr + BCI_MSG_ID) >> 3); */
memcpy_fromio(&tmp32, msg_addr + BCI_MSG_ID, 4);
obj->rx_msg.id = be32_to_cpu(tmp32 >> 3);
if (len > 0)
{
/* standard frame - 11 bit identifier */
/* the ID is stored in motorola format (big endian), left justified */
- /* obj->rx_msg.id = be16_to_cpu(readw(msg_addr + BCI_MSG_ID) >> 5); */
+ /* obj->rx_msg.id = be16_to_cpu(can_readw(msg_addr + BCI_MSG_ID) >> 5); */
memcpy_fromio(&tmp16, msg_addr + BCI_MSG_ID, 2);
obj->rx_msg.id = be16_to_cpu(tmp16 >> 5);
if (len > 0)
else
{
/* this is a status message */
- status = readw(msg_addr + BCI_MSG_CAN_STATUS);
+ status = can_readw(msg_addr + BCI_MSG_CAN_STATUS);
DEBUGMSG ("ipci165_irq_read_handler[%i]: CAN status=%04x\n",chip->chip_idx, status);
/* wake up the reset thread if the CAN is in bus off */
/* update pointer */
queue->idx = (queue->idx + 1) % BCI_QUEUE_SIZE;
/* release the buffer */
- writeb(BCI_MSG_STATUS_FREE, msg_addr + BCI_MSG_STATUS);
+ can_writeb(BCI_MSG_STATUS_FREE, msg_addr + BCI_MSG_STATUS);
msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
- } while (readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL);
+ } while (can_readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL);
}
{
struct ipci165_chip_t *chip_data = ((struct ipci165_chip_t *)chip->chip_data);
struct bci_queue_t *queue = &chip_data->tx_queue;
- unsigned long queue_addr = queue->addr;
- unsigned long msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
+ can_ioptr_t queue_addr = queue->addr;
+ can_ioptr_t msg_addr = queue_addr + queue->idx * BCI_MSG_SIZE;
struct canque_slot_t *tx_slot;
int len;
while ((canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot) >=0))
{
if (test_bit(CHIP_FLAG_RESET,&chip_data->flags) ||
- (readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL))
+ (can_readb(msg_addr + BCI_MSG_STATUS) == BCI_MSG_STATUS_FULL))
{
canque_again_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
((tx_slot->msg.flags & MSG_RTR) ? BCI_MSG_FRAME_RTR : 0) |
((tx_slot->msg.flags & MSG_EXT) ? BCI_MSG_FRAME_EXT : 0);
- writeb(BCI_MSG_SIZE - 2, msg_addr + BCI_MSG_NUM);
- writeb(BCI_MSG_TYPE_CAN, msg_addr + BCI_MSG_TYPE);
- writeb(frame_info, msg_addr + BCI_MSG_FRAME);
+ can_writeb(BCI_MSG_SIZE - 2, msg_addr + BCI_MSG_NUM);
+ can_writeb(BCI_MSG_TYPE_CAN, msg_addr + BCI_MSG_TYPE);
+ can_writeb(frame_info, msg_addr + BCI_MSG_FRAME);
if (frame_info & BCI_MSG_FRAME_EXT)
{
/* extended frame - 29 bit identifier */
/* update pointer */
queue->idx = (queue->idx + 1) % BCI_QUEUE_SIZE;
/* mark the buffer as full */
- writeb(BCI_MSG_STATUS_FULL, msg_addr + BCI_MSG_STATUS);
+ can_writeb(BCI_MSG_STATUS_FULL, msg_addr + BCI_MSG_STATUS);
/* wake up the controller */
ipci165_generate_irq(chip->hostdevice);
/* check receive queue for messages */
queue = &chip_data->rx_queue;
- if (readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
+ if (can_readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
== BCI_MSG_STATUS_FULL)
ipci165_irq_read_handler(chip, obj);
queue = &chip_data->tx_queue;
-/* if (readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
+/* if (can_readb(queue->addr + queue->idx * BCI_MSG_SIZE + BCI_MSG_STATUS)
== BCI_MSG_STATUS_FREE) */
{
can_msgobj_set_fl(obj,TX_REQUEST);
* acknowledged and ipci165_irq_chip_handler is called for every channel.
* File: src/ipci165.c
*/
-can_irqreturn_t ipci165_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+can_irqreturn_t ipci165_irq_handler(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id))
{
int retval;
struct candevice_t *candev = (struct candevice_t *)dev_id;
- unsigned long crm_addr = candev->io_addr;
- unsigned long ucr1_addr = crm_addr + CRM_UCR + 1;
+ can_ioptr_t crm_addr = candev->aux_base_addr;
+ can_ioptr_t ucr1_addr = crm_addr + CRM_UCR + 1;
struct canchip_t *chip;
unsigned char icr;
int i;
/* DEBUGMSG ("ipci165_irq_handler\n"); */
/* read interrupt control register (byte 0) */
- icr = readb(crm_addr + CRM_ICR);
+ icr = can_readb(crm_addr + CRM_ICR);
if ((icr & 0x44) == 0x44)
{
DEBUGMSG ("ipci165_irq_handler: pending interrupt\n");
/* confirm pending interrupt */
- writeb(readb(ucr1_addr) | 0x01, ucr1_addr);
- writeb(readb(ucr1_addr) & ~0x01, ucr1_addr);
+ can_writeb(can_readb(ucr1_addr) | 0x01, ucr1_addr);
+ can_writeb(can_readb(ucr1_addr) & ~0x01, ucr1_addr);
/* call interrupt handler for every channel */
for (i=0 ; i < candev->nr_all_chips ; i++)
*/
int ipci165_request_io(struct candevice_t *candev)
{
- unsigned long dpram_addr;
- unsigned long crm_addr;
- unsigned long fix_addr;
+ unsigned long dpram_addr; /* physical address before remap for this function */
+ unsigned long crm_addr; /* physical address before remap for this function */
+ unsigned long fix_addr; /* physical address before remap for this function */
int i,j;
DEBUGMSG ("ipci165_request_io\n");
{
CANMSG ("This card was not fixed!\n");
- if (candev->io_addr == 0)
+ if (candev->aux_base_addr == NULL)
{
CANMSG ("You have to specify IO address parameter!\n");
return -EINVAL;
}
CANMSG ("Using specified IO address value for the memory [0x%lx]\n",
- candev->io_addr);
+ can_ioptr2ulong(candev->aux_base_addr));
}
else
{
CANMSG ("Fixed card. Using of 3 region [0x%lx]\n", fix_addr);
- candev->io_addr = fix_addr;
+ candev->aux_base_addr = fix_addr;
}
pci_write_config_dword (candev->sysdevptr.pcidev,
{
#endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
- if ((candev->dev_base_addr = (long) ioremap(dpram_addr,
+ if ((candev->dev_base_addr = ioremap(dpram_addr,
pci_resource_len(candev->sysdevptr.pcidev,2))))
{
DEBUGMSG ("ipci165_request_io: dpram remapped to 0x%lx\n", candev->dev_base_addr);
- if ((candev->io_addr = (long) ioremap(crm_addr,
+ if ((candev->aux_base_addr = ioremap(crm_addr,
pci_resource_len(candev->sysdevptr.pcidev,0))))
{
- DEBUGMSG ("ipci165_request_io: crm remapped to 0x%lx\n", candev->io_addr);
+ DEBUGMSG ("ipci165_request_io: crm remapped to 0x%lx\n", can_ioptr2ulong(candev->aux_base_addr));
/* all resources has been allocated */
- candev->res_addr=candev->io_addr;
/* Because of my mapping, I cannot use the
can_base_addr_fixup(candev, remap_addr) to remap the addresses */
return 0;
} else CANMSG("Unable to remap memory at: 0x%lx\n", crm_addr);
- iounmap((void*)candev->io_addr);
+ iounmap(candev->aux_base_addr);
} else CANMSG("Unable to remap memory at: 0x%lx\n", dpram_addr);
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 0);
}
#endif
- iounmap((void*)candev->io_addr);
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->aux_base_addr);
+ iounmap(candev->dev_base_addr);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 2);
*/
int ipci165_download_fw(struct candevice_t *candev)
{
- unsigned long dpram_addr = candev->dev_base_addr;
+ can_ioptr_t dpram_addr = candev->dev_base_addr;
char board_name[BOARD_NAME_LEN+1];
char hw_version[HW_VERSION_LEN+1];
char mode[MODE_LEN+1];
while (fwArray->len)
{
/* fill buffer */
- writeb(LD_CMD_DOWNLOAD, dpram_addr + OF_LD_CMD);
- writeb(fwArray->len, dpram_addr + OF_LD_NUM);
- writeb(0, dpram_addr + OF_LD_NUM + 1);
+ can_writeb(LD_CMD_DOWNLOAD, dpram_addr + OF_LD_CMD);
+ can_writeb(fwArray->len, dpram_addr + OF_LD_NUM);
+ can_writeb(0, dpram_addr + OF_LD_NUM + 1);
- writel(fwArray->addr, dpram_addr + OF_LD_ADDRESS);
- /* writel already performes the cpu_to_le32 conversion by itself */
- /* writel(cpu_to_le32(fwArray->addr), dpram_addr + OF_LD_ADDRESS); */
+ can_writel(fwArray->addr, dpram_addr + OF_LD_ADDRESS);
+ /* can_writel already performes the cpu_to_le32 conversion by itself */
+ /* can_writel(cpu_to_le32(fwArray->addr), dpram_addr + OF_LD_ADDRESS); */
memcpy_toio(dpram_addr + OF_LD_DATA, fwArray->a_data, fwArray->len);
dump_mem((void *)(dpram_addr + OF_LD_SYNC), fwArray->len + 8);
#endif
/* buffer is prepared, set flag for loader */
- writeb(1, dpram_addr + OF_LD_SYNC);
+ can_writeb(1, dpram_addr + OF_LD_SYNC);
/* update pointer */
fwArray++;
/* wait for the loader */
attempt = 1000;
- while (readb(dpram_addr + OF_LD_SYNC) != 0)
+ while (can_readb(dpram_addr + OF_LD_SYNC) != 0)
{
udelay(100);
if (--attempt == 0)
CANMSG ("Firmware downladed successfully\n");
/* start the FW */
- writeb(LD_CMD_START_FW, dpram_addr + OF_LD_CMD);
- writeb(1, dpram_addr + OF_LD_SYNC);
+ can_writeb(LD_CMD_START_FW, dpram_addr + OF_LD_CMD);
+ can_writeb(1, dpram_addr + OF_LD_SYNC);
ipci165_delay (500);
return 0;
*/
int ipci165_reset(struct candevice_t *candev)
{
- unsigned long crm_addr = candev->io_addr;
+ can_ioptr_t crm_addr = candev->aux_base_addr;
unsigned long test_data;
char buffer[BCI_CMD_MAX_LEN];
int i, size, chips;
DEBUGMSG ("ipci165_reset: hardware reset\n");
/* reset the HW */
- ucr = readb(crm_addr + CRM_UCR + 3);
- writeb(ucr | 0x40, crm_addr + CRM_UCR + 3);
+ ucr = can_readb(crm_addr + CRM_UCR + 3);
+ can_writeb(ucr | 0x40, crm_addr + CRM_UCR + 3);
udelay(100);
- writeb(ucr & ~0x40, crm_addr + CRM_UCR + 3);
+ can_writeb(ucr & ~0x40, crm_addr + CRM_UCR + 3);
/* wait a little bit */
ipci165_delay(200);
#include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
- #include <linux/config.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+#include <linux/config.h>
#endif
#if defined(MODVERSIONS)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
#include <linux/tqueue.h>
-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
- #include <linux/devfs_fs_kernel.h>
+#else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+ #include <linux/devfs_fs_kernel.h>
+ #endif
#endif
#include <linux/wait.h>
#include <linux/signal.h>
#include <linux/interrupt.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
+ #include <asm/semaphore.h>
+#else
+ #include <linux/semaphore.h>
+#endif
-#include <asm/semaphore.h>
#include <linux/smp_lock.h>
#include "../include/kthread.h"
in the down operation below until the thread has reached
the up() operation.
*/
- init_MUTEX_LOCKED(&kthread->startstop_sem);
+ sema_init(&kthread->startstop_sem, 0);
/* store the function to be executed in the data passed to
the launcher */
will unlock it. As soon as we see the semaphore
unlocked, we know that the thread has exited.
*/
- init_MUTEX_LOCKED(&kthread->startstop_sem);
+ sema_init(&kthread->startstop_sem,0);
/* We need to do a memory barrier here to be sure that
the flags are visible on all CPUs.
{
unsigned long tmp;
/* Disable interrupts from card */
- tmp = inl(candev->dev_base_addr + S5920_INTCSR);
+ tmp = can_inl(candev->dev_base_addr + S5920_INTCSR);
tmp &= ~INTCSR_ADDON_INTENABLE_M;
- outl(tmp, candev->dev_base_addr + S5920_INTCSR);
+ can_outl(tmp, candev->dev_base_addr + S5920_INTCSR);
}
void kv_pcican_connect_irq(struct candevice_t *candev)
{
unsigned long tmp;
/* Enable interrupts from card */
- tmp = inl(candev->dev_base_addr + S5920_INTCSR);
+ tmp = can_inl(candev->dev_base_addr + S5920_INTCSR);
tmp |= INTCSR_ADDON_INTENABLE_M;
- outl(tmp, candev->dev_base_addr + S5920_INTCSR);
+ can_outl(tmp, candev->dev_base_addr + S5920_INTCSR);
}
}
-void kv_pcican_write_register(unsigned data, unsigned long address)
+void kv_pcican_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
-unsigned kv_pcican_read_register(unsigned long address)
+unsigned kv_pcican_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
int kv_pcican_reset(struct candevice_t *candev)
DEBUGMSG("Resetting kv_pcican hardware ...\n");
/* Assert PTADR# - we're in passive mode so the other bits are not important */
- outl(0x80808080L, candev->dev_base_addr + S5920_PTCR);
+ can_outl(0x80808080L, candev->dev_base_addr + S5920_PTCR);
kv_pcican_disconnect_irq(candev);
* email:pisa@cmp.felk.cvut.cz
* This software is released under the GPL-License.
* Version lincan-0.3 17 Jun 2004
- */
+ *
+ * 15 July 2008 updated by Philippe Corbes, email:philippe.corbes@logibag.com
+ * This driver has been designed to support "Memory (MEM)" mode.
+ * For example: Memory, MEM:0xD0000 => io=0xD0000.
+ * Configure the card with m437set.com provided by seco before loading driver.
+ * This software is released under the GPL-License.
+ */
-/*
- * Support for the SECO M437
- *
+/*
+ * Support for the SECO M437
+ *
* SECO M437 is a pc104 format, i82527 controller based card
- * produced by SECO http://www.seco.it
+ * produced by SECO http://www.seco.it
* This driver uses the Memory Mapped I/O mode, and should be
* working with all cards supporting this mode.
*
#define IO_RANGE 0x100
-static long base = 0L;
-
/**
* m437_request_io: - reserve io or memory range for can board
* @candev: pointer to candevice/board which asks for io. Field @io_addr
*
* The function m437_request_io() is used to reserve the io-memory. If your
* hardware uses a dedicated memory range as hardware control registers you
- * will have to add the code to reserve this memory as well.
+ * will have to add the code to reserve this memory as well.
* %IO_RANGE is the io-memory range that gets reserved, please adjust according
* your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
* #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
*/
int m437_request_io(struct candevice_t *candev)
{
+ can_ioptr_t remap_addr;
if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
- CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
+ CANMSG("M437 Unable to request IO-memory: 0x%lx\n",candev->io_addr);
return -ENODEV;
}
- if ( !( base = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
- CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ CANMSG("M437 Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return -ENODEV;
-
+
+ }
+ CANMSG("M437 Registered IO-memory: 0x%lx - 0x%lx\n",
+ candev->io_addr, candev->io_addr + IO_RANGE - 1);
+ CANMSG("M437 IO-memory: 0x%lx Remapped to: 0x%lx\n",
+ (unsigned long)candev->io_addr, (unsigned long)remap_addr);
+
+ /* remap the chip and pointers on objects */
+ can_base_addr_fixup(candev, remap_addr);
+
+#ifdef CAN_DEBUG
+ {
+ int objnr;
+ for (objnr=0; objnr<15 ; objnr++) {
+ DEBUGMSG("M437 Message%d remapped to: 0x%lx\n", objnr+1, candev->chip[0]->msgobj[objnr]->obj_base_addr);
+ }
}
- DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
+#endif /*CAN_DEBUG*/
+
return 0;
}
*/
int m437_release_io(struct candevice_t *candev)
{
+ /*
+ * The full board reset is more robust solution
+ * than reset of communication objects
+ * Philippe Corbes, 06 jun 2008
+ */
+#if 0 /* Object reset method */
unsigned i;
/* disable IRQ generation */
- m437_write_register(iCTL_CCE, iCTL);
+ m437_write_register(iCTL_CCE, candev->dev_base_addr+iCTL);
/* clear all message objects */
for (i=1; i<=15; i++) {
RXIE_RES |
TXIE_RES |
MVAL_RES,
- i*0x10+iMSGCTL0);
+ candev->dev_base_addr+i*0x10+iMSGCTL0);
m437_write_register(
NEWD_RES |
MLST_RES |
CPUU_RES |
TXRQ_RES |
RMPD_RES,
- i*0x10+iMSGCTL1);
+ candev->dev_base_addr+i*0x10+iMSGCTL1);
}
-
+
/* power down i82527 */
- m437_write_register(iCPU_PWD, iCPU);
-
+ m437_write_register(iCPU_PWD, candev->dev_base_addr+iCPU);
+
+#else /* Full board reset */
+ m437_reset(candev);
+#endif /* Full board reset */
+
/* release I/O memory mapping */
- iounmap((void*)base);
+ iounmap(candev->dev_base_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
+ CANMSG("M437 release - OK\n");
+
return 0;
}
* m437_reset - hardware reset routine
* @candev: Pointer to candevice/board structure
*
- * The function m437_reset() is used to give a hardware reset. This is
- * rather hardware specific so I haven't included example code. Don't forget to
+ * The function m437_reset() is used to give a hardware reset. This is
+ * rather hardware specific so I haven't included example code. Don't forget to
* check the reset status of the chip before returning.
* Return Value: The function returns zero on success or %-ENODEV on failure
* File: src/m437.c
+ * from Philippe Corbes, 08 July 2008
*/
int m437_reset(struct candevice_t *candev)
{
+ int i=0;
+
+ DEBUGMSG("Resetting %s hardware ...\n", candev->hwname);
+ for (i = 0 ; i < 10 ; i++) {
+ m437_write_register(0x01,candev->dev_base_addr+candev->res_addr);
+ }
+ m437_write_register(0x0,candev->dev_base_addr+candev->res_addr);
+
+ /* Check hardware reset status */
+ i=0;
+ while ( (m437_read_register(candev->dev_base_addr+iCPU) & iCPU_RST) && (i<=15)) {
+ udelay(20000);
+ i++;
+ }
+ if (i>=15) {
+ CANMSG("M437 Reset status timeout! Please check your hardware.\n");
+ return -ENODEV;
+ }
+ else
+ DEBUGMSG("Chip0 reset status ok.\n");
+
return 0;
}
* Return Value: The function always returns zero
* File: src/m437.c
*/
-int m437_init_hw_data(struct candevice_t *candev)
+int m437_init_hw_data(struct candevice_t *candev)
{
DEBUGMSG("m437_init_hw_data()\n");
candev->res_addr=RESET_ADDR;
candev->nr_82527_chips=1;
candev->nr_sja1000_chips=0;
- candev->nr_all_chips=1;
+ candev->nr_all_chips=1;
candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
/* The M437 has no programmable IRQ */
* The entry @int_clk_reg holds hardware specific options for the Clock Out
* register. Options defined in the %i82527.h file:
* %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
- * The entry @int_bus_reg holds hardware specific options for the Bus
+ * The entry @int_bus_reg holds hardware specific options for the Bus
* Configuration register. Options defined in the %i82527.h file:
* %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
* The entry @int_cpu_reg holds hardware specific options for the cpu interface
int m437_init_chip_data(struct candevice_t *candev, int chipnr)
{
i82527_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=candev->dev_base_addr;
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_CEN;
- candev->chip[chipnr]->int_clk_reg =
+ candev->chip[chipnr]->int_clk_reg =
iCLK_CD0 | iCLK_CD1 | iCLK_CD2 | iCLK_SL0 | iCLK_SL1;
candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
* CAN chip. In case of the sja1000 there's only one message object but on the
* i82527 chip there are 15.
* The code below is for a i82527 chip and initializes the object base addresses
- * The entry @obj_base_addr represents the first memory address of the message
+ * The entry @obj_base_addr represents the first memory address of the message
* object. In case of the sja1000 @obj_base_addr is taken the same as the chips
* base address.
* Unless the hardware uses a segmented memory map, flags can be set zero.
int m437_init_obj_data(struct canchip_t *chip, int objnr)
{
chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
-
+
return 0;
}
* m437_program_irq - program interrupts
* @candev: Pointer to candevice/board structure
*
- * The function m437_program_irq() is used for hardware that uses
+ * The function m437_program_irq() is used for hardware that uses
* programmable interrupts. If your hardware doesn't use programmable interrupts
- * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
- * leave this function unedited. Again this function is hardware specific so
+ * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
+ * leave this function unedited. Again this function is hardware specific so
* there's no example code.
* Return value: The function returns zero on success or %-ENODEV on failure
* File: src/m437.c
*/
int m437_program_irq(struct candevice_t *candev)
{
+ DEBUGMSG("M437 Programmable interrupt is not supported by the hardware!\n");
return 0;
}
* Return Value: The function does not return a value
* File: src/m437.c
*/
-void m437_write_register(unsigned data, unsigned long address)
+void m437_write_register(unsigned data, can_ioptr_t address)
{
- writeb(data,base+address);
+ DEBUGMSG("m437_write_register(@0x%lx=0x%x)\n", address, data);
+ can_writeb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/m437.c
*/
-unsigned m437_read_register(unsigned long address)
+unsigned m437_read_register(can_ioptr_t address)
{
- return readb(base+address);
+ unsigned data;
+ data = can_readb(address);
+ DEBUGMSG("m437_read_register(@0x%lx=0x%x)\n", address, data);
+ return data;
}
/* !!! Don't change this function !!! */
char *hw[MAX_HW_CARDS]={NULL,};
int irq[MAX_IRQ]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
unsigned long io[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1};
+long clockfreq[MAX_HW_CARDS];
int stdmask=0;
int extmask=0;
int mo15mask=0;
unsigned int hw_specified;
unsigned int irq_specified;
unsigned int io_specified;
+unsigned int clockfreq_specified;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))
/* Module parameters, some must be supplied at module loading time */
MODULE_PARM(major,"1i");
/*MODULE_PARM(minor, "1-" __MODULE_STRING(MAX_TOT_CHIPS)"i");*/
MODULE_PARM(hw, "1-" __MODULE_STRING(MAX_HW_CARDS)"s");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_IRQ)"i");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
+MODULE_PARM(clockfreq, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
MODULE_PARM(stdmask, "1i");
MODULE_PARM(extmask, "1i");
MODULE_PARM(mo15mask, "1i");
MODULE_PARM(processlocal, "1i");
-#else /* LINUX_VERSION_CODE >= 2,6,0 */
+#else /* LINUX_VERSION_CODE >= 2,6,12 */
module_param(major, int, 0);
module_param_array(minor, int, &minor_specified, 0);
module_param(extended, int, 0);
module_param_array(baudrate, int, &baudrate_specified, 0);
module_param_array(hw, charp, &hw_specified, 0);
module_param_array(irq, int, &irq_specified, 0);
-module_param_array(io, int, &io_specified, 0);
+module_param_array(io, ulong, &io_specified, 0);
+module_param_array(clockfreq, long, &clockfreq_specified, 0);
module_param(stdmask, int, 0);
module_param(extmask, int, 0);
module_param(mo15mask, int, 0);
module_param(processlocal, int, 0);
-#endif /* LINUX_VERSION_CODE >= 2,6,0 */
+#endif /* LINUX_VERSION_CODE >= 2,6,12 */
MODULE_PARM_DESC(major,"can be used to change default major [" __MODULE_STRING(CAN_MAJOR) "]");
MODULE_PARM_DESC(minor,"can be used to change default starting minor for each channel");
MODULE_PARM_DESC(hw,"list of boards types to initialize - virtual,pip5,...");
MODULE_PARM_DESC(irq,"list of iterrupt signal numbers, most ISA has one per chip, no value for PCI or virtual");
MODULE_PARM_DESC(io,"IO address for each board, use 0 for PCI or virtual");
+MODULE_PARM_DESC(clockfreq,"base board clock source frequency in step of 1kHz");
MODULE_PARM_DESC(stdmask,"default standard mask for i82527 chips");
MODULE_PARM_DESC(extmask,"default extended mask for i82527 chips");
MODULE_PARM_DESC(mo15mask,"mask for communication object 15 of i82527 chips");
{
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
char dev_name[32];
- #else
+ #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
struct class_device *this_dev;
+ #else
+ struct device *this_dev;
#endif
int dev_minor;
for(i=0;i<MAX_TOT_MSGOBJS;i++) {
#else
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL, "can%d", dev_minor);
- #else /* >= 2.6.15 */
+ #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL, "can%d", dev_minor);
- #endif /* >= 2.6.15 */
+ #else /* >= 2.6.26 */
+ this_dev=device_create_drvdata(can_class, NULL, MKDEV(major, dev_minor), objects_p[i], "can%d", dev_minor);
+ #endif /* >= 2.6.26 */
if(IS_ERR(this_dev)){
CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
+ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
}else{
/*this_dev->class_data=objects_p[i];*/
class_set_devdata(this_dev,objects_p[i]);
+ #endif /* <= 2.6.25 */
}
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
canqueue_rtl_done();
#endif /*CAN_WITH_RTL*/
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
unregister_chrdev(major,DEVICE_NAME);
- #else /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
- res=unregister_chrdev(major,DEVICE_NAME);
- if (res<0)
- CANMSG("Error unloading CAN driver, error: %d\n",res);
- else
- CANMSG("No CAN devices or driver setup error.\n");
- #endif /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
+ CANMSG("No CAN devices or driver setup error.\n");
register_error:
if ( can_del_mem_list() )
#else
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL, "can%d", dev_minor);
- #else /* >= 2.6.15 */
+ #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL, "can%d", dev_minor);
- #endif /* >= 2.6.15 */
+ #else /* >= 2.6.26 */
+ this_dev=device_create_drvdata(can_class, NULL, MKDEV(major, dev_minor), objects_p[i], "can%d", dev_minor);
+ #endif /* >= 2.6.26 */
if(IS_ERR(this_dev)){
CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
+ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
}else{
/*this_dev->class_data=objects_p[i];*/
class_set_devdata(this_dev,objects_p[i]);
+ #endif /* <= 2.6.25 */
}
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
#ifdef CONFIG_DEVFS_FS
devfs_remove("can%d", dev_minor);
#endif
+ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
class_device_destroy(can_class, MKDEV(major, dev_minor));
+ #else /* >= 2.6.26 */
+ device_destroy(can_class, MKDEV(major, dev_minor));
+ #endif /* >= 2.6.26 */
}
#endif
}
void cleanup_module(void)
{
- int res=0,i=0;
+#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ int i=0;
+#endif
#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
usbcan_exit();
#ifdef CONFIG_DEVFS_FS
devfs_remove("can%d", dev_minor);
#endif
+ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
class_device_destroy(can_class, MKDEV(major, dev_minor));
+ #else /* >= 2.6.26 */
+ device_destroy(can_class, MKDEV(major, dev_minor));
+ #endif /* >= 2.6.26 */
}
#endif
}
if ( can_del_mem_list() )
CANMSG("Error deallocating memory\n");
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
unregister_chrdev(major,DEVICE_NAME);
- #else /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
- res=unregister_chrdev(major,DEVICE_NAME);
- if (res<0)
- CANMSG("Error unregistering CAN driver, error: %d\n",res);
- #endif /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
}
if ( (hw[0] == NULL) | (io[0] == -1) ) {
//CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
CANMSG("Autodetection works only for USB devices, supply your type of hardware for PCI devices \n");
- CANMSG("Example: # insmod can.o hw=pip5 irq=4 io=0x8000\n");
+ CANMSG("Example: # insmod lincan.ko hw=pip5 irq=4 io=0x8000\n");
//return -ENODEV;
}
DEBUGMSG("Resetting msmcan hardware ...\n");
/* we don't use template_write_register because we don't use the two first
registers of the card but the third in order to make a hard reset */
- /* outb (1, msmcan_base + candev->res_addr); */
+ /* can_outb (1, msmcan_base + candev->res_addr); */
/* terrible MSMCAN reset design - best to comment out */
i82527_fill_chipspecops(candev->chip[chipnr]);
/* device uses indexed access */
candev->chip[chipnr]->chip_base_addr=
- candev->io_addr << 16;
+ can_ioport2ioptr(candev->io_addr << 16);
candev->chip[chipnr]->clock = 16000000;
/* The CLKOUT has to be enabled to reset MSMCAN MAX1232 watchdog */
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_CEN;
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific write process.
*/
-void msmcan_write_register(unsigned data, unsigned long address)
+void msmcan_write_register(unsigned data, can_ioptr_t address)
{
/* address is combination of base address shifted left by 16 and index */
can_spin_irqflags_t flags;
+ unsigned long addr=can_ioptr2ulong(address);
/* the msmcan card has two registers, the data register at 0x0
and the address register at 0x01 */
can_spin_lock_irqsave(&msmcan_port_lock,flags);
- outb(address & 0xff, (address>>16)+1);
- outb(data, address>>16);
+ can_outb(addr & 0xff, (addr>>16)+1);
+ can_outb(data, addr>>16);
can_spin_unlock_irqrestore(&msmcan_port_lock,flags);
}
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific read process.
*/
-unsigned msmcan_read_register(unsigned long address)
+unsigned msmcan_read_register(can_ioptr_t address)
{
/* this is the same thing that the function write_register.
We use the two register, we write the address where we
data */
unsigned char ret;
can_spin_irqflags_t flags;
-
+ unsigned long addr=can_ioptr2ulong(address);
can_spin_lock_irqsave(&msmcan_port_lock,flags);
- outb(address & 0xff, (address>>16)+1);
- ret=inb(address>>16);
+ can_outb(addr & 0xff, (addr>>16)+1);
+ ret=can_inb(addr>>16);
can_spin_unlock_irqrestore(&msmcan_port_lock,flags);
return ret;
}
(unsigned long)candev->io_addr);
}
- if (!(candev->dev_base_addr = (long)ioremap(candev->io_addr, IO_RANGE))) {
+ if (!(candev->dev_base_addr = ioremap(candev->io_addr, IO_RANGE))) {
DEBUGMSG
("Failed to map IO-memory: 0x%lx - 0x%lx, mapped to 0x%lx\n",
(unsigned long)candev->io_addr,
*/
int ns_dev_release_io(struct candevice_t *candev)
{
- u16 tempReg;
- int i;
-
DEBUGMSG("(c%d)ns_dev_release_io (...)\n", candev->chip[0]->chip_idx);
/* Release I/O memory mapping */
- iounmap((void *)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
/* Release the memory region */
can_release_mem_region(candev->io_addr, IO_RANGE);
*/
int ns_dev_init_hw_data(struct candevice_t *candev)
{
- u32 sys_contVA = 0;
+ can_ioptr_t sys_contVA = NULL;
/* LUCAN : Magic numbers */
- if (!(sys_contVA = (u32) ioremap(NS9750_PERIPHERAL_BASE_ADDRESS,
+ if (!(sys_contVA = ioremap(NS9750_PERIPHERAL_BASE_ADDRESS,
NS9750_PERIPHERAL_MAP_SIZE))) {
DEBUGMSG("Failed to map FPGA memory\n");
return -EIO;
} else {
DEBUGMSG("Writing to NS9750 sys cont\n");
- writel((BUS_WIDTH_16BIT | ACTIVE_LOW_CHIP_SELECT),
+ can_writel((BUS_WIDTH_16BIT | ACTIVE_LOW_CHIP_SELECT),
sys_contVA + NS9750_SYSTEM_CONTROLLER_OFFSET);
}
/* We have finished with this mapping */
- iounmap((void *)sys_contVA);
+ iounmap(sys_contVA);
candev->nr_82527_chips = 0;
candev->nr_sja1000_chips = 0;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void ns_dev_write_register(unsigned data, unsigned long address)
+void ns_dev_write_register(unsigned data, can_ioptr_t address)
{
int i;
//unsigned long usecs = 1;
- writew(data, address);
+ can_writew(data, address);
//udelay( usecs );
for (i = 0; i < 5; i++) ;
}
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned ns_dev_read_register(unsigned long address)
+unsigned ns_dev_read_register(can_ioptr_t address)
{
u16 value, i;
- value = readw(address);
+ value = can_readw(address);
//udelay( usecs );
for (i = 0; i < 5; i++) ;
- value = readw(address);
+ value = can_readw(address);
//udelay( usecs );
for (i = 0; i < 5; i++) ;
DEBUGMSG("Resetting nsi hardware ...\n");
/* we don't use template_write_register because we don't use the two first
register of the card but the third in order to make a hard reset */
- outb (1, nsican_base + candev->res_addr);
- outb (0, nsican_base + candev->res_addr);
+ can_outb (1, nsican_base + candev->res_addr);
+ can_outb (0, nsican_base + candev->res_addr);
for (i = 1; i < 1000; i++)
udelay (1000);
{
i82527_fill_chipspecops(candev->chip[chipnr]);
candev->chip[chipnr]->chip_base_addr=
- candev->io_addr;
+ can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
nsican_irq=candev->chip[chipnr]->chip_irq;
nsican_base=candev->chip[chipnr]->chip_base_addr;
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific write process.
*/
-void nsi_write_register(unsigned data, unsigned long address)
+void nsi_write_register(unsigned data, can_ioptr_t address)
{
/* address is an absolute address */
/* write the relative address on the eight LSB bits
and the data on the eight MSB bits in one time */
- outw(address-nsican_base + (256 * data), nsican_base);
+ can_outw(address-nsican_base + (256 * data), nsican_base);
}
/* The function template_read_register is used to read from hardware registers
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific read process.
*/
-unsigned nsi_read_register(unsigned long address)
+unsigned nsi_read_register(can_ioptr_t address)
{
/* this is the same thing that the function write_register.
We use the two register, we write the address where we
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&nsican_port_lock,flags);
- outb(address-nsican_base, nsican_base);
- ret=inb(nsican_base+1);
+ can_outb(address-nsican_base, nsican_base);
+ ret=can_inb(nsican_base+1);
can_spin_unlock_irqrestore(&nsican_port_lock,flags);
return ret;
}
#include <linux/module.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
- #define ioread32 readl
- #define iowrite32 writel
- #define ioread8 readb
- #define iowrite8 writeb
- #define wmb()
- #define rmb()
+ #define ioread32 can_readl
+ #define iowrite32 can_writel
+ #define ioread8 can_readb
+ #define iowrite8 can_writeb
#else
#endif
-#define INT_CONF 0x00000040 /* valeur de config du registre INTCSR du PLX */
+#define INT_CONF 0x00000040 /* value for register INTCSR of PLX */
#define NSI_VENDOR_ID 0x1637
#define NSI_CANPCI_DEVICE_ID 0x0001
enum PORT2 { P2_0=1, P2_1=1<<1, P2_2=1<<2, P2_3=1<<3, P2_4=1<<4, P2_5=1<<5, P2_6=1<<6, P2_7=1<<7 };
-/* Definition de tous les registres du PLX */
-#define PLX_CNTRL 0x50 /* Regitre de control */
-#define PLX_INTCSR 0x4C /* Registe pour les interruptions */
-
-/* Horloge en Hz du chip i82527 respecter le tableau suivant: */
-/* =========================================
- * | XTAL | SCLK (DSC bit) | MCLK (DMC bit) |
- * |======|================|================|
- * | 4MHz | 4MHz (0) | 4MHz (0) | NE PAS OUBLIER DE POSITIONNER LES BITS DSC et DMC EN FONTION
- * | 8MHz | 8MHz (0) | 8MHz (0) |
- * |10MHz | 10MHz (0) | 5MHz (1) |
- * |12MHz | 6MHZ (1) | 6MHZ (0) |
- * |16MHz | 8MHz (1) | 8MHz (0) |
- * ========================================== */
+/*PLX register definition */
+#define PLX_CNTRL 0x50 /* Controle register */
+#define PLX_INTCSR 0x4C /* Interruption controle register */
+
+/* This value define the i82527 clock frequency */
#define iCLOCK 16000000
-static CAN_DEFINE_SPINLOCK(nsicanpci_port_lock);
/* Il faut reserver 4 zones:
* BAR0: 128 octets memoire (32bits) pour les registres du PLX9052
*/
/* Variables globales contenant les @ des IO-Memory apres remap */
#define NB_VALID_BAR 4
-void* addr_BAR_remap[NB_VALID_BAR]={0,0,0,0};
+
+typedef struct {
+ void* addr_BAR_remap[NB_VALID_BAR];
+}t_CardArray;
void nsi_canpci_connect_irq(struct candevice_t *candev)
{
- /* Preparation du registre pour configurer les INT locales 1 et 2 du PLX, INT actif à l'etat Haut */
-// iowrite32(INT_CONF,(void*)(candev->dev_base_addr+PLX_INTCSR));
-// wmb();
-// DEBUGMSG("Interruptions du PLX configurees !!\n");
-
+//Not used
}
void nsi_canpci_disconnect_irq(struct candevice_t *candev)
{
-// Il faut aussi desactiver les interruption du PLX, sous peine de freeze au prochain init_module
-// tout en laissant le bit isa mis a 1
- iowrite32(0x0,(void*)(candev->dev_base_addr+PLX_INTCSR));
- wmb();
- DEBUGMSG("disable interruption du PLX\n");
+//on disconnecting interrupt we need to disable interruption form PLX
+ iowrite32(0x0,(void*)(candev->io_addr+PLX_INTCSR));
+ DEBUGMSG("PLX interrupt disabled\n");
}
int nsi_canpci_config_irqs(struct canchip_t *chip, short irqs)
unsigned long it_mask,it_reg;
struct candevice_t *candev;
it_mask=0;
- DEBUGMSG("NSI Interrupt configuration\n");
+ DEBUGMSG("Configuring NSI CANPCI interrupt\n");
can_write_reg(chip,irqs,iCTL);
if( (irqs&0x0E)!=0)
{//At least one interrupt source requested
DEBUGMSG("starting interrupt on chip 1\n");
it_mask=8;
}
- candev=(struct candevice_t *)chip->chip_data;
- it_reg = ioread32( (void*)(candev->dev_base_addr+PLX_INTCSR));
- rmb();
+ candev=chip->hostdevice;
+ it_reg = ioread32( (void*)(candev->io_addr+PLX_INTCSR));
it_reg|=it_mask|0x40;
- iowrite32(it_reg,(void*)(candev->dev_base_addr+PLX_INTCSR));
- wmb();
+ iowrite32(it_reg,(void*)(candev->io_addr+PLX_INTCSR));
}
else
{//No more interrupt source
DEBUGMSG("stoping interrupt on chip 1\n");
it_mask=8;
}
- candev=(struct candevice_t *)chip->chip_data;
- it_reg = ioread32( (void*)(candev->dev_base_addr+PLX_INTCSR));
- rmb();
+ candev=chip->hostdevice;
+ it_reg = ioread32( (void*)(candev->io_addr+PLX_INTCSR));
it_reg&=~it_mask;
- iowrite32(it_reg,(void*)(candev->dev_base_addr+PLX_INTCSR));
- wmb();
+ iowrite32(it_reg,(void*)(candev->io_addr+PLX_INTCSR));
}
return 0;
}
int nsi_canpci_i82527_chip_config(struct canchip_t *chip)
{
- //Normale fonction
can_write_reg(chip,chip->int_cpu_reg,iCPU); // Configure cpu interface
can_write_reg(chip,(iCTL_CCE|iCTL_INI),iCTL); // Enable configuration
i82527_seg_write_reg(chip,chip->int_clk_reg,iCLK); // Set clock out slew rates
i82527_seg_write_reg(chip,chip->int_bus_reg,iBUS); /* Bus configuration */
- can_write_reg(chip,P2_2|P2_1,iP2C); // Configure P2_2,P2_1 en sortie
- can_write_reg(chip,P2_2|P2_1,iP2O); // Positionne P2_2 a 1
+ can_write_reg(chip,P2_2|P2_1,iP2C); // The pin P2_2,P2_1 of the 527 must be set as output
+ can_write_reg(chip,P2_2|P2_1,iP2O); // and P2_2 must be set to 1
can_write_reg(chip,0x00,iSTAT); /* Clear error status register */
DEBUGMSG("starting chip 1\n");
it_mask=8;
}
- candev=(struct candevice_t *)chip->chip_data;
- it_reg = ioread32( (void*)(candev->dev_base_addr+PLX_INTCSR));
+ candev=chip->hostdevice;
+ it_reg = ioread32( (void*)(candev->io_addr+PLX_INTCSR));
rmb();
it_reg|=it_mask|0x40;
- iowrite32(it_reg,(void*)(candev->dev_base_addr+PLX_INTCSR));
+ iowrite32(it_reg,(void*)(candev->io_addr+PLX_INTCSR));
wmb();
i82527_start_chip(chip);
return 0;
DEBUGMSG("stoping chip 1\n");
it_mask=8;
}
- candev=(struct candevice_t *)chip->chip_data;
- it_reg = ioread32( (void*)(candev->dev_base_addr+PLX_INTCSR));
+ candev=chip->hostdevice;
+ it_reg = ioread32( (void*)(candev->io_addr+PLX_INTCSR));
rmb();
it_reg&=~it_mask;
- iowrite32(it_reg,(void*)(candev->dev_base_addr+PLX_INTCSR));
+ iowrite32(it_reg,(void*)(candev->io_addr+PLX_INTCSR));
wmb();
i82527_stop_chip(chip);
return 0;
int retcode;
unsigned long it_reg;
struct candevice_t *candev;
- candev=(struct candevice_t *)chip->chip_data;
+ candev=chip->hostdevice;
retcode = CANCHIP_IRQ_NONE;
- it_reg = ioread32( (void*)(candev->dev_base_addr+PLX_INTCSR));
+ it_reg = ioread32( (void*)(candev->io_addr+PLX_INTCSR));
rmb();
if(chip->chip_idx==0)
{
if((it_reg &0x4)!=0) //interrupt active
{
if(i82527_irq_handler(irq,chip)==CANCHIP_IRQ_NONE)
- {//soucis avec les IT
+ {//some trouble with IT
it_reg&=~(0x01);
- CANMSG("IT du canal0 annulee pour cause de dysonctionnement\n");
+ CANMSG("Unexcepted interruption from canal0, interruption is canceled\n");
}else
{
}
else
{
- if((it_reg &0x20)!=0) //interrupt active
+ if((it_reg &0x20)!=0) //interrupt is set
{
if(i82527_irq_handler(irq,chip)==CANCHIP_IRQ_NONE)
{//soucis avec les IT
it_reg&=~(0x08);
- CANMSG("IT du canal1 annulee pour cause de dysonctionnement\n");
+ CANMSG("Unexcepted interruption from canal1, interruption is canceled\n");
}else
{
retcode=CANCHIP_IRQ_HANDLED;
int nsi_canpci_request_io(struct candevice_t *candev)
{
(void)candev;
- if(addr_BAR_remap[0]==NULL)
+ if(candev->dev_base_addr==0)
return -EIO;
return 0;
}
{
unsigned long reg_reset;
struct pci_dev *pcidev = candev->sysdevptr.pcidev;
- DEBUGMSG("Liberation des io de la carte \n");
+ DEBUGMSG("Releasing board io\n");
nsi_canpci_disconnect_irq(candev);
- // Recherche du registre de controle du PLX parmi les IO-port du PLX */
- reg_reset = ioread32( (void*)(candev->dev_base_addr+PLX_CNTRL));
+ // First, set RESET signal to 0
+ reg_reset = ioread32( (void*)(candev->io_addr+PLX_CNTRL));
reg_reset&=(~(0x40000000));
rmb();
- iowrite32( (reg_reset | 0x40000000 ),(void*)(candev->dev_base_addr+PLX_CNTRL)); /* Mise à '1' du bit reset */
+ //Then set it to '1' for reseting the board
+ iowrite32( (reg_reset | 0x40000000 ),(void*)(candev->io_addr+PLX_CNTRL));
wmb();
- udelay(2500); /* Reset supérieur a 1ms car necessaire aux i82527 */
- iowrite32( (reg_reset ),(void*)(candev->dev_base_addr+PLX_CNTRL)); /* Mise à '0' du bit reset */
+ udelay(2500); /* This delay must be greater than 1ms for i82527 */
+ iowrite32( (reg_reset ),(void*)(candev->io_addr+PLX_CNTRL)); //Releasing RESET signal
wmb();
- udelay(2500); /* Reset supérieur a 1ms car necessaire aux i82527 */
- iounmap(addr_BAR_remap[0]);
- iounmap(addr_BAR_remap[1]);
- iounmap(addr_BAR_remap[2]);
- iounmap(addr_BAR_remap[3]);
-
+ udelay(2500); // Waiting for some additionnal time before writing in the 82527
+ iounmap(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]);
+ iounmap(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[1]);
+ iounmap(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[2]);
+ iounmap(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[3]);
+ kfree((void*)(candev->dev_base_addr));
pci_release_region(pcidev,0);
pci_release_region(pcidev,1);
pci_release_region(pcidev,2);
{
unsigned long reg_reset;
- DEBUGMSG("Reset de la carte !!!\n");
- /* Il faut aussi desactiver les interruption du PLX, sous peine de freeze au prochain init_module */
+ DEBUGMSG("Board reset !!!\n");
+ // Before reset disconnet interrupt to avoir freeze
nsi_canpci_disconnect_irq(candev);
- // Recherche du registre de controle du PLX parmi les IO-port du PLX */
- reg_reset = ioread32( (void*)(candev->dev_base_addr+PLX_CNTRL));
+ // First, set RESET signal to 0
+ reg_reset = ioread32( (void*)(candev->io_addr+PLX_CNTRL));
reg_reset&=(~(0x40000000));
- iowrite32( (reg_reset | 0x40000000 ),(void*)(candev->dev_base_addr+PLX_CNTRL)); /* Mise à '1' du bit reset */
+ //Then set it to '1' for reseting the board
+ iowrite32( (reg_reset | 0x40000000 ),(void*)(candev->io_addr+PLX_CNTRL));
wmb();
- udelay(2500); /* Reset supérieur a 1ms car necessaire aux i82527 */
- iowrite32(reg_reset,(void*)(candev->dev_base_addr+PLX_CNTRL)); /* Mise à '0' du bit reset */
+ udelay(2500); /* This delay must be greater than 1ms for i82527 */
+ iowrite32(reg_reset,(void*)(candev->io_addr+PLX_CNTRL)); //Releasing RESET signal
wmb();
- udelay(2500); /* Attente, pour laisser les composants s'initialiser */
- DEBUGMSG("Reset termine !!!\n");
+ udelay(2500); // Waiting for some additionnal time before writing in the 82527
+ DEBUGMSG("Reset done !!!\n");
nsi_canpci_connect_irq(candev);
return 0;
{
struct pci_dev *pcidev = NULL;
- /* recherche de la carte NSI CANPCI sur le bus */
+ /* looking for NSI CANPCI ident on the pci bus*/
do
{
pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID, pcidev);
{
return -EIO;
}
+ candev->dev_base_addr=(unsigned long)(kmalloc(sizeof(t_CardArray),GFP_ATOMIC));
- addr_BAR_remap[0]=ioremap(pci_resource_start(pcidev,0),pci_resource_len(pcidev,0) );
- addr_BAR_remap[1]=ioremap(pci_resource_start(pcidev,1),pci_resource_len(pcidev,1) );
- addr_BAR_remap[2]=ioremap(pci_resource_start(pcidev,2),pci_resource_len(pcidev,2) );
- addr_BAR_remap[3]=ioremap(pci_resource_start(pcidev,3),pci_resource_len(pcidev,3) );
+ if((unsigned long)candev->dev_base_addr==0)
+ return -EIO;
+ //PLX register
+ ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]=ioremap(pci_resource_start(pcidev,0),pci_resource_len(pcidev,0) );
+ //PLX IO
+ ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[1]=ioremap(pci_resource_start(pcidev,1),pci_resource_len(pcidev,1) );
+ //Chip 0
+ ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[2]=ioremap(pci_resource_start(pcidev,2),pci_resource_len(pcidev,2) );
+ //Chip 1
+ ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[3]=ioremap(pci_resource_start(pcidev,3),pci_resource_len(pcidev,3) );
- candev->dev_base_addr=(unsigned long)(addr_BAR_remap[0]);
+ //Short acces to plx register
+ candev->io_addr=(unsigned long)(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]);
return 0;
}
candev->chip[chipnr]->chipspecops->stop_chip=nsi_canpci_stop_chip;
candev->chip[chipnr]->chipspecops->config_irqs=nsi_canpci_config_irqs;
candev->chip[chipnr]->chipspecops->irq_handler=nsi_canpci_irq_handler;
- candev->chip[chipnr]->chip_data =candev;
+ /*candev->chip[chipnr]->chip_data = NULL;*/
- candev->chip[chipnr]->chip_base_addr= (unsigned long)addr_BAR_remap[chipnr+2];
- candev->chip[chipnr]->clock = 16000000;
+ candev->chip[chipnr]->chip_base_addr= (unsigned long) (((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[chipnr+2]);
+ candev->chip[chipnr]->clock = iCLOCK;
candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
candev->chip[chipnr]->flags=CHIP_IRQ_PCI;
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC+iCPU_CEN;
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific write process.
*/
-void nsi_canpci_write_register(unsigned data, unsigned long address)
+void nsi_canpci_write_register(unsigned data, can_ioptr_t address)
{
iowrite8((u8)data,(void*)address);
- wmb(); /* Assure que la donnee a ete ecrite */
}
/* The function template_read_register is used to read from hardware registers
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific read process.
*/
-unsigned nsi_canpci_read_register(unsigned long address)
+unsigned nsi_canpci_read_register(can_ioptr_t address)
{
- /* this is the same thing that the function write_register.
- We use the two register, we write the address where we
- want to read in a first time. In a second time we read the
- data */
- unsigned char ret;
- can_spin_irqflags_t flags;
- can_spin_lock_irqsave(&nsicanpci_port_lock,flags);
- rmb();
- ret=ioread8((void*)address);
- can_spin_unlock_irqrestore(&nsicanpci_port_lock,flags);
- return ret;
+ return ioread8((void*)address);
}
struct canque_ends_t *qends;
struct canque_edge_t *edge;
can_spin_irqflags_t iflags;
+ char openflag; // Martin Petera: Object already opened
if ( ((obj=objects_p[MINOR_NR]) == NULL) ||
((chip=objects_p[MINOR_NR]->hostchip) == NULL) ) {
atomic_inc(&obj->obj_used);
DEBUGMSG("Device %d opened %d times.\n", MINOR_NR, atomic_read(&obj->obj_used));
+ openflag = can_msgobj_test_fl(obj,OPENED); // Martin Petera: store previous status
can_msgobj_set_fl(obj,OPENED);
if (chip->flags & CHIP_CONFIGURED)
CANMSG("Error configuring chip.\n");
else
chip->flags |= CHIP_CONFIGURED;
+ } /* End of chip configuration */
+
+ /* Martin Petera: Fix for HCAN2
+ * pre_read was called only once -> Opening second MSG object from userspace
+ * didn't call function to configure MSG object for receive.
+ * FIX: Call pre_read once for each MSG object
+ **/
+ if (!openflag) {
if (chip->chipspecops->pre_read_config(chip,obj)<0)
CANMSG("Error initializing chip for receiving\n");
+ }
- } /* End of chip configuration */
canuser = (struct canuser_t *)kmalloc(sizeof(struct canuser_t), GFP_KERNEL);
if(canuser == NULL) goto no_canuser;
#endif
return 0;
-
+
no_rx_qedge:
canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED);
canque_edge_decref(edge);
// sja1000_fill_chipspecops(candev->chip[chipnr]);
sja1000p_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr = candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr = can_ioport2ioptr(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;
return 0;
}
-void oscar_write_register(unsigned data, unsigned long address)
+void oscar_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
-unsigned oscar_read_register(unsigned long address)
+unsigned oscar_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
/* !!! Don't change this function !!! */
* Return Value: The function does not return a value
* File: src/pc-i03.c
*/
-void pci03_write_register(unsigned data, unsigned long address)
+void pci03_write_register(unsigned data, can_ioptr_t address)
{
unsigned int *pci03_base_ptr;
unsigned short address_to_write;
* Return Value: The function returns the value stored in @address
* File: src/pc-i03.c
*/
-unsigned pci03_read_register(unsigned long address)
+unsigned pci03_read_register(can_ioptr_t address)
{
unsigned int *pci03_base_ptr;
unsigned short address_to_read;
#define ECR_PORT_SIZE 1 // size of the associated ECR register
#define DNG_DEFAULT_COUNT 4 // count of defaults for init
-typedef void (*PARPORT_IRQ_HANLDER)(int, void *, struct pt_regs *);
+typedef void (*PARPORT_IRQ_HANLDER)(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id));
/****************************************************************************/
// GLOBALS
static void _parport_disable_irq(struct DONGLE_PORT *dng)
{
u16 _PC_ = (u16)dng->dwPort + 2;
- outb(inb(_PC_) & ~0x10, _PC_);
+ can_outb(can_inb(_PC_) & ~0x10, _PC_);
}
static void _parport_enable_irq(struct DONGLE_PORT *dng)
{
u16 _PC_ = (u16)dng->dwPort + 2;
- outb(inb(_PC_) | 0x10, _PC_);
+ can_outb(can_inb(_PC_) | 0x10, _PC_);
}
u16 _PB_ = _PA_ + 1;
u16 _PC_ = _PB_ + 1;
u8 b0, b1 ;
- u8 irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
+ u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&pcan_lock, flags);
- outb((0x0B ^ 0x0D) | irqEnable, _PC_);
- outb((port & 0x1F) | 0x80, _PA_);
- outb((0x0B ^ 0x0C) | irqEnable, _PC_);
- b1=nibble_decode[inb(_PB_)>>3];
- outb(0x40, _PA_);
- b0=nibble_decode[inb(_PB_)>>3];
- outb((0x0B ^ 0x0D) | irqEnable, _PC_);
+ can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
+ can_outb((port & 0x1F) | 0x80, _PA_);
+ can_outb((0x0B ^ 0x0C) | irqEnable, _PC_);
+ b1=nibble_decode[can_inb(_PB_)>>3];
+ can_outb(0x40, _PA_);
+ b0=nibble_decode[can_inb(_PB_)>>3];
+ can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
can_spin_unlock_irqrestore(&pcan_lock, flags);
{
u16 _PA_ = (u16)dng->dwPort;
u16 _PC_ = _PA_ + 2;
- u8 irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
+ u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&pcan_lock, flags);
- outb((0x0B ^ 0x0D) | irqEnable, _PC_);
- outb(port & 0x1F, _PA_);
- outb((0x0B ^ 0x0C) | irqEnable, _PC_);
- outb(data, _PA_);
- outb((0x0B ^ 0x0D) | irqEnable, _PC_);
+ can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
+ can_outb(port & 0x1F, _PA_);
+ can_outb((0x0B ^ 0x0C) | irqEnable, _PC_);
+ can_outb(data, _PA_);
+ can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
can_spin_unlock_irqrestore(&pcan_lock, flags);
}
u16 _PA_ = (u16)dng->dwPort;
u16 _PC_ = _PA_ + 2;
u8 wert;
- u8 irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
+ u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&pcan_lock, flags);
- outb((0x0B ^ 0x0F) | irqEnable, _PC_);
- outb((port & 0x1F) | 0x80, _PA_);
- outb((0x0B ^ 0x2E) | irqEnable, _PC_);
- wert = inb(_PA_);
- outb((0x0B ^ 0x0F) | irqEnable, _PC_);
+ can_outb((0x0B ^ 0x0F) | irqEnable, _PC_);
+ can_outb((port & 0x1F) | 0x80, _PA_);
+ can_outb((0x0B ^ 0x2E) | irqEnable, _PC_);
+ wert = can_inb(_PA_);
+ can_outb((0x0B ^ 0x0F) | irqEnable, _PC_);
can_spin_unlock_irqrestore(&pcan_lock, flags);
{
u16 wEcr = dng->wEcr;
- dng->ucOldECRContent = inb(wEcr);
- outb((dng->ucOldECRContent & 0x1F) | 0x20, wEcr);
+ dng->ucOldECRContent = can_inb(wEcr);
+ can_outb((dng->ucOldECRContent & 0x1F) | 0x20, wEcr);
if (dng->ucOldECRContent == 0xff)
DEBUGMSG("%s: realy ECP mode configured?\n", DEVICE_NAME);
{
u16 wEcr = dng->wEcr;
- outb(dng->ucOldECRContent, wEcr);
+ can_outb(dng->ucOldECRContent, wEcr);
DEBUGMSG("%s: restore ECR\n", DEVICE_NAME);
}
wPort = (u16)dng->dwPort;
// save old port contents
- dng->ucOldDataContent = inb(wPort);
- dng->ucOldControlContent = inb(wPort + 2);
+ dng->ucOldDataContent = can_inb(wPort);
+ dng->ucOldControlContent = can_inb(wPort + 2);
// switch to epp mode if possible
if (dng->wType == HW_DONGLE_SJA_EPP)
restoreECR(dng);
// restore port state
- outb(dng->ucOldDataContent, wPort);
- outb(dng->ucOldControlContent, wPort + 2);
+ can_outb(dng->ucOldDataContent, wPort);
+ can_outb(dng->ucOldControlContent, wPort + 2);
parport_release(dng->pardev);
candev->chip[chipnr]->chip_type=CHIP_TYPE;
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_clk_reg = 0x0;
candev->chip[chipnr]->int_bus_reg = 0x0;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void pcan_dongle_write_register(unsigned data, unsigned long address)
+void pcan_dongle_write_register(unsigned data, can_ioptr_t address)
{
address -= dongle_port.chip->chip_base_addr; // it's in mutiplexed mode
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned pcan_dongle_read_register(unsigned long address)
+unsigned pcan_dongle_read_register(can_ioptr_t address)
{
u8 val;
--- /dev/null
+/* pcan_pci.c - support for PEAK System PCAN-PCI cards
+ * 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
+ */
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/sja1000p.h"
+
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+/* This card is based on Infineon's PSB 4600 PITA bridge */
+
+#define PITA_ICR 0x00 /* interrupt control register */
+#define PITA_ICR_STAT 0x00 /* - status/IRQ pending bits */
+#define PITA_ICR_IEN 0x02 /* - IRQ enable bits */
+#define PITA_GPIOICR 0x18 /* general purpose IO interface control register */
+#define PITA_MISC 0x1C /* misc register */
+
+#define PCAN_PCI_CONFIG_PORT_SIZE 0x1000 /* size of the config io-memory */
+#define PCAN_PCI_PORT_SIZE 0x0400 /* size of a channel io-memory */
+
+#define PCAN_PCI_VENDOR_ID 0x001C /* PCAN-PCI and clones vednor id */
+#define PCAN_PCI_PRODUCT_ID 0x0001 /* PCAN-PCI and clones device ID */
+
+/* Standard value: Pushpull (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1) */
+#define PCAN_PCI_OCR_DEFAULT_STD 0xFA
+
+#define PCAN_PCI_BYTES_PER_CIRCUIT 0x400
+#define PCAN_PCI_BYTES_PER_REG 4
+
+/* Conversion of the chip index to IRQ register mask */
+static unsigned int pcan_pci_idx2mask[4]={
+ 0x0002,
+ 0x0001,
+ 0x0040,
+ 0x0080
+};
+
+void pcan_pci_disconnect_irq(struct candevice_t *candev)
+{
+ u16 w;
+
+ /* disable interrupts sources */
+ w = can_readw(candev->aux_base_addr + PITA_ICR_IEN);
+ can_writew(w & ~0xC3, candev->aux_base_addr + PITA_ICR_IEN);
+}
+
+void pcan_pci_connect_irq(struct candevice_t *candev)
+{
+ u16 w;
+ int i;
+
+ /* clear previous accumulated status */
+ can_writew(0xC3, candev->aux_base_addr + PITA_ICR_STAT);
+
+ /* enable interrupts sources */
+ w = can_readw(candev->aux_base_addr + PITA_ICR_IEN);
+ for(i = 0; i < candev->nr_all_chips; i++)
+ w |= pcan_pci_idx2mask[i];
+ can_writew(w, candev->aux_base_addr + PITA_ICR_IEN);
+}
+
+
+int pcan_pci_request_io(struct candevice_t *candev)
+{
+ unsigned long ctrl_addr;
+ unsigned long io_addr;
+ int i;
+
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ if(pci_request_region(candev->sysdevptr.pcidev, 0, "pcan_pci_ctrl") != 0){
+ CANMSG("Request of pcan_pci_ctrl range failed\n");
+ return -ENODEV;
+ }else if(pci_request_region(candev->sysdevptr.pcidev, 1, "pcan_pci_io") != 0){
+ CANMSG("Request of pcan_pci_io range failed\n");
+ goto error_io;
+ }
+ #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ if(pci_request_regions(candev->sysdevptr.pcidev, "pcan_pci") != 0){
+ CANMSG("Request of pcan_pci_bridge regions failed\n");
+ return -ENODEV;
+ }
+ #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+
+ ctrl_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
+ if (!(candev->aux_base_addr = ioremap(ctrl_addr,
+ pci_resource_len(candev->sysdevptr.pcidev,0)))) {
+ CANMSG("Unable to access I/O memory at: 0x%lx\n", ctrl_addr);
+ goto error_ioremap_ctrl;
+ }
+
+ io_addr=pci_resource_start(candev->sysdevptr.pcidev,1);;
+ if (!(candev->dev_base_addr = ioremap(io_addr,
+ pci_resource_len(candev->sysdevptr.pcidev,1)))) {
+ CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
+ goto error_ioremap_io;
+ }
+
+ candev->io_addr=io_addr;
+ candev->res_addr=ctrl_addr;
+
+ /*
+ * this is redundant with chip initialization, but remap address
+ * can change when resources are temporarily released
+ */
+ for(i=0;i<candev->nr_all_chips;i++) {
+ struct canchip_t *chip=candev->chip[i];
+ if(!chip) continue;
+ chip->chip_base_addr = candev->dev_base_addr +
+ i * PCAN_PCI_BYTES_PER_CIRCUIT;
+ if(!chip->msgobj[0]) continue;
+ chip->msgobj[0]->obj_base_addr=chip->chip_base_addr;
+ }
+
+ pcan_pci_disconnect_irq(candev);
+
+ /* Configure PITA */
+ can_writew(0x0005, candev->aux_base_addr + PITA_GPIOICR + 2); /* set GPIO control register */
+
+ can_writeb(0x00, candev->aux_base_addr + PITA_GPIOICR); /* enable all channels */
+
+ can_writeb(0x05, candev->aux_base_addr + PITA_MISC + 3); /* toggle reset */
+ mdelay(5);
+ writeb(0x04, candev->aux_base_addr + PITA_MISC + 3); /* leave parport mux mode */
+ wmb();
+
+ return 0;
+
+ error_ioremap_io:
+ iounmap(candev->aux_base_addr);
+ error_ioremap_ctrl:
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ pci_release_region(candev->sysdevptr.pcidev, 1);
+ error_io:
+ 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 -ENODEV;
+}
+
+int pcan_pci_release_io(struct candevice_t *candev)
+{
+ pcan_pci_disconnect_irq(candev);
+
+ iounmap(candev->dev_base_addr);
+ iounmap(candev->aux_base_addr);
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ 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 pcan_pci_write_register(unsigned data, can_ioptr_t address)
+{
+ address += ((can_ioptr2ulong(address)&(PCAN_PCI_BYTES_PER_CIRCUIT-1))
+ *(PCAN_PCI_BYTES_PER_REG-1));
+ can_writeb(data,address);
+}
+
+unsigned pcan_pci_read_register(can_ioptr_t address)
+{
+ address += ((can_ioptr2ulong(address)&(PCAN_PCI_BYTES_PER_CIRCUIT-1))
+ *(PCAN_PCI_BYTES_PER_REG-1));
+ return can_readb(address);
+}
+
+int pcan_pci_irq_handler(int irq, struct canchip_t *chip)
+{
+ struct candevice_t *candev=chip->hostdevice;
+ int ret;
+ unsigned int icr_stat;
+ unsigned int chip_mask = pcan_pci_idx2mask[chip->chip_idx];
+
+ icr_stat = can_readw(candev->aux_base_addr + PITA_ICR_STAT);
+
+ if(!(icr_stat & chip_mask)) return CANCHIP_IRQ_NONE;
+
+ ret = sja1000p_irq_handler(irq, chip);
+
+ can_writew(chip_mask, candev->aux_base_addr + PITA_ICR_STAT);
+
+ return ret;
+}
+
+int pcan_pci_reset(struct candevice_t *candev)
+{
+ int i=0,chip_nr;
+ struct canchip_t *chip;
+ unsigned cdr;
+
+ DEBUGMSG("Resetting pcan_pci hardware ...\n");
+
+ pcan_pci_disconnect_irq(candev);
+
+ for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
+ if(!candev->chip[chip_nr]) continue;
+ chip=candev->chip[chip_nr];
+
+ pcan_pci_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
+ udelay(1000);
+
+ cdr=pcan_pci_read_register(chip->chip_base_addr+SJACDR);
+ pcan_pci_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ pcan_pci_write_register(0, chip->chip_base_addr+SJAIER);
+
+ i=20;
+ pcan_pci_write_register(0, chip->chip_base_addr+SJAMOD);
+ while (pcan_pci_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
+ if(!i--) return -ENODEV;
+ udelay(1000);
+ pcan_pci_write_register(0, chip->chip_base_addr+SJAMOD);
+ }
+
+ cdr=pcan_pci_read_register(chip->chip_base_addr+SJACDR);
+ pcan_pci_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ pcan_pci_write_register(0, chip->chip_base_addr+SJAIER);
+
+ pcan_pci_read_register(chip->chip_base_addr+SJAIR);
+ }
+
+
+ pcan_pci_connect_irq(candev);
+
+ return 0;
+}
+
+int pcan_pci_init_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = NULL;
+ int i;
+ int nr_chips;
+ u16 subsysid;
+
+ i = 0;
+ do {
+ pcidev = pci_find_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID, pcidev);
+ if(pcidev == NULL) {
+ printk(KERN_ERR "No unused PCAN_PCI #%d card found\n", i);
+ return -ENODEV;
+ }
+ i++;
+ } while(can_check_dev_taken(pcidev));
+
+ if (pci_enable_device (pcidev)){
+ printk(KERN_ERR "Enable PCAN_PCI failed\n");
+ return -EIO;
+ }
+ candev->sysdevptr.pcidev=pcidev;
+
+ if(pci_read_config_word(pcidev, 0x2E, &subsysid))
+ goto error_ret;
+
+ if(pci_write_config_word(pcidev, 0x04, 2))
+ goto error_ret;
+
+ if(pci_write_config_word(pcidev, 0x44, 0))
+ goto error_ret;
+
+ wmb();
+
+ for(i=0;i<2;i++){
+ if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
+ printk(KERN_ERR "PCAN_PCI region %d is not memory\n",i);
+ goto error_ret;
+ }
+ }
+
+ candev->res_addr=pci_resource_start(pcidev,0); /* Control registers */
+ candev->io_addr=pci_resource_start(pcidev,1); /* SJA1000 chips are mapped here */
+ candev->dev_base_addr=pci_resource_start(pcidev,1);
+
+ /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
+
+ if(subsysid >= 12)
+ nr_chips = 4;
+ else if(subsysid >= 10)
+ nr_chips = 3;
+ else if(subsysid >= 4)
+ nr_chips = 2;
+ else
+ nr_chips = 1;
+
+ candev->nr_82527_chips=0;
+ candev->nr_sja1000_chips=nr_chips;
+ candev->nr_all_chips=nr_chips;
+
+ printk(KERN_INFO "Found PCAN_PCI device with %d chip(s)\n", nr_chips);
+
+ return 0;
+
+error_ret:
+
+ printk(KERN_CRIT "Setup of PCAN_PCI failed\n");
+ pci_disable_device (pcidev);
+ return -EIO;
+}
+
+int pcan_pci_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+
+ if(candev->sysdevptr.pcidev==NULL)
+ return -ENODEV;
+
+ sja1000p_fill_chipspecops(candev->chip[chipnr]);
+
+ /* special version of the IRQ handler is required for PCAN_PCI board */
+ candev->chip[chipnr]->chipspecops->irq_handler=pcan_pci_irq_handler;
+
+ candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
+
+ candev->chip[chipnr]->chip_base_addr=
+ can_ioport2ioptr(candev->io_addr+chipnr*PCAN_PCI_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 = sjaCDR_CBP | sjaCDR_CLK_OFF;
+ candev->chip[chipnr]->sja_ocr_reg = PCAN_PCI_OCR_DEFAULT_STD;
+ candev->chip[chipnr]->clock = 16000000;
+ candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
+
+ return 0;
+}
+
+int pcan_pci_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+ return 0;
+}
+
+int pcan_pci_program_irq(struct candevice_t *candev)
+{
+
+ return 0;
+}
+
+int pcan_pci_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = pcan_pci_request_io;
+ hwspecops->release_io = pcan_pci_release_io;
+ hwspecops->reset = pcan_pci_reset;
+ hwspecops->init_hw_data = pcan_pci_init_hw_data;
+ hwspecops->init_chip_data = pcan_pci_init_chip_data;
+ hwspecops->init_obj_data = pcan_pci_init_obj_data;
+ hwspecops->write_register = pcan_pci_write_register;
+ hwspecops->read_register = pcan_pci_read_register;
+ hwspecops->program_irq = pcan_pci_program_irq;
+ return 0;
+}
+
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
DEBUGMSG("Resetting pccanf/s hardware ...\n");
while (i < 1000000) {
i++;
- outb(0x00,candev->res_addr);
+ can_outb(0x00,candev->res_addr);
}
- outb(0x01,candev->res_addr);
- outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
+ can_outb(0x01,candev->res_addr);
+ can_outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
/* Check hardware reset status */
i=0;
- while ( (inb(candev->chip[0]->chip_base_addr+SJACR) & sjaCR_RR)
+ while ( (can_inb(candev->chip[0]->chip_base_addr+SJACR) & sjaCR_RR)
&& (i<=15) ) {
udelay(20000);
i++;
DEBUGMSG("Resetting pccan-d hardware ...\n");
while (i < 1000000) {
i++;
- outb(0x00,candev->res_addr);
+ can_outb(0x00,candev->res_addr);
}
- outb(0x01,candev->res_addr);
- outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
- outb(0x00,candev->chip[1]->chip_base_addr+SJACR);
+ can_outb(0x01,candev->res_addr);
+ can_outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
+ can_outb(0x00,candev->chip[1]->chip_base_addr+SJACR);
/* Check hardware reset status */
i=0;
for (chip_nr=0; chip_nr<2; chip_nr++) {
i=0;
- while ( (inb(candev->chip[chip_nr]->chip_base_addr +
+ while ( (can_inb(candev->chip[chip_nr]->chip_base_addr +
SJACR) & sjaCR_RR) && (i<=15) ) {
udelay(20000);
i++;
DEBUGMSG("Resetting pccan-q hardware ...\n");
while (i < 100000) {
i++;
- outb(0x00,candev->res_addr);
+ can_outb(0x00,candev->res_addr);
}
outb_p(0x01,candev->res_addr);
- outb(0x00,candev->chip[2]->chip_base_addr+SJACR);
- outb(0x00,candev->chip[3]->chip_base_addr+SJACR);
+ can_outb(0x00,candev->chip[2]->chip_base_addr+SJACR);
+ can_outb(0x00,candev->chip[3]->chip_base_addr+SJACR);
/* Check hardware reset status */
for (chip_nr=0; chip_nr<2; chip_nr++) {
i=0;
- while( (inb(candev->chip[chip_nr]->chip_base_addr +
+ while( (can_inb(candev->chip[chip_nr]->chip_base_addr +
iCPU) & iCPU_RST) && (i<=15) ) {
udelay(20000);
i++;
}
for (chip_nr=2; chip_nr<4; chip_nr++) {
i=0;
- while( (inb(candev->chip[chip_nr]->chip_base_addr +
+ while( (can_inb(candev->chip[chip_nr]->chip_base_addr +
SJACR) & sjaCR_RR) && (i<=15) ) {
udelay(20000);
i++;
candev->chip[chipnr]->sja_ocr_reg =
sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
}
- candev->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x2000+candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(0x1000*chipnr+0x2000+candev->io_addr);
}
else {
sja1000_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x4000+candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(0x1000*chipnr+0x4000+candev->io_addr);
candev->chip[chipnr]->flags = 0;
candev->chip[chipnr]->int_cpu_reg = 0;
candev->chip[chipnr]->int_clk_reg = 0;
}
}
}
- outb(irq_reg_value,0x6000+candev->io_addr);
+ can_outb(irq_reg_value,0x6000+candev->io_addr);
DEBUGMSG("Configured pccan hardware interrupts\n");
- outb(0x80,0x6000+candev->io_addr+0x02);
+ can_outb(0x80,0x6000+candev->io_addr+0x02);
DEBUGMSG("Selected pccan on-board 16 MHz oscillator\n");
return 0;
}
-inline void pccan_write_register(unsigned data, unsigned long address)
+inline void pccan_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
-unsigned pccan_read_register(unsigned long address)
+unsigned pccan_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
int pccanf_register(struct hwspecops_t *hwspecops)
DEBUGMSG("Resetting pcccan-1 hardware ...\n");
while (i < 1000000) {
i++;
- outb(0x0,candev->res_addr);
+ can_outb(0x0,candev->res_addr);
}
/* Check hardware reset status */
i=0;
- outb(iCPU,candev->io_addr+0x1);
- while ( (inb(candev->io_addr+0x2)&0x80) && (i<=15) ) {
+ can_outb(iCPU,candev->io_addr+0x1);
+ while ( (can_inb(candev->io_addr+0x2)&0x80) && (i<=15) ) {
udelay(20000);
i++;
}
int pcccan_init_chip_data(struct candevice_t *candev, int chipnr)
{
i82527_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_DMC;
candev->chip[chipnr]->int_clk_reg = iCLK_SL1 | iCLK_CD0;
* Return Value: The function does not return a value
* File: src/pcccan.c
*/
-void pcccan_write_register(unsigned data, unsigned long address)
+void pcccan_write_register(unsigned data, can_ioptr_t address)
{
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&pcccan_port_lock,flags);
- outb(address - pcccan_base, pcccan_base+1);
- outb(data, pcccan_base+6);
+ can_outb(address - pcccan_base, pcccan_base+1);
+ can_outb(data, pcccan_base+6);
can_spin_unlock_irqrestore(&pcccan_port_lock,flags);
}
* Return Value: The function returns the value stored in @address
* File: src/pcccan.c
*/
-unsigned pcccan_read_register(unsigned long address)
+unsigned pcccan_read_register(can_ioptr_t address)
{
unsigned ret;
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&pcccan_port_lock,flags);
- outb(address - pcccan_base, pcccan_base+1);
- ret=inb(pcccan_base+2);
+ can_outb(address - pcccan_base, pcccan_base+1);
+ ret=can_inb(pcccan_base+2);
can_spin_unlock_irqrestore(&pcccan_port_lock,flags);
return ret;
*/
int pcm3680_request_io(struct candevice_t *candev)
{
- unsigned long remap_addr;
+ can_ioptr_t remap_addr;
if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - pcm3680")) {
CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
return -ENODEV;
}
- if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return -ENODEV;
{
sja1000p_fill_chipspecops(candev->chip[chipnr]);
candev->chip[chipnr]->chip_base_addr=
- candev->io_addr + 0x200*chipnr;
+ candev->dev_base_addr + 0x200*chipnr;
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_clk_reg = 0x0;
candev->chip[chipnr]->int_bus_reg = 0x0;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void pcm3680_write_register(unsigned data, unsigned long address)
+void pcm3680_write_register(unsigned data, can_ioptr_t address)
{
- writeb(data,address);
+ can_writeb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned pcm3680_read_register(unsigned long address)
+unsigned pcm3680_read_register(can_ioptr_t address)
{
- return readb(address);
+ return can_readb(address);
}
/* !!! Don't change this function !!! */
*/
int pikronisa_request_io(struct candevice_t *candev)
{
- int remap_addr;
+ can_ioptr_t remap_addr;
if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - pikronisa")) {
CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
return -ENODEV;
}
- if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return -ENODEV;
int pikronisa_release_io(struct candevice_t *candev)
{
/* release I/O memory mapping */
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return 0;
/*sja1000_fill_chipspecops(candev->chip[chipnr]);*/
sja1000p_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=candev->dev_base_addr;
candev->chip[chipnr]->clock = 24000000;
candev->chip[chipnr]->int_clk_reg = 0x0;
candev->chip[chipnr]->int_bus_reg = 0x0;
* Return Value: The function does not return a value
* File: src/pikronisa.c
*/
-void pikronisa_write_register(unsigned data, unsigned long address)
+void pikronisa_write_register(unsigned data, can_ioptr_t address)
{
/*DEBUGMSG("pikronisa_write_register: addr=0x%lx data=0x%x",
address,data);*/
- writeb(data,address);
+ can_writeb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/pikronisa.c
*/
-unsigned pikronisa_read_register(unsigned long address)
+unsigned pikronisa_read_register(can_ioptr_t address)
{
- return readb(address);
+ return can_readb(address);
}
/* !!! Don't change this function !!! */
*/
int pimx1_request_io(struct candevice_t *candev)
{
- int remap_addr;
+ can_ioptr_t remap_addr;
if(pimx1_setup_hardware(candev)<0){
CANMSG("PiMX1 board hardware setup failure\n");
* Return Value: The function does not return a value
* File: src/pikronisa.c
*/
-void pimx1_write_register(unsigned data, unsigned long address)
+void pimx1_write_register(unsigned data, can_ioptr_t address)
{
/*DEBUGMSG("pimx1_write_register: addr=0x%lx data=0x%x\n",
address,data);*/
- writeb(data,address);
+ can_writeb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/pikronisa.c
*/
-unsigned pimx1_read_register(unsigned long address)
+unsigned pimx1_read_register(can_ioptr_t address)
{
- return readb(address);
+ return can_readb(address);
}
/**
DEBUGMSG("Resetting %s hardware ...\n", candev->hwname);
while (i < 1000000) {
i++;
- outb(0x01, candev->res_addr);
+ can_outb(0x01, candev->res_addr);
}
- outb(0x0, candev->res_addr);
+ can_outb(0x0, candev->res_addr);
/* Check hardware reset status */
i = 0;
- while ((inb(candev->io_addr + iCPU) & iCPU_RST) && (i <= 15)) {
+ while ((can_inb(candev->io_addr + iCPU) & iCPU_RST) && (i <= 15)) {
udelay(20000);
i++;
}
int pip_init_chip_data(struct candevice_t *candev, int chipnr)
{
i82527_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr = candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr = can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 8000000;
candev->chip[chipnr]->int_cpu_reg = 0;
candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
unsigned char can_addr = 0, can_reg = 0;
DEBUGMSG("pip_program_irq\n");
/* Reset can controller */
- outb(0x01, candev->res_addr);
+ can_outb(0x01, candev->res_addr);
if (strcmp(candev->hwname, "pip5") == 0) {
irq_mask = PIP5_IRQ_MAP;
} else if (strcmp(candev->hwname, "pip6") == 0) {
return -ENODEV;
}
}
- can_reg = inb(PIP_CANRES_REG);
+ can_reg = can_inb(PIP_CANRES_REG);
DEBUGMSG("PIP_CANRES was 0x%x\n", can_reg);
can_reg = (candev->chip[0]->chip_irq << 4) | can_addr;
DEBUGMSG("Setting PIP_CANRES_REG to 0x%x\n", can_reg);
- outb((candev->chip[0]->chip_irq << 4) | can_addr, PIP_CANRES_REG);
+ can_outb((candev->chip[0]->chip_irq << 4) | can_addr, PIP_CANRES_REG);
/* re-enable the chip */
- outb(0x00, candev->res_addr);
+ can_outb(0x00, candev->res_addr);
return 0;
}
-void pip_write_register(unsigned data, unsigned long address)
+void pip_write_register(unsigned data, can_ioptr_t address)
{
- outb(data, address);
+ can_outb(data, address);
}
-unsigned pip_read_register(unsigned long address)
+unsigned pip_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
/* !!! Don't change these functions !!! */
static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
+#define CAN_PROC_ROOT (&proc_root)
+#else /* >= 2.6.26 */
+#define CAN_PROC_ROOT (NULL)
+#endif /* >= 2.6.26 */
+
static int cc=0; /* static counter for each CAN chip */
static struct canproc_t can_proc_base;
mutex_init(&proc_mutex);
base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
- S_IXUGO, &proc_root);
+ S_IXUGO, CAN_PROC_ROOT);
if (base->can_proc_entry == NULL)
return -ENODEV;
if (remove_channels_from_procdir())
return -ENODEV;
/* name: "can" */
- if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
+ if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
return -ENODEV;
return 0;
len += sprintf(buf+len,"type : %s\n",chip->chip_type);
len += sprintf(buf+len,"index : %d\n",chip->chip_idx);
len += sprintf(buf+len,"irq : %d\n",chip->chip_irq);
- len += sprintf(buf+len,"addr : %lu\n",chip->chip_base_addr);
+ len += sprintf(buf+len,"addr : %lu\n",
+ can_ioptr2ulong(chip->chip_base_addr));
len += sprintf(buf+len,"config : %s\n",
- (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
+ (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
len += sprintf(buf+len,"clock : %ld Hz\n",chip->clock);
len += sprintf(buf+len,"baud : %ld\n",chip->baudrate);
len += sprintf(buf+len,"num obj : %d\n",chip->max_objects);
int init_hwspecops(struct candevice_t *candev, int *irqnum_p);
int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
-int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
+int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate, long clock);
int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr);
int next_minor=0;
* This function is prepared to simplify board specific xxx_request_io() function
* for memory mapped devices.
*/
-int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
+int can_base_addr_fixup(struct candevice_t *candev, can_ioptr_t new_base)
{
- unsigned long offs;
+ long offs;
int i, j;
offs=new_base-candev->dev_base_addr;
int chipnr;
long bd;
int irqsig=-1;
+ long clock;
candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
if (candev==NULL)
candev->hwname=hw[card];
candev->io_addr=io[card];
candev->dev_base_addr=io[card];
+ clock=clockfreq[card];
candev->hwspecops=(struct hwspecops_t *)can_checked_malloc(sizeof(struct hwspecops_t));
if (candev->hwspecops==NULL)
bd=baudrate[*chan_param_idx_p+chipnr];
if(!bd) bd=baudrate[0];
- if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
+ if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000, clock*1000)))
goto error_chip;
}
* @chipnr: index of the chip in the corresponding device/board structure
* @irq: chip IRQ number or (-1) if not appropriate
* @baudrate: baudrate in the units of 1Bd
+ * @clock: optional chip base clock frequency in 1Hz step
*
* Chip structure is allocated and chip specific operations are filled by
* call to board specific init_chip_data() which calls chip specific
*
* Return Value: returns negative number in the case of fail
*/
-int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate)
+int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate, long clock)
{
struct canchip_t *chip;
int objnr;
chip->hostdevice=candev;
chip->chip_irq=irq;
chip->baudrate=baudrate;
+ chip->clock=clock;
chip->flags=0x0;
if(candev->hwspecops->init_chip_data(candev,chipnr)<0)
--- /dev/null
+/* sh7760.c
+* Linux CAN-bus device driver.
+* This software is released under the GPL-License.
+*/
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/sh7760.h"
+#include "../include/hcan2.h"
+
+int sh7760_request_io(struct candevice_t *candev)
+{
+ if (!can_request_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE, DEVICE_NAME)) {
+ CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
+ return -ENODEV;
+ }
+
+ DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + candev->nr_all_chips * IO_RANGE - 1);
+ return 0;
+}
+
+int sh7760_release_io(struct candevice_t *candev)
+{
+ can_release_io_region(candev->io_addr, candev->nr_all_chips * IO_RANGE);
+
+ return 0;
+}
+
+int sh7760_reset(struct candevice_t *candev)
+{
+ int i;
+ DEBUGMSG("Resetting HCAN2 chips ...\n");
+
+ for (i = 0; i < candev->nr_all_chips; i++)
+ {
+ /* !!! Assuming this card has ONLY HCAN2 chips !!! */
+ if (hcan2_reset_chip(candev->chip[i])) return -ENODEV;
+ }
+
+ return 0;
+}
+
+int sh7760_init_hw_data(struct candevice_t *candev)
+{
+ /* candev->res_addr = RESET_ADDR; */
+ candev->nr_82527_chips = NR_82527;
+ candev->nr_sja1000_chips = NR_SJA1000;
+ candev->nr_all_chips = NR_ALL;
+ /* candev->flags |= CANDEV_PROGRAMMABLE_IRQ; */
+
+ return 0;
+}
+int sh7760_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+ hcan2_fill_chipspecops(candev->chip[chipnr]);
+
+ candev->chip[chipnr]->chip_base_addr = can_ioport2ioptr(candev->io_addr) + chipnr * SH7760_CAN_CHIP_OFFSET; /* one chip with 2 interfaces */
+ candev->chip[chipnr]->clock = SH7760_CAN_CLOCK;
+ candev->chip[chipnr]->chip_irq = SH7760_CAN_IRQ + chipnr;
+ candev->chip[chipnr]->hostdevice = candev;
+
+ return 0;
+}
+
+int sh7760_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr = (can_ioptr_t) HCAN2_MB0 + HCAN2_MB_OFFSET * objnr;
+
+ return 0;
+}
+
+int sh7760_program_irq(struct candevice_t *candev)
+{
+ /* sh7760 doesn't use programmable interrupt */
+ return 0;
+}
+
+
+void sh7760_write_register(unsigned data, can_ioptr_t address)
+{
+ /* address is an absolute address */
+ writew(data, address);
+}
+
+unsigned sh7760_read_register(can_ioptr_t address)
+{
+ /* address is an absolute address */
+ return readw(address);
+}
+
+int sh7760_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = sh7760_request_io;
+ hwspecops->release_io = sh7760_release_io;
+ hwspecops->reset = sh7760_reset;
+ hwspecops->init_hw_data = sh7760_init_hw_data;
+ hwspecops->init_chip_data = sh7760_init_chip_data;
+ hwspecops->init_obj_data = sh7760_init_obj_data;
+ hwspecops->program_irq = sh7760_program_irq;
+ hwspecops->write_register = sh7760_write_register;
+ hwspecops->read_register = sh7760_read_register;
+ return 0;
+}
chipspecops->start_chip = sja1000_start_chip;
chipspecops->stop_chip = sja1000_stop_chip;
chipspecops->irq_handler = sja1000_irq_handler;
- chipspecops->irq_handler = NULL;
+ chipspecops->irq_accept = NULL;
return 0;
}
int i=0;
DEBUGMSG("Resetting smartcan hardware ...\n");
- outb(0x00,candev->res_addr);
+ can_outb(0x00,candev->res_addr);
while (i < 1000000) {
i++;
- outb(0x01,candev->res_addr);
+ can_outb(0x01,candev->res_addr);
}
- outb(0x00,candev->res_addr);
+ can_outb(0x00,candev->res_addr);
/* Check hardware reset status */
i=0;
- outb(candev->io_addr+iCPU,candev->io_addr);
- while ( (inb(candev->io_addr+1)&0x80) && (i<=15) ) {
+ can_outb(candev->io_addr+iCPU,candev->io_addr);
+ while ( (can_inb(candev->io_addr+1)&0x80) && (i<=15) ) {
udelay(20000);
i++;
}
int smartcan_init_chip_data(struct candevice_t *candev, int chipnr)
{
i82527_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
}
-void smartcan_write_register(unsigned data, unsigned long address)
+void smartcan_write_register(unsigned data, can_ioptr_t address)
{
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&smartcan_port_lock,flags);
- outb(address-smartcan_base,smartcan_base);
- outb(data,smartcan_base+1);
+ can_outb(address-smartcan_base,smartcan_base);
+ can_outb(data,smartcan_base+1);
can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
}
-unsigned smartcan_read_register(unsigned long address)
+unsigned smartcan_read_register(can_ioptr_t address)
{
unsigned ret;
can_spin_irqflags_t flags;
can_spin_lock_irqsave(&smartcan_port_lock,flags);
- outb(address-smartcan_base,smartcan_base);
- ret=inb(smartcan_base+1);
+ can_outb(address-smartcan_base,smartcan_base);
+ ret=can_inb(smartcan_base+1);
can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
return ret;
}
#include "../include/i82527.h"
int ssvcan_irq[2]={-1,-1};
-unsigned long ssvcan_base=0x0;
+can_ioptr_t ssvcan_base=0x0;
static CAN_DEFINE_SPINLOCK(ssv_port_lock);
{
i82527_fill_chipspecops(candev->chip[chipnr]);
candev->chip[chipnr]->chip_base_addr=
- candev->io_addr+0x100*chipnr;
+ can_ioport2ioptr(candev->io_addr+0x100*chipnr);
candev->chip[chipnr]->clock = 16000000;
ssvcan_irq[chipnr]=candev->chip[chipnr]->chip_irq;
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific write process.
*/
-void ssv_write_register(unsigned data, unsigned long address)
+void ssv_write_register(unsigned data, can_ioptr_t address)
{
/* address is an absolute address */
/* write the relative address on the eight LSB bits
and the data on the eight MSB bits in one time */
if((address-ssvcan_base)<0x100)
- outw(address-ssvcan_base + (256 * data), ssvcan_base);
+ can_outw(address-ssvcan_base + (256 * data), ssvcan_base);
else
- outw(address-ssvcan_base-0x100 + (256 * data), ssvcan_base+0x02);
+ can_outw(address-ssvcan_base-0x100 + (256 * data), ssvcan_base+0x02);
}
/* The function template_read_register is used to read from hardware registers
* on the CAN chip. You should only have to edit this function if your hardware
* uses some specific read process.
*/
-unsigned ssv_read_register(unsigned long address)
+unsigned ssv_read_register(can_ioptr_t address)
{
/* this is the same thing that the function write_register.
We use the two register, we write the address where we
if((address-ssvcan_base)<0x100)
{
can_spin_lock_irqsave(&ssv_port_lock,flags);
- outb(address-ssvcan_base, ssvcan_base);
- ret=inb(ssvcan_base+1);
+ can_outb(address-ssvcan_base, ssvcan_base);
+ ret=can_inb(ssvcan_base+1);
can_spin_unlock_irqrestore(&ssv_port_lock,flags);
}
else
{
can_spin_lock_irqsave(&ssv_port_lock,flags);
- outb(address-ssvcan_base-0x100, ssvcan_base+0x02);
- ret=inb(ssvcan_base+1+0x02);
+ can_outb(address-ssvcan_base-0x100, ssvcan_base+0x02);
+ ret=can_inb(ssvcan_base+1+0x02);
can_spin_unlock_irqrestore(&ssv_port_lock,flags);
}
* components/comm/contrib directory. */
#endif
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif /*IRQF_SHARED*/
/**
* can_checked_malloc - memory allocation with registering of requested blocks
*
* File: src/setup.c
*/
-can_irqreturn_t can_default_irq_dispatch(int irq, void *dev_id, struct pt_regs *regs)
+can_irqreturn_t can_default_irq_dispatch(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id))
{
int retval;
struct canchip_t *chip=(struct canchip_t *)dev_id;
- retval=chip->chipspecops->irq_handler(irq, chip);
+ retval=chip->chipspecops->irq_handler(irq_number, chip);
return CAN_IRQ_RETVAL(retval);
}
return 1;
if ((chip->flags & CHIP_IRQ_VME) == 0) {
- if (request_irq(chip->chip_irq,can_default_irq_dispatch,SA_SHIRQ,DEVICE_NAME,chip))
+ if (request_irq(chip->chip_irq,can_default_irq_dispatch,IRQF_SHARED,DEVICE_NAME,chip))
return -1;
else {
DEBUGMSG("Registered interrupt %d\n",chip->chip_irq);
/*sja1000_fill_chipspecops(candev->chip[chipnr]);*/
/*sja1000p_fill_chipspecops(candev->chip[chipnr]);*/
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
candev->chip[chipnr]->clock = 16000000;
candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
* Return Value: The function does not return a value
* File: src/template.c
*/
-void template_write_register(unsigned data, unsigned long address)
+void template_write_register(unsigned data, can_ioptr_t address)
{
- outb(data,address);
+ can_outb(data,address);
}
/**
* Return Value: The function returns the value stored in @address
* File: src/template.c
*/
-unsigned template_read_register(unsigned long address)
+unsigned template_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
/* !!! Don't change this function !!! */
static CAN_DEFINE_SPINLOCK(ts7kv_win_lock);
-long clock[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1};
-MODULE_PARM(clock, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
-MODULE_PARM_DESC(clock,"clock frequency for each board in step of 1kHz");
-
-long tscanio[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1};
-MODULE_PARM(tscanio, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
-MODULE_PARM_DESC(tscanio,"TSCAN CAN controller IO address for each board");
+unsigned long tscanio[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1};
+unsigned int tscanio_specified;
#if defined(TS7XXX_IO8_BASE)&&defined(TSXXX_BASE_IO)
int tsxxx_base=TS7XXX_IO8_BASE+TSXXX_BASE_IO;
#else /*TS7XXX_IO8_BASE*/
unsigned long tsxxx_base=0;
#endif /*TS7XXX_IO8_BASE*/
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))
+MODULE_PARM(tscanio, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
MODULE_PARM(tsxxx_base, "1i");
+#else /* LINUX_VERSION_CODE >= 2,6,12 */
+module_param_array(tscanio, int, &tscanio_specified, 0);
+module_param(tsxxx_base, ulong, 0);
+#endif /* LINUX_VERSION_CODE >= 2,6,12 */
+
+MODULE_PARM_DESC(tscanio,"TSCAN CAN controller IO address for each board");
MODULE_PARM_DESC(tsxxx_base,"The base of the ISA/8-bit IO space for TSxxx CAN peripherals in the system");
-unsigned short ts7kv_isused = 0x0;
/**
* tscan1_request_io: - reserve io or memory range for can board
default: mode=0x60; break;
}
- outb(0x00, candev->io_addr+TSCAN1_WIN_REG);
- outb(mode, candev->io_addr+TSCAN1_MOD_REG);
+ can_outb(0x00, candev->io_addr+TSCAN1_WIN_REG);
+ can_outb(mode, candev->io_addr+TSCAN1_MOD_REG);
return 0;
}
can_release_io_region(remap_can_io_addr, TSXXX_CAN_RANGE);
}
- outb(0x20, candev->io_addr+TSCAN1_MOD_REG);
+ can_outb(0x20, candev->io_addr+TSCAN1_MOD_REG);
can_release_io_region(candev->io_addr, TSXXX_IO_RANGE);
return 0;
return -ENODEV;
do {
- if (inb(remap_io_addr+TSXXX_ID0_REG)!=TSCAN1_ID0 ||
- inb(remap_io_addr+TSXXX_ID1_REG)!=TSCAN1_ID1)
+ if (can_inb(remap_io_addr+TSXXX_ID0_REG)!=TSCAN1_ID0 ||
+ can_inb(remap_io_addr+TSXXX_ID1_REG)!=TSCAN1_ID1)
break;
- outb(0x00, remap_io_addr+TSCAN1_WIN_REG);
- outb(0x20, remap_io_addr+TSCAN1_MOD_REG);
+ can_outb(0x00, remap_io_addr+TSCAN1_WIN_REG);
+ can_outb(0x20, remap_io_addr+TSCAN1_MOD_REG);
if(pjmp)
- *pjmp = inb(remap_io_addr+TSCAN1_JMP_REG);
+ *pjmp = can_inb(remap_io_addr+TSCAN1_JMP_REG);
result = 0;
} while (0);
io_addr = candev->io_addr;
if(io_addr && (io_addr != (unsigned long)-1)) {
- remap_io_addr = io_addr = tsxxx_base;
+ remap_io_addr = io_addr + tsxxx_base;
if(tscan1_check_presence(remap_io_addr, &jmp)){
CANMSG("No TSCAN1 card found at address 0xlx\n");
}
io_addr = TSCAN1_BASE_IO + i*TSXXX_IO_RANGE;
- remap_io_addr = io_addr = tsxxx_base;
+ remap_io_addr = io_addr + tsxxx_base;
for (j = 0; j < MAX_HW_CARDS; j++) {
if(io[j] == io_addr){
return -ENODEV;
do {
- if (inb(remap_io_addr+TSXXX_ID0_REG)!=TS7KV_ID0 ||
- inb(remap_io_addr+TSXXX_ID1_REG)!=TS7KV_ID1)
+ if (can_inb(remap_io_addr+TSXXX_ID0_REG)!=TS7KV_ID0 ||
+ can_inb(remap_io_addr+TSXXX_ID1_REG)!=TS7KV_ID1)
break;
if(pjmp)
- *pjmp = inb(remap_io_addr+TS7KV_JMP_REG);
+ *pjmp = can_inb(remap_io_addr+TS7KV_JMP_REG);
result = 0;
} while (0);
io_addr = candev->io_addr;
if(io_addr && (io_addr != (unsigned long)-1)) {
- remap_io_addr = io_addr = tsxxx_base;
+ remap_io_addr = io_addr + tsxxx_base;
if(ts7kv_check_presence(remap_io_addr, &jmp)){
CANMSG("No TS7KV card found at address 0xlx\n");
}
io_addr = TS7KV_BASE_IO + i*TSXXX_IO_RANGE;
- remap_io_addr = io_addr = tsxxx_base;
+ remap_io_addr = io_addr + tsxxx_base;
for (j = 0; j < MAX_HW_CARDS; j++) {
if(io[j] == io_addr){
*/
int tscan1_init_chip_data(struct candevice_t *candev, int chipnr)
{
- unsigned long clk;
+ unsigned long default_clk = 16000 * 1000;
int jmp;
int irq = -1;
- clk = clock[candev->candev_idx];
- if(!clk || (clk == -1))
- clk = 16000 * 1000;
- else
- clk *= 1000;
-
/* unused reset address is used to store jumper setting */
jmp = candev->res_addr;
sja1000p_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->clock = clk;
+ if(candev->chip[chipnr]->clock <= 0)
+ candev->chip[chipnr]->clock = default_clk;
candev->chip[chipnr]->int_clk_reg = 0x0;
candev->chip[chipnr]->int_bus_reg = 0x0;
candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
int ts7kv_init_chip_data(struct candevice_t *candev, int chipnr)
{
- unsigned long clk;
+ unsigned long default_clk = 16000 * 1000;
int jmp;
int irq = -1;
- clk = clock[candev->candev_idx];
- if(!clk || (clk == -1))
- clk = 24000 * 1000;
- else
- clk *= 1000;
-
/* unused reset address is used to store jumper setting */
jmp = candev->res_addr;
sja1000p_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->clock = clk;
+ if(candev->chip[chipnr]->clock <= 0)
+ candev->chip[chipnr]->clock = default_clk;
candev->chip[chipnr]->int_clk_reg = 0x0;
candev->chip[chipnr]->int_bus_reg = 0x0;
candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
* Return Value: The function does not return a value
* File: src/tscan1.c
*/
-void tscan1_write_register(unsigned data, unsigned long address)
+void tscan1_write_register(unsigned data, can_ioptr_t address)
{
- outb(data, address);
+ can_outb(data, address);
}
-void ts7kv_write_register(unsigned data, unsigned long address)
+void ts7kv_write_register(unsigned data, can_ioptr_t address)
{
- unsigned long base = address & ~0x1f;
+ unsigned long addr=can_ioptr2ulong(address);
+ can_ioptr_t base = can_ulong2ioptr(addr & ~0x1f);
unsigned char nwin = 0x10;
unsigned char savewin;
can_spin_irqflags_t flags;
- if((address&0x1f) > 0x1d) {
+ if((addr&0x1f) > 0x1d) {
nwin++;
address -= 0x10;
}
can_spin_lock_irqsave(&ts7kv_win_lock,flags);
- savewin = inb(base+TS7KV_WIN_REG);
+ savewin = can_inb(base+TS7KV_WIN_REG);
if(nwin == savewin) {
- outb(data, address);
+ can_outb(data, address);
}else{
- outb(nwin, base+TS7KV_WIN_REG);
- outb(data, address);
- outb(savewin, base+TS7KV_WIN_REG);
+ can_outb(nwin, base+TS7KV_WIN_REG);
+ can_outb(data, address);
+ can_outb(savewin, base+TS7KV_WIN_REG);
}
can_spin_unlock_irqrestore(&ts7kv_win_lock,flags);
}
* Return Value: The function returns the value stored in @address
* File: src/tscan1.c
*/
-unsigned tscan1_read_register(unsigned long address)
+unsigned tscan1_read_register(can_ioptr_t address)
{
- return inb(address);
+ return can_inb(address);
}
-unsigned ts7kv_read_register(unsigned long address)
+unsigned ts7kv_read_register(can_ioptr_t address)
{
- unsigned long base = address & ~0x1f;
+ unsigned long addr=can_ioptr2ulong(address);
+ can_ioptr_t base = can_ulong2ioptr(addr & ~0x1f);
unsigned char nwin = 0x10;
unsigned char savewin;
unsigned val;
can_spin_irqflags_t flags;
- if((address&0x1f) > 0x1d) {
+ if((addr&0x1f) > 0x1d) {
nwin++;
address -= 0x10;
}
can_spin_lock_irqsave(&ts7kv_win_lock,flags);
- savewin = inb(base+TS7KV_WIN_REG);
+ savewin = can_inb(base+TS7KV_WIN_REG);
if(nwin == savewin) {
- val = inb(address);
+ val = can_inb(address);
}else{
- outb(nwin, base+TS7KV_WIN_REG);
- val = inb(address);
- outb(savewin, base+TS7KV_WIN_REG);
+ can_outb(nwin, base+TS7KV_WIN_REG);
+ val = can_inb(address);
+ can_outb(savewin, base+TS7KV_WIN_REG);
}
can_spin_unlock_irqrestore(&ts7kv_win_lock,flags);
*/
int unican_request_io(struct candevice_t *candev)
{
- unsigned long remap_addr;
+ can_ioptr_t remap_addr;
if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - unican")) {
CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
return -ENODEV;
}
- if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return -ENODEV;
*/
int unican_release_io(struct candevice_t *candev)
{
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
can_release_mem_region(candev->io_addr,IO_RANGE);
return 0;
}
chip->int_clk_reg = 0x0;
chip->int_bus_reg = 0x0;
chip->max_objects = 1;
- chip->chip_base_addr=candev->io_addr;
+ chip->chip_base_addr=candev->dev_base_addr;
CANMSG("initializing unican chip operations\n");
chip->chipspecops->chip_config=unican_chip_config;
int unican_pci_request_io(struct candevice_t *candev)
{
- unsigned long remap_addr;
+ can_ioptr_t remap_addr;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
if(pci_request_region(candev->sysdevptr.pcidev, 0, "unican_pci") != 0){
}
#endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
- candev->dev_base_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
- candev->io_addr=candev->dev_base_addr;
- candev->res_addr=candev->dev_base_addr;
+ candev->io_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
+ candev->res_addr=candev->io_addr;
- if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+ if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 0);
can_base_addr_fixup(candev, remap_addr);
DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
DEBUGMSG("VMA: dev_base_addr: 0x%lx chip_base_addr: 0x%lx\n",
- candev->dev_base_addr, candev->chip[0]->chip_base_addr);
+ can_ioptr2ulong(candev->dev_base_addr),
+ can_ioptr2ulong(candev->chip[0]->chip_base_addr));
return 0;
}
int unican_pci_release_io(struct candevice_t *candev)
{
- iounmap((void*)candev->dev_base_addr);
+ iounmap(candev->dev_base_addr);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
pci_release_region(candev->sysdevptr.pcidev, 0);
#else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
printk(KERN_CRIT "Unican PCI region 0 is not MEM\n");
return -EIO;
}
- candev->dev_base_addr=pci_resource_start(pcidev,0);
- candev->io_addr=candev->dev_base_addr;
- candev->res_addr=candev->dev_base_addr;
+ candev->io_addr=pci_resource_start(pcidev,0);
+ candev->res_addr=candev->io_addr;
+ candev->dev_base_addr=NULL;
/*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
# Generic directory or leaf node makefile for OCERA make framework
ifndef MAKERULES_DIR
-MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
endif
ifeq ($(MAKERULES_DIR),)
all : default
.DEFAULT::
@echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
-else
+else
include $(MAKERULES_DIR)/Makefile.rules
endif