⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 spi设备uclinux驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
            temp &= ~(0xff << 8);
            temp |= (0x55 << 8);
            outl(temp, PINSEL0);
        }        if (num == 1)
        {
            temp = inl(PINSEL1);
            PinSel1Save =  temp & (0xff << 2);
            temp &= ~(0xff << 2);
            temp |= (0xaa << 2);
            outl(temp, PINSEL1);
        }
        sema_init(&(SpiDevices[num].sem), 1);
        SpiDevices[num].BaseAddr = num * (S1PCR - S0PCR) + S0PCR;
        outl(8, SpiDevices[num].BaseAddr + S0PCCR - S0PCR);
        inl(SpiDevices[num].BaseAddr + S0PSR - S0PCR);        outl(1 << 5, SpiDevices[num].BaseAddr + S0PCR - S0PCR);
        filp->private_data = &SpiDevices[num];
        local_irq_restore(flag);
    }    SpiDevices[num].usage++;
    MOD_INC_USE_COUNT;    return 0;          /* success */} /*********************************************************************************************************
** Function name: spi_release
** Descriptions:  release device
** Input:inode:   information of device
**       filp:    pointer of file
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        static int spi_release(struct inode *inode, struct file *filp) {    unsigned long flag;    int num;    u32 temp;
    
    num = MINOR(inode->i_rdev);    if (num >= MAX_SPI)    {        return -ENODEV;    }
    MOD_DEC_USE_COUNT;    SpiDevices[num].usage--;
    if (SpiDevices[num].usage == 0)
    {
        local_irq_save(flag);
        if (num == 0)
        {
            temp = inl(PINSEL0);
            temp &= ~(0xff << 8);
            temp |= PinSel0Save;
            outl(temp, PINSEL0);
        }        if (num == 1)
        {
            temp = inl(PINSEL1);
            temp &= ~(0xff << 2);
            temp |= PinSel1Save;
            outl(temp, PINSEL1);
        }        local_irq_restore(flag);
    }
    return(0); } /*********************************************************************************************************
** Function name: spi_ioctl
** Descriptions:  IO control function
** Input:inode:   information of device
**       filp:    pointer of file
**       cmd:     command
**       arg:     additive parameter
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        static int spi_ioctl(struct inode *inode, struct file *filp,                        unsigned int cmd, unsigned long arg){
    int num;    u32 temp;
    Spi_Dev *dep;
    num = MINOR(inode->i_rdev);    if (num >= MAX_SPI)    {        return -ENODEV;    }

    if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)    {        return -ENOTTY;    }    if (_IOC_NR(cmd) >= SPI_MAXNR)    {        return -ENOTTY;    }    
    dep = filp->private_data;

    switch(cmd)    {        case SPI_SET_CLKDIV:
            if (arg < 8)
            {
                arg = 8;
            }
            arg++;
            arg &= ~1;
            outl(arg, dep->BaseAddr + S0PCCR - S0PCR);            break;        case SPI_SET_CPHA_FIRST:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp &= ~(1 << 3);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_SET_CPHA_SECOND:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp |= (1 << 3);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_SET_CPOL_LOW:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp |= (1 << 4);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_SET_CPOL_HIGHT:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp &= ~(1 << 4);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_SET_LSBF_BIT0:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp |= (1 << 6);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_SET_LSBF_BIT7:
            temp = inl(dep->BaseAddr + S0PCR - S0PCR);
            temp &= ~(1 << 6);
            outl(temp, dep->BaseAddr + S0PCR - S0PCR);
            break;
        case SPI_WR_DATA:
            if (!access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)))
            {
                return -EFAULT;            }
            if (!access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)))
            {
                return -EFAULT;            }
            get_user(temp, (u8 *)arg);
                        outl(temp, dep->BaseAddr + S0PDR - S0PCR);
            while (1)
            {
                temp = inl(dep->BaseAddr + S0PSR - S0PCR);
                if ((temp & (1 << 7)) != 0)
                {
                    break;
                }
                if (temp != 0)
                {
                    return -EIO;
                }
            }
            temp = inl(dep->BaseAddr + S0PDR - S0PCR);

            put_user(temp, (u8 *)arg);            break;
        case SPI_START:
            if (down_interruptible(&dep->sem))
            {
                return -ERESTARTSYS;
            }            break;        case SPI_END:
            up(&dep->sem);
            break;        default:            return -ENOTTY;            break;    }    return 0;}
/*********************************************************************************************************
** Function name: spi_init
** Descriptions:  init driver
** Input:none
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        int spi_init(void){    int  result;
    
    result = register_chrdev(MAJOR_NR,  DEVICE_NAME,  &spi_fops);     if (result < 0)    {        printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", MAJOR_NR );        return(result);     } 
    if (MAJOR_NR == 0)    {        MAJOR_NR = result; /* dynamic */    }

    printk(KERN_INFO DEVICE_NAME ": init OK\n");    return(0); }/*********************************************************************************************************
** Function name: spi_cleanup
** Descriptions:  exit driver
** Input:none
** Output none
** Created by:    Chenmingji
** Created Date:  2005-4-29
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        void spi_cleanup(void){
    unregister_chrdev(MAJOR_NR, DEVICE_NAME);}/***********************************************************************************************************                            End Of File********************************************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -