Exemplo n.º 1
0
static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
{
	struct at91mci_host *host = _host;
	int present = !gpio_get_value(irq_to_gpio(irq));

	/*
	 * we expect this irq on both insert and remove,
	 * and use a short delay to debounce.
	 */
	if (present != host->present) {
		host->present = present;
		pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
			present ? "insert" : "remove");
		if (!present) {
			pr_debug("****** Resetting SD-card bus width ******\n");
			at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
		}
		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
	}
	return IRQ_HANDLED;
}
Exemplo n.º 2
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
#if 0 // kimhyuns remove to recognize card
	// for issue fix for ecim G0100145817
	if(host->bus_dead )
#else
	if((host->bus_dead) && (host->index!=0))
#endif	
	{
		printk("No Suspend resume in case of bus-dead if init failed -- %s \r\n",__FUNCTION__);
		return 0;
	}

	mmc_bus_get(host);
	 if (host->bus_ops && !host->bus_dead) {
		if ( host->card && mmc_card_sdio(host->card)){    //ijihyun.jung -Sec VinsQ
			printk("mmc%d:mmc_resume_host: skip mmc_power_up()\n", host->index);
		} else {
			mmc_power_up(host);
	         }
		mmc_select_voltage(host, host->ocr);//cyj_dc23 -kernel 협의
		BUG_ON(!host->bus_ops->resume);
		host->bus_ops->resume(host);
	} 
	  mmc_bus_put(host); 
	
	 /* 
	  * We add a slight delay here so that resume can progress 
	 * in parallel.
	  */ 
	if ( host->card && mmc_card_sdio(host->card)) {	//ijihyun.jung -Sec VinsQ
	 	printk("mmc%d:mmc_resume_host: skip mmc_detect_change()\n", host->index);
	 }
	 else{
	 	printk("mmc%d:mmc_resume_host: excute mmc_detect_change()\n", host->index);
 		mmc_detect_change(host, 1);  
	 }
	
	return 0;
} 
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int status;

	/*
	 * In case host->ops are not yet initialized return immediately.
	 * The card will get detected later when host driver calls
	 * mmc_add_host() after host->ops are initialized.
	 */
	if (!host->ops)
		goto out;

	if (host->ops->card_event)
		host->ops->card_event(host);

	status = mmc_gpio_get_status(host);
	if (unlikely(status < 0))
		goto out;

#ifdef VENDOR_EDIT
        //[email protected], 2014-07-10 Add for retry 5 times when new sdcard init error
        host->detect_change_retry = 5;
#endif /* VENDOR_EDIT */

	if (status ^ ctx->status) {
		pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n",
				mmc_hostname(host), ctx->status, status,
				(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ?
				"HIGH" : "LOW");
		ctx->status = status;
		/* Schedule a card detection after a debounce timeout */
		mmc_detect_change(host, msecs_to_jiffies(200));
	}
out:

	return IRQ_HANDLED;
}
Exemplo n.º 4
0
static irqreturn_t sunximmc_irq(int irq, void *dev_id)
{
    struct sunxi_mmc_host *smc_host = dev_id;
    unsigned long iflags;

    spin_lock_irqsave(&smc_host->lock, iflags);

    smc_host->sdio_int = 0;
    if (smc_host->cd_mode == CARD_DETECT_BY_DATA3)
    {
        smc_host->change = 0;
    }

    sdxc_check_status(smc_host);

    if (smc_host->wait == SDC_WAIT_FINALIZE)
    {
        tasklet_schedule(&smc_host->tasklet);
    }

    spin_unlock_irqrestore(&smc_host->lock, iflags);

    /* sdio interrupt call */
    if (smc_host->sdio_int)
    {
        mmc_signal_sdio_irq(smc_host->mmc);
//    	SMC_MSG("- sdio int -\n");
    }

    /* card detect change */
    if (smc_host->cd_mode == CARD_DETECT_BY_DATA3)
    {
        if (smc_host->change)
        {
            mmc_detect_change(smc_host->mmc, msecs_to_jiffies(300));
        }
    }

    return IRQ_HANDLED;
}
Exemplo n.º 5
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
	int err = 0;

	mmc_bus_get(host);
	if (mmc_bus_manual_resume(host)) {
		host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME;
		mmc_bus_put(host);
		return 0;
	}

	if (host->bus_ops && !host->bus_dead) {
		mmc_power_up(host);
		mmc_select_voltage(host, host->ocr);
		BUG_ON(!host->bus_ops->resume);
		err = host->bus_ops->resume(host);
		if (err) {
			printk(KERN_WARNING "%s: error %d during resume "
					    "(card was removed?)\n",
					    mmc_hostname(host), err);
			err = 0;
		}
	}
	mmc_bus_put(host);
#if defined(CONFIG_ATH_WIFI) || defined(CONFIG_BCM_WIFI)
	if (host->index == ATH_WIFI_SDCC_INDEX) {		
		pr_info("%s: mmc_resume_host in wifi slot skip cmd7\n",   mmc_hostname(host));
		return err;
	}
#endif 

	/*
	 * We add a slight delay here so that resume can progress
	 * in parallel.
	 */
	mmc_detect_change(host, 1);

	return err;
}
Exemplo n.º 6
0
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int status;

	/*
	 * In case host->ops are not yet initialized return immediately.
	 * The card will get detected later when host driver calls
	 * mmc_add_host() after host->ops are initialized.
	 */
	if (!host->ops)
		goto out;

	if (host->ops->card_event)
		host->ops->card_event(host);

	status = mmc_gpio_read_status(host);
	if (unlikely(status < 0))
		goto out;

	if (status ^ ctx->status) {
		pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n",
				mmc_hostname(host), ctx->status, status,
				(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ?
				"HIGH" : "LOW");
		ctx->status = status;
		host->card_bad = 0;
		host->requests = 0ULL;
		host->request_errors = 0ULL;

		/* Schedule a card detection after a debounce timeout */
		mmc_detect_change(host, msecs_to_jiffies(200));
	}
out:

	return IRQ_HANDLED;
}
int wlan_device_set_carddetect(int val)
{
	pr_info("%s: %d\n", __func__, val);
	mdelay(100);
#if 0
	wlan_device_cd = val;
	if (wifi_status_cb) {
		wifi_status_cb(val, wifi_status_cb_devid);
	} else
		pr_warning("%s: Nobody to notify\n", __func__);
#endif

#ifdef CONFIG_WLAN_SDIO
//	sdhci_bus_scan();
       if(wlan_mmc) {
		mmc_detect_change(wlan_mmc, 0);
       } else {
		pr_info("%s  wlan_mmc is null,carddetect failed \n ",__func__);
       }
#endif
	return 0;
}
Exemplo n.º 8
0
static void s3c24xx_irq_cd_handler( void *param )
{
    struct mmc_host	*host=(struct mmc_host *) param;

    /* We want the MMC/SD stack to redetect if this IRQ goes off. To do this */
    /* we remove the bus when this IRQ occurs. mmc_detect_change will then */
    /* make sure the bus is reenumerated. */
    mmc_flush_scheduled_work();
    mmc_bus_get(host);
    if (host->bus_ops && !host->bus_dead) {
        if (host->bus_ops->remove)
            host->bus_ops->remove(host);

        mmc_claim_host(host);
        mmc_detach_bus(host);
        mmc_release_host(host);
    }
    mmc_bus_put(host);

    mmc_detect_change( host, HZ/10 );
    return;
}
Exemplo n.º 9
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
	int err = 0;

	mmc_bus_get(host);
	if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) {
		host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME;
		mmc_bus_put(host);
		return 0;
	}

	if (host->bus_ops && !host->bus_dead) {
		mmc_power_up(host);
		mmc_select_voltage(host, host->ocr);
		BUG_ON(!host->bus_ops->resume);
		err = host->bus_ops->resume(host);
		if (err) {
			printk(KERN_WARNING "%s: error %d during resume "
					    "(card was removed?)\n",
					    mmc_hostname(host), err);
			if (host->bus_ops->remove)
				host->bus_ops->remove(host);
			mmc_claim_host(host);
			mmc_detach_bus(host);
			mmc_release_host(host);
			/* no need to bother upper layers */
			err = 0;
		}
	}
	mmc_bus_put(host);

	/*
	 * We add a slight delay here so that resume can progress
	 * in parallel.
	 */
	mmc_detect_change(host, 1);

	return err;
}
Exemplo n.º 10
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
	int err = 0;

	mmc_bus_get(host);
	if (mmc_bus_manual_resume(host)) {
#ifndef CONFIG_PM_RUNTIME
		host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME;
#endif
		mmc_bus_put(host);
		return 0;
	}

	if (host->bus_ops && !host->bus_dead) {
		if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
			mmc_power_up(host);
			mmc_select_voltage(host, host->ocr);
		}
		BUG_ON(!host->bus_ops->resume);
		err = host->bus_ops->resume(host);
		if (err) {
			printk(KERN_WARNING "%s: error %d during resume "
					    "(card was removed?)\n",
					    mmc_hostname(host), err);
			err = 0;
		}
	}
	mmc_bus_put(host);

	/*
	 * We add a slight delay here so that resume can progress
	 * in parallel.
	 */
	if (!(host->pm_flags & MMC_PM_KEEP_POWER))
		mmc_detect_change(host, 1);

	return err;
}
Exemplo n.º 11
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
	int err = 0;

	mmc_bus_get(host);
	if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) {
		host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME;
		mmc_bus_put(host);
		return 0;
	}

	if (host->bus_ops && !host->bus_dead) {
		if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
			mmc_power_up(host);
			mmc_select_voltage(host, host->ocr);
		}
		BUG_ON(!host->bus_ops->resume);
		err = host->bus_ops->resume(host);
		if (err) {
			printk(KERN_WARNING "%s: error %d during resume "
					    "(card was removed?)\n",
					    mmc_hostname(host), err);
			err = 0;
		}
	}
	mmc_bus_put(host);

	/*
	 * We add a slight delay here so that resume can progress
	 * in parallel.
	 */
#if 1 /* ATHENV */
	if (!host->card || host->card->type != MMC_TYPE_SDIO) 
#endif /* ATHENV */
	mmc_detect_change(host, 1);

	return err;
}
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
{
	struct mmc_host *host = dev_id;
	struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
	int status;

	status = mmc_cd_get_status(host);
	if (unlikely(status < 0))
		goto out;

	if (status ^ cd->status) {
		pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n",
				mmc_hostname(host), cd->status, status,
				(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ?
				"HIGH" : "LOW");
		cd->status = status;

		/* Schedule a card detection after a debounce timeout */
		mmc_detect_change(host, msecs_to_jiffies(100));
	}
out:
	return IRQ_HANDLED;
}
Exemplo n.º 13
0
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
{
	struct mmc_host *host = dev_id;
	struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
	int status;

	status = mmc_cd_get_status(host);
	if (unlikely(status < 0))
		goto out;

	if (status ^ cd->status) {
		pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n",
				mmc_hostname(host), cd->status, status,
				(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ?
				"HIGH" : "LOW");
		cd->status = status;

#ifdef CONFIG_MACH_LGE
		if(!status )   //active high & active low  status value is low when sdcard ejected . 
		{
			mmc_gpio_irq_flag =1;	
		}
		
		else 
		{
			mmc_gpio_irq_flag =0;	
		}
		pr_info("%s: mmc_gpio_irq_flagd !!!!! %d\n",mmc_hostname(host),mmc_gpio_irq_flag );
		
#endif 
		/* Schedule a card detection after a debounce timeout */
		mmc_detect_change(host, msecs_to_jiffies(100));
	}
out:
	return IRQ_HANDLED;
}
Exemplo n.º 14
0
static void hi_mci_detect_card(unsigned long arg)
{
	struct himci_host *host = (struct himci_host *)arg;
	unsigned int i, curr_status, status[3], detect_retry_count = 0;

	himci_assert(host);

	while (1) {
		for (i = 0; i < 3; i++) {
			status[i] = hi_mci_sys_card_detect(host);
			udelay(10);
		}
		if ((status[0] == status[1]) && (status[0] == status[2]))
			break;

		detect_retry_count++;
		if (detect_retry_count >= retry_count) {
			himci_error("this is a dithering,card detect error!");
			goto err;
		}
	}
	curr_status = status[0];
	if (curr_status != host->card_status) {
		himci_trace(2, "begin card_status = %d\n", host->card_status);
		host->card_status = curr_status;
		if (curr_status != CARD_UNPLUGED) {
			hi_mci_init_card(host);
			printk(KERN_INFO "card connected!\n");
		} else
			printk(KERN_INFO "card disconnected!\n");

		mmc_detect_change(host->mmc, 0);
	}
err:
	mod_timer(&host->timer, jiffies + detect_time);
}
Exemplo n.º 15
0
/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{

#ifdef CONFIG_HUAWEI_WIFI_SDCC
    struct msmsdcc_host *sdcc_host = mmc_priv(host);
#endif

    mmc_bus_get(host);
    if (host->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) {
        host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME;
        mmc_bus_put(host);
        return 0;
    }

    if (host->bus_ops && !host->bus_dead) {
        mmc_power_up(host);
        mmc_select_voltage(host, host->ocr);
        BUG_ON(!host->bus_ops->resume);
        host->bus_ops->resume(host);
    }
    mmc_bus_put(host);

    /*
     * We add a slight delay here so that resume can progress
     * in parallel.
     */
#ifdef CONFIG_HUAWEI_WIFI_SDCC
    if (sdcc_host->pdev_id != ATH_WLAN_SLOT) {
#endif
        mmc_detect_change(host, 1);
#ifdef CONFIG_HUAWEI_WIFI_SDCC
    }
#endif

    return 0;
}
Exemplo n.º 16
0
static ssize_t
set_polling(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct mmc_host *mmc = dev_get_drvdata(dev);
	struct msmsdcc_host *host = mmc_priv(mmc);
	int value;
	unsigned long flags;

	sscanf(buf, "%d", &value);

	spin_lock_irqsave(&host->lock, flags);
	if (value) {
		mmc->caps |= MMC_CAP_NEEDS_POLL;
		mmc_detect_change(host->mmc, 0);
	} else {
		mmc->caps &= ~MMC_CAP_NEEDS_POLL;
	}
#ifdef CONFIG_HAS_EARLYSUSPEND
	host->polling_enabled = mmc->caps & MMC_CAP_NEEDS_POLL;
#endif
	spin_unlock_irqrestore(&host->lock, flags);
	return count;
}
Exemplo n.º 17
0
void sdhci_s3c_force_presence_change(struct platform_device *pdev)
{
        struct sdhci_host *host = platform_get_drvdata(pdev);
	printk(KERN_DEBUG "%s : Enter",__FUNCTION__);
	mmc_detect_change(host->mmc, msecs_to_jiffies(0));
}
Exemplo n.º 18
0
void mmc_start_host(struct mmc_host *host)
{
	mmc_power_off(host);
	mmc_detect_change(host, 0);
}
Exemplo n.º 19
0
static void sh_mmcif_detect(struct mmc_host *mmc)
{
	mmc_detect_change(mmc, 0);
}
Exemplo n.º 20
0
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
{
	
	mmc_detect_change(dev_id, msecs_to_jiffies(100));
	return IRQ_HANDLED;
}
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int status;
#ifdef CONFIG_HUAWEI_KERNEL
	unsigned long duration =0;
#endif
	/*
	 * In case host->ops are not yet initialized return immediately.
	 * The card will get detected later when host driver calls
	 * mmc_add_host() after host->ops are initialized.
	 */
	if (!host->ops)
		goto out;

	if (host->ops->card_event)
		host->ops->card_event(host);

	status = mmc_gpio_get_status(host);
	if (unlikely(status < 0))
		goto out;

	if (status ^ ctx->status) {
		pr_info("%s: slot status change detected (%d -> %d), GPIO_ACTIVE_%s\n",
				mmc_hostname(host), ctx->status, status,
				(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) ?
				"HIGH" : "LOW");
		ctx->status = status;
#ifdef CONFIG_HUAWEI_KERNEL
		duration = jiffies - msmsdcc_irqtime;
		/* current msmsdcc is present, add to handle dithering */
		if (status)
		{
			/* the distance of two interrupts can not less than 7 second */
			if (duration < (7 * HZ))
			{
				duration = (7 * HZ) - duration;
			}
			else
			{
				/* 100 millisecond */
				duration = msecs_to_jiffies(100);
			}
		}
		else
		{
			duration = msecs_to_jiffies(2000);
		}
		mmc_detect_change(host, duration);
		msmsdcc_irqtime = jiffies;
#else
		/* Schedule a card detection after a debounce timeout */
		mmc_detect_change(host, msecs_to_jiffies(200));
#endif
	}
out:

	return IRQ_HANDLED;
}
Exemplo n.º 22
0
static void mmc_detect_callback(unsigned long data)
{
	mmc_detect_change(mmc_detect.devid);
}
Exemplo n.º 23
0
static void imxmci_tasklet_fnc(unsigned long data)
{
	struct imxmci_host *host = (struct imxmci_host *)data;
	u32 stat;
	unsigned int data_dir_mask = 0;	/* STATUS_WR_CRC_ERROR_CODE_MASK */
	int timeout = 0;

	if(atomic_read(&host->stuck_timeout) > 4) {
		char *what;
		timeout = 1;
		stat = MMC_STATUS;
		host->status_reg = stat;
		if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
				what = "RESP+DMA";
			else
				what = "RESP";
		else
			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
				if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
					what = "DATA";
				else
					what = "DMA";
			else
				what = "???";

		dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
		       what, stat, MMC_INT_MASK);
		dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
		       MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
		dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n",
		       host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size);
	}

	if(!host->present || timeout)
		host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
				    STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;

	if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
		clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);

		stat = MMC_STATUS;
		/*
		 * This is not required in theory, but there is chance to miss some flag
		 * which clears automatically by mask write, FreeScale original code keeps
		 * stat from IRQ time so do I
		 */
		stat |= host->status_reg;

		if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
			imxmci_busy_wait_for_status(host, &stat,
					STATUS_END_CMD_RESP | STATUS_ERR_MASK,
					20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
		}

		if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
			if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
				imxmci_cmd_done(host, stat);
			if(host->data && (stat & STATUS_ERR_MASK))
				imxmci_data_done(host, stat);
		}

		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
			stat |= MMC_STATUS;
			if(imxmci_cpu_driven_data(host, &stat)){
				if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
					imxmci_cmd_done(host, stat);
				atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
							&host->pending_events);
				imxmci_data_done(host, stat);
			}
		}
	}

	if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
	   !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {

		stat = MMC_STATUS;
		/* Same as above */
		stat |= host->status_reg;

		if(host->dma_dir == DMA_TO_DEVICE) {
			data_dir_mask = STATUS_WRITE_OP_DONE;
		} else {
			data_dir_mask = STATUS_DATA_TRANS_DONE;
		}

		if(stat & data_dir_mask) {
			clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
			imxmci_data_done(host, stat);
		}
	}

	if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {

		if(host->cmd)
			imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);

		if(host->data)
			imxmci_data_done(host, STATUS_TIME_OUT_READ |
					 STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);

		if(host->req)
			imxmci_finish_request(host, host->req);

		mmc_detect_change(host->mmc, msecs_to_jiffies(100));

	}
}
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	mmc_detect_change(dev_id, msecs_to_jiffies(100));
	return IRQ_HANDLED;
}
Exemplo n.º 25
0
static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id)
{
	mmc_detect_change(dev_id, msecs_to_jiffies(200));
	return IRQ_HANDLED;
}
Exemplo n.º 26
0
void mmc_start_host(struct mmc_host *host)
{
	mmc_power_off(host);
	mmc_detect_change(host, msecs_to_jiffies(host->init_delay));
}
Exemplo n.º 27
0
static int __devinit sunximmc_probe(struct platform_device *pdev)
{
    struct sunxi_mmc_host *smc_host = NULL;
    struct mmc_host	*mmc = NULL;
    int ret = 0;
    char mmc_para[16] = {0};
    int card_detmode = 0;

    SMC_MSG("%s: pdev->name: %s, pdev->id: %d\n", dev_name(&pdev->dev), pdev->name, pdev->id);
    mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
    if (!mmc)
    {
        SMC_ERR("mmc alloc host failed\n");
    	ret = -ENOMEM;
    	goto probe_out;
    }

    smc_host = mmc_priv(mmc);
    memset((void*)smc_host, 0, sizeof(smc_host));
    smc_host->mmc = mmc;
    smc_host->pdev = pdev;

    spin_lock_init(&smc_host->lock);
    tasklet_init(&smc_host->tasklet, sunximmc_tasklet, (unsigned long) smc_host);

    smc_host->cclk  = 400000;
    smc_host->mod_clk = SMC_MAX_MOD_CLOCK(pdev->id);
    smc_host->clk_source = SMC_MOD_CLK_SRC(pdev->id);

    mmc->ops        = &sunximmc_ops;
    mmc->ocr_avail	= MMC_VDD_32_33 | MMC_VDD_33_34;
    mmc->caps	    = MMC_CAP_4_BIT_DATA|MMC_CAP_MMC_HIGHSPEED|MMC_CAP_SD_HIGHSPEED|MMC_CAP_SDIO_IRQ;
    mmc->f_min 	    = 400000;
    mmc->f_max      = SMC_MAX_IO_CLOCK(pdev->id);
#ifdef MMC_PM_IGNORE_PM_NOTIFY
    if (pdev->id==3 && !mmc_pm_io_shd_suspend_host())
        mmc->pm_flags = MMC_PM_IGNORE_PM_NOTIFY;
#endif

    mmc->max_blk_count	= 4095;
    mmc->max_blk_size	= 4095;
    mmc->max_req_size	= 4095 * 512;              //32bit byte counter = 2^32 - 1
    mmc->max_seg_size	= mmc->max_req_size;
    mmc->max_segs	    = 256;

    if (sunximmc_resource_request(smc_host))
    {
        SMC_ERR("%s: Failed to get resouce.\n", dev_name(&pdev->dev));
        goto probe_free_host;
    }

    if (sunximmc_set_src_clk(smc_host))
    {
        goto probe_free_host;
    }
    sunximmc_init_controller(smc_host);
    smc_host->power_on = 1;
    sunximmc_procfs_attach(smc_host);

    /* irq */
    smc_host->irq = platform_get_irq(pdev, 0);
    if (smc_host->irq == 0)
    {
    	dev_err(&pdev->dev, "Failed to get interrupt resouce.\n");
    	ret = -EINVAL;
    	goto probe_free_resource;
    }

    if (request_irq(smc_host->irq, sunximmc_irq, 0, DRIVER_NAME, smc_host))
    {
    	dev_err(&pdev->dev, "Failed to request smc card interrupt.\n");
    	ret = -ENOENT;
    	goto probe_free_irq;
    }
    disable_irq(smc_host->irq);

    /* add host */
    ret = mmc_add_host(mmc);
    if (ret)
    {
    	dev_err(&pdev->dev, "Failed to add mmc host.\n");
    	goto probe_free_irq;
    }
    platform_set_drvdata(pdev, mmc);

    //fetch card detecetd mode
    sprintf(mmc_para, "mmc%d_para", pdev->id);
    ret = script_parser_fetch(mmc_para, "sdc_detmode", &card_detmode, sizeof(int));
    if (ret)
    {
    	SMC_ERR("sdc fetch card detect mode failed\n");
    }

    smc_host->cd_mode = card_detmode;
    if (smc_host->cd_mode == CARD_DETECT_BY_GPIO)
    {
        //initial card detect timer
        init_timer(&smc_host->cd_timer);
        smc_host->cd_timer.expires = jiffies + 1*HZ;
        smc_host->cd_timer.function = &sunximmc_cd_timer;
        smc_host->cd_timer.data = (unsigned long)smc_host;
        add_timer(&smc_host->cd_timer);
        smc_host->present = 0;
    }

    enable_irq(smc_host->irq);

	mutex_lock(&sw_host_rescan_mutex);
	if (smc_host->cd_mode == CARD_ALWAYS_PRESENT ||
	    sw_host_rescan_pending[pdev->id]) {
		smc_host->present = 1;
        mmc_detect_change(smc_host->mmc, msecs_to_jiffies(300));
    }

    sw_host[pdev->id] = smc_host;
	mutex_unlock(&sw_host_rescan_mutex);

    SMC_MSG("mmc%d Probe: base:0x%p irq:%u dma:%u pdes:0x%p, ret %d.\n",
            pdev->id, smc_host->smc_base, smc_host->irq, smc_host->dma_no, smc_host->pdes, ret);

    goto probe_out;

probe_free_irq:
    if (smc_host->irq)
    {
        free_irq(smc_host->irq, smc_host);
    }

probe_free_resource:
    sunximmc_resource_release(smc_host);

probe_free_host:
    mmc_free_host(mmc);

probe_out:
    return ret;
}
Exemplo n.º 28
0
static int mmc_queue_thread(void *d)
{
	struct mmc_queue *mq = d;
	struct request_queue *q = mq->queue;
	struct request *req;
	//ruanmeisi_20100603
	int issue_ret = 0;

#ifdef CONFIG_MMC_PERF_PROFILING
	ktime_t start, diff;
	struct mmc_host *host = mq->card->host;
	unsigned long bytes_xfer;
#endif


	current->flags |= PF_MEMALLOC;

	down(&mq->thread_sem);
	do {
        req = NULL;

		//ruanmeisi_20100603
		if (kthread_should_stop()) {
			remove_all_req(mq);
			break;
		}
		//end
		spin_lock_irq(q->queue_lock);
		set_current_state(TASK_INTERRUPTIBLE);
		if (!blk_queue_plugged(q))
			req = blk_fetch_request(q);
		mq->req = req;
		spin_unlock_irq(q->queue_lock);

		if (!req) {
			if (kthread_should_stop()) {
				set_current_state(TASK_RUNNING);
				break;
			}
			up(&mq->thread_sem);
			schedule();
			down(&mq->thread_sem);
			continue;
		}
		set_current_state(TASK_RUNNING);
#ifdef CONFIG_MMC_AUTO_SUSPEND
		mmc_auto_suspend(mq->card->host, 0);
#endif
#ifdef CONFIG_MMC_BLOCK_PARANOID_RESUME
		if (mq->check_status) {
			struct mmc_command cmd;
			int retries = 3;

			do {
				int err;

				cmd.opcode = MMC_SEND_STATUS;
				cmd.arg = mq->card->rca << 16;
				cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;

				mmc_claim_host(mq->card->host);
				err = mmc_wait_for_cmd(mq->card->host, &cmd, 5);
				mmc_release_host(mq->card->host);

				if (err) {
					printk(KERN_ERR "%s: failed to get status (%d)\n",
					       __func__, err);
					msleep(5);
					retries--;
					continue;
				}
				printk(KERN_DEBUG "%s: status 0x%.8x\n", __func__, cmd.resp[0]);
			} while (retries &&
				(!(cmd.resp[0] & R1_READY_FOR_DATA) ||
				(R1_CURRENT_STATE(cmd.resp[0]) == 7)));
			mq->check_status = 0;
                }
#endif
//ruanmeisi_20100529
	
		
		#ifdef CONFIG_MMC_PERF_PROFILING
		bytes_xfer = blk_rq_bytes(req);
		if (rq_data_dir(req) == READ) {
			start = ktime_get();
			issue_ret = mq->issue_fn(mq, req);
			diff = ktime_sub(ktime_get(), start);
			host->perf.rbytes_mmcq += bytes_xfer;
			host->perf.rtime_mmcq =
				ktime_add(host->perf.rtime_mmcq, diff);
		} else {
			start = ktime_get();
			issue_ret = mq->issue_fn(mq, req);
			diff = ktime_sub(ktime_get(), start);
			host->perf.wbytes_mmcq += bytes_xfer;
			host->perf.wtime_mmcq =
				ktime_add(host->perf.wtime_mmcq, diff);
		}
#else
				issue_ret = mq->issue_fn(mq, req);
#endif

		//ruanmeisi
		if (0 == issue_ret) {
			int err;
			mmc_claim_host(mq->card->host);
			err = mmc_send_status(mq->card, NULL);
			mmc_release_host(mq->card->host);
			if (err) {
				printk(KERN_ERR "rms:%s: failed to get status (%d) maybe the card is removed\n",
				       __func__, err);
				//sdcard is removed?
				mmc_detect_change(mq->card->host, 0);
				msleep(500);
				//set_current_state(TASK_INTERRUPTIBLE);
				//schedule_timeout(HZ / 2);
				continue;
			}
		}
	} while (1);
	up(&mq->thread_sem);

	return 0;
}
static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id)
{
	struct goldfish_mmc_host * host = (struct goldfish_mmc_host *)dev_id;
	u16 status;
	int end_command = 0;
	int end_transfer = 0;
	int transfer_error = 0;
	int state_changed = 0;
	int cmd_timeout = 0;

	while ((status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS)) != 0) {
		GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status);

		if (status & MMC_STAT_END_OF_CMD) {
			end_command = 1;
		}

		if (status & MMC_STAT_END_OF_DATA) {
			end_transfer = 1;
		}
		if (status & MMC_STAT_STATE_CHANGE) {
			state_changed = 1;
		}

                if (status & MMC_STAT_CMD_TIMEOUT) {
			end_command = 0;
			cmd_timeout = 1;
                }
	}

	if (cmd_timeout) {
		struct mmc_request *mrq = host->mrq;
		mrq->cmd->error = -ETIMEDOUT;
		host->mrq = NULL;
		mmc_request_done(host->mmc, mrq);
	}

	if (end_command) {
		goldfish_mmc_cmd_done(host, host->cmd);
	}
	if (transfer_error)
		goldfish_mmc_xfer_done(host, host->data);
	else if (end_transfer) {
		host->dma_done = 1;
		goldfish_mmc_end_of_data(host, host->data);
	} else if (host->data != NULL && host->mrq->cmd->opcode == 13) {
		/*
		 * WORKAROUND -- after porting this driver from 2.6 to 3.4,
		 * this case pops up during device initialization.
		 * This happens as the host stack is sending ACMD13 which
		 * involves data read while goldfish emulator implementation
		 * only supports CMD13 which does not have data phase.
		 * The workaround works by passing garbage result to the stack.
		 * TODO -- To implement proper response
		 */
		host->dma_done = 1;
		goldfish_mmc_end_of_data(host, host->data);
	}

	if (state_changed) {
		u32 state = GOLDFISH_MMC_READ(host, MMC_STATE);
		pr_info("%s: Card detect now %d\n", __func__,
			(state & MMC_STATE_INSERTED));
		mmc_detect_change(host->mmc, 0);
	}

	if (!end_command && !end_transfer &&
	    !transfer_error && !state_changed && !cmd_timeout) {
		status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS);
		dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
		if (status != 0) {
			GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status);
			GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0);
		}
	}

	return IRQ_HANDLED;
}
static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev)
{
	mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100));
}