Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2008 Sebastian Haas (initial chardev implementation)
0004  * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com>
0005  * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/delay.h>
0013 #include <linux/io.h>
0014 #include <pcmcia/cistpl.h>
0015 #include <pcmcia/ds.h>
0016 #include <linux/can.h>
0017 #include <linux/can/dev.h>
0018 #include "sja1000.h"
0019 
0020 #define DRV_NAME "ems_pcmcia"
0021 
0022 MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
0023 MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
0024 MODULE_LICENSE("GPL v2");
0025 
0026 #define EMS_PCMCIA_MAX_CHAN 2
0027 
0028 struct ems_pcmcia_card {
0029     int channels;
0030     struct pcmcia_device *pcmcia_dev;
0031     struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
0032     void __iomem *base_addr;
0033 };
0034 
0035 #define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
0036 
0037 /*
0038  * The board configuration is probably following:
0039  * RX1 is connected to ground.
0040  * TX1 is not connected.
0041  * CLKO is not connected.
0042  * Setting the OCR register to 0xDA is a good idea.
0043  * This means  normal output mode , push-pull and the correct polarity.
0044  */
0045 #define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
0046 
0047 /*
0048  * In the CDR register, you should set CBP to 1.
0049  * You will probably also want to set the clock divider value to 7
0050  * (meaning direct oscillator output) because the second SJA1000 chip
0051  * is driven by the first one CLKOUT output.
0052  */
0053 #define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
0054 #define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
0055 #define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
0056 #define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
0057 
0058 #define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
0059 #define EMS_CMD_MAP   0x03 /* Map CAN controllers into card' memory */
0060 #define EMS_CMD_UMAP  0x02 /* Unmap CAN controllers from card' memory */
0061 
0062 static struct pcmcia_device_id ems_pcmcia_tbl[] = {
0063     PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
0064                  0xa338573f, 0xe4575800),
0065     PCMCIA_DEVICE_NULL,
0066 };
0067 
0068 MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
0069 
0070 static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
0071 {
0072     return readb(priv->reg_base + port);
0073 }
0074 
0075 static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
0076                  u8 val)
0077 {
0078     writeb(val, priv->reg_base + port);
0079 }
0080 
0081 static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
0082 {
0083     struct ems_pcmcia_card *card = dev_id;
0084     struct net_device *dev;
0085     irqreturn_t retval = IRQ_NONE;
0086     int i, again;
0087 
0088     /* Card not present */
0089     if (readw(card->base_addr) != 0xAA55)
0090         return IRQ_HANDLED;
0091 
0092     do {
0093         again = 0;
0094 
0095         /* Check interrupt for each channel */
0096         for (i = 0; i < card->channels; i++) {
0097             dev = card->net_dev[i];
0098             if (!dev)
0099                 continue;
0100 
0101             if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
0102                 again = 1;
0103         }
0104         /* At least one channel handled the interrupt */
0105         if (again)
0106             retval = IRQ_HANDLED;
0107 
0108     } while (again);
0109 
0110     return retval;
0111 }
0112 
0113 /*
0114  * Check if a CAN controller is present at the specified location
0115  * by trying to set 'em into the PeliCAN mode
0116  */
0117 static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
0118 {
0119     /* Make sure SJA1000 is in reset mode */
0120     ems_pcmcia_write_reg(priv, SJA1000_MOD, 1);
0121     ems_pcmcia_write_reg(priv, SJA1000_CDR, CDR_PELICAN);
0122 
0123     /* read reset-values */
0124     if (ems_pcmcia_read_reg(priv, SJA1000_CDR) == CDR_PELICAN)
0125         return 1;
0126 
0127     return 0;
0128 }
0129 
0130 static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
0131 {
0132     struct ems_pcmcia_card *card = pdev->priv;
0133     struct net_device *dev;
0134     int i;
0135 
0136     free_irq(pdev->irq, card);
0137 
0138     for (i = 0; i < card->channels; i++) {
0139         dev = card->net_dev[i];
0140         if (!dev)
0141             continue;
0142 
0143         printk(KERN_INFO "%s: removing %s on channel #%d\n",
0144                DRV_NAME, dev->name, i);
0145         unregister_sja1000dev(dev);
0146         free_sja1000dev(dev);
0147     }
0148 
0149     writeb(EMS_CMD_UMAP, card->base_addr);
0150     iounmap(card->base_addr);
0151     kfree(card);
0152 
0153     pdev->priv = NULL;
0154 }
0155 
0156 /*
0157  * Probe PCI device for EMS CAN signature and register each available
0158  * CAN channel to SJA1000 Socket-CAN subsystem.
0159  */
0160 static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
0161 {
0162     struct sja1000_priv *priv;
0163     struct net_device *dev;
0164     struct ems_pcmcia_card *card;
0165     int err, i;
0166 
0167     /* Allocating card structures to hold addresses, ... */
0168     card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
0169     if (!card)
0170         return -ENOMEM;
0171 
0172     pdev->priv = card;
0173     card->channels = 0;
0174 
0175     card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
0176     if (!card->base_addr) {
0177         err = -ENOMEM;
0178         goto failure_cleanup;
0179     }
0180 
0181     /* Check for unique EMS CAN signature */
0182     if (readw(card->base_addr) != 0xAA55) {
0183         err = -ENODEV;
0184         goto failure_cleanup;
0185     }
0186 
0187     /* Request board reset */
0188     writeb(EMS_CMD_RESET, card->base_addr);
0189 
0190     /* Make sure CAN controllers are mapped into card's memory space */
0191     writeb(EMS_CMD_MAP, card->base_addr);
0192 
0193     /* Detect available channels */
0194     for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
0195         dev = alloc_sja1000dev(0);
0196         if (!dev) {
0197             err = -ENOMEM;
0198             goto failure_cleanup;
0199         }
0200 
0201         card->net_dev[i] = dev;
0202         priv = netdev_priv(dev);
0203         priv->priv = card;
0204         SET_NETDEV_DEV(dev, &pdev->dev);
0205         dev->dev_id = i;
0206 
0207         priv->irq_flags = IRQF_SHARED;
0208         dev->irq = pdev->irq;
0209         priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
0210             (i * EMS_PCMCIA_CAN_CTRL_SIZE);
0211 
0212         /* Check if channel is present */
0213         if (ems_pcmcia_check_chan(priv)) {
0214             priv->read_reg  = ems_pcmcia_read_reg;
0215             priv->write_reg = ems_pcmcia_write_reg;
0216             priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
0217             priv->ocr = EMS_PCMCIA_OCR;
0218             priv->cdr = EMS_PCMCIA_CDR;
0219             priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
0220 
0221             /* Register SJA1000 device */
0222             err = register_sja1000dev(dev);
0223             if (err) {
0224                 free_sja1000dev(dev);
0225                 goto failure_cleanup;
0226             }
0227 
0228             card->channels++;
0229 
0230             printk(KERN_INFO "%s: registered %s on channel "
0231                    "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
0232                    i, priv->reg_base, dev->irq);
0233         } else
0234             free_sja1000dev(dev);
0235     }
0236 
0237     if (!card->channels) {
0238         err = -ENODEV;
0239         goto failure_cleanup;
0240     }
0241 
0242     err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
0243               DRV_NAME, card);
0244     if (!err)
0245         return 0;
0246 
0247 failure_cleanup:
0248     ems_pcmcia_del_card(pdev);
0249     return err;
0250 }
0251 
0252 /*
0253  * Setup PCMCIA socket and probe for EMS CPC-CARD
0254  */
0255 static int ems_pcmcia_probe(struct pcmcia_device *dev)
0256 {
0257     int csval;
0258 
0259     /* General socket configuration */
0260     dev->config_flags |= CONF_ENABLE_IRQ;
0261     dev->config_index = 1;
0262     dev->config_regs = PRESENT_OPTION;
0263 
0264     /* The io structure describes IO port mapping */
0265     dev->resource[0]->end = 16;
0266     dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
0267     dev->resource[1]->end = 16;
0268     dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
0269     dev->io_lines = 5;
0270 
0271     /* Allocate a memory window */
0272     dev->resource[2]->flags =
0273         (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
0274     dev->resource[2]->start = dev->resource[2]->end = 0;
0275 
0276     csval = pcmcia_request_window(dev, dev->resource[2], 0);
0277     if (csval) {
0278         dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
0279             csval);
0280         return 0;
0281     }
0282 
0283     csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
0284     if (csval) {
0285         dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
0286             csval);
0287         return 0;
0288     }
0289 
0290     csval = pcmcia_enable_device(dev);
0291     if (csval) {
0292         dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
0293             csval);
0294         return 0;
0295     }
0296 
0297     ems_pcmcia_add_card(dev, dev->resource[2]->start);
0298     return 0;
0299 }
0300 
0301 /*
0302  * Release claimed resources
0303  */
0304 static void ems_pcmcia_remove(struct pcmcia_device *dev)
0305 {
0306     ems_pcmcia_del_card(dev);
0307     pcmcia_disable_device(dev);
0308 }
0309 
0310 static struct pcmcia_driver ems_pcmcia_driver = {
0311     .name = DRV_NAME,
0312     .probe = ems_pcmcia_probe,
0313     .remove = ems_pcmcia_remove,
0314     .id_table = ems_pcmcia_tbl,
0315 };
0316 module_pcmcia_driver(ems_pcmcia_driver);