Hi Matthias,
Matthias Fuchs wrote:
Hi,
attached you will find a patch that adds support for memory mapped
SJA1000 CAN controllers as they often can be found on embedded boards.
The driver is based on the rtmen_isa driver.
What about using request_mem_region()? While looking to the driver I now
realize, that it's mainly duplicated code. Does it not make more sense
to make a combined io/mem driver. If io address < 32K it's an io driver
else a mem driver.
------------------------------------------------------------------------
Index: ksrc/drivers/can/sja1000/Kconfig
===================================================================
--- ksrc/drivers/can/sja1000/Kconfig (revision 1564)
+++ ksrc/drivers/can/sja1000/Kconfig (working copy)
@@ -13,6 +13,16 @@
int "Maximum number of ISA devices"
default 4
+config XENO_DRIVERS_RTCAN_SJA1000_MEM
+ depends on XENO_DRIVERS_RTCAN_SJA1000
+ tristate "Memory mapped controllers"
+ default n
+
+config XENO_DRIVERS_RTCAN_SJA1000_MEM_MAX_DEV
+ depends on XENO_DRIVERS_RTCAN_SJA1000_MEM
+ int "Maximum number of memory mapped controllers"
+ default 4
+
config XENO_DRIVERS_RTCAN_SJA1000_PEAK_PCI
depends on XENO_DRIVERS_RTCAN_SJA1000
tristate "PEAK PCI Card"
Index: ksrc/drivers/can/sja1000/rtcan_mem.c
===================================================================
--- ksrc/drivers/can/sja1000/rtcan_mem.c (revision 0)
+++ ksrc/drivers/can/sja1000/rtcan_mem.c (revision 0)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2006 Matthias Fuchs <[EMAIL PROTECTED]>,
+ * Jan Kiszka <[EMAIL PROTECTED]>
+ *
+ * RTCAN driver for memory mapped SJA1000 CAN controller
+ * This code has been tested on esd's CPCI405/EPPC405 PPC405 systems.
+ *
+ * This driver is derived from the rtcan-isa driver by
+ * Wolfgang Grandegger and Sebastian Smolorz.
+ *
+ * Copyright (C) 2006 Wolfgang Grandegger <[EMAIL PROTECTED]>
+ * Copyright (C) 2005, 2006 Sebastian Smolorz
+ * <[EMAIL PROTECTED]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; eitherer version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+
+#include <rtdm/rtdm_driver.h>
+
+#include <rtdm/rtcan.h>
+#include <rtcan_dev.h>
+#include <rtcan_raw.h>
+#include <rtcan_internal.h>
+#include <rtcan_sja1000.h>
+#include <rtcan_sja1000_regs.h>
+
+#define RTCAN_DEV_NAME "rtcan%d"
+#define RTCAN_DRV_NAME "sja1000-mem"
+
+#ifdef CONFIG_XENO_DRIVERS_RTCAN_MEM_MAX_DEVS
+#define RTCAN_MEM_MAX_DEV CONFIG_XENO_DRIVERS_RTCAN_MEM_MAX_DEV
+#else
+#define RTCAN_MEM_MAX_DEV 2
+#endif
+
+static char *mem_board_name = "mem mapped";
+
+MODULE_AUTHOR("Matthias Fuchs <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION("RTCAN driver for memory mapped SJA1000 controller");
+MODULE_SUPPORTED_DEVICE("mem mapped");
+MODULE_LICENSE("GPL");
+
+static u32 mem[RTCAN_MEM_MAX_DEV];
+static int irq[RTCAN_MEM_MAX_DEV];
+static u32 clock[RTCAN_MEM_MAX_DEV];
+static u8 ocr[RTCAN_MEM_MAX_DEV];
+static u8 cdr[RTCAN_MEM_MAX_DEV];
+
+compat_module_int_param_array(mem, RTCAN_MEM_MAX_DEV);
+compat_module_int_param_array(irq, RTCAN_MEM_MAX_DEV);
+compat_module_int_param_array(clock, RTCAN_MEM_MAX_DEV);
+compat_module_byte_param_array(ocr, RTCAN_MEM_MAX_DEV);
+compat_module_byte_param_array(cdr, RTCAN_MEM_MAX_DEV);
+
+MODULE_PARM_DESC(mem, "The io-memory address");
+MODULE_PARM_DESC(irq, "The interrupt number");
+MODULE_PARM_DESC(clock, "External clock frequency (default 16 MHz)");
+MODULE_PARM_DESC(ocr, "Value of output control register (default 0x1a)");
+MODULE_PARM_DESC(cdr, "Value of clock divider register (default 0xc8");
+
+#define RTCAN_MEM_RANGE 0x80
+
+struct rtcan_mem
+{
+ u8 *vmem;
+};
+
+static struct rtcan_device *rtcan_mem_devs[RTCAN_MEM_MAX_DEV];
+
+static u8 rtcan_mem_readreg(struct rtcan_device *dev, int reg)
+{
+ struct rtcan_mem *board = (struct rtcan_mem *)dev->board_priv;
+ return readb(board->vmem + reg);
+}
+
+static void rtcan_mem_writereg(struct rtcan_device *dev, int reg, u8 val)
+{
+ struct rtcan_mem *board = (struct rtcan_mem *)dev->board_priv;
+ writeb(val, board->vmem + reg);
+}
+
+int __init rtcan_mem_init_one(int idx)
+{
+ struct rtcan_device *dev;
+ struct rtcan_sja1000 *chip;
+ struct rtcan_mem *board;
+ int ret;
+
+ if ((dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000),
+ sizeof(struct rtcan_mem))) == NULL)
+ return -ENOMEM;
+
+ chip = (struct rtcan_sja1000 *)dev->priv;
+ board = (struct rtcan_mem *)dev->board_priv;
+
+ dev->board_name = mem_board_name;
+
+ chip->irq_num = irq[idx];
+ chip->irq_flags = RTDM_IRQTYPE_SHARED;
+ chip->read_reg = rtcan_mem_readreg;
+ chip->write_reg = rtcan_mem_writereg;
+
+ if (!request_mem_region(mem[idx], RTCAN_MEM_RANGE, RTCAN_DRV_NAME)) {
+ ret = -EBUSY;
+ goto out_dev_free;
+ }
+
+ /* ioremap io memory */
+ if (!(board->vmem = (u8*)ioremap(mem[idx], RTCAN_MEM_RANGE))) {
+ release_mem_region(mem[idx], RTCAN_MEM_RANGE);
+ ret = -EBUSY;