linux/drivers/net/can/sja1000/sja1000_isa.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the version 2 of the GNU General Public License
   6 * as published by the Free Software Foundation
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software
  15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/isa.h>
  21#include <linux/interrupt.h>
  22#include <linux/netdevice.h>
  23#include <linux/delay.h>
  24#include <linux/irq.h>
  25#include <linux/io.h>
  26#include <linux/can.h>
  27#include <linux/can/dev.h>
  28#include <linux/can/platform/sja1000.h>
  29
  30#include "sja1000.h"
  31
  32#define DRV_NAME "sja1000_isa"
  33
  34#define MAXDEV 8
  35
  36MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
  37MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the ISA bus");
  38MODULE_LICENSE("GPL v2");
  39
  40#define CLK_DEFAULT     16000000        /* 16 MHz */
  41#define CDR_DEFAULT     (CDR_CBP | CDR_CLK_OFF)
  42#define OCR_DEFAULT     OCR_TX0_PUSHPULL
  43
  44static unsigned long port[MAXDEV];
  45static unsigned long mem[MAXDEV];
  46static int __devinitdata irq[MAXDEV];
  47static int __devinitdata clk[MAXDEV];
  48static char __devinitdata cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
  49static char __devinitdata ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
  50static char __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
  51
  52module_param_array(port, ulong, NULL, S_IRUGO);
  53MODULE_PARM_DESC(port, "I/O port number");
  54
  55module_param_array(mem, ulong, NULL, S_IRUGO);
  56MODULE_PARM_DESC(mem, "I/O memory address");
  57
  58module_param_array(indirect, byte, NULL, S_IRUGO);
  59MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
  60
  61module_param_array(irq, int, NULL, S_IRUGO);
  62MODULE_PARM_DESC(irq, "IRQ number");
  63
  64module_param_array(clk, int, NULL, S_IRUGO);
  65MODULE_PARM_DESC(clk, "External oscillator clock frequency "
  66                 "(default=16000000 [16 MHz])");
  67
  68module_param_array(cdr, byte, NULL, S_IRUGO);
  69MODULE_PARM_DESC(cdr, "Clock divider register "
  70                 "(default=0x48 [CDR_CBP | CDR_CLK_OFF])");
  71
  72module_param_array(ocr, byte, NULL, S_IRUGO);
  73MODULE_PARM_DESC(ocr, "Output control register "
  74                 "(default=0x18 [OCR_TX0_PUSHPULL])");
  75
  76#define SJA1000_IOSIZE          0x20
  77#define SJA1000_IOSIZE_INDIRECT 0x02
  78
  79static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg)
  80{
  81        return readb(priv->reg_base + reg);
  82}
  83
  84static void sja1000_isa_mem_write_reg(const struct sja1000_priv *priv,
  85                                      int reg, u8 val)
  86{
  87        writeb(val, priv->reg_base + reg);
  88}
  89
  90static u8 sja1000_isa_port_read_reg(const struct sja1000_priv *priv, int reg)
  91{
  92        return inb((unsigned long)priv->reg_base + reg);
  93}
  94
  95static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
  96                                       int reg, u8 val)
  97{
  98        outb(val, (unsigned long)priv->reg_base + reg);
  99}
 100
 101static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
 102                                             int reg)
 103{
 104        unsigned long base = (unsigned long)priv->reg_base;
 105
 106        outb(reg, base);
 107        return inb(base + 1);
 108}
 109
 110static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
 111                                                int reg, u8 val)
 112{
 113        unsigned long base = (unsigned long)priv->reg_base;
 114
 115        outb(reg, base);
 116        outb(val, base + 1);
 117}
 118
 119static int __devinit sja1000_isa_match(struct device *pdev, unsigned int idx)
 120{
 121        if (port[idx] || mem[idx]) {
 122                if (irq[idx])
 123                        return 1;
 124        } else if (idx)
 125                return 0;
 126
 127        dev_err(pdev, "insufficient parameters supplied\n");
 128        return 0;
 129}
 130
 131static int __devinit sja1000_isa_probe(struct device *pdev, unsigned int idx)
 132{
 133        struct net_device *dev;
 134        struct sja1000_priv *priv;
 135        void __iomem *base = NULL;
 136        int iosize = SJA1000_IOSIZE;
 137        int err;
 138
 139        if (mem[idx]) {
 140                if (!request_mem_region(mem[idx], iosize, DRV_NAME)) {
 141                        err = -EBUSY;
 142                        goto exit;
 143                }
 144                base = ioremap_nocache(mem[idx], iosize);
 145                if (!base) {
 146                        err = -ENOMEM;
 147                        goto exit_release;
 148                }
 149        } else {
 150                if (indirect[idx] > 0 ||
 151                    (indirect[idx] == -1 && indirect[0] > 0))
 152                        iosize = SJA1000_IOSIZE_INDIRECT;
 153                if (!request_region(port[idx], iosize, DRV_NAME)) {
 154                        err = -EBUSY;
 155                        goto exit;
 156                }
 157        }
 158
 159        dev = alloc_sja1000dev(0);
 160        if (!dev) {
 161                err = -ENOMEM;
 162                goto exit_unmap;
 163        }
 164        priv = netdev_priv(dev);
 165
 166        dev->irq = irq[idx];
 167        priv->irq_flags = IRQF_SHARED;
 168        if (mem[idx]) {
 169                priv->reg_base = base;
 170                dev->base_addr = mem[idx];
 171                priv->read_reg = sja1000_isa_mem_read_reg;
 172                priv->write_reg = sja1000_isa_mem_write_reg;
 173        } else {
 174                priv->reg_base = (void __iomem *)port[idx];
 175                dev->base_addr = port[idx];
 176
 177                if (iosize == SJA1000_IOSIZE_INDIRECT) {
 178                        priv->read_reg = sja1000_isa_port_read_reg_indirect;
 179                        priv->write_reg = sja1000_isa_port_write_reg_indirect;
 180                } else {
 181                        priv->read_reg = sja1000_isa_port_read_reg;
 182                        priv->write_reg = sja1000_isa_port_write_reg;
 183                }
 184        }
 185
 186        if (clk[idx])
 187                priv->can.clock.freq = clk[idx] / 2;
 188        else if (clk[0])
 189                priv->can.clock.freq = clk[0] / 2;
 190        else
 191                priv->can.clock.freq = CLK_DEFAULT / 2;
 192
 193        if (ocr[idx] != -1)
 194                priv->ocr = ocr[idx] & 0xff;
 195        else if (ocr[0] != -1)
 196                priv->ocr = ocr[0] & 0xff;
 197        else
 198                priv->ocr = OCR_DEFAULT;
 199
 200        if (cdr[idx] != -1)
 201                priv->cdr = cdr[idx] & 0xff;
 202        else if (cdr[0] != -1)
 203                priv->cdr = cdr[0] & 0xff;
 204        else
 205                priv->cdr = CDR_DEFAULT;
 206
 207        dev_set_drvdata(pdev, dev);
 208        SET_NETDEV_DEV(dev, pdev);
 209
 210        err = register_sja1000dev(dev);
 211        if (err) {
 212                dev_err(pdev, "registering %s failed (err=%d)\n",
 213                        DRV_NAME, err);
 214                goto exit_unmap;
 215        }
 216
 217        dev_info(pdev, "%s device registered (reg_base=0x%p, irq=%d)\n",
 218                 DRV_NAME, priv->reg_base, dev->irq);
 219        return 0;
 220
 221 exit_unmap:
 222        if (mem[idx])
 223                iounmap(base);
 224 exit_release:
 225        if (mem[idx])
 226                release_mem_region(mem[idx], iosize);
 227        else
 228                release_region(port[idx], iosize);
 229 exit:
 230        return err;
 231}
 232
 233static int __devexit sja1000_isa_remove(struct device *pdev, unsigned int idx)
 234{
 235        struct net_device *dev = dev_get_drvdata(pdev);
 236        struct sja1000_priv *priv = netdev_priv(dev);
 237
 238        unregister_sja1000dev(dev);
 239        dev_set_drvdata(pdev, NULL);
 240
 241        if (mem[idx]) {
 242                iounmap(priv->reg_base);
 243                release_mem_region(mem[idx], SJA1000_IOSIZE);
 244        } else {
 245                if (priv->read_reg == sja1000_isa_port_read_reg_indirect)
 246                        release_region(port[idx], SJA1000_IOSIZE_INDIRECT);
 247                else
 248                        release_region(port[idx], SJA1000_IOSIZE);
 249        }
 250        free_sja1000dev(dev);
 251
 252        return 0;
 253}
 254
 255static struct isa_driver sja1000_isa_driver = {
 256        .match = sja1000_isa_match,
 257        .probe = sja1000_isa_probe,
 258        .remove = __devexit_p(sja1000_isa_remove),
 259        .driver = {
 260                .name = DRV_NAME,
 261        },
 262};
 263
 264static int __init sja1000_isa_init(void)
 265{
 266        int err = isa_register_driver(&sja1000_isa_driver, MAXDEV);
 267
 268        if (!err)
 269                printk(KERN_INFO
 270                       "Legacy %s driver for max. %d devices registered\n",
 271                       DRV_NAME, MAXDEV);
 272        return err;
 273}
 274
 275static void __exit sja1000_isa_exit(void)
 276{
 277        isa_unregister_driver(&sja1000_isa_driver);
 278}
 279
 280module_init(sja1000_isa_init);
 281module_exit(sja1000_isa_exit);
 282