/* * PCM3680 Remarks * * Adresses used related to the Basde adress (set by dip switches) * Base address (hex) CAN controller * base:0000h - base:00FFh Basic- Port 1 * base:0100h - base:01FFh HW reset Basic - Port 1 * base:0200h - base:02FFh Basic- Port 2 * base:0300h - base:03FFh HW reset Basic - Port 2 * base:0400h - base:0FFFh Not used * * Each CAN channel uses 0x200 bytes */ int CAN_VendorInit (int minor) { DBGin("CAN_VendorInit"); can_range[minor] = 0x200; /* Some LINUX systems, e.g. the PIP10 I tested on, * locate already the memory using the information * provided in the "Option ROM" * The memory is marked as "Adapter-ROM" in /proc/iomem. * In this case the drive should not try to allocate the IO mem */ #if !defined(PC104_OPTION_ROM) /* Request the controllers address space */ if(NULL == request_mem_region(Base[minor], can_range[minor], "CAN-IO")) { DBGprint(DBG_DATA,("Request_mem-Region CAN-IO failed at 0x%x\n", Base[minor])); return -EBUSY; } #endif controller_available(Base[minor], 1); can_base[minor] = ioremap(Base[minor], can_range[minor]); /* now the virtual address can be used for the register access macros */ if( Base[minor] & 0x200 ) { /* printk("Resetting Advantech Pcm-3680 [contr 1]\n"); */ /* perform HW reset 2. contr*/ writeb(0xff, can_base[minor] + 0x300); } else { /* printk("Resetting Advantech Pcm-3680 [contr 0]\n"); */ /* perform HW reset 1. contr*/ writeb(0xff, can_base[minor] + 0x100); } mdelay(100); if( IRQ[minor] > 0 || IRQ[minor] > MAX_IRQNUMBER ){ int err; err = request_irq( IRQ[minor], CAN_Interrupt, SA_SHIRQ, "Can", &Can_minors[minor]); if( !err ){ DBGprint(DBG_BRANCH,("Requested IRQ: %d @ 0x%lx", IRQ[minor], (unsigned long)CAN_Interrupt)); IRQ_requested[minor] = 1; } else { release_mem_region(Base[minor], can_range[minor]); DBGout(); return -EBUSY; } } else { /* Invalid IRQ number in /proc/.../IRQ */ release_mem_region(Base[minor], can_range[minor]); DBGout(); return -EBUSY; } DBGout(); return 0; }
/* scan the pci bus look for vendor/device Id == Siemens PITA if found look for subvendor id if found write to pita register 1c in the first address range the value 0x04000000 */ int pcimod_scan(void) { int i, pos = 0; int bus, fun; unsigned char headertype = 0; u32 id; u32 vdid; /* vendor/device id */ int candev = 0; /* number of found devices */ if (!pcibios_present()) { printk("CAN: No PCI bios present\n"); return ENODEV; } /* printk("CAN: PCI bios present!\n"); */ /* * This code is derived from "drivers/pci/pci.c". This means that * the GPL applies to this source file and credit is due to the * original authors (Drew Eckhardt, Frederic Potter, David * Mosberger-Tang) */ for (bus = 0; !bus; bus++) { /* only bus 0 :-) */ for (fun=0; fun < 0x100 && pos < PAGE_SIZE; fun++) { if (!PCI_FUNC(fun)) /* first function */ pcibios_read_config_byte(bus,fun,PCI_HEADER_TYPE, &headertype); else if (!(headertype & 0x80)) continue; /* the following call gets vendor AND device ID */ pcibios_read_config_dword(bus, fun, PCI_VENDOR_ID, &id); if (!id || id == ~0) { headertype = 0; continue; } /* v-endor and d-evice id */ vdid = id; #if 0 printk(" -- found pci device, vendor id = %u/0x%x , device 0x%x\n", (id & 0xffff), (id & 0xffff), (id >> 16)); #endif pcibios_read_config_dword(bus, fun, PCI_CLASS_REVISION, &id); #if 0 printk(" class 0x%x, Revision %d\n", (id >> 8), (id & 0x0ff)); #endif if(vdid == (PCI_VENDOR + (PCI_DEVICE << 16))) { unsigned char irq; u16 cmd; u32 svdid; /* subsystem vendor/device id */ /* found EMS CAN CPC-PCI */ vdid = 0; /* reset it */ printk(" found Siemens PITA PCI-Chip\n"); pcibios_read_config_byte(bus, fun, PCI_INTERRUPT_LINE, &irq); printk(" using IRQ %d\n", irq); pcibios_read_config_word(bus, fun, PCI_COMMAND, &cmd); /* printk(" cmd: 0x%x\n", cmd); */ /* PCI_COMMAND should be at least PCI_COMMAND_MEMORY */ pcibios_write_config_word(bus, fun, /* PCI_COMMAND, PCI_COMMAND_MEMORY); */ PCI_COMMAND, PCI_COMMAND_MEMORY + PCI_COMMAND_MASTER ); pcibios_read_config_word(bus, fun, PCI_COMMAND, &cmd); /* printk(" cmd: 0x%x\n", cmd); */ pcibios_read_config_dword(bus, fun, PCI_SUBSYSTEM_VENDOR_ID, &svdid); /* printk(" s_vendor 0x%x, s_device 0x%x\n", */ /* (svdid & 0xffff), (svdid >> 16)); */ /* How can we be sure that that is an EMS CAN card ?? */ for (i = 0; addresses[i]; i++) { u32 curr, mask; char *type; pcibios_read_config_dword(bus, fun, addresses[i], &curr); cli(); pcibios_write_config_dword(bus, fun, addresses[i], ~0); pcibios_read_config_dword(bus, fun, addresses[i], &mask); pcibios_write_config_dword(bus, fun, addresses[i], curr); sti(); /* printk(" region %i: mask 0x%08lx, now at 0x%08lx\n", i, */ /* (unsigned long)mask, */ /* (unsigned long)curr); */ #if 0 /* we don't need this message, so we don't need this code */ if (!mask) { printk(" region %i not existent\n", i); break; } #endif /* extract the type, and the programmable bits */ if (mask & PCI_BASE_ADDRESS_SPACE) { type = "I/O"; mask &= PCI_BASE_ADDRESS_IO_MASK; } else { type = "mem"; mask &= PCI_BASE_ADDRESS_MEM_MASK; } /* printk(" region %i: type %s, size %i\n", i, */ /* type, ~mask+1); */ if(i == 0) { /* BAR0 internal PITA registers */ unsigned long ptr = (unsigned long)ioremap(curr, 256); /* enable memory access */ /* printk("write to pita\n"); */ writel(0x04000000, ptr + 0x1c); Can_pitapci_control[candev] = ptr; } if(i == 1) { /* BAR1 parallel I/O * at address 0 are some EMS control registers * at address 0x400 the first controller area * at address 0x600 the second controller area * registers are read as 32bit * * at adress 0 we can verify the card * 0x55 0xaa 0x01 0xcb */ /* dump_CAN(curr, 4); */ reset_CPC_PCI(curr); /* enable interrupts Int_0 */ /* write to PITAs ICR register */ writel(0x00020000, Can_pitapci_control[candev] + 0x0); /* dump_CAN(curr + 0x400, 4); */ if(controller_available(curr + 0x400, 4)) { printk("CAN: at pos 1\n"); if(candev > 4) { printk("CAN: only 4 devices supported\n"); break; /* the devices scan loop */ } Base[candev] = (unsigned long)ioremap(curr + 0x400, 32*4); IOModel[candev] = 'm'; IRQ[candev] = irq; candev++; } else { printk("CAN: NO at pos 1\n"); } /* dump_CAN(curr + 0x600, 4); */ if(controller_available(curr + 0x600, 4)) { printk("CAN: at pos 2\n"); if(candev > 4) { printk("CAN: only 4 devices supported\n"); break; /* the devices scan loop */ } /* share the board control register with prev ch */ Can_pitapci_control[candev] = Can_pitapci_control[candev - 1]; Base[candev] = (unsigned long)ioremap(curr + 0x600, 32*4); IOModel[candev] = 'm'; IRQ[candev] = irq; candev++; } else { printk("CAN: NO at pos 2\n"); } } } } /* EMS CPC-PCI */ } /* for all devices */ } /* for all busses */ return 0; }