linux/drivers/net/can/sja1000/ems_pcmcia.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2008 Sebastian Haas (initial chardev implementation)
   4 * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com>
   5 * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net>
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/interrupt.h>
  11#include <linux/netdevice.h>
  12#include <linux/delay.h>
  13#include <linux/io.h>
  14#include <pcmcia/cistpl.h>
  15#include <pcmcia/ds.h>
  16#include <linux/can.h>
  17#include <linux/can/dev.h>
  18#include "sja1000.h"
  19
  20#define DRV_NAME "ems_pcmcia"
  21
  22MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
  23MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
  24MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card");
  25MODULE_LICENSE("GPL v2");
  26
  27#define EMS_PCMCIA_MAX_CHAN 2
  28
  29struct ems_pcmcia_card {
  30        int channels;
  31        struct pcmcia_device *pcmcia_dev;
  32        struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
  33        void __iomem *base_addr;
  34};
  35
  36#define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
  37
  38/*
  39 * The board configuration is probably following:
  40 * RX1 is connected to ground.
  41 * TX1 is not connected.
  42 * CLKO is not connected.
  43 * Setting the OCR register to 0xDA is a good idea.
  44 * This means  normal output mode , push-pull and the correct polarity.
  45 */
  46#define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
  47
  48/*
  49 * In the CDR register, you should set CBP to 1.
  50 * You will probably also want to set the clock divider value to 7
  51 * (meaning direct oscillator output) because the second SJA1000 chip
  52 * is driven by the first one CLKOUT output.
  53 */
  54#define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
  55#define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
  56#define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
  57#define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
  58
  59#define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
  60#define EMS_CMD_MAP   0x03 /* Map CAN controllers into card' memory */
  61#define EMS_CMD_UMAP  0x02 /* Unmap CAN controllers from card' memory */
  62
  63static struct pcmcia_device_id ems_pcmcia_tbl[] = {
  64        PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
  65                                 0xa338573f, 0xe4575800),
  66        PCMCIA_DEVICE_NULL,
  67};
  68
  69MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
  70
  71static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
  72{
  73        return readb(priv->reg_base + port);
  74}
  75
  76static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
  77                                 u8 val)
  78{
  79        writeb(val, priv->reg_base + port);
  80}
  81
  82static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
  83{
  84        struct ems_pcmcia_card *card = dev_id;
  85        struct net_device *dev;
  86        irqreturn_t retval = IRQ_NONE;
  87        int i, again;
  88
  89        /* Card not present */
  90        if (readw(card->base_addr) != 0xAA55)
  91                return IRQ_HANDLED;
  92
  93        do {
  94                again = 0;
  95
  96                /* Check interrupt for each channel */
  97                for (i = 0; i < card->channels; i++) {
  98                        dev = card->net_dev[i];
  99                        if (!dev)
 100                                continue;
 101
 102                        if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
 103                                again = 1;
 104                }
 105                /* At least one channel handled the interrupt */
 106                if (again)
 107                        retval = IRQ_HANDLED;
 108
 109        } while (again);
 110
 111        return retval;
 112}
 113
 114/*
 115 * Check if a CAN controller is present at the specified location
 116 * by trying to set 'em into the PeliCAN mode
 117 */
 118static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
 119{
 120        /* Make sure SJA1000 is in reset mode */
 121        ems_pcmcia_write_reg(priv, SJA1000_MOD, 1);
 122        ems_pcmcia_write_reg(priv, SJA1000_CDR, CDR_PELICAN);
 123
 124        /* read reset-values */
 125        if (ems_pcmcia_read_reg(priv, SJA1000_CDR) == CDR_PELICAN)
 126                return 1;
 127
 128        return 0;
 129}
 130
 131static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
 132{
 133        struct ems_pcmcia_card *card = pdev->priv;
 134        struct net_device *dev;
 135        int i;
 136
 137        free_irq(pdev->irq, card);
 138
 139        for (i = 0; i < card->channels; i++) {
 140                dev = card->net_dev[i];
 141                if (!dev)
 142                        continue;
 143
 144                printk(KERN_INFO "%s: removing %s on channel #%d\n",
 145                       DRV_NAME, dev->name, i);
 146                unregister_sja1000dev(dev);
 147                free_sja1000dev(dev);
 148        }
 149
 150        writeb(EMS_CMD_UMAP, card->base_addr);
 151        iounmap(card->base_addr);
 152        kfree(card);
 153
 154        pdev->priv = NULL;
 155}
 156
 157/*
 158 * Probe PCI device for EMS CAN signature and register each available
 159 * CAN channel to SJA1000 Socket-CAN subsystem.
 160 */
 161static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
 162{
 163        struct sja1000_priv *priv;
 164        struct net_device *dev;
 165        struct ems_pcmcia_card *card;
 166        int err, i;
 167
 168        /* Allocating card structures to hold addresses, ... */
 169        card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
 170        if (!card)
 171                return -ENOMEM;
 172
 173        pdev->priv = card;
 174        card->channels = 0;
 175
 176        card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
 177        if (!card->base_addr) {
 178                err = -ENOMEM;
 179                goto failure_cleanup;
 180        }
 181
 182        /* Check for unique EMS CAN signature */
 183        if (readw(card->base_addr) != 0xAA55) {
 184                err = -ENODEV;
 185                goto failure_cleanup;
 186        }
 187
 188        /* Request board reset */
 189        writeb(EMS_CMD_RESET, card->base_addr);
 190
 191        /* Make sure CAN controllers are mapped into card's memory space */
 192        writeb(EMS_CMD_MAP, card->base_addr);
 193
 194        /* Detect available channels */
 195        for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
 196                dev = alloc_sja1000dev(0);
 197                if (!dev) {
 198                        err = -ENOMEM;
 199                        goto failure_cleanup;
 200                }
 201
 202                card->net_dev[i] = dev;
 203                priv = netdev_priv(dev);
 204                priv->priv = card;
 205                SET_NETDEV_DEV(dev, &pdev->dev);
 206                dev->dev_id = i;
 207
 208                priv->irq_flags = IRQF_SHARED;
 209                dev->irq = pdev->irq;
 210                priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
 211                        (i * EMS_PCMCIA_CAN_CTRL_SIZE);
 212
 213                /* Check if channel is present */
 214                if (ems_pcmcia_check_chan(priv)) {
 215                        priv->read_reg  = ems_pcmcia_read_reg;
 216                        priv->write_reg = ems_pcmcia_write_reg;
 217                        priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
 218                        priv->ocr = EMS_PCMCIA_OCR;
 219                        priv->cdr = EMS_PCMCIA_CDR;
 220                        priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
 221
 222                        /* Register SJA1000 device */
 223                        err = register_sja1000dev(dev);
 224                        if (err) {
 225                                free_sja1000dev(dev);
 226                                goto failure_cleanup;
 227                        }
 228
 229                        card->channels++;
 230
 231                        printk(KERN_INFO "%s: registered %s on channel "
 232                               "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
 233                               i, priv->reg_base, dev->irq);
 234                } else
 235                        free_sja1000dev(dev);
 236        }
 237
 238        err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
 239                          DRV_NAME, card);
 240        if (!err)
 241                return 0;
 242
 243failure_cleanup:
 244        ems_pcmcia_del_card(pdev);
 245        return err;
 246}
 247
 248/*
 249 * Setup PCMCIA socket and probe for EMS CPC-CARD
 250 */
 251static int ems_pcmcia_probe(struct pcmcia_device *dev)
 252{
 253        int csval;
 254
 255        /* General socket configuration */
 256        dev->config_flags |= CONF_ENABLE_IRQ;
 257        dev->config_index = 1;
 258        dev->config_regs = PRESENT_OPTION;
 259
 260        /* The io structure describes IO port mapping */
 261        dev->resource[0]->end = 16;
 262        dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 263        dev->resource[1]->end = 16;
 264        dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
 265        dev->io_lines = 5;
 266
 267        /* Allocate a memory window */
 268        dev->resource[2]->flags =
 269                (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
 270        dev->resource[2]->start = dev->resource[2]->end = 0;
 271
 272        csval = pcmcia_request_window(dev, dev->resource[2], 0);
 273        if (csval) {
 274                dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
 275                        csval);
 276                return 0;
 277        }
 278
 279        csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
 280        if (csval) {
 281                dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
 282                        csval);
 283                return 0;
 284        }
 285
 286        csval = pcmcia_enable_device(dev);
 287        if (csval) {
 288                dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
 289                        csval);
 290                return 0;
 291        }
 292
 293        ems_pcmcia_add_card(dev, dev->resource[2]->start);
 294        return 0;
 295}
 296
 297/*
 298 * Release claimed resources
 299 */
 300static void ems_pcmcia_remove(struct pcmcia_device *dev)
 301{
 302        ems_pcmcia_del_card(dev);
 303        pcmcia_disable_device(dev);
 304}
 305
 306static struct pcmcia_driver ems_pcmcia_driver = {
 307        .name = DRV_NAME,
 308        .probe = ems_pcmcia_probe,
 309        .remove = ems_pcmcia_remove,
 310        .id_table = ems_pcmcia_tbl,
 311};
 312module_pcmcia_driver(ems_pcmcia_driver);
 313