linux/drivers/net/can/sja1000/sja1000_isa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/module.h>
   8#include <linux/platform_device.h>
   9#include <linux/interrupt.h>
  10#include <linux/netdevice.h>
  11#include <linux/delay.h>
  12#include <linux/irq.h>
  13#include <linux/io.h>
  14#include <linux/can/dev.h>
  15#include <linux/can/platform/sja1000.h>
  16
  17#include "sja1000.h"
  18
  19#define DRV_NAME "sja1000_isa"
  20
  21#define MAXDEV 8
  22
  23MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
  24MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the ISA bus");
  25MODULE_LICENSE("GPL v2");
  26
  27#define CLK_DEFAULT     16000000        /* 16 MHz */
  28#define CDR_DEFAULT     (CDR_CBP | CDR_CLK_OFF)
  29#define OCR_DEFAULT     OCR_TX0_PUSHPULL
  30
  31static unsigned long port[MAXDEV];
  32static unsigned long mem[MAXDEV];
  33static int irq[MAXDEV];
  34static int clk[MAXDEV];
  35static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
  36static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
  37static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
  38static spinlock_t indirect_lock[MAXDEV];  /* lock for indirect access mode */
  39
  40module_param_hw_array(port, ulong, ioport, NULL, 0444);
  41MODULE_PARM_DESC(port, "I/O port number");
  42
  43module_param_hw_array(mem, ulong, iomem, NULL, 0444);
  44MODULE_PARM_DESC(mem, "I/O memory address");
  45
  46module_param_hw_array(indirect, int, ioport, NULL, 0444);
  47MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
  48
  49module_param_hw_array(irq, int, irq, NULL, 0444);
  50MODULE_PARM_DESC(irq, "IRQ number");
  51
  52module_param_array(clk, int, NULL, 0444);
  53MODULE_PARM_DESC(clk, "External oscillator clock frequency "
  54                 "(default=16000000 [16 MHz])");
  55
  56module_param_array(cdr, byte, NULL, 0444);
  57MODULE_PARM_DESC(cdr, "Clock divider register "
  58                 "(default=0x48 [CDR_CBP | CDR_CLK_OFF])");
  59
  60module_param_array(ocr, byte, NULL, 0444);
  61MODULE_PARM_DESC(ocr, "Output control register "
  62                 "(default=0x18 [OCR_TX0_PUSHPULL])");
  63
  64#define SJA1000_IOSIZE          0x20
  65#define SJA1000_IOSIZE_INDIRECT 0x02
  66
  67static struct platform_device *sja1000_isa_devs[MAXDEV];
  68
  69static u8 sja1000_isa_mem_read_reg(const struct sja1000_priv *priv, int reg)
  70{
  71        return readb(priv->reg_base + reg);
  72}
  73
  74static void sja1000_isa_mem_write_reg(const struct sja1000_priv *priv,
  75                                      int reg, u8 val)
  76{
  77        writeb(val, priv->reg_base + reg);
  78}
  79
  80static u8 sja1000_isa_port_read_reg(const struct sja1000_priv *priv, int reg)
  81{
  82        return inb((unsigned long)priv->reg_base + reg);
  83}
  84
  85static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
  86                                       int reg, u8 val)
  87{
  88        outb(val, (unsigned long)priv->reg_base + reg);
  89}
  90
  91static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
  92                                             int reg)
  93{
  94        unsigned long flags, base = (unsigned long)priv->reg_base;
  95        u8 readval;
  96
  97        spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
  98        outb(reg, base);
  99        readval = inb(base + 1);
 100        spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
 101
 102        return readval;
 103}
 104
 105static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
 106                                                int reg, u8 val)
 107{
 108        unsigned long flags, base = (unsigned long)priv->reg_base;
 109
 110        spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
 111        outb(reg, base);
 112        outb(val, base + 1);
 113        spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
 114}
 115
 116static int sja1000_isa_probe(struct platform_device *pdev)
 117{
 118        struct net_device *dev;
 119        struct sja1000_priv *priv;
 120        void __iomem *base = NULL;
 121        int iosize = SJA1000_IOSIZE;
 122        int idx = pdev->id;
 123        int err;
 124
 125        dev_dbg(&pdev->dev, "probing idx=%d: port=%#lx, mem=%#lx, irq=%d\n",
 126                idx, port[idx], mem[idx], irq[idx]);
 127
 128        if (mem[idx]) {
 129                if (!request_mem_region(mem[idx], iosize, DRV_NAME)) {
 130                        err = -EBUSY;
 131                        goto exit;
 132                }
 133                base = ioremap(mem[idx], iosize);
 134                if (!base) {
 135                        err = -ENOMEM;
 136                        goto exit_release;
 137                }
 138        } else {
 139                if (indirect[idx] > 0 ||
 140                    (indirect[idx] == -1 && indirect[0] > 0))
 141                        iosize = SJA1000_IOSIZE_INDIRECT;
 142                if (!request_region(port[idx], iosize, DRV_NAME)) {
 143                        err = -EBUSY;
 144                        goto exit;
 145                }
 146        }
 147
 148        dev = alloc_sja1000dev(0);
 149        if (!dev) {
 150                err = -ENOMEM;
 151                goto exit_unmap;
 152        }
 153        priv = netdev_priv(dev);
 154
 155        dev->irq = irq[idx];
 156        priv->irq_flags = IRQF_SHARED;
 157        if (mem[idx]) {
 158                priv->reg_base = base;
 159                dev->base_addr = mem[idx];
 160                priv->read_reg = sja1000_isa_mem_read_reg;
 161                priv->write_reg = sja1000_isa_mem_write_reg;
 162        } else {
 163                priv->reg_base = (void __iomem *)port[idx];
 164                dev->base_addr = port[idx];
 165
 166                if (iosize == SJA1000_IOSIZE_INDIRECT) {
 167                        priv->read_reg = sja1000_isa_port_read_reg_indirect;
 168                        priv->write_reg = sja1000_isa_port_write_reg_indirect;
 169                        spin_lock_init(&indirect_lock[idx]);
 170                } else {
 171                        priv->read_reg = sja1000_isa_port_read_reg;
 172                        priv->write_reg = sja1000_isa_port_write_reg;
 173                }
 174        }
 175
 176        if (clk[idx])
 177                priv->can.clock.freq = clk[idx] / 2;
 178        else if (clk[0])
 179                priv->can.clock.freq = clk[0] / 2;
 180        else
 181                priv->can.clock.freq = CLK_DEFAULT / 2;
 182
 183        if (ocr[idx] != 0xff)
 184                priv->ocr = ocr[idx];
 185        else if (ocr[0] != 0xff)
 186                priv->ocr = ocr[0];
 187        else
 188                priv->ocr = OCR_DEFAULT;
 189
 190        if (cdr[idx] != 0xff)
 191                priv->cdr = cdr[idx];
 192        else if (cdr[0] != 0xff)
 193                priv->cdr = cdr[0];
 194        else
 195                priv->cdr = CDR_DEFAULT;
 196
 197        platform_set_drvdata(pdev, dev);
 198        SET_NETDEV_DEV(dev, &pdev->dev);
 199        dev->dev_id = idx;
 200
 201        err = register_sja1000dev(dev);
 202        if (err) {
 203                dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
 204                        DRV_NAME, err);
 205                goto exit_unmap;
 206        }
 207
 208        dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n",
 209                 DRV_NAME, priv->reg_base, dev->irq);
 210        return 0;
 211
 212 exit_unmap:
 213        if (mem[idx])
 214                iounmap(base);
 215 exit_release:
 216        if (mem[idx])
 217                release_mem_region(mem[idx], iosize);
 218        else
 219                release_region(port[idx], iosize);
 220 exit:
 221        return err;
 222}
 223
 224static int sja1000_isa_remove(struct platform_device *pdev)
 225{
 226        struct net_device *dev = platform_get_drvdata(pdev);
 227        struct sja1000_priv *priv = netdev_priv(dev);
 228        int idx = pdev->id;
 229
 230        unregister_sja1000dev(dev);
 231
 232        if (mem[idx]) {
 233                iounmap(priv->reg_base);
 234                release_mem_region(mem[idx], SJA1000_IOSIZE);
 235        } else {
 236                if (priv->read_reg == sja1000_isa_port_read_reg_indirect)
 237                        release_region(port[idx], SJA1000_IOSIZE_INDIRECT);
 238                else
 239                        release_region(port[idx], SJA1000_IOSIZE);
 240        }
 241        free_sja1000dev(dev);
 242
 243        return 0;
 244}
 245
 246static struct platform_driver sja1000_isa_driver = {
 247        .probe = sja1000_isa_probe,
 248        .remove = sja1000_isa_remove,
 249        .driver = {
 250                .name = DRV_NAME,
 251        },
 252};
 253
 254static int __init sja1000_isa_init(void)
 255{
 256        int idx, err;
 257
 258        for (idx = 0; idx < MAXDEV; idx++) {
 259                if ((port[idx] || mem[idx]) && irq[idx]) {
 260                        sja1000_isa_devs[idx] =
 261                                platform_device_alloc(DRV_NAME, idx);
 262                        if (!sja1000_isa_devs[idx]) {
 263                                err = -ENOMEM;
 264                                goto exit_free_devices;
 265                        }
 266                        err = platform_device_add(sja1000_isa_devs[idx]);
 267                        if (err) {
 268                                platform_device_put(sja1000_isa_devs[idx]);
 269                                goto exit_free_devices;
 270                        }
 271                        pr_debug("%s: platform device %d: port=%#lx, mem=%#lx, "
 272                                 "irq=%d\n",
 273                                 DRV_NAME, idx, port[idx], mem[idx], irq[idx]);
 274                } else if (idx == 0 || port[idx] || mem[idx]) {
 275                                pr_err("%s: insufficient parameters supplied\n",
 276                                       DRV_NAME);
 277                                err = -EINVAL;
 278                                goto exit_free_devices;
 279                }
 280        }
 281
 282        err = platform_driver_register(&sja1000_isa_driver);
 283        if (err)
 284                goto exit_free_devices;
 285
 286        pr_info("Legacy %s driver for max. %d devices registered\n",
 287                DRV_NAME, MAXDEV);
 288
 289        return 0;
 290
 291exit_free_devices:
 292        while (--idx >= 0) {
 293                if (sja1000_isa_devs[idx])
 294                        platform_device_unregister(sja1000_isa_devs[idx]);
 295        }
 296
 297        return err;
 298}
 299
 300static void __exit sja1000_isa_exit(void)
 301{
 302        int idx;
 303
 304        platform_driver_unregister(&sja1000_isa_driver);
 305        for (idx = 0; idx < MAXDEV; idx++) {
 306                if (sja1000_isa_devs[idx])
 307                        platform_device_unregister(sja1000_isa_devs[idx]);
 308        }
 309}
 310
 311module_init(sja1000_isa_init);
 312module_exit(sja1000_isa_exit);
 313