Re: [PATCH 2/2] mmc: sdhci-pci: add runtime pm support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Adrian...

> +#ifdef CONFIG_PM_RUNTIME
> +
> +static int sdhci_pci_runtime_suspend(struct device *dev)
> +{
> +	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
> +	struct sdhci_pci_chip *chip;
> +	struct sdhci_pci_slot *slot;
> +	pm_message_t state = { .event = PM_EVENT_SUSPEND };
> +	int i, ret;
> +
> +	chip = pci_get_drvdata(pdev);
> +	if (!chip)
> +		return 0;
> +
> +	for (i = 0; i < chip->num_slots; i++) {
> +		slot = chip->slots[i];
> +		if (!slot)
> +			continue;
> +
> +		ret = sdhci_runtime_suspend_host(slot->host);
> +
> +		if (ret) {
> +			for (i--; i >= 0; i--)
> +				sdhci_runtime_resume_host(chip->slots[i]->host);
> +			return ret;
> +		}
> +	}
> +
> +	if (chip->fixes && chip->fixes->suspend) {
> +		ret = chip->fixes->suspend(chip, state);
> +		if (ret) {
> +			for (i = chip->num_slots - 1; i >= 0; i--)
> +				sdhci_runtime_resume_host(chip->slots[i]->host);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}


sdhci_runtime_resume_host() is missed return-value.
And i looked into sdhci_runtime_resume/suspend_host()...but
always return 0...why did you check return-value..?

> +
> +static int sdhci_pci_runtime_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
> +	struct sdhci_pci_chip *chip;
> +	struct sdhci_pci_slot *slot;
> +	int i, ret;
> +
> +	chip = pci_get_drvdata(pdev);
> +	if (!chip)
> +		return 0;
> +
> +	if (chip->fixes && chip->fixes->resume) {
> +		ret = chip->fixes->resume(chip);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	for (i = 0; i < chip->num_slots; i++) {
> +		slot = chip->slots[i];
> +		if (!slot)
> +			continue;
> +
> +		ret = sdhci_runtime_resume_host(slot->host);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int sdhci_pci_runtime_idle(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +#else
> +
> +#define sdhci_pci_runtime_suspend	NULL
> +#define sdhci_pci_runtime_resume	NULL
> +#define sdhci_pci_runtime_idle		NULL
> +
> +#endif
> +
> +static const struct dev_pm_ops sdhci_pci_pm_ops = {
> +	.runtime_suspend = sdhci_pci_runtime_suspend,
> +	.runtime_resume = sdhci_pci_runtime_resume,
> +	.runtime_idle = sdhci_pci_runtime_idle,
> +};
> +
>  /*****************************************************************************\
>   *                                                                           *
>   * Device probing/removal                                                    *
> @@ -1132,6 +1290,21 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
>  	sdhci_free_host(slot->host);
>  }
>  
> +static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
> +{
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_allow(dev);
> +	pm_runtime_set_autosuspend_delay(dev, 50);
> +	pm_runtime_use_autosuspend(dev);
> +	pm_suspend_ignore_children(dev, 1);
> +}
> +
> +static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
> +{
> +	pm_runtime_forbid(dev);
> +	pm_runtime_get_noresume(dev);
> +}
> +
>  static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
>  				     const struct pci_device_id *ent)
>  {
> @@ -1207,6 +1380,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
>  		chip->slots[i] = slot;
>  	}
>  
> +	sdhci_pci_runtime_pm_allow(&pdev->dev);
> +
>  	return 0;
>  
>  free:
> @@ -1223,6 +1398,8 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
>  	int i;
>  	struct sdhci_pci_chip *chip;
>  
> +	sdhci_pci_runtime_pm_forbid(&pdev->dev);
> +
>  	chip = pci_get_drvdata(pdev);
>  
>  	if (chip) {
> @@ -1243,6 +1420,9 @@ static struct pci_driver sdhci_driver = {
>  	.remove =	__devexit_p(sdhci_pci_remove),
>  	.suspend =	sdhci_pci_suspend,
>  	.resume	=	sdhci_pci_resume,
> +	.driver =	{
> +		.pm =   &sdhci_pci_pm_ops
> +	},
>  };
>  
>  /*****************************************************************************\
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index d66a7a1..787b877 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -20,6 +20,7 @@
>  #include <linux/slab.h>
>  #include <linux/scatterlist.h>
>  #include <linux/regulator/consumer.h>
> +#include <linux/pm_runtime.h>
>  
>  #include <linux/leds.h>
>  
> @@ -41,6 +42,7 @@
>  #define MAX_TUNING_LOOP 40
>  
>  static unsigned int debug_quirks = 0;
> +static unsigned int debug_quirks2;
>  
>  static void sdhci_finish_data(struct sdhci_host *);
>  
> @@ -49,6 +51,20 @@ static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc);
>  static void sdhci_tuning_timer(unsigned long data);
>  
> +#ifdef CONFIG_PM_RUNTIME
> +static int sdhci_runtime_pm_get(struct sdhci_host *host);
> +static int sdhci_runtime_pm_put(struct sdhci_host *host);
> +#else
> +static inline int sdhci_runtime_pm_get(struct sdhci_host *host)
> +{
> +	return 0;
> +}
> +static inline int sdhci_runtime_pm_put(struct sdhci_host *host)
> +{
> +	return 0;
> +}
> +#endif
> +
>  static void sdhci_dumpregs(struct sdhci_host *host)
>  {
>  	printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
> @@ -132,6 +148,9 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
>  	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>  		return;
>  
> +	if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION)
> +		return;
> +
>  	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
>  			      SDHCI_CARD_PRESENT;
>  	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
> @@ -251,11 +270,14 @@ static void sdhci_led_control(struct led_classdev *led,
>  
>  	spin_lock_irqsave(&host->lock, flags);
>  
> +	if (host->runtime_suspended)
> +		goto out;
> +
>  	if (brightness == LED_OFF)
>  		sdhci_deactivate_led(host);
>  	else
>  		sdhci_activate_led(host);
> -
> +out:
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  #endif
> @@ -1209,6 +1231,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  
>  	host = mmc_priv(mmc);
>  
> +	sdhci_runtime_pm_get(host);
> +
>  	spin_lock_irqsave(&host->lock, flags);
>  
>  	WARN_ON(host->mrq != NULL);
> @@ -1269,14 +1293,11 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
>  {
> -	struct sdhci_host *host;
>  	unsigned long flags;
>  	u8 ctrl;
>  
> -	host = mmc_priv(mmc);
> -
>  	spin_lock_irqsave(&host->lock, flags);
>  
>  	if (host->flags & SDHCI_DEVICE_DEAD)
> @@ -1426,7 +1447,16 @@ out:
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int check_ro(struct sdhci_host *host)
> +static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +
> +	sdhci_runtime_pm_get(host);
> +	sdhci_do_set_ios(host, ios);
> +	sdhci_runtime_pm_put(host);
> +}
> +
> +static int sdhci_check_ro(struct sdhci_host *host)
>  {
>  	unsigned long flags;
>  	int is_readonly;
> @@ -1450,19 +1480,16 @@ static int check_ro(struct sdhci_host *host)
>  
>  #define SAMPLE_COUNT	5
>  
> -static int sdhci_get_ro(struct mmc_host *mmc)
> +static int sdhci_do_get_ro(struct sdhci_host *host)
>  {
> -	struct sdhci_host *host;
>  	int i, ro_count;
>  
> -	host = mmc_priv(mmc);
> -
>  	if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
> -		return check_ro(host);
> +		return sdhci_check_ro(host);
>  
>  	ro_count = 0;
>  	for (i = 0; i < SAMPLE_COUNT; i++) {
> -		if (check_ro(host)) {
> +		if (sdhci_check_ro(host)) {
>  			if (++ro_count > SAMPLE_COUNT / 2)
>  				return 1;
>  		}
> @@ -1479,38 +1506,56 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
>  		host->ops->hw_reset(host);
>  }
>  
> -static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +static int sdhci_get_ro(struct mmc_host *mmc)
>  {
> -	struct sdhci_host *host;
> -	unsigned long flags;
> -
> -	host = mmc_priv(mmc);
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int ret;
>  
> -	spin_lock_irqsave(&host->lock, flags);
> +	sdhci_runtime_pm_get(host);
> +	ret = sdhci_do_get_ro(host);
> +	sdhci_runtime_pm_put(host);
> +	return ret;
> +}
>  
> +static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
> +{
>  	if (host->flags & SDHCI_DEVICE_DEAD)
>  		goto out;
>  
>  	if (enable)
> +		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
> +	else
> +		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
> +
> +	/* SDIO IRQ will be enabled as appropriate in runtime resume */
> +	if (host->runtime_suspended)
> +		goto out;
> +
> +	if (enable)
>  		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
>  	else
>  		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
>  out:
>  	mmiowb();
> +}
> +
> +static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	unsigned long flags;
>  
> +	spin_lock_irqsave(&host->lock, flags);
> +	sdhci_enable_sdio_irq_nolock(host, enable);
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -	struct mmc_ios *ios)
> +static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> +						struct mmc_ios *ios)
>  {
> -	struct sdhci_host *host;
>  	u8 pwr;
>  	u16 clk, ctrl;
>  	u32 present_state;
>  
> -	host = mmc_priv(mmc);
> -
>  	/*
>  	 * Signal Voltage Switching is only applicable for Host Controllers
>  	 * v3.00 and above.
> @@ -1603,6 +1648,20 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  		return 0;
>  }
>  
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +	struct mmc_ios *ios)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int err;
> +
> +	if (host->version < SDHCI_SPEC_300)
> +		return 0;
> +	sdhci_runtime_pm_get(host);
> +	err = sdhci_do_start_signal_voltage_switch(host, ios);
> +	sdhci_runtime_pm_put(host);
> +	return err;
> +}
> +
>  static int sdhci_execute_tuning(struct mmc_host *mmc)
>  {
>  	struct sdhci_host *host;
> @@ -1614,6 +1673,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
>  
>  	host = mmc_priv(mmc);
>  
> +	sdhci_runtime_pm_get(host);
>  	disable_irq(host->irq);
>  	spin_lock(&host->lock);
>  
> @@ -1631,6 +1691,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
>  	else {
>  		spin_unlock(&host->lock);
>  		enable_irq(host->irq);
> +		sdhci_runtime_pm_put(host);
>  		return 0;
>  	}
>  
> @@ -1656,7 +1717,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
>  	timeout = 150;
>  	do {
>  		struct mmc_command cmd = {0};
> -		struct mmc_request mrq = {0};
> +		struct mmc_request mrq = {NULL};
>  
>  		if (!tuning_loop_counter && !timeout)
>  			break;
> @@ -1774,18 +1835,16 @@ out:
>  	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
>  	spin_unlock(&host->lock);
>  	enable_irq(host->irq);
> +	sdhci_runtime_pm_put(host);
>  
>  	return err;
>  }
>  
> -static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
> +static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable)
>  {
> -	struct sdhci_host *host;
>  	u16 ctrl;
>  	unsigned long flags;
>  
> -	host = mmc_priv(mmc);
> -
>  	/* Host Controller v3.00 defines preset value registers */
>  	if (host->version < SDHCI_SPEC_300)
>  		return;
> @@ -1801,14 +1860,25 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
>  	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
>  		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> +		host->flags |= SDHCI_PV_ENABLED;
>  	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
>  		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> +		host->flags &= ~SDHCI_PV_ENABLED;
>  	}
>  
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
>  
> +static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +
> +	sdhci_runtime_pm_get(host);
> +	sdhci_do_enable_preset_value(host, enable);
> +	sdhci_runtime_pm_put(host);
> +}
> +
>  static const struct mmc_host_ops sdhci_ops = {
>  	.request	= sdhci_request,
>  	.set_ios	= sdhci_set_ios,
> @@ -1835,19 +1905,19 @@ static void sdhci_tasklet_card(unsigned long param)
>  
>  	spin_lock_irqsave(&host->lock, flags);
>  
> -	if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
> -		if (host->mrq) {
> -			printk(KERN_ERR "%s: Card removed during transfer!\n",
> -				mmc_hostname(host->mmc));
> -			printk(KERN_ERR "%s: Resetting controller.\n",
> -				mmc_hostname(host->mmc));
> +	/* Check host->mrq first in case we are runtime suspended */
> +	if (host->mrq &&
> +	    !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
> +		printk(KERN_ERR "%s: Card removed during transfer!\n",
> +			mmc_hostname(host->mmc));
> +		printk(KERN_ERR "%s: Resetting controller.\n",
> +			mmc_hostname(host->mmc));
>  
> -			sdhci_reset(host, SDHCI_RESET_CMD);
> -			sdhci_reset(host, SDHCI_RESET_DATA);
> +		sdhci_reset(host, SDHCI_RESET_CMD);
> +		sdhci_reset(host, SDHCI_RESET_DATA);
>  
> -			host->mrq->cmd->error = -ENOMEDIUM;
> -			tasklet_schedule(&host->finish_tasklet);
> -		}
> +		host->mrq->cmd->error = -ENOMEDIUM;
> +		tasklet_schedule(&host->finish_tasklet);
>  	}
>  
>  	spin_unlock_irqrestore(&host->lock, flags);
> @@ -1863,14 +1933,16 @@ static void sdhci_tasklet_finish(unsigned long param)
>  
>  	host = (struct sdhci_host*)param;
>  
> +	spin_lock_irqsave(&host->lock, flags);
> +
>          /*
>           * If this tasklet gets rescheduled while running, it will
>           * be run again afterwards but without any active request.
>           */
> -	if (!host->mrq)
> +	if (!host->mrq) {
> +		spin_unlock_irqrestore(&host->lock, flags);
>  		return;
> -
> -	spin_lock_irqsave(&host->lock, flags);
> +	}
>  
>  	del_timer(&host->timer);
>  
> @@ -1914,6 +1986,7 @@ static void sdhci_tasklet_finish(unsigned long param)
>  	spin_unlock_irqrestore(&host->lock, flags);
>  
>  	mmc_request_done(host->mmc, mrq);
> +	sdhci_runtime_pm_put(host);
>  }
>  
>  static void sdhci_timeout_timer(unsigned long data)
> @@ -2145,12 +2218,19 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>  static irqreturn_t sdhci_irq(int irq, void *dev_id)
>  {
>  	irqreturn_t result;
> -	struct sdhci_host* host = dev_id;
> +	struct sdhci_host *host = dev_id;
>  	u32 intmask;
>  	int cardint = 0;
>  
>  	spin_lock(&host->lock);
>  
> +	if (host->runtime_suspended) {
> +		spin_unlock(&host->lock);
> +		printk(KERN_WARNING "%s: got irq while runtime suspended\n",
> +		       mmc_hostname(host->mmc));
> +		return IRQ_HANDLED;
> +	}
> +
>  	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
>  
>  	if (!intmask || intmask == 0xffffffff) {
> @@ -2284,7 +2364,6 @@ int sdhci_resume_host(struct sdhci_host *host)
>  			return ret;
>  	}
>  
> -
>  	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
>  		if (host->ops->enable_dma)
>  			host->ops->enable_dma(host);
> @@ -2323,6 +2402,90 @@ EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
>  
>  #endif /* CONFIG_PM */
>  
> +#ifdef CONFIG_PM_RUNTIME
> +
> +static int sdhci_runtime_pm_get(struct sdhci_host *host)
> +{
> +	return pm_runtime_get_sync(host->mmc->parent);
> +}
> +
> +static int sdhci_runtime_pm_put(struct sdhci_host *host)
> +{
> +	pm_runtime_mark_last_busy(host->mmc->parent);
> +	return pm_runtime_put_autosuspend(host->mmc->parent);
> +}
> +
> +int sdhci_runtime_suspend_host(struct sdhci_host *host)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	/* Disable tuning since we are suspending */
> +	if (host->version >= SDHCI_SPEC_300 &&
> +	    host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		del_timer_sync(&host->tuning_timer);
> +		host->flags &= ~SDHCI_NEEDS_RETUNING;
> +	}
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
> +	spin_unlock_irqrestore(&host->lock, flags);
> +
> +	synchronize_irq(host->irq);
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +	host->runtime_suspended = true;
> +	spin_unlock_irqrestore(&host->lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
> +
> +int sdhci_runtime_resume_host(struct sdhci_host *host)
> +{
> +	unsigned long flags;
> +	int ret = 0, host_flags = host->flags;
> +
> +	if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
> +		if (host->ops->enable_dma)
> +			host->ops->enable_dma(host);
> +	}
> +
> +	sdhci_init(host, 0);
> +
> +	/* Force clock and power re-program */
> +	host->pwr = 0;
> +	host->clock = 0;
> +	sdhci_do_set_ios(host, &host->mmc->ios);
> +
> +	sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
> +	if (host_flags & SDHCI_PV_ENABLED)
> +		sdhci_do_enable_preset_value(host, true);
> +
> +	/* Set the re-tuning expiration flag */
> +	if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
> +	    (host->tuning_mode == SDHCI_TUNING_MODE_1))
> +		host->flags |= SDHCI_NEEDS_RETUNING;
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +
> +	host->runtime_suspended = false;
> +
> +	/* Enable SDIO IRQ */
> +	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
> +		sdhci_enable_sdio_irq_nolock(host, true);
> +
> +	/* Enable Card Detection */
> +	sdhci_enable_card_detection(host);
> +
> +	spin_unlock_irqrestore(&host->lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
> +
> +#endif
> +
>  /*****************************************************************************\
>   *                                                                           *
>   * Device allocation/registration                                            *
> @@ -2365,6 +2528,8 @@ int sdhci_add_host(struct sdhci_host *host)
>  
>  	if (debug_quirks)
>  		host->quirks = debug_quirks;
> +	if (debug_quirks2)
> +		host->quirks2 = debug_quirks2;
>  
>  	sdhci_reset(host, SDHCI_RESET_ALL);
>  
> @@ -2887,9 +3052,11 @@ module_init(sdhci_drv_init);
>  module_exit(sdhci_drv_exit);
>  
>  module_param(debug_quirks, uint, 0444);
> +module_param(debug_quirks2, uint, 0444);
>  
>  MODULE_AUTHOR("Pierre Ossman <pierre@xxxxxxxxx>");
>  MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
>  MODULE_LICENSE("GPL");
>  
>  MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
> +MODULE_PARM_DESC(debug_quirks, "Force certain other quirks.");
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 7bd919c..0a5b654 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -379,4 +379,9 @@ extern int sdhci_resume_host(struct sdhci_host *host);
>  extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
>  #endif
>  
> +#ifdef CONFIG_PM_RUNTIME
> +extern int sdhci_runtime_suspend_host(struct sdhci_host *host);
> +extern int sdhci_runtime_resume_host(struct sdhci_host *host);
> +#endif
> +
>  #endif /* __SDHCI_HW_H */
> diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
> index 5666f3a..e4b6935 100644
> --- a/include/linux/mmc/sdhci.h
> +++ b/include/linux/mmc/sdhci.h
> @@ -88,6 +88,10 @@ struct sdhci_host {
>  /* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
>  #define SDHCI_QUIRK_UNSTABLE_RO_DETECT			(1<<31)
>  
> +	unsigned int quirks2;	/* More deviations from spec. */
> +
> +#define SDHCI_QUIRK2_OWN_CARD_DETECTION			(1<<0)
> +
>  	int irq;		/* Device IRQ */
>  	void __iomem *ioaddr;	/* Mapped address */
>  
> @@ -115,6 +119,8 @@ struct sdhci_host {
>  #define SDHCI_NEEDS_RETUNING	(1<<5)	/* Host needs retuning */
>  #define SDHCI_AUTO_CMD12	(1<<6)	/* Auto CMD12 support */
>  #define SDHCI_AUTO_CMD23	(1<<7)	/* Auto CMD23 support */
> +#define SDHCI_PV_ENABLED	(1<<8)	/* Preset value enabled */
> +#define SDHCI_SDIO_IRQ_ENABLED	(1<<9)	/* SDIO irq enabled */
>  
>  	unsigned int version;	/* SDHCI spec. version */
>  
> @@ -125,6 +131,8 @@ struct sdhci_host {
>  	unsigned int clock;	/* Current clock (MHz) */
>  	u8 pwr;			/* Current voltage */
>  
> +	bool runtime_suspended;	/* Host is runtime suspended */
> +
>  	struct mmc_request *mrq;	/* Current request */
>  	struct mmc_command *cmd;	/* Current command */
>  	struct mmc_data *data;	/* Current data request */


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux