From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Thu, 20 Mar 2003 12:43:29 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Thu, 20 Mar 2003 12:43:29 -0500 Received: from mail.copper.net ([65.247.64.20]:58381 "EHLO mail.copper.net") by vger.kernel.org with ESMTP id ; Thu, 20 Mar 2003 12:42:52 -0500 Message-ID: <005501c2ef09$c6f93480$54491cd8@CEVE> From: "george cewe" To: Subject: submission of CAN driver for i82527 chip Date: Thu, 20 Mar 2003 12:54:36 -0500 Organization: ceve inc MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0052_01C2EEDF.DCC6A9C0" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.50.4522.1200 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200 Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org This is a multi-part message in MIME format. ------=_NextPart_000_0052_01C2EEDF.DCC6A9C0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Dear Kernel Maintainer; Please find enclosed 2 files of a driver for Intel 82527 CAN Controller, This driver is a simplified version of 'ocan' driver by Allesandro Rubini. 'jcan' is a character driver for kernel 2.4 and up, I inserted it in linux_root/drivers/char directory. I tested it on embedded MPC823 platform, but it should be running on other platforms as well. This is first time I submit a Linux driver and I would appreciate your comments. regards George Cewe. ------=_NextPart_000_0052_01C2EEDF.DCC6A9C0 Content-Type: text/plain; name="jcan.h" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="jcan.h" /*=0A= * jcan.h -- header for the CAN driver=0A= *=0A= * Copyright (C) 2003 George Cewe =0A= * Copyright (C) 2003 Advanced Concepts Inc.=0A= * Copyright (C) 2002 Alessandro Rubini =0A= * Copyright (C) 2001 Ascensit S.p.A =0A= * Author: Rodolfo Giometti =0A= *=0A= *=0A= * This program is free software; you can redistribute it and/or modify=0A= * it under the terms of the GNU General Public License as published by=0A= * the Free Software Foundation; either version 2 of the License, or=0A= * (at your option) any later version.=0A= *=0A= * This program is distributed in the hope that it will be useful,=0A= * but WITHOUT ANY WARRANTY; without even the implied warranty of=0A= * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A= * GNU General Public License for more details.=0A= *=0A= * You should have received a copy of the GNU General Public License=0A= * along with this program; if not, write to the Free Software=0A= * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA = 02111-1307, USA.=0A= */=0A= =0A= #ifndef __JCAN_H__=0A= #define __JCAN_H__=0A= =0A= #include =0A= =0A= #define CAN_READ_BUFS 64 /* read buffer has 64 messages */=0A= =0A= =0A= #define I527_XTD_XTD 0x04=0A= #define I527_XTD_STD 0x00=0A= =0A= /*=0A= * data structures used in both kernel and user space (mostly for ioctl)=0A= */=0A= typedef enum=0A= { B_100K=0A= ,B_125K=0A= ,B_250K=0A= ,B_500K=0A= ,B_1M=0A= ,BPS_MAX=0A= } BPS;=0A= =0A= typedef struct =0A= {=0A= __u8 reg;=0A= __u8 val;=0A= } CAN_REG;=0A= =0A= #define CAN_MULTIREG_MAX 16=0A= typedef struct =0A= {=0A= __u8 first, last;=0A= __u8 regs[CAN_MULTIREG_MAX];=0A= } CAN_MULTIREG;=0A= =0A= typedef struct=0A= {=0A= __u8 data[256];=0A= } CAN_ALLREGS;=0A= =0A= typedef struct=0A= {=0A= __u32 m_msg15;=0A= __u32 m_xtd;=0A= __u16 m_std;=0A= } CAN_MASKS;=0A= =0A= /* This structure is both part of the device structure and arg of ioctl = */=0A= typedef struct=0A= {=0A= __u32 id;=0A= __u8 msgobj; /* 1..15 */=0A= __u8 flags;=0A= __u8 config; /* same as config register */=0A= __u8 dlc; /* data length counter */=0A= __u8 data[8];=0A= __u16 error; /* also for alignment */=0A= } CAN_MSG;=0A= =0A= /* And these are the message flags */=0A= #define CAN_MSGFLAG_WRITE 0x01=0A= #define CAN_MSGFLAG_READ 0x02 /* set either write read */=0A= #define CAN_MSGFLAG_DOREMOTE 0x04 /* send a remote frame, for reading */=0A= #define CAN_MSGFLAG_PEEKONLY 0x08 /* used by IOCPEEK */=0A= =0A= #define CAN_ERROR_MASK 0x07 /* Tx error code */=0A= #define CAN_ERROR_MSGLST 0x10 /* Message lost error */=0A= #define CAN_ERROR_OVRFLW 0x80 /* Read buffer overflow */=0A= =0A= =0A= /*=0A= * ioctl() definitons=0A= */=0A= =0A= /* Use 'z' as magic number */=0A= #define CAN_IOC_MAGIC 'z' /* like other CAN drivers, per = ioctl-number.txt */=0A= =0A= #define CAN_IOCRESET _IO(CAN_IOC_MAGIC, 0)=0A= =0A= /* individual registers */=0A= #define CAN_IOCREADREG _IOWR(CAN_IOC_MAGIC, 1, CAN_REG)=0A= #define CAN_IOCWRITEREG _IOW(CAN_IOC_MAGIC, 2, CAN_REG)=0A= =0A= /* range of registers */=0A= #define CAN_IOCREADMULTI _IOWR(CAN_IOC_MAGIC, 3, CAN_MULTIREG)=0A= #define CAN_IOCWRITEMULTI _IOW(CAN_IOC_MAGIC, 4, CAN_MULTIREG)=0A= =0A= /* one message */=0A= #define CAN_IOCSETUPMSG _IOW(CAN_IOC_MAGIC, 5, CAN_MSG)=0A= #define CAN_IOCWRITEMSG _IOW(CAN_IOC_MAGIC, 6, CAN_MSG)=0A= #define CAN_IOCTXMSG _IOW(CAN_IOC_MAGIC, 7, unsigned long)=0A= #define CAN_IOCRXMSG _IOWR(CAN_IOC_MAGIC, 8, CAN_MSG)=0A= #define CAN_IOCRELEASEMSG _IOW(CAN_IOC_MAGIC, 9, unsigned long)=0A= =0A= /* all registers */=0A= #define CAN_IOCREADALL _IOR(CAN_IOC_MAGIC, 10, CAN_ALLREGS)=0A= =0A= /* masks, times, bus configuration */=0A= #define CAN_IOCGETMASKS _IOR(CAN_IOC_MAGIC, 11, CAN_MASKS)=0A= #define CAN_IOCSETMASKS _IOW(CAN_IOC_MAGIC, 12, CAN_MASKS)=0A= =0A= #define CAN_IOCGETBPS _IOR(CAN_IOC_MAGIC, 13, unsigned long) =0A= #define CAN_IOCSETBPS _IOW(CAN_IOC_MAGIC, 14, unsigned long)=0A= =0A= #define CAN_IOCGETBUSCONF _IOR(CAN_IOC_MAGIC, 15, CAN_REG)=0A= #define CAN_IOCSETBUSCONF _IOW(CAN_IOC_MAGIC, 16, CAN_REG)=0A= =0A= /* misc */=0A= #define CAN_IOCSOFTRESET _IO(CAN_IOC_MAGIC, 17)=0A= =0A= #define CAN_IOCWRITEQ _IOW(CAN_IOC_MAGIC, 18, CAN_MSG)=0A= #define CAN_IOCGIRQCOUNT _IOR(CAN_IOC_MAGIC, 19, unsigned long)=0A= =0A= #define CAN_IOCREQSIGNAL _IOW(CAN_IOC_MAGIC, 20, unsigned long)=0A= =0A= /* I/O ports */=0A= #define CAN_IOCINPUT _IOWR(CAN_IOC_MAGIC, 21, CAN_REG)=0A= #define CAN_IOCOUTPUT _IOW(CAN_IOC_MAGIC, 22, CAN_REG)=0A= #define CAN_IOCIOCFG _IOW(CAN_IOC_MAGIC, 23, CAN_REG)=0A= =0A= /* peek (like rx) */=0A= #define CAN_IOCPEEKMSG _IOWR(CAN_IOC_MAGIC, 24, CAN_MSG)=0A= =0A= #define CAN_IOC_MAXNR 24=0A= =0A= #endif /* __JCAN_H__ */=0A= =0A= =0A= =0A= ------=_NextPart_000_0052_01C2EEDF.DCC6A9C0 Content-Type: text/plain; name="jcan.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="jcan.c" /*=0A= * jcan.c -- CAN driver for i82527=0A= *=0A= * Copyright (C) 2003 George Cewe =0A= * Copyright (C) 2003 Advanced Concepts Inc.=0A= * Copyright (C) 2002 Alessandro Rubini =0A= * Copyright (C) 2002 System SpA =0A= *=0A= * This program is free software; you can redistribute it and/or modify=0A= * it under the terms of the GNU General Public License as published by=0A= * the Free Software Foundation; either version 2 of the License, or=0A= * (at your option) any later version.=0A= *=0A= * This program is distributed in the hope that it will be useful,=0A= * but WITHOUT ANY WARRANTY; without even the implied warranty of=0A= * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A= * GNU General Public License for more details.=0A= *=0A= * You should have received a copy of the GNU General Public License=0A= * along with this program; if not, write to the Free Software=0A= * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA = 02111-1307, USA.=0A= *=0A= *=0A= * This driver is a simplified version of "ocan" driver by Alessandro = Rubini.=0A= * It supports one memory mapped Intel i82527 CAN chip, running under = J1939=0A= * protocol (250kBps, extended message id).=0A= * =0A= */=0A= =0A= #define __NO_VERSION__=0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= =0A= #include =0A= #include =0A= #ifdef __powerpc__=0A= #include =0A= #endif=0A= #include "jcan.h"=0A= =0A= /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=0A= * Messaging stuff=0A= */=0A= #undef PDEBUG /* undef it, just in case */=0A= =0A= #ifdef CAN_DEBUG=0A= #ifdef __KERNEL__=0A= /* This one if debugging is on, and kernel space */=0A= #define PDEBUG(fmt, args...) printk(KERN_DEBUG CAN_TEXT fmt,##args)=0A= #else=0A= /* This one for user space */=0A= #define PDEBUG(fmt, args...) fprintf(stdout, fmt, ##args)=0A= #endif=0A= #else=0A= /* nothing */=0A= #define PDEBUG(fmt, args...) /* nothing */=0A= #endif /* CAN_DEBUG */=0A= =0A= #ifdef CAN_DEBUG=0A= #define debug 1=0A= #else=0A= #define debug 0=0A= #endif=0A= =0A= // base address and interrupt number=0A= #define IO_ADDR 0xffff0000=0A= #define IO_RANGE 0x100=0A= #define IRQ_NUM SIU_IRQ3=0A= =0A= #ifndef CAN_MAJOR=0A= #define CAN_MAJOR 91 =0A= #endif=0A= =0A= #define CAN_NAME "jcan"=0A= #define CAN_TEXT "jcan: "=0A= =0A= /*=0A= * Sysctl constants=0A= */=0A= #define DEV_CAN 2658 /* random for /proc/sys/dev/jcan/ */=0A= =0A= /* inside /proc/sys/dev/jcan, each backend can use 100 keys */=0A= =0A= /*=0A= * minor allocation: each device has 1 general entry point, 15=0A= * message-buffer entry points and a few information/error files.=0A= * So it will need 5 bits. This accounts for up to eight devices=0A= */=0A= =0A= #define CAN_DEV_TYPE(minor) ((minor)&0x1f)=0A= #define CAN_DEV_TYPE_GENERIC 0 /* 1..15 are the message objects */=0A= #define CAN_DEV_TYPE_ERROR 16=0A= #define CAN_DEV_TYPE_IO1 17=0A= #define CAN_DEV_TYPE_IO2 18=0A= =0A= #define CAN_DEV_NUM(minor) ((minor)>>5) =0A= =0A= /* =0A= * Device structures=0A= */=0A= =0A= #define CAN_BUFSIZE 64 /* 64 pointers for msg packets */=0A= =0A= // i82527 related definitions = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A= =0A= #define I527_MSG_OBJS 16 /* 0 is the whole device, 1..15 are objects */=0A= #define I527_FIRST_OBJ 1=0A= =0A= /* 82527 address map (referred from base address) & internal bits.=0A= See the 82527 data-sheet page 9 and following */=0A= #define I527_MAP_SIZE 0x100=0A= #define I527_CTRL_REG 0x00=0A= #define I527_CCE 0x40=0A= #define I527_EIE 0x08=0A= #define I527_SIE 0x04=0A= #define I527_IE 0x02=0A= #define I527_INIT 0x01=0A= =0A= #define I527_STAT_REG 0x01=0A= #define I527_STAT_REG_DEFAULT 0x07=0A= =0A= #define I527_CPU_INT_REG 0x02=0A= #define I527_RSTST 0x80=0A= #define I527_DSC 0x40=0A= #define I527_DMC 0x20=0A= #define I527_PWD 0x10=0A= #define I527_SLEEP 0x08=0A= #define I527_MUX 0x04=0A= #define I527_CEN 0x01=0A= =0A= /* Reserved 0x03 */=0A= #define I527_HI_SPEED_RD 0x04=0A= #define I527_GMASK_STD 0x06=0A= #define I527_GMASK_XTD 0x08=0A= #define I527_MSG15_MASK 0x0c=0A= =0A= /* Message 1 0x10 */=0A= #define I527_MSG_OFF 0x10 /* No size definition here */=0A= #define I527_MSG_CTRL 0x00=0A= #define I527_MSGVAL_R 0xff7f /* *********************** */=0A= #define I527_MSGVAL_S 0xffbf /* WARNING!!! */=0A= #define I527_TXIE_R 0xffdf /* These masks must be */=0A= #define I527_TXIE_S 0xffef /* &-ed and *NOT* |-ed */=0A= #define I527_RXIE_R 0xfff7 /* */=0A= #define I527_RXIE_S 0xfffb /* */=0A= #define I527_INTPND_R 0xfffd /* */=0A= #define I527_INTPND_S 0xfffe /* */=0A= #define I527_RMTPND_R 0x7fff /* WARNING!!! */=0A= #define I527_RMTPND_S 0xbfff /* These masks must be */=0A= #define I527_TXRQST_R 0xdfff /* &-ed and *NOT* |-ed */=0A= #define I527_TXRQST_S 0xefff /* */=0A= #define I527_MSGLST_R 0xf7ff /* */=0A= #define I527_MSGLST_S 0xfbff /* */=0A= #define I527_CPUUPD_R 0xf7ff /* WARNING!!! */=0A= #define I527_CPUUPD_S 0xfbff /* These masks must be */=0A= #define I527_NEWDAT_R 0xfdff /* &-ed and *NOT* |-ed */=0A= #define I527_NEWDAT_S 0xfeff /* *********************** */=0A= #define I527_MSG_ARBIT 0x02=0A= #define I527_MSG_CFG 0x06=0A= #define I527_DLC_MASK 0xf0=0A= #define I527_DLC_SHIFT 4=0A= #define I527_DLC_MASK0 0x0f=0A= #define I527_DIR 0x08=0A= #define I527_DIR_TX 0x08=0A= #define I527_DIR_RX 0x00=0A= #define I527_XTD 0x04=0A= #define I527_MSG_DATA 0x07 /* 8 bytes */=0A= #define I527_CLKOUT_REG 0x1f=0A= #define I527_SL_MASK 0x30=0A= #define I527_SL_SHIFT 4=0A= #define I527_SL_MASK0 0x03=0A= #define I527_CLKDIV_MASK 0x0f=0A= #define I527_CLKDIV_SHIFT 0=0A= #define I527_CLKDIV_MASK0 0x0f=0A= =0A= /* Message 2 0x20 */=0A= #define I527_BUSCFG_REG 0x2f=0A= #define I527_COBY 0x40=0A= #define I527_POL 0x20=0A= #define I527_DCT1 0x08=0A= #define I527_DCR1 0x02=0A= #define I527_DCR0 0x01=0A= =0A= /* Message 3 0x30 */=0A= #define I527_BITT0_REG 0x3f=0A= #define I527_SJW_MASK 0xc0=0A= #define I527_SJW_SHIFT 0x06=0A= #define I527_SJW_MASK0 0x03=0A= #define I527_BRP_MASK 0x3f=0A= #define I527_BRP_SHIFT 0=0A= #define I527_BRP_MASK0 0x3f=0A= =0A= /* Message 4 0x40 */=0A= #define I527_BITT1_REG 0x4f=0A= #define I527_SPL_MASK 0x80=0A= #define I527_SPL_SHIFT 7=0A= #define I527_SPL_MASK0 0x01=0A= #define I527_TSEG2_MASK 0x70=0A= #define I527_TSEG2_SHIFT 4=0A= #define I527_TSEG2_MASK0 0x07=0A= #define I527_TSEG1_MASK 0x0f=0A= #define I527_TSEG1_SHIFT 0=0A= #define I527_TSEG1_MASK0 0x0f=0A= =0A= /* Message 5 0x50 */=0A= #define I527_INT_REG 0x5f=0A= =0A= /* Message 6 0x60 */=0A= /* Reserved 0x6f */=0A= =0A= /* Message 7 0x70 */=0A= /* Reserved 0x7f */=0A= =0A= /* Message 8 0x80 */=0A= /* Reserved 0x8f */=0A= =0A= /* Message 9 0x90 */=0A= #define I527_P1CONF 0x9f=0A= =0A= /* Message 10 0xa0 */=0A= #define I527_P2CONF 0xaf=0A= =0A= /* Message 11 0xb0 */=0A= #define I527_P1IN 0xbf=0A= =0A= /* Message 12 0xc0 */=0A= #define I527_P2IN 0xcf=0A= =0A= /* Message 13 0xd0 */=0A= #define I527_P1OUT 0xdf=0A= =0A= /* Message 14 0xe0 */=0A= #define I527_P2OUT 0xef=0A= =0A= /* Message 15 0xf0 */=0A= #define I527_SER_RST_ADD 0xff=0A= =0A= typedef struct=0A= {=0A= __u8 cpuint;=0A= __u8 clkout;=0A= __u8 bittm0;=0A= __u8 bittm1;=0A= } CAN_BPS; =0A= =0A= /*=0A= * WARNING: can_times fields must all be __u8, because I sometimes=0A= * iniitalize it from arrays of bytes (for example dev->hal->h_defaults)=0A= */=0A= typedef struct =0A= {=0A= __u8 t_dsc;=0A= __u8 t_dmc;=0A= __u8 t_clkout_div;=0A= __u8 t_clkout_slew;=0A= __u8 t_sjw;=0A= __u8 t_spl;=0A= __u8 t_brp;=0A= __u8 t_tseg1;=0A= __u8 t_tseg2;=0A= } CAN_TIMES;=0A= =0A= /* This is the MSGOBJ structure */=0A= typedef struct =0A= {=0A= u32 obj_id; /* current id */=0A= struct file *owner; /* someone is waiting for a = message */=0A= volatile u16 obj_flags; /* object-specific flags */=0A= u8 regbase; /* register offset */=0A= volatile u8 error; /* error on message */=0A= spinlock_t lock;=0A= unsigned long flags; =0A= wait_queue_head_t read_q; /* read queue */=0A= struct fasync_struct *async_read_q; /* async read queue */=0A= wait_queue_head_t write_q; /* write queue */=0A= struct fasync_struct *async_write_q; /* async write queue*/=0A= volatile int head;=0A= volatile int tail;=0A= CAN_MSG **msg; /* allocated using CAN_BUFSIZE = */;=0A= } CAN_MSGOBJ;=0A= =0A= /* object flags and error flags, used internally */=0A= #define CAN_OBJFLAG_WRITE 0x01 /* being used to write/read */=0A= #define CAN_OBJFLAG_READ 0x02 /* (same values as MSGFLAG) */=0A= #define CAN_OBJFLAG_REMOTE 0x04 /* remote flag on */=0A= #define CAN_OBJFLAG_HWBUSY 0x40 /* message is being transmitted = */=0A= #define CAN_OBJFLAG_BUSY 0x80 /* message is in use */=0A= =0A= =0A= /* error notification via signals */=0A= typedef struct =0A= {=0A= struct file *file;=0A= int signal;=0A= pid_t pid;=0A= } CAN_ERROR;=0A= #define CAN_NR_ERROR_FILES 4 /* at most 4 processes can get a signal */=0A= =0A= typedef struct =0A= {=0A= u32 base;=0A= volatile u32 irq_count;=0A= u8 usecount;=0A= volatile u8 statusbyte;=0A= u8 registered;=0A= u8 gotirq;=0A= CAN_MSGOBJ *objs[I527_MSG_OBJS];=0A= CAN_ERROR errorinfo[CAN_NR_ERROR_FILES];=0A= wait_queue_head_t error_q;=0A= BPS eBps;=0A= } CAN_DEV;=0A= =0A= =0A= static kmem_cache_t *gpsCache; // The memory cache for msg packets=0A= static CAN_DEV gsDev; // The device data =0A= =0A= static const CAN_BPS gasBps[BPS_MAX] =3D=0A= { {0x40, 0x31, 0x03, 0x4d} // 100k=0A= ,{0x40, 0x31, 0x03, 0x49} // 125k=0A= ,{0x40, 0x31, 0x01, 0x49} // 250k=0A= ,{0x40, 0x31, 0x00, 0x49} // 500k=0A= ,{0x40, 0x31, 0x00, 0x14} // 1M=0A= };=0A= =0A= static spinlock_t can_lock =3D SPIN_LOCK_UNLOCKED;=0A= =0A= /////////////////////////////////////////////////////////////////////////= ////=0A= static int can_readb(CAN_DEV *dev, u_char reg)=0A= {=0A= return readb((volatile unsigned char *)(dev->base + reg));=0A= }=0A= =0A= //-----------------------------------------------------------------------= ----=0A= static int can_writeb(CAN_DEV *dev, u_char reg, unsigned char val)=0A= {=0A= writeb(val, (volatile unsigned char *)(dev->base + reg));=0A= return 0;=0A= }=0A= =0A= /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=0A= * basic functions use direct methods=0A= */=0A= #define i527_read_reg(dev, reg) \=0A= (can_readb((dev), (reg)))=0A= =0A= #define i527_write_reg(dev, reg, value) \=0A= (can_writeb((dev), (reg), (value)))=0A= =0A= /*=0A= * bit-setting operation and its use=0A= */=0A= extern inline int i527_bits(CAN_DEV *dev, int reg,=0A= int bits, int value)=0A= {=0A= int res =3D i527_read_reg(dev, reg);=0A= if (res < 0) return res;=0A= res =3D (res & ~bits) | (bits & value);=0A= return i527_write_reg(dev, reg, res);=0A= }=0A= =0A= #define can_enable_irq(dev) i527_bits((dev), I527_CTRL_REG, \=0A= I527_EIE|I527_IE, I527_EIE|I527_IE)=0A= =0A= #define can_disable_irq(dev) i527_bits((dev), I527_CTRL_REG, \=0A= I527_EIE|I527_IE, 0)=0A= =0A= #define can_read_msg_dlc(dev, n) \=0A= ((i527_read_msgcfg(dev, n) & I527_DLC_MASK) \=0A= >> I527_DLC_SHIFT)=0A= =0A= #define can_write_msg_dlc(dev, n, dlc) \=0A= (i527_bits((dev), n * I527_MSG_OFF + I527_MSG_CFG, \=0A= I527_DLC_MASK, (dlc) << I527_DLC_SHIFT))=0A= =0A= /*=0A= * Enable/disable configuration changes=0A= */=0A= =0A= /* enable and return previous value */=0A= extern inline int can_enable_cfg(CAN_DEV *dev)=0A= {=0A= int res =3D i527_read_reg(dev, I527_CTRL_REG);=0A= if (res < 0) return res;=0A= if (res & I527_CCE) return I527_CCE;=0A= res =3D i527_write_reg(dev, I527_CTRL_REG, res | I527_CCE);=0A= if (res < 0) return res;=0A= return 0;=0A= }=0A= =0A= /* disable and return previous value */=0A= extern inline int can_disable_cfg(CAN_DEV *dev)=0A= {=0A= int res =3D i527_read_reg(dev, I527_CTRL_REG);=0A= if (res < 0) return res;=0A= if (!(res & I527_CCE)) return 0;=0A= res =3D i527_write_reg(dev, I527_CTRL_REG, res & ~I527_CCE);=0A= if (res < 0) return res;=0A= return I527_CCE;=0A= }=0A= =0A= /* restore previous value */=0A= extern inline int can_restore_cfg(CAN_DEV *dev, int prev)=0A= {=0A= return i527_bits(dev, I527_CTRL_REG, I527_CCE, prev);=0A= }=0A= =0A= /*=0A= * higher level functions (can't be in i82527.h, for strange = dependencies)=0A= */=0A= =0A= extern inline int i527_read_msgcfg(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj)=0A= {=0A= return i527_read_reg(dev, obj->regbase + I527_MSG_CFG);=0A= }=0A= =0A= extern inline int i527_write_msgcfg(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj, int val)=0A= {=0A= if (val & ~0xff) return -EINVAL;=0A= return i527_write_reg(dev, obj->regbase + I527_MSG_CFG, val);=0A= }=0A= =0A= extern inline u16 i527_read_std_mask(CAN_DEV *dev)=0A= {=0A= /* errors are ignored, hmm... */=0A= u16 ret =3D i527_read_reg(dev, I527_GMASK_STD) << 8=0A= | i527_read_reg(dev, I527_GMASK_STD + 1);=0A= return ret;=0A= }=0A= =0A= extern inline void i527_write_std_mask(CAN_DEV *dev, u16 val)=0A= {=0A= /* errors are ignored, hmm... */=0A= i527_write_reg(dev, I527_GMASK_STD, val >> 8);=0A= i527_write_reg(dev, I527_GMASK_STD + 1, val & 0xff);=0A= }=0A= =0A= extern inline u32 i527_read_x_mask(CAN_DEV *dev)=0A= {=0A= /* errors are ignored, hmm... */=0A= u32 ret =3D i527_read_reg(dev, I527_GMASK_XTD) << 24=0A= | i527_read_reg(dev, I527_GMASK_XTD + 1) << 16=0A= | i527_read_reg(dev, I527_GMASK_XTD + 2) << 8=0A= | i527_read_reg(dev, I527_GMASK_XTD + 3);=0A= return ret;=0A= }=0A= =0A= extern inline void i527_write_x_mask(CAN_DEV *dev, u32 val)=0A= {=0A= /* errors are ignored, hmm... */=0A= i527_write_reg(dev, I527_GMASK_XTD, val >> 24);=0A= i527_write_reg(dev, I527_GMASK_XTD + 1, (val >> 16) & 0xff);=0A= i527_write_reg(dev, I527_GMASK_XTD + 2, (val >> 8) & 0xff);=0A= i527_write_reg(dev, I527_GMASK_XTD + 3, (val >> 0) & 0xff);=0A= }=0A= =0A= =0A= extern inline u32 i527_read_15_mask(CAN_DEV *dev)=0A= {=0A= /* errors are ignored, hmm... */=0A= u32 ret =3D i527_read_reg(dev, I527_MSG15_MASK) << 24=0A= | i527_read_reg(dev, I527_MSG15_MASK + 1) << 16=0A= | i527_read_reg(dev, I527_MSG15_MASK + 2) << 8=0A= | i527_read_reg(dev, I527_MSG15_MASK + 3);=0A= return ret;=0A= }=0A= =0A= extern inline void i527_write_15_mask(CAN_DEV *dev,=0A= u32 val)=0A= {=0A= /* errors are ignored, hmm... */=0A= i527_write_reg(dev, I527_MSG15_MASK, val >> 24);=0A= i527_write_reg(dev, I527_MSG15_MASK + 1, (val >> 16) & 0xff);=0A= i527_write_reg(dev, I527_MSG15_MASK + 2, (val >> 8) & 0xff);=0A= i527_write_reg(dev, I527_MSG15_MASK + 3, (val >> 0) & 0xff);=0A= }=0A= =0A= extern inline u16 i527_read_msgctrl(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj)=0A= {=0A= /* FIXME: this is used little-endian, but doesn't need to be 16b */=0A= =0A= /* errors are ignored, hmm... */=0A= u16 ret =3D i527_read_reg(dev, obj->regbase + I527_MSG_CTRL)=0A= | (i527_read_reg(dev, obj->regbase + I527_MSG_CTRL +1 )=0A= << 8);=0A= return ret;=0A= }=0A= =0A= extern inline void i527_write_msgctrl(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj, u16 val)=0A= {=0A= /* FIXME: this is used little-endian, but doesn't need to be 16b */=0A= =0A= /* errors are ignored, hmm... */=0A= i527_write_reg(dev, obj->regbase + I527_MSG_CTRL, val & 0xff);=0A= i527_write_reg(dev, obj->regbase + I527_MSG_CTRL + 1, val >> 8);=0A= }=0A= =0A= /* write a single byte of msgctrl, twice as fast as the function above */=0A= extern inline void i527_msgflag(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj, u16 act)=0A= {=0A= if ((act & 0xff) =3D=3D 0xff)=0A= i527_write_reg(dev, obj->regbase + I527_MSG_CTRL + 1, act >> 8);=0A= else=0A= i527_write_reg(dev, obj->regbase + I527_MSG_CTRL, act & 0xff);=0A= }=0A= /* same, but for unallocated objects */=0A= extern inline void i527_msgflag_noobj(CAN_DEV *dev,=0A= int msgnum, u16 act)=0A= {=0A= if ((act & 0xff) =3D=3D 0xff)=0A= i527_write_reg(dev, msgnum*I527_MSG_OFF + I527_MSG_CTRL + 1,=0A= act >> 8);=0A= else=0A= i527_write_reg(dev, msgnum*I527_MSG_OFF + I527_MSG_CTRL,=0A= act & 0xff);=0A= }=0A= /* read a single byte of msgctrl (use the _S flag. Hm....) */=0A= extern inline int i527_check_msgflag(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj, u16 act)=0A= {=0A= u16 reg;=0A= if ((act & 0xff) =3D=3D 0xff) {=0A= reg =3D i527_read_reg(dev, obj->regbase + I527_MSG_CTRL + 1);=0A= return !((reg << 8) & ~act);=0A= }=0A= reg =3D i527_read_reg(dev, obj->regbase + I527_MSG_CTRL);=0A= return !(reg & ~act);=0A= }=0A= =0A= extern inline u32 i527_read_msgarb(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj)=0A= {=0A= int port =3D obj->regbase + I527_MSG_ARBIT;=0A= =0A= /* errors are ignored, hmm... */=0A= u32 ret =3D i527_read_reg(dev, port) << 24=0A= | i527_read_reg(dev, port + 1) << 16=0A= | i527_read_reg(dev, port + 2) << 8=0A= | i527_read_reg(dev, port + 3);=0A= return ret;=0A= }=0A= =0A= extern inline void i527_write_msgarb(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj, u32 val)=0A= {=0A= int port =3D obj->regbase + I527_MSG_ARBIT;=0A= =0A= i527_write_reg(dev, port, val >> 24);=0A= i527_write_reg(dev, port + 1, (val >> 16) & 0xff);=0A= i527_write_reg(dev, port + 2, (val >> 8) & 0xff);=0A= i527_write_reg(dev, port + 3, (val >> 0) & 0xff);=0A= }=0A= =0A= extern inline void i527_read_msgdata(CAN_DEV *dev,=0A= CAN_MSGOBJ *obj,=0A= int n, u8 *data)=0A= {=0A= int i;=0A= u8 reg =3D obj->regbase + I527_MSG_DATA;=0A= =0A= for (i=3D0; iregbase + I527_MSG_DATA;=0A= =0A= if (!n) return;=0A= i527_msgflag(dev, obj, I527_CPUUPD_S); /* CPU updating */=0A= for (i=3D0; i