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

📄 mss_sdio.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 2 页
字号:
    ret = kernel_thread(sdio_queue_thread, NULL, CLONE_KERNEL);    if (ret < 0 )        return ret;    // enable sdio interrupt    mss_set_sdio_int(cmmb_dev.card->slot->host, 1);    // clean identifition register    sdio_read_ioreg(cmmb_dev.card, FN1, FUNC1_INT_IDENTIFY_REG, &tmp);    // clean counter register    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER1_REG, 0);    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER2_REG, 0);    sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER3_REG, 0);    return 0;}static int sdio_release(struct inode * inode, struct file *file){    cmmb_dev.flags = SDIO_QUEUE_EXIT;    wake_up_interruptible(&cmmb_dev.wq);    return 0;}static ssize_t sdio_read(struct file *f, char __user *buf, size_t count, loff_t *offset){    int readlen;        if (cmmb_dev.datalen == 0)        return 0;            if (cmmb_dev.datalen > count)        readlen = count;    else        readlen = cmmb_dev.datalen;    if (cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX-cmmb_dev.readp > readlen)    {        copy_to_user(buf, cmmb_dev.readp, readlen);        cmmb_dev.readp += readlen;    }    else    {        readlen = cmmb_dev.databuf+CMMB_FRAME_SIZE_MAX-cmmb_dev.readp;        copy_to_user(buf, cmmb_dev.readp, readlen);        cmmb_dev.readp = cmmb_dev.databuf;    }        cmmb_dev.datalen -= readlen;        //printk("Kernel sdio_read: %d, left %d\n",readlen,cmmb_dev.datalen);    return readlen;}static ssize_t sdio_write(struct file *f, const char __user *buf, size_t count, loff_t *offset){	unsigned char *tempP;
	unsigned char tempChar;	int ret;	unsigned int datalen;	unsigned char *data;
    datalen = count;
	if (datalen == 0)
		return 0;

    data= kzalloc(count, GFP_KERNEL);    if (data == NULL)    {        printk("write Functon kzalloc error\n");        return -1;    }    copy_from_user(data, buf, count);	// set write counter 
	tempChar = datalen & 0xFF;
    ret = sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER4_REG, tempChar);    if (ret < 0)    {        kfree(data);        return -2;    }

	tempChar = (datalen & 0xFF00) >> 8;    ret = sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER5_REG, tempChar);    if (ret < 0)    {        kfree(data);        return -2;    }

	tempChar = (datalen & 0xFF0000) >> 16;
    ret = sdio_write_ioreg(cmmb_dev.card, FN1, FUNC1_DATA_COUNTER6_REG, tempChar);    if (ret < 0)    {        kfree(data);        return -2;    }    
	// send data by command53
	// I only implement command53 byte mode, so the max length to send is 512 bytes
	// If you can implement command53 block mode, you can send more then 512 bytes one time
	tempP = data;
	while(datalen > CMMB_DATA_BLOCK_SIZE)
	{        ret = sdio_write_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, CMMB_DATA_BLOCK_SIZE, tempP);        if (ret < 0)        {            kfree(data);            printk("sdio driver: write Block error0\n");            return -3;        }

		datalen -= CMMB_DATA_BLOCK_SIZE;
		tempP += CMMB_DATA_BLOCK_SIZE;
	}	if(datalen > 0)
	{
        ret = sdio_write_iomem(cmmb_dev.card, FN1, FUNC1_DATA_REG, BLOCK_MODE, FIXED_ADDRESS, 1, datalen, tempP);        if (ret < 0)        {            kfree(data);            printk("sdio driver: write Block error1\n");            return -3;        }
	}
    kfree(data);    
	return count;}struct file_operations sdio_cmmb_fops = {    open: sdio_open,	read: sdio_read,	write: sdio_write,	release: sdio_release,};static intsbi_remove_card(struct device *dev){    struct mss_card *card;    card = container_of(dev, struct mss_card, dev);    class_device_destroy(cmmb_dev.sdio_class, cmmb_dev.cdev->dev);
    class_destroy(cmmb_dev.sdio_class);	devfs_remove("sdio-cmmb");    unregister_chrdev_region(cmmb_dev.cdev->dev, 1);    cdev_del(cmmb_dev.cdev);	cmmb_dev.cdev = NULL;	if (cmmb_dev.databuf)	    kfree(cmmb_dev.databuf);    return 0;}/********************************************************		Global Functions********************************************************/voidsbi_interrupt(struct mss_card *card){    //ENTER();    wake_up_interruptible(&cmmb_dev.wq);    //LEAVE();}static intsbi_suspend_card(struct device *dev, pm_message_t state, u32 level){    if (level == SUSPEND_DISABLE) {#ifndef CONFIG_CPU_MONAHANS_LV        mhn_mfp_set_edge(MFP_FFDSR, MFP_EDGE_FALL);#endif		mss_set_clock(cmmb_dev.card->slot->host, cmmb_dev.card->slot->host->f_min);    }    return 0;}static intsbi_resume_card(struct device *dev, u32 level){    printk("sbi resume back level:%d\n", level);    if (level == RESUME_ENABLE) {		mss_set_clock(cmmb_dev.card->slot->host, cmmb_dev.card->slot->host->f_max);    }    return 0;}static int sbi_probe_card(struct device *dev){    struct mss_card *card;    struct sdio_card *sdio_card;    int ret = 0;    //ENTER();    card = container_of(dev, struct mss_card, dev);    if (card->card_type != MSS_SDIO_CARD) {        ret = -ENODEV;          //STATUS_FAILURE;        goto done;    }    sdio_card = card->prot_card;    if (!card) {        ret = -ENODEV;          //STATUS_FAILURE;        goto done;    }    ret = 0;	memset(&cmmb_dev, 0, sizeof(sdio_dev));	cmmb_dev.databuf = kzalloc(CMMB_FRAME_SIZE_MAX, GFP_KERNEL);	if (cmmb_dev.databuf == 0)	{	    printk("kzalloc databuf error\n");	    return -ENODEV;	}    cmmb_dev.readp = cmmb_dev.databuf;    cmmb_dev.writep = cmmb_dev.databuf;	cmmb_dev.cdev = cdev_alloc();	cmmb_dev.cdev->owner = THIS_MODULE;    cdev_init(cmmb_dev.cdev,&sdio_cmmb_fops);    alloc_chrdev_region(&cmmb_dev.cdev->dev, 0, 1, "/dev/sdio");    ret = cdev_add(cmmb_dev.cdev, cmmb_dev.cdev->dev, 1); 	if(ret < 0)	{		cdev_del(cmmb_dev.cdev);		cmmb_dev.cdev = NULL;		printk("Error! Couldn't register /dev/sdio driver\n");		goto done;	}      cmmb_dev.sdio_class=class_create(THIS_MODULE, "sdio");
      if(IS_ERR(cmmb_dev.sdio_class))      {
        ret=-1;
        goto out_class;
      };      class_device_create(cmmb_dev.sdio_class, cmmb_dev.cdev->dev,NULL, "sdio");	    devfs_mk_cdev(cmmb_dev.cdev->dev, S_IFCHR | S_IRUSR | S_IWUSR, "sdio");	cmmb_dev.card = card;  done:    printk("TelePath Cmmb Sdio Device find!\n");    sdio_write_ioreg(cmmb_dev.card, FN1, 0x05, 0x30); //pxd temp    //LEAVE();    return ret;  out_class:
    class_device_destroy(cmmb_dev.sdio_class, cmmb_dev.cdev->dev);
    class_destroy(cmmb_dev.sdio_class);    return ret;}static struct mss_driver mss_sdio_driver = {    .driver = {               .name = "cmmbdriver",               .probe = sbi_probe_card,               .remove = sbi_remove_card,               .suspend = sbi_suspend_card,               .resume = sbi_resume_card,               },    .sdio_int_handler = sbi_interrupt,};/***************************************************************************** * *   module init and exit functions * ****************************************************************************/static int mss_sdio_card_driver_init(void){	int ret;	//ENTER();	ret = register_mss_driver(&mss_sdio_driver);	//LEAVE();	return ret;}static void mss_sdio_card_driver_exit(void){	//ENTER();	unregister_mss_driver(&mss_sdio_driver);	//LEAVE();}module_init(mss_sdio_card_driver_init);module_exit(mss_sdio_card_driver_exit);MODULE_AUTHOR("Pxd");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Block device driver for SDIO card");

⌨️ 快捷键说明

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