root/drivers/net/can/softing/softing_cs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. softingcs_find_platform_data
  2. softingcs_reset
  3. softingcs_enable_irq
  4. softingcs_probe_config
  5. softingcs_remove
  6. softingcs_pdev_release
  7. softingcs_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2008-2010
   4  *
   5  * - Kurt Van Dijck, EIA Electronics
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/kernel.h>
  10 #include <linux/slab.h>
  11 
  12 #include <pcmcia/cistpl.h>
  13 #include <pcmcia/ds.h>
  14 
  15 #include "softing_platform.h"
  16 
  17 static int softingcs_index;
  18 static DEFINE_SPINLOCK(softingcs_index_lock);
  19 
  20 static int softingcs_reset(struct platform_device *pdev, int v);
  21 static int softingcs_enable_irq(struct platform_device *pdev, int v);
  22 
  23 /*
  24  * platform_data descriptions
  25  */
  26 #define MHZ (1000*1000)
  27 static const struct softing_platform_data softingcs_platform_data[] = {
  28 {
  29         .name = "CANcard",
  30         .manf = 0x0168, .prod = 0x001,
  31         .generation = 1,
  32         .nbus = 2,
  33         .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
  34         .dpram_size = 0x0800,
  35         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
  36         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
  37         .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
  38         .reset = softingcs_reset,
  39         .enable_irq = softingcs_enable_irq,
  40 }, {
  41         .name = "CANcard-NEC",
  42         .manf = 0x0168, .prod = 0x002,
  43         .generation = 1,
  44         .nbus = 2,
  45         .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
  46         .dpram_size = 0x0800,
  47         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
  48         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
  49         .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
  50         .reset = softingcs_reset,
  51         .enable_irq = softingcs_enable_irq,
  52 }, {
  53         .name = "CANcard-SJA",
  54         .manf = 0x0168, .prod = 0x004,
  55         .generation = 1,
  56         .nbus = 2,
  57         .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
  58         .dpram_size = 0x0800,
  59         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
  60         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
  61         .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
  62         .reset = softingcs_reset,
  63         .enable_irq = softingcs_enable_irq,
  64 }, {
  65         .name = "CANcard-2",
  66         .manf = 0x0168, .prod = 0x005,
  67         .generation = 2,
  68         .nbus = 2,
  69         .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
  70         .dpram_size = 0x1000,
  71         .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
  72         .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
  73         .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
  74         .reset = softingcs_reset,
  75         .enable_irq = NULL,
  76 }, {
  77         .name = "Vector-CANcard",
  78         .manf = 0x0168, .prod = 0x081,
  79         .generation = 1,
  80         .nbus = 2,
  81         .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
  82         .dpram_size = 0x0800,
  83         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
  84         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
  85         .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
  86         .reset = softingcs_reset,
  87         .enable_irq = softingcs_enable_irq,
  88 }, {
  89         .name = "Vector-CANcard-SJA",
  90         .manf = 0x0168, .prod = 0x084,
  91         .generation = 1,
  92         .nbus = 2,
  93         .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
  94         .dpram_size = 0x0800,
  95         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
  96         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
  97         .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
  98         .reset = softingcs_reset,
  99         .enable_irq = softingcs_enable_irq,
 100 }, {
 101         .name = "Vector-CANcard-2",
 102         .manf = 0x0168, .prod = 0x085,
 103         .generation = 2,
 104         .nbus = 2,
 105         .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
 106         .dpram_size = 0x1000,
 107         .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
 108         .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
 109         .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
 110         .reset = softingcs_reset,
 111         .enable_irq = NULL,
 112 }, {
 113         .name = "EDICcard-NEC",
 114         .manf = 0x0168, .prod = 0x102,
 115         .generation = 1,
 116         .nbus = 2,
 117         .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
 118         .dpram_size = 0x0800,
 119         .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
 120         .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
 121         .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
 122         .reset = softingcs_reset,
 123         .enable_irq = softingcs_enable_irq,
 124 }, {
 125         .name = "EDICcard-2",
 126         .manf = 0x0168, .prod = 0x105,
 127         .generation = 2,
 128         .nbus = 2,
 129         .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
 130         .dpram_size = 0x1000,
 131         .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
 132         .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
 133         .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
 134         .reset = softingcs_reset,
 135         .enable_irq = NULL,
 136 }, {
 137         0, 0,
 138 },
 139 };
 140 
 141 MODULE_FIRMWARE(fw_dir "bcard.bin");
 142 MODULE_FIRMWARE(fw_dir "ldcard.bin");
 143 MODULE_FIRMWARE(fw_dir "cancard.bin");
 144 MODULE_FIRMWARE(fw_dir "cansja.bin");
 145 
 146 MODULE_FIRMWARE(fw_dir "bcard2.bin");
 147 MODULE_FIRMWARE(fw_dir "ldcard2.bin");
 148 MODULE_FIRMWARE(fw_dir "cancrd2.bin");
 149 
 150 static const struct softing_platform_data
 151 *softingcs_find_platform_data(unsigned int manf, unsigned int prod)
 152 {
 153         const struct softing_platform_data *lp;
 154 
 155         for (lp = softingcs_platform_data; lp->manf; ++lp) {
 156                 if ((lp->manf == manf) && (lp->prod == prod))
 157                         return lp;
 158         }
 159         return NULL;
 160 }
 161 
 162 /*
 163  * platformdata callbacks
 164  */
 165 static int softingcs_reset(struct platform_device *pdev, int v)
 166 {
 167         struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
 168 
 169         dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
 170         return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
 171 }
 172 
 173 static int softingcs_enable_irq(struct platform_device *pdev, int v)
 174 {
 175         struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
 176 
 177         dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
 178         return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
 179 }
 180 
 181 /*
 182  * pcmcia check
 183  */
 184 static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)
 185 {
 186         struct softing_platform_data *pdat = priv_data;
 187         struct resource *pres;
 188         int memspeed = 0;
 189 
 190         WARN_ON(!pdat);
 191         pres = pcmcia->resource[PCMCIA_IOMEM_0];
 192         if (resource_size(pres) < 0x1000)
 193                 return -ERANGE;
 194 
 195         pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
 196         if (pdat->generation < 2) {
 197                 pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
 198                 memspeed = 3;
 199         } else {
 200                 pres->flags |= WIN_DATA_WIDTH_16;
 201         }
 202         return pcmcia_request_window(pcmcia, pres, memspeed);
 203 }
 204 
 205 static void softingcs_remove(struct pcmcia_device *pcmcia)
 206 {
 207         struct platform_device *pdev = pcmcia->priv;
 208 
 209         /* free bits */
 210         platform_device_unregister(pdev);
 211         /* release pcmcia stuff */
 212         pcmcia_disable_device(pcmcia);
 213 }
 214 
 215 /*
 216  * platform_device wrapper
 217  * pdev->resource has 2 entries: io & irq
 218  */
 219 static void softingcs_pdev_release(struct device *dev)
 220 {
 221         struct platform_device *pdev = to_platform_device(dev);
 222         kfree(pdev);
 223 }
 224 
 225 static int softingcs_probe(struct pcmcia_device *pcmcia)
 226 {
 227         int ret;
 228         struct platform_device *pdev;
 229         const struct softing_platform_data *pdat;
 230         struct resource *pres;
 231         struct dev {
 232                 struct platform_device pdev;
 233                 struct resource res[2];
 234         } *dev;
 235 
 236         /* find matching platform_data */
 237         pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
 238         if (!pdat)
 239                 return -ENOTTY;
 240 
 241         /* setup pcmcia device */
 242         pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
 243                 CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 244         ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
 245         if (ret)
 246                 goto pcmcia_failed;
 247 
 248         ret = pcmcia_enable_device(pcmcia);
 249         if (ret < 0)
 250                 goto pcmcia_failed;
 251 
 252         pres = pcmcia->resource[PCMCIA_IOMEM_0];
 253         if (!pres) {
 254                 ret = -EBADF;
 255                 goto pcmcia_bad;
 256         }
 257 
 258         /* create softing platform device */
 259         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 260         if (!dev) {
 261                 ret = -ENOMEM;
 262                 goto mem_failed;
 263         }
 264         dev->pdev.resource = dev->res;
 265         dev->pdev.num_resources = ARRAY_SIZE(dev->res);
 266         dev->pdev.dev.release = softingcs_pdev_release;
 267 
 268         pdev = &dev->pdev;
 269         pdev->dev.platform_data = (void *)pdat;
 270         pdev->dev.parent = &pcmcia->dev;
 271         pcmcia->priv = pdev;
 272 
 273         /* platform device resources */
 274         pdev->resource[0].flags = IORESOURCE_MEM;
 275         pdev->resource[0].start = pres->start;
 276         pdev->resource[0].end = pres->end;
 277 
 278         pdev->resource[1].flags = IORESOURCE_IRQ;
 279         pdev->resource[1].start = pcmcia->irq;
 280         pdev->resource[1].end = pdev->resource[1].start;
 281 
 282         /* platform device setup */
 283         spin_lock(&softingcs_index_lock);
 284         pdev->id = softingcs_index++;
 285         spin_unlock(&softingcs_index_lock);
 286         pdev->name = "softing";
 287         dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
 288         ret = platform_device_register(pdev);
 289         if (ret < 0)
 290                 goto platform_failed;
 291 
 292         dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
 293         return 0;
 294 
 295 platform_failed:
 296         kfree(dev);
 297 mem_failed:
 298 pcmcia_bad:
 299 pcmcia_failed:
 300         pcmcia_disable_device(pcmcia);
 301         pcmcia->priv = NULL;
 302         return ret;
 303 }
 304 
 305 static const struct pcmcia_device_id softingcs_ids[] = {
 306         /* softing */
 307         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
 308         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
 309         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
 310         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
 311         /* vector, manufacturer? */
 312         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
 313         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
 314         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
 315         /* EDIC */
 316         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
 317         PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
 318         PCMCIA_DEVICE_NULL,
 319 };
 320 
 321 MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
 322 
 323 static struct pcmcia_driver softingcs_driver = {
 324         .owner          = THIS_MODULE,
 325         .name           = "softingcs",
 326         .id_table       = softingcs_ids,
 327         .probe          = softingcs_probe,
 328         .remove         = softingcs_remove,
 329 };
 330 
 331 module_pcmcia_driver(softingcs_driver);
 332 
 333 MODULE_DESCRIPTION("softing CANcard driver"
 334                 ", links PCMCIA card to softing driver");
 335 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */