Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
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;
}