Hi all, I have changed the Major of my drivers at 251 and 252 and now all work fine.
Thanks. -----Mensaje original----- De: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] En nombre de rflores Enviado el: lunes, 09 de julio de 2007 15:23 Para: 'uClinux development list' Asunto: [uClinux-dev] open device problem Hi All, I'm writing two character drivers under uClinux in a AT91, one is a simple driver that, through ioctl, writes and reads in specific HW registers; the other is a software emulated spi which uses a timer and interrupts. If I compile the kernel with only one of this drivers, all the operations over the device driver (open, read, write, close, ioctl) work correctly, but if I compile the kernel with two drivers, I can't open any device in the application. It returns with errno=20 (Not a directory). I create the devices under the Makefile of the vendor. DEVICES = \ \ spi,c,120,1 \ \ swg,c,50,1 \ \ In the uClinux start-up, the drivers executes all the init function correctly Zarlink MVTX2801A detected Zarlink Port0 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable Zarlink Port1 detected : Link down , Gigabit Ethernet Mode , Zarlink Port2 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable Zarlink Port3 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable SWSPI: Initializating Software SPI driver for AT91xx40 SWSPI: Attached at Timer-2 (irq = 6) But, in the application, the open function returns -1 and errno = 20. /> /> llaccess test Unable open device errno = 20/> /> If I only compile with one driver: Zarlink MVTX2801A detected Zarlink Port0 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable Zarlink Port1 detected : Link down , Gigabit Ethernet Mode , Zarlink Port2 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable Zarlink Port3 detected : Link up , Gigabit Ethernet Mode , Full Duplex Mode , Flow Control Enable /> llaccess test Open = 3 IOCTL 0x9d00 = 0xda IOCTL 0x9d01 = 0x97 IOCTL 0x9d01 = 0x98 IOCTL 0x9d01 = 0x97 IOCTL 0x9d01 = 0x97 /> What's wrong? All source code of these drivers: sd_api_conf.h #ifndef _SD_API_CONF_H_ #define _SD_API_CONF_H_ #define SD_PIN_NSS 25 #define SD_PIN_PROTECT 24 #define SD_PIN_PRESENT 11 #define SD_PIN_MISO 20 #define SD_PIN_MOSI 19 #define SD_PIN_SCK 18 #define SD_IDLE_WAIT_MAX 1000000 #define SD_BLOCKSIZE 512 #define SD_BLOCKSIZE_NBITS 9 #endif spi.h #ifndef _SPI_H_ #define _SPI_H_ #define SWSPI_MAJOR 120 #define SWSPI_FREQ 20000 #define SWSPI_RC (CONFIG_ARM_CLK>>1)/SWSPI_FREQ /*Capture Mode Register*/ #define TCCLKS(x) (x & 0x07) << 0 #define CLKI(x) (x & 0x01) << 3 #define BURST(x) (x & 0x03) << 4 #define LDBSTOP(x) (x & 0x01) << 5 #define LDBDIS(x) (x & 0x01) << 7 #define ETRGEDG(x) (x & 0x03) << 8 #define ABETRG(x) (x & 0x01) << 10 #define CPCTRG(x) (x & 0x01) << 14 #define WAVE(x) (x & 0x01) << 15 #define LDRA(x) (x & 0x03) << 16 #define LDRB(x) (x & 0x03) << 18 static int __init swspi_init (void); int spi_send_byte (char byte); char spi_receive_byte (void); static ssize_t swspi_write (struct file *filp,const char *buf,ssize_t count,loff_t *f_pos); static ssize_t swspi_read (struct file *filp,char *buf, ssize_t count,loff_t *f_pos); static int spi_open(struct inode *inode, struct file *filp); static int spi_release(struct inode *inode, struct file *filp); void spi_cs_assert (void); void spi_cs_deassert (void); static void SWSPI_IRQ_Handler (int irq,void *dev_id,struct pt_regs *regs); #endif spi.c #include <linux/config.h> #include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/fs.h> #include <linux/iobuf.h> #include <linux/major.h> #include <linux/blkdev.h> #include <linux/raw.h> #include <linux/interrupt.h> #include <linux/capability.h> #include <linux/smp_lock.h> #include <linux/spinlock.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/semaphore.h> #include <asm/arch/widewlan.h> #include "sd_api_conf.h" #include "spi.h" #if (SPI_TIMER==0) # define SPI_TIMER_IRQ_NUM IRQ_TC0 #elif (SPI_TIMER==1) # define SPI_TIMER_IRQ_NUM IRQ_TC1 #elif (SPI_TIMER==2) # define SPI_TIMER_IRQ_NUM IRQ_TC2 #else #error Wierd -- SPI_TIMER is not defined or something.... #endif static char spi_byte = 0; static int openflag_spi = 0; static spinlock_t irq_spi_lock; static struct semaphore spi_sem; static struct irqaction spi_timer_irq = { SWSPI_IRQ_Handler, 0, 0, "swspi", NULL, NULL }; extern int setup_arm_irq(int, struct irqaction *); extern void at91_mask_irq(unsigned int irq); extern void at91_unmask_irq(unsigned int irq); extern void at91_mask_ack_irq(unsigned int irq); EXPORT_SYMBOL(swspi_init); EXPORT_SYMBOL(swspi_cleanup); static struct file_operations swspi_fops = { read: swspi_read, write: swspi_write, open: spi_open, release: spi_release, // ioctl: spi_ioctl, }; static int spi_open(struct inode *inode, struct file *filp) { if ( openflag_spi ) return -EBUSY; MOD_INC_USE_COUNT; openflag_spi = 1; return 0; } static int spi_release(struct inode *inode, struct file *filp) { openflag_spi = 0; MOD_DEC_USE_COUNT; return 0; } static int cleanup_swspi (void){ return (unregister_chrdev(SWSPI_MAJOR, "spi")); } static int __init swspi_init (void) { int result; if (SPI_TIMER == KERNEL_TIMER){ printk(KERN_INFO "SWSPI: Timer is the same that Kernel Timer.... driver not initializated\n"); return (-1); } printk(KERN_INFO "SWSPI: Initializating Software SPI driver for AT91xx40\n"); result = register_chrdev(SWSPI_MAJOR, "spi", &swspi_fops); if( result < 0 ){ printk(KERN_INFO "SWSPI: Unable to get %d major\n",SWSPI_MAJOR); return result; } /*SPI timer structures*/ register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[SPI_TIMER].ch; /* enable Spi timer */ HW_AT91_TIMER_INIT(SPI_TIMER) /*Configuring SD/SPI I/O pins*/ /*Enable SD/SPI pins as General Purpose IO Pins*/ /*Those pines are for GCM-AT91 Board*/ ((volatile struct pio_regs *)AT91_PIOA_BASE)->per = PIO(SD_PIN_NSS)|PIO(SD_PIN_PROTECT)| PIO(SD_PIN_PRESENT)| PIO(SD_PIN_MISO)| PIO(SD_PIN_MOSI)| PIO(SD_PIN_SCK); /*Disable Interrupts for those pins*/ ((volatile struct pio_regs *)AT91_PIOA_BASE)->idr = PIO(SD_PIN_NSS)|PIO(SD_PIN_PROTECT)| PIO(SD_PIN_PRESENT)| PIO(SD_PIN_MISO)| PIO(SD_PIN_MOSI)| PIO(SD_PIN_SCK); /*Enable NSS, MOSI and SCK as outputs*/ ((volatile struct pio_regs *)AT91_PIOA_BASE)->oer = PIO(SD_PIN_NSS) | PIO(SD_PIN_MOSI)| PIO(SD_PIN_SCK); /*Enable PROTECT, PRESENT and MISO as inputs*/ ((volatile struct pio_regs *)AT91_PIOA_BASE)->odr = PIO(SD_PIN_PROTECT)| PIO(SD_PIN_PRESENT)|PIO(SD_PIN_MISO); /*Timer SPI configuration*/ tc->rc = SWSPI_RC ; //20Khz with 50Mhz clk tt->bmr = TC2XC2S(1) | TC1XC1S(1) | TC0XC0S (1); //No external inputs tc->cmr = 0x00000000; tc->cmr = TCCLKS(0) | CPCTRG(1) ; //Compare mode //RC Compare trigger enabled //Clock = MCK/2 on rising edge tc->idr = TC_CPCS ; //Disable Interrupts on RC Compare tc->ccr = TC_CLKEN ; //Enables clock /*Interrupt configuration */ /*By default the timers interrupt are highlevel */ /*See /linux-2.4.x/arch/armnommu/mach-atmel/irq.c */ spin_lock_init(&irq_spi_lock); spin_lock(&irq_spi_lock); setup_arm_irq(SPI_TIMER_IRQ_NUM, &spi_timer_irq); at91_unmask_irq(SPI_TIMER_IRQ_NUM); //Enable AIC interrupt spin_unlock(&irq_spi_lock); // Variables initialization sema_init(&spi_sem,0); spi_byte = 0x00; // Start Clock tc->ccr = TC_SWTRG | TC_CLKEN; tc->ccr = TC_CLKEN; spi_cs_deassert(); printk(KERN_INFO "SWSPI: Attached at Timer%d (irq = %d) \n",(4-SPI_TIMER_IRQ_NUM),SPI_TIMER_IRQ_NUM); return(0); } int spi_send_byte (char byte) { /*SPI timer structures*/ register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[SPI_TIMER].ch; spin_lock(&irq_spi_lock); spi_byte = byte & 0xFF; tc->ier = TC_CPCS; //Enable interrupt on RC Compare spin_unlock(&irq_spi_lock); down_interruptible(&spi_sem); return(byte); } char spi_receive_byte (void) { /*SPI timer structures*/ register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[SPI_TIMER].ch; spin_lock(&irq_spi_lock); spi_byte = spi_byte | 0xFF; tc->ier = TC_CPCS; //Enable Interrupt on RC Compare spin_unlock(&irq_spi_lock); down_interruptible(&spi_sem); return(spi_byte); } static ssize_t swspi_write (struct file *filp,const char *buf, ssize_t count,loff_t *f_pos) { int i = 0; for (i=0; i<count; i++) { spi_send_byte(buf[i]); } return (i); } static ssize_t swspi_read (struct file *filp,char *buf, ssize_t count,loff_t *f_pos) { int i; for (i=0; i<count; i++) { buf[i] = spi_receive_byte(); } return (i); } void spi_cs_assert (void) { ((volatile struct pio_regs *)AT91_PIOA_BASE)->codr = PIO(SD_PIN_NSS); } void spi_cs_deassert (void) { ((volatile struct pio_regs *)AT91_PIOA_BASE)->sodr = PIO(SD_PIN_NSS); } static void SWSPI_IRQ_Handler (int irq,void *dev_id,struct pt_regs *regs) { static int sent_bits = 0; static int irq_count = 0; unsigned long sr; /*SPI timer structures*/ register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[SPI_TIMER].ch; sr = tc->sr; //Read Status register, it's mandatory. // Fall edge Clock ((volatile struct pio_regs *)AT91_PIOA_BASE)->codr = PIO(SD_PIN_SCK); // Set bit to transfer - MSb first if (spi_byte & 0x80) { ((volatile struct pio_regs *)AT91_PIOA_BASE)->sodr = PIO(SD_PIN_MOSI); }else { ((volatile struct pio_regs *)AT91_PIOA_BASE)->codr = PIO(SD_PIN_MOSI); } // Rise edge Clock ((volatile struct pio_regs *)AT91_PIOA_BASE)->sodr = PIO(SD_PIN_SCK); // Read incomming bit if ((((volatile struct pio_regs *)AT91_PIOA_BASE)->pdsr >> SD_PIN_MISO ) & 0x00000001) { spi_byte = (spi_byte << 1) | 0x01; } else { spi_byte = (spi_byte << 1) & 0xFE; } sent_bits++; irq_count++; if (sent_bits == 8){ spin_lock(&irq_spi_lock); sent_bits = 0; tc->idr=TC_CPCS; //Disable interrupt on RC Compare spin_unlock(&irq_spi_unlock); up(&spi_sem); } } MODULE_AUTHOR ("Ramon Flores <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION ("Software SPI Driver for AT91xx40"); MODULE_LICENSE ("GPL"); module_init (swspi_init); module_cleanup (cleanup_swspi); zarlink.h #include <linux/ioctl.h> #define ZARLINK_MAJOR 50 #define ZARLINK_IOC_MAGIC 'k' + ZARLINK_MAJOR /* GCM Zarlink GigaSwitch Implementation */ #define SWITCH_REG_DEVICE_ACTIVE 0x0FFF #define SWITCH_REG_READBACK 0x1000 #define SWITCH_REG_ECR1P0 0x0000 #define SWITCH_REG_ECR1P1 0x0002 #define SWITCH_REG_ECR1P2 0x0004 #define SWITCH_REG_ECR1P3 0x0006 #define SWITCH_REG_DPST 0x0F06 #define SWITCH_REG_DTST 0x0F07 #define SWITCH_VAL_CHIP_ON 0xDA #define SWITCH_VAL_MODULE_DETECTED 0x80 #define SWITCH_VAL_GIGA 0x10 #define SWITCH_VAL_LINK_DOWN 0X08 #define SWITCH_VAL_FAST 0X04 #define SWITCH_VAL_FULL_DUPLEX 0X02 #define SWITCH_VAL_FLOW_CONTROL 0X01 #define SWITCH_PORT_UP 0X18 #define SWITCH_PORT_DOWN 0x10 #define SWITCH_PORT_DOWN_ZERO 0xF7 #define SWITCH_PORT_FULLDUPLEX 0XFD #define SWITCH_PORT_HALFDUPLEX 0x02 #define SWITCH_PORT_FLOWCONTROL_ON 0XFE #define SWITCH_PORT_FLOWCONTROL_OFF 0X01 #define SWITCH_PORT_FLOWCONTROL_SIM 0XD0 #define SWITCH_PORT_FLOWCONTROL_ASIM 0X20 #define SWITCH_PORT_CONF 0xD8 #define SWITCH_PORT0 0X00 #define SWITCH_PORT1 0X01 #define SWITCH_PORT2 0X02 #define SWITCH_PORT3 0X03 #define WAIT_SPI_ACCESS 2 /*Define ZARLINK IOCTLS*/ /* Q means Query - reponse on the return value*/ #define ZARLINK_IOCQACTIVE _IO(ZARLINK_IOC_MAGIC,0) #define ZARLINK_IOCQPORT _IO(ZARLINK_IOC_MAGIC,1) #define ZARLINK_IOCTPORT_UP _IO(ZARLINK_IOC_MAGIC,2) #define ZARLINK_IOCTPORT_DOWN _IO(ZARLINK_IOC_MAGIC,3) #define ZARLINK_IOCTPORT_FULLDUPLEX _IO(ZARLINK_IOC_MAGIC,4) #define ZARLINK_IOCTPORT_HALFDUPLEX _IO(ZARLINK_IOC_MAGIC,5) #define ZARLINK_IOCTPORT_FLOWCONTROL_ON _IO(ZARLINK_IOC_MAGIC,6) #define ZARLINK_IOCTPORT_FLOWCONTROL_OFF _IO(ZARLINK_IOC_MAGIC,7) #define ZARLINK_IOCTPORT_FLOWCONTROL_SIM _IO(ZARLINK_IOC_MAGIC,8) #define ZARLINK_IOCTPORT_FLOWCONTROL_ASIM _IO(ZARLINK_IOC_MAGIC,9) zarlink.c #include <linux/config.h> #include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/fs.h> #include <linux/iobuf.h> #include <linux/major.h> #include <linux/blkdev.h> #include <linux/raw.h> #include <linux/capability.h> #include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/arch/widewlan.h> #include <linux/zarlink.h> EXPORT_SYMBOL(zarlink_init); static int openflag_zarlink = 0; static int zarlink_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned int arg){ unsigned int byteRead; unsigned long inbAddress; unsigned long outbAddress; unsigned long outbData; switch(cmd){ case ZARLINK_IOCQACTIVE: byteRead = inb (FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DEVICE_ACTIVE); break; case ZARLINK_IOCQPORT: switch(arg){ case SWITCH_PORT0: outbData = SWITCH_PORT0; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST; inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST; break; case SWITCH_PORT1: outbData = SWITCH_PORT1; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST; inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST; break; case SWITCH_PORT2: outbData = SWITCH_PORT2; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST; inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST; break; case SWITCH_PORT3: outbData = SWITCH_PORT3; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST; inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST; break; default: byteRead = (-ENOTTY); return (byteRead); break; } outb (outbData,outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_UP: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_UP); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_DOWN: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_DOWN) & SWITCH_PORT_DOWN_ZERO; outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_FULLDUPLEX: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_HALFDUPLEX) & SWITCH_PORT_FULLDUPLEX; outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_HALFDUPLEX: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_HALFDUPLEX); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_FLOWCONTROL_ON: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead & SWITCH_PORT_FLOWCONTROL_ON); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_FLOWCONTROL_OFF: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); return (byteRead); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_FLOWCONTROL_OFF); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_FLOWCONTROL_SIM: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead & SWITCH_PORT_FLOWCONTROL_SIM); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; case ZARLINK_IOCTPORT_FLOWCONTROL_ASIM: switch(arg){ case SWITCH_PORT0: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ; break; case SWITCH_PORT1: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P1 ; break; case SWITCH_PORT2: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ; break; case SWITCH_PORT3: inbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; outbAddress = FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ; break; default: byteRead = (-ENOTTY); break; } byteRead = inb ( inbAddress ); mdelay(WAIT_SPI_ACCESS); outbData = (byteRead | SWITCH_PORT_FLOWCONTROL_ASIM); outb ( outbData , outbAddress); mdelay(WAIT_SPI_ACCESS); byteRead = inb ( inbAddress ); break; default: byteRead = (-ENOTTY); break; } return(byteRead); } /*Not implemented open and release actions, these actions*/ /*are not necessary*/ /* int zarlink_open (struct inode *inode,struct file *filep){ return 0; } int zarlink_release (struct inode *inode,struct file *filep){ return 0; }*/ static int zarlink_open(struct inode *inode, struct file *filp) { if ( openflag_zarlink ) return -EBUSY; MOD_INC_USE_COUNT; openflag_zarlink = 1; return 0; } static int zarlink_release(struct inode *inode, struct file *filp) { openflag_zarlink = 0; MOD_DEC_USE_COUNT; return 0; } static struct file_operations zarlink_fops = { // read: zarlink_read, // write: zarlink_write, open: zarlink_open, release: zarlink_release, ioctl: zarlink_ioctl, }; void cleanup_zarlink (void){ unregister_chrdev(ZARLINK_MAJOR, "swg"); } static int __init zarlink_init (void) { unsigned char byteRead; int result; /* Reset all devices*/ outw(0x000E,FPGA_ADDR_BASE + SYS_RESETS); outw(0x000C,FPGA_ADDR_BASE + SYS_RESETS); mdelay(10); outw(0x000E,FPGA_ADDR_BASE + SYS_RESETS); mdelay(10); outw(0x000C,FPGA_ADDR_BASE + SYS_RESETS); outw(0x0008,FPGA_ADDR_BASE + SYS_RESETS); outw(0x0000,FPGA_ADDR_BASE + SYS_RESETS); /* Set-up Switch Interface*/ /* 0xD8 -> Link-up at 1Gbps*/ /* 0x00 Port0, 0x02 Port1, 0x04 Port2, 0x06 Port3*/ byteRead = inb (FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DEVICE_ACTIVE); if( byteRead == SWITCH_VAL_CHIP_ON){ /*Register de driver*/ result = register_chrdev(ZARLINK_MAJOR, "swg", &zarlink_fops); if( result < 0 ){ printk(KERN_INFO "Zarlink: Unable to get %d major\n",ZARLINK_MAJOR); return result; } printk(KERN_INFO "Zarlink MVTX2801A detected\n"); /* Configure Ports */ outb (SWITCH_PORT_CONF,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P0 ); outb (SWITCH_PORT_CONF,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P2 ); outb (SWITCH_PORT_CONF,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_ECR1P3 ); /* Read Status */ /* Port 0 */ outb (SWITCH_PORT0,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST); byteRead = inb ( FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST ); if ( byteRead & SWITCH_VAL_MODULE_DETECTED ){ printk (KERN_INFO "Zarlink Port0 detected : "); if ( !(byteRead & SWITCH_VAL_LINK_DOWN) ){ printk ("Link up , "); }else{ printk ("Link down , "); } if ( byteRead & SWITCH_VAL_GIGA ){ printk ("Gigabit Ethernet Mode , "); }else if ( byteRead & SWITCH_VAL_FAST ){ printk ("Fast Ethernet Mode , "); } if ( byteRead & SWITCH_VAL_FULL_DUPLEX ){ printk ("Full Duplex Mode , "); } if ( byteRead & SWITCH_VAL_FLOW_CONTROL ){ printk ("Flow Control Enable"); } printk("\n"); }else{ printk (KERN_INFO "Zarlink Port0 NOT detected\n"); } /* Port 1 */ outb (SWITCH_PORT1,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST); byteRead = inb ( FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST ); if ( byteRead & SWITCH_VAL_MODULE_DETECTED ){ printk (KERN_INFO "Zarlink Port1 detected : "); if ( !(byteRead & SWITCH_VAL_LINK_DOWN) ){ printk ("Link up , "); }else{ printk ("Link down , "); } if ( byteRead & SWITCH_VAL_GIGA ){ printk ("Gigabit Ethernet Mode , "); }else if ( byteRead & SWITCH_VAL_FAST ){ printk ("Fast Ethernet Mode , "); } if ( byteRead & SWITCH_VAL_FULL_DUPLEX ){ printk ("Full Duplex Mode , "); } if ( byteRead & SWITCH_VAL_FLOW_CONTROL ){ printk ("Flow Control Enable"); } printk("\n"); }else{ printk (KERN_INFO "Zarlink Port1 NOT detected\n"); } /* Port 2 */ outb (SWITCH_PORT2,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST); byteRead = inb ( FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST ); if ( byteRead & SWITCH_VAL_MODULE_DETECTED ){ printk (KERN_INFO "Zarlink Port2 detected : "); if ( !(byteRead & SWITCH_VAL_LINK_DOWN) ){ printk ("Link up , "); }else{ printk ("Link down , "); } if ( byteRead & SWITCH_VAL_GIGA ){ printk ("Gigabit Ethernet Mode , "); }else if ( byteRead & SWITCH_VAL_FAST ){ printk ("Fast Ethernet Mode , "); } if ( byteRead & SWITCH_VAL_FULL_DUPLEX ){ printk ("Full Duplex Mode , "); } if ( byteRead & SWITCH_VAL_FLOW_CONTROL ){ printk ("Flow Control Enable"); } printk("\n"); }else{ printk (KERN_INFO "Zarlink Port2 NOT detected\n"); } /* Port 3 */ outb (SWITCH_PORT3,FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DPST); byteRead = inb ( FPGA_ADDR_BASE + GIGA_SWITCH_OFFSET + SWITCH_REG_DTST ); if ( byteRead & SWITCH_VAL_MODULE_DETECTED ){ printk (KERN_INFO "Zarlink Port3 detected : "); if ( !(byteRead & SWITCH_VAL_LINK_DOWN) ){ printk ("Link up , "); }else{ printk ("Link down , "); } if ( byteRead & SWITCH_VAL_GIGA ){ printk ("Gigabit Ethernet Mode , "); }else if ( byteRead & SWITCH_VAL_FAST ){ printk ("Fast Ethernet Mode , "); } if ( byteRead & SWITCH_VAL_FULL_DUPLEX ){ printk ("Full Duplex Mode , "); } if ( byteRead & SWITCH_VAL_FLOW_CONTROL ){ printk ("Flow Control Enable"); } printk("\n"); }else{ printk (KERN_INFO "Zarlink Port3 NOT detected\n"); } }else{ printk(KERN_INFO "Zarlink MVTX2801A NOT detected\n"); } return (0); } MODULE_AUTHOR ("Ramon Flores <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION ("Zarlink Switch GigabitEthernet Driver"); MODULE_LICENSE ("GPL"); //MODULE_PARM_DESC (io,"I/O Base Address"); //MODULE_PARM (io,"i"); module_init (zarlink_init); Thanks, Ramon _______________________________________________ uClinux-dev mailing list [email protected] http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by [email protected] To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev _______________________________________________ uClinux-dev mailing list [email protected] http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by [email protected] To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev
