2 * drivers/net/can/softing/softing_cs.c
6 * - Kurt Van Dijck, EIA Electronics
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the version 2 of the GNU General Public License
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/version.h>
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/sched.h>
28 #include <linux/ptrace.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/timer.h>
32 #include <linux/major.h>
35 #include <pcmcia/cs_types.h>
36 #include <pcmcia/cs.h>
37 #include <pcmcia/cistpl.h>
38 #include <pcmcia/ciscode.h>
39 #include <pcmcia/ds.h>
40 #include <pcmcia/cisreg.h>
42 #include <asm/system.h>
47 struct softing softing;
50 #define softing2cs(x) container_of((x), struct softing_cs, softing)
52 /* card descriptions */
53 static const struct softing_desc carddescs[] = {
56 .manf = 0x0168, .prod = 0x001,
58 .freq = 16, .max_brp = 32, .max_sjw = 4,
60 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
61 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
62 .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
64 .name = "CANcard-NEC",
65 .manf = 0x0168, .prod = 0x002,
67 .freq = 16, .max_brp = 32, .max_sjw = 4,
69 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
70 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
71 .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
73 .name = "CANcard-SJA",
74 .manf = 0x0168, .prod = 0x004,
76 .freq = 20, .max_brp = 32, .max_sjw = 4,
78 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
79 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
80 .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
83 .manf = 0x0168, .prod = 0x005,
85 .freq = 24, .max_brp = 64, .max_sjw = 4,
87 .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
88 .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
89 .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
91 .name = "Vector-CANcard",
92 .manf = 0x0168, .prod = 0x081,
94 .freq = 16, .max_brp = 64, .max_sjw = 4,
96 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
97 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
98 .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
100 .name = "Vector-CANcard-SJA",
101 .manf = 0x0168, .prod = 0x084,
103 .freq = 20, .max_brp = 32, .max_sjw = 4,
104 .dpram_size = 0x0800,
105 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
106 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
107 .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
109 .name = "Vector-CANcard-2",
110 .manf = 0x0168, .prod = 0x085,
112 .freq = 24, .max_brp = 64, .max_sjw = 4,
113 .dpram_size = 0x0800,
114 .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
115 .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
116 .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
118 .name = "EDICcard-NEC",
119 .manf = 0x0168, .prod = 0x102,
121 .freq = 16, .max_brp = 64, .max_sjw = 4,
122 .dpram_size = 0x0800,
123 .boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
124 .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
125 .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
127 .name = "EDICcard-2",
128 .manf = 0x0168, .prod = 0x105,
130 .freq = 24, .max_brp = 64, .max_sjw = 4,
131 .dpram_size = 0x0800,
132 .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
133 .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
134 .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
139 MODULE_FIRMWARE(fw_dir "bcard.bin");
140 MODULE_FIRMWARE(fw_dir "ldcard.bin");
141 MODULE_FIRMWARE(fw_dir "cancard.bin");
142 MODULE_FIRMWARE(fw_dir "cansja.bin");
144 MODULE_FIRMWARE(fw_dir "bcard2.bin");
145 MODULE_FIRMWARE(fw_dir "ldcard2.bin");
146 MODULE_FIRMWARE(fw_dir "cancrd2.bin");
148 static const struct softing_desc *softing_cs_lookup_desc
149 (unsigned int manf, unsigned int prod)
151 const struct softing_desc *lp = carddescs;
152 for (; lp->name; ++lp) {
153 if ((lp->manf == manf) && (lp->prod == prod))
165 static const char __devinit *lookup_mask(const struct lookup *lp, int *i)
167 for (; lp->a; ++lp) {
176 static int card_reset_via_pcmcia(struct softing *sdev, int v)
178 struct pcmcia_device *pcmcia = to_pcmcia_dev(sdev->dev);
180 reg.Function = 0; /* socket */
181 reg.Action = CS_WRITE;
183 reg.Value = v ? 0 : 0x20;
184 return pcmcia_access_configuration_register(pcmcia, ®);
187 static int card_reset_via_dpram(struct softing *sdev, int v)
190 spin_lock_bh(&sdev->spin);
191 sdev->dpram.virt[0xe00] &= ~1;
192 spin_unlock_bh(&sdev->spin);
193 card_reset_via_pcmcia(sdev, v);
195 card_reset_via_pcmcia(sdev, v);
196 spin_lock_bh(&sdev->spin);
197 sdev->dpram.virt[0xe00] |= 1;
198 spin_unlock_bh(&sdev->spin);
203 static int card_enable_irq_via_pcmcia(struct softing *sdev, int v)
206 struct pcmcia_device *pcmcia = to_pcmcia_dev(sdev->dev);
208 memset(®, 0, sizeof(reg));
209 reg.Function = 0; /* socket */
210 reg.Action = CS_WRITE;
212 reg.Value = v ? 0x60 : 0;
213 ret = pcmcia_access_configuration_register(pcmcia, ®);
215 dev_alert(&pcmcia->dev, "failed %u\n", ret);
219 /* TODO: in 2.6.26, __devinitconst works*/
220 static const __devinitdata struct lookup pcmcia_io_attr[] = {
221 { IO_DATA_PATH_WIDTH_AUTO , "[auto]" , },
222 { IO_DATA_PATH_WIDTH_8 , "8bit" , },
223 { IO_DATA_PATH_WIDTH_16 , "16bit" , },
227 static const __devinitdata struct lookup pcmcia_mem_attr[] = {
228 { WIN_ADDR_SPACE_IO , "IO" , },
229 { WIN_MEMORY_TYPE_AM , "typeAM" , },
230 { WIN_ENABLE , "enable" , },
231 { WIN_DATA_WIDTH_8 , "8bit" , },
232 { WIN_DATA_WIDTH_16 , "16bit" , },
233 { WIN_DATA_WIDTH_32 , "32bit" , },
234 { WIN_PAGED , "paged" , },
235 { WIN_SHARED , "shared" , },
236 { WIN_FIRST_SHARED , "first_shared", },
237 { WIN_USE_WAIT , "wait" , },
238 { WIN_STRICT_ALIGN , "strict_align", },
239 { WIN_MAP_BELOW_1MB , "below_1MB" , },
240 { WIN_PREFETCH , "prefetch" , },
241 { WIN_CACHEABLE , "cacheable" , },
245 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
247 struct pcmcia_cfg_mem {
251 cistpl_cftable_entry_t dflt;
253 static int pcmcia_loop_config(struct pcmcia_device *p_dev,
254 int (*conf_check) (struct pcmcia_device *p_dev,
255 cistpl_cftable_entry_t *cfg,
256 cistpl_cftable_entry_t *dflt,
261 struct pcmcia_cfg_mem *cfg_mem;
267 cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL);
271 /* get the current Vcc setting */
272 vcc = p_dev->socket->socket.Vcc;
274 tuple = &cfg_mem->tuple;
275 tuple->TupleData = cfg_mem->buf;
276 tuple->TupleDataMax = sizeof(cfg_mem->buf)-1;
277 tuple->TupleOffset = 0;
278 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
279 tuple->Attributes = 0;
281 ret = pcmcia_get_first_tuple(p_dev, tuple);
283 cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
285 if (pcmcia_get_tuple_data(p_dev, tuple))
288 if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse))
292 p_dev->conf.ConfigIndex = cfg->index;
293 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
294 cfg_mem->dflt = *cfg;
296 ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
301 ret = pcmcia_get_next_tuple(p_dev, tuple);
308 static int dev_conf_check(struct pcmcia_device *pdev,
309 cistpl_cftable_entry_t *cf, cistpl_cftable_entry_t *def_cf,
310 unsigned int vcc, void *priv_data)
312 struct softing_cs *csdev = priv_data;
313 struct softing *sdev = &csdev->softing;
318 /* power settings (Vcc & Vpp) */
319 if (cf->vcc.present & (1 << CISTPL_POWER_VNOM)) {
320 if (vcc != cf->vcc.param[CISTPL_POWER_VNOM]/10000) {
321 dev_alert(&pdev->dev, "cf->Vcc mismatch\n");
324 } else if (def_cf->vcc.present & (1 << CISTPL_POWER_VNOM)) {
325 if (vcc != def_cf->vcc.param[CISTPL_POWER_VNOM]/10000) {
326 dev_alert(&pdev->dev, "cf->Vcc mismatch\n");
330 if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
332 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
334 else if (def_cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
336 = def_cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
339 if (cf->irq.IRQInfo1 || def_cf->irq.IRQInfo1)
340 pdev->conf.Attributes |= CONF_ENABLE_IRQ;
347 if ((cf->mem.nwin > 0) || (def_cf->mem.nwin > 0)) {
350 = (cf->mem.nwin) ? &cf->mem : &def_cf->mem;
351 /* softing specific: choose 8 or 16bit access */
352 csdev->win.Attributes = ((sdev->desc->generation >= 2)
353 ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8)
356 csdev->win.Base = mem->win[0].host_addr;
357 csdev->win.Size = mem->win[0].len;
358 csdev->win.AccessSpeed = 0;
359 /* softing specific: choose slower access for old cards */
360 if (sdev->desc->generation < 2) {
361 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
363 = MAP_ACTIVE | MAP_USE_WAIT;
364 pdev->win->ctl.speed = 3;
366 csdev->win.Attributes |= WIN_USE_WAIT;
367 csdev->win.AccessSpeed = 3;
370 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
371 ret = pcmcia_request_window(&pdev, &csdev->win, &pdev->win);
373 ret = pcmcia_request_window(pdev, &csdev->win, &pdev->win);
376 dev_alert(&pdev->dev,
377 "pcmcia_request_window() mismatch\n");
381 map.CardOffset = mem->win[0].card_addr;
382 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
383 if (pcmcia_map_mem_page(pdev->win, &map)) {
385 if (pcmcia_map_mem_page(pdev, pdev->win, &map)) {
387 dev_alert(&pdev->dev,
388 "pcmcia_map_mem_page() mismatch\n");
392 dev_info(&pdev->dev, "no memory window in tuple %u\n",
399 pcmcia_disable_device(pdev);
403 static void driver_remove(struct pcmcia_device *pcmcia)
405 struct softing *card = (struct softing *)pcmcia->priv;
406 struct softing_cs *cs = softing2cs(card);
407 dev_dbg(&pcmcia->dev, "%s, device '%s'\n"
408 , card->id.name, pcmcia->devname);
410 /* release pcmcia stuff */
411 pcmcia_disable_device(pcmcia);
416 static int __devinit driver_probe(struct pcmcia_device *pcmcia)
418 struct softing_cs *cs;
419 struct softing *card;
421 char line[1024]; /* possible memory corruption */
423 dev_dbg(&pcmcia->dev, "on %s\n", pcmcia->devname);
425 /* Create new softing device */
426 cs = kzalloc(sizeof(*cs), GFP_KERNEL);
432 card->dev = &pcmcia->dev;
434 card->id.manf = pcmcia->manf_id;
435 card->id.prod = pcmcia->card_id;
436 card->desc = softing_cs_lookup_desc(card->id.manf, card->id.prod);
438 dev_alert(&pcmcia->dev, "unknown card\n");
439 goto description_failed;
441 if (card->desc->generation >= 2) {
442 card->fn.reset = card_reset_via_dpram;
444 card->fn.reset = card_reset_via_pcmcia;
445 card->fn.enable_irq = card_enable_irq_via_pcmcia;
450 pcmcia->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
451 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
452 pcmcia->irq.IRQInfo1 = IRQ_LEVEL_ID;
454 pcmcia->irq.Handler = 0;
455 pcmcia->conf.Attributes = 0;
456 pcmcia->conf.IntType = INT_MEMORY_AND_IO;
458 if (pcmcia_loop_config(pcmcia, dev_conf_check, cs))
461 if (pcmcia_request_irq(pcmcia, &pcmcia->irq))
464 if (pcmcia_request_configuration(pcmcia, &pcmcia->conf))
467 card->dpram.phys = cs->win.Base;
468 card->dpram.size = cs->win.Size;
470 if (card->dpram.size != 0x1000) {
471 dev_alert(&pcmcia->dev, "dpram size 0x%lx mismatch\n",
476 /* Finally, report what we've done */
478 str += sprintf(str, "config index %u", pcmcia->conf.ConfigIndex);
479 if (pcmcia->conf.Vpp)
480 str += sprintf(str, ", Vpp %d.%d",
481 pcmcia->conf.Vpp/10, pcmcia->conf.Vpp%10);
482 if (pcmcia->conf.Attributes & CONF_ENABLE_IRQ) {
483 str += sprintf(str, ", irq %d", pcmcia->irq.AssignedIRQ);
484 card->irq.nr = pcmcia->irq.AssignedIRQ;
490 str += sprintf(str, ", mem 0x%08lx-0x%08lx"
492 , card->dpram.phys + card->dpram.size-1);
493 tmp = cs->win.Attributes;
495 p = lookup_mask(pcmcia_mem_attr, &tmp);
498 str += sprintf(str, " %s", p);
501 dev_info(&pcmcia->dev, "%s\n", line);
503 if (mk_softing(card))
513 pcmcia_disable_device(pcmcia);
517 static struct pcmcia_device_id driver_ids[] = {
519 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
520 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
521 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
522 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
523 /* vector , manufacturer? */
524 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
525 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
526 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
528 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
529 PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
533 MODULE_DEVICE_TABLE(pcmcia, driver_ids);
535 static struct pcmcia_driver softing_cs_driver = {
536 .owner = THIS_MODULE,
538 .name = "softing_cs",
540 .probe = driver_probe,
541 .remove = driver_remove,
542 .id_table = driver_ids,
545 static int __init mod_start(void)
547 return pcmcia_register_driver(&softing_cs_driver);
550 static void __exit mod_stop(void)
552 pcmcia_unregister_driver(&softing_cs_driver);
555 module_init(mod_start);
556 module_exit(mod_stop);
558 MODULE_DESCRIPTION("softing CANcard driver"
559 ", links PCMCIA card to softing driver");
560 MODULE_LICENSE("GPL");
561 MODULE_SUPPORTED_DEVICE("softing CANcard2");