Re: [PATCH 1/7] sdhci: Rework some of the quirk behaviour

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

 



On Mon, Sep 13, 2010 at 06:38:48PM +0100, Alan Cox wrote:
> As the quirks go ever more complex it's getting harder and harder to integrate
> new drivers. The Intel MID devices add a whole further collection of new
> quirks so instead of quirks start moving some stuff to overridable functions.
> 
> We also introduce an sdhci_reset_all helper which is told if the reset is
> being done during init (which needs to be avoided by some hw) or on exit
> in which case it doesn't.
> 
> Arguably the driver wants to be lots of drivers and "libsdhci" but that would
> be a massive undertaking.
> 
> Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
> ---
> 
>  drivers/mmc/host/Kconfig           |   11 ++
>  drivers/mmc/host/Makefile          |    1 
>  drivers/mmc/host/sdhci-intel-mid.c |  163 ++++++++++++++++++++++++++++++++++++

Why are those added here and not in patch 3/7?

>  drivers/mmc/host/sdhci-pci.c       |   56 ++++++++++++
>  drivers/mmc/host/sdhci.c           |   61 ++++++++++---
>  drivers/mmc/host/sdhci.h           |   20 ++++
>  include/linux/pci_ids.h            |    2 
>  7 files changed, 296 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/mmc/host/sdhci-intel-mid.c

From having a glimpse, there is MID-specific stuff all over the patch.
This makes finding the actual "quirk rework" harder.

> 
> 
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index ce099c4..ffa40f1 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -81,6 +81,17 @@ config MMC_RICOH_MMC
>  
>  	  If unsure, say Y.
>  
> +config MMC_SDHCI_INTEL_MID
> +	tristate "SDHCI support on Intel MID platforms"
> +	depends on MMC_SDHCI_PCI
> +	help
> +	  This includes support for the SDHCI controllers found on Intel
> +	  MID platform systems.
> +
> +	  If you have a controller with this interface, say Y or M here.
> +
> +	  If unsure, say N.
> +
>  config MMC_SDHCI_OF
>  	tristate "SDHCI support on OpenFirmware platforms"
>  	depends on MMC_SDHCI && PPC_OF
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 697bbfe..21c80f0 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
>  obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
>  obj-$(CONFIG_MMC_SDHCI_MV)	+= sdhci-mv.o
>  obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
> +obj-$(CONFIG_MMC_SDHCI_INTEL_MID)	+= sdhci-intel-mid.o
>  obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
>  obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o
>  obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
> diff --git a/drivers/mmc/host/sdhci-intel-mid.c b/drivers/mmc/host/sdhci-intel-mid.c
> new file mode 100644
> index 0000000..2828831
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-intel-mid.c
> @@ -0,0 +1,163 @@
> +#include <linux/delay.h>
> +#include <linux/highmem.h>
> +#include <linux/io.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <linux/scatterlist.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <linux/leds.h>
> +
> +#include <linux/mmc/host.h>
> +
> +#include "sdhci.h"
> +
> +/*
> + *	Support code for SDHCI on Intel MID platforms. We have lots
> + * 	of quirks specific to these platforms so wrap them up in one place
> + *	that keeps them out of the main flow. We can't just make it a new
> + *	driver as the shdci core code isn't really a library.
> + */
> + 
> +static void sdhci_broken_reset(struct sdhci_host *host, u8 mask)
> +{
> +	unsigned long timeout;
> +	u32 uninitialized_var(ier);
> +
> +	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
> +		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
> +			SDHCI_CARD_PRESENT))
> +			return;
> +	}
> +
> +	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
> +		ier = sdhci_readl(host, SDHCI_INT_ENABLE);
> +
> +	sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
> +
> +	if (mask & SDHCI_RESET_ALL)
> +		host->clock = 0;
> +
> +	/* Wait max 100 ms */
> +	timeout = 100;
> +
> +	/* hw clears the bit when it's done */
> +	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
> +		if (timeout == 0) {
> +			printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
> +				mmc_hostname(host->mmc), (int)mask);
> +		}
> +		timeout--;
> +		mdelay(1);
> +	}
> +	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
> +		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
> +}
> +
> +static void sdhci_mid_broken_resetall(struct sdhci_host *host, int down)
> +{
> +	if (down)
> +		sdhci_broken_reset(host, SDHCI_RESET_ALL);
> +}
> +
> +static void sdhci_mid_init_no_reset(struct sdhci_host *host, int soft)
> +{
> +	u32 intmask;
> +
> +	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
> +	sdhci_writel(host,
> +		intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
> +		SDHCI_INT_STATUS);
> +
> +        /* Ensure any IRQ left over from pre boot time (eg from Kboot) does
> +           not turn up and cause chaos */
> +	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
> +	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
> +
> +	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
> +		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
> +		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
> +		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
> +		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
> +
> +	if (soft) {
> +		/* force clock reconfiguration */
> +		host->clock = 0;
> +		sdhci_set_ios(host->mmc, &host->mmc->ios);
> +	}
> +
> +	/* disable wakeup signal during initialization */
> +	sdhci_writeb(host, 0x0, SDHCI_WAKE_UP_CONTROL);
> +}
> +
> +/*
> + * HW problem exists in LNW A3 so clock register has to be set
> + * for every command if both SDIO0 and SDIO1 are enabled.
> + */
> +static void sdhci_clock_reset(struct sdhci_host *host)
> +{
> +	u16 clk;
> +	unsigned long timeout;
> +
> +	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +
> +	clk |= SDHCI_CLOCK_CARD_EN;
> +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> +	/* Wait max 10 ms */
> +	timeout = 10;
> +	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
> +		& SDHCI_CLOCK_INT_STABLE)) {
> +		if (timeout == 0) {
> +			printk(KERN_ERR "%s: Internal clock never "
> +				"stabilised.\n",
> +				mmc_hostname(host->mmc));
> +			sdhci_dumpregs(host);
> +			return;
> +		}
> +		timeout--;
> +		mdelay(1);
> +	}
> +}
> +
> +static void sdhci_clockreset_wcmd(struct sdhci_host *host,
> +				struct mmc_command *cmd, int flags)
> +{
> +	sdhci_clock_reset(host);
> + 	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
> +}
> +
> +static void sdhci_lnw_a3_set_ios(struct sdhci_host *host,
> +					struct mmc_ios *ios, u8 ctrl)
> +{
> +	/*
> +	 * For LNW A3, HISPD bit has to be cleared in order to
> +	 * enable the 50MHz clock
> +	 */
> +	if (ios->timing == MMC_TIMING_SD_HS ||
> +			ios->timing == MMC_TIMING_MMC_HS)
> +		ctrl |= SDHCI_CTRL_HISPD;
> +	else
> +		ctrl &= ~SDHCI_CTRL_HISPD;
> +	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
> +}
> +
> +/*
> + * HW problem exists in LNW A3 which leads to fake interrupt on SDIO1 if SDIO0
> + * and SDIO1 are both enabled.
> + */
> +static void sdhci_lnw_a3_unexpected_cmd(struct sdhci_host *host, u32 intmask)
> +{
> +}
> +
> +struct sdhci_ops sdhci_intel_mrst_hc = {
> +	.reset = sdhci_broken_reset,
> +	.init = sdhci_mid_init_no_reset,
> +	.set_ios = sdhci_lnw_a3_set_ios,
> +	.reset_all = sdhci_mid_broken_resetall,
> +	.write_command = sdhci_clockreset_wcmd,
> +	.unexpected_cmd_irq = sdhci_lnw_a3_unexpected_cmd,
> +};
> +EXPORT_SYMBOL_GPL(sdhci_intel_mrst_hc);
> +
> +
> diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
> index e8aa99d..3e29e94 100644
> --- a/drivers/mmc/host/sdhci-pci.c
> +++ b/drivers/mmc/host/sdhci-pci.c
> @@ -54,6 +54,8 @@ struct sdhci_pci_fixes {
>  	int			(*suspend)(struct sdhci_pci_chip*,
>  					pm_message_t);
>  	int			(*resume)(struct sdhci_pci_chip*);
> +
> +	struct sdhci_ops	*host_ops;
>  };
>  
>  struct sdhci_pci_slot {
> @@ -397,6 +399,35 @@ static const struct sdhci_pci_fixes sdhci_via = {
>  	.probe		= via_probe,
>  };
>  
> +#if defined(CONFIG_MMC_SDHCI_INTEL_MID) || defined(CONFIG_MMC_SDHCI_INTEL_MID_MODULE)
> +
> +/*
> + * ADMA operation is disabled for Moorestown platform due to
> + * hardware bugs.
> + */
> +static int mrst_hc0_probe(struct sdhci_pci_chip *chip)
> +{
> +	/*
> +	 * slots number is fixed here for MRST as SDIO3 is never used and has
> +	 * hardware bugs.
> +	 */
> +	chip->num_slots = 1;
> +	return 0;
> +}

Why is this function here and not in sdhci-intel-mid.c?

> +
> +static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
> +	.quirks		= SDHCI_QUIRK_BROKEN_ADMA,
> +	.probe		= mrst_hc0_probe,
> +	.host_ops	= &sdhci_intel_mrst_hc,
> +};
> +
> +static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1 = {
> +	.quirks		= SDHCI_QUIRK_BROKEN_ADMA,
> +	.host_ops	= &sdhci_intel_mrst_hc,
> +};
> +
> +#endif
> +
>  static const struct pci_device_id pci_ids[] __devinitdata = {
>  	{
>  		.vendor		= PCI_VENDOR_ID_RICOH,
> @@ -494,6 +525,23 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
>  		.driver_data	= (kernel_ulong_t)&sdhci_via,
>  	},
>  
> +#if defined(CONFIG_MMC_SDHCI_INTEL_MID) || defined(CONFIG_MMC_SDHCI_INTEL_MID_MODULE)
> +	{
> +		.vendor		= PCI_VENDOR_ID_INTEL,
> +		.device		= PCI_DEVICE_ID_INTEL_MRST_SD0,
> +		.subvendor	= PCI_ANY_ID,
> +		.subdevice	= PCI_ANY_ID,
> +		.driver_data	= (kernel_ulong_t)&sdhci_intel_mrst_hc0,
> +	},
> +
> +	{
> +		.vendor		= PCI_VENDOR_ID_INTEL,
> +		.device		= PCI_DEVICE_ID_INTEL_MRST_SD1,
> +		.subvendor	= PCI_ANY_ID,
> +		.subdevice	= PCI_ANY_ID,
> +		.driver_data	= (kernel_ulong_t)&sdhci_intel_mrst_hc1,
> +	},
> +#endif
>  	{	/* Generic SD host controller */
>  		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
>  	},
> @@ -509,7 +557,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
>   *                                                                           *
>  \*****************************************************************************/
>  
> -static int sdhci_pci_enable_dma(struct sdhci_host *host)
> +int sdhci_pci_enable_dma(struct sdhci_host *host)
>  {
>  	struct sdhci_pci_slot *slot;
>  	struct pci_dev *pdev;
> @@ -533,6 +581,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(sdhci_pci_enable_dma);
>  
>  static struct sdhci_ops sdhci_pci_ops = {
>  	.enable_dma	= sdhci_pci_enable_dma,
> @@ -687,7 +736,10 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
>  	slot->pci_bar = bar;
>  
>  	host->hw_name = "PCI";
> -	host->ops = &sdhci_pci_ops;
> +	if (chip->fixes->host_ops)
> +		host->ops = chip->fixes->host_ops;
> +	else
> +		host->ops = &sdhci_pci_ops;
>  	host->quirks = chip->quirks;
>  
>  	host->irq = pdev->irq;
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index f608626..9d8091a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -45,7 +45,7 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  
> -static void sdhci_dumpregs(struct sdhci_host *host)
> +void sdhci_dumpregs(struct sdhci_host *host)
>  {
>  	printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
>  
> @@ -87,6 +87,7 @@ static void sdhci_dumpregs(struct sdhci_host *host)
>  
>  	printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
>  }
> +EXPORT_SYMBOL_GPL(sdhci_dumpregs);
>  
>  /*****************************************************************************\
>   *                                                                           *
> @@ -94,7 +95,7 @@ static void sdhci_dumpregs(struct sdhci_host *host)
>   *                                                                           *
>  \*****************************************************************************/
>  
> -static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
> +void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
>  {
>  	u32 ier;
>  
> @@ -104,6 +105,7 @@ static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
>  	sdhci_writel(host, ier, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_clear_set_irqs);
>  
>  static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
>  {
> @@ -143,6 +145,11 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
>  	unsigned long timeout;
>  	u32 uninitialized_var(ier);
>  
> +	if (host->ops->reset) {
> +		host->ops->reset(host, mask);
> +		return;
> +	}
> +
>  	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
>  		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
>  			SDHCI_CARD_PRESENT))
> @@ -176,14 +183,21 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
>  		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
>  }
>  
> -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
> +/* Down is true if we are shutting down the port */
> +static void sdhci_reset_all(struct sdhci_host *host, int down)
> +{
> +	if (host->ops->reset_all)
> +		host->ops->reset_all(host, down);
> +	else
> +		sdhci_reset(host, SDHCI_RESET_ALL);
> +}
>  
>  static void sdhci_init(struct sdhci_host *host, int soft)
>  {
>  	if (soft)
>  		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
>  	else
> -		sdhci_reset(host, SDHCI_RESET_ALL);
> +		sdhci_reset_all(host, 0);
>  
>  	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
>  		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
> @@ -945,7 +959,11 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
>  	if (cmd->data)
>  		flags |= SDHCI_CMD_DATA;
>  
> -	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
> +	if (host->ops->write_command)
> +		host->ops->write_command(host, cmd, flags);
> +	else
> +		sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
> +						SDHCI_COMMAND);
>  }
>  
>  static void sdhci_finish_command(struct sdhci_host *host)
> @@ -1139,7 +1157,7 @@ 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)
> +void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  {
>  	struct sdhci_host *host;
>  	unsigned long flags;
> @@ -1186,9 +1204,13 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	else
>  		ctrl &= ~SDHCI_CTRL_HISPD;
>  
> -	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
> +	if (host->ops->set_ios)
> +		host->ops->set_ios(host, ios, ctrl);
> +	else
> +		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>  
> -	/*
> +	/*	FIXME: This can also be moved to ops->set_ios
> +	 *
>  	 * Some (ENE) controllers go apeshit on some ios operation,
>  	 * signalling timeout and CRC errors even on CMD0. Resetting
>  	 * it on each ios seems to solve the problem.
> @@ -1200,6 +1222,7 @@ out:
>  	mmiowb();
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_set_ios);
>  
>  static int sdhci_get_ro(struct mmc_host *mmc)
>  {
> @@ -1383,10 +1406,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
>  	BUG_ON(intmask == 0);
>  
>  	if (!host->cmd) {
> -		printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
> -			"though no command operation was in progress.\n",
> -			mmc_hostname(host->mmc), (unsigned)intmask);
> -		sdhci_dumpregs(host);
> +		if (host->ops->unexpected_cmd_irq)
> +			host->ops->unexpected_cmd_irq(host, intmask);
> +		else {
> +			printk(KERN_ERR "%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
> +				mmc_hostname(host->mmc), (unsigned)intmask);
> +			sdhci_dumpregs(host);
> +		}
>  		return;
>  	}
>  
> @@ -1703,7 +1729,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	if (debug_quirks)
>  		host->quirks = debug_quirks;
>  
> -	sdhci_reset(host, SDHCI_RESET_ALL);
> +	sdhci_reset_all(host, 0);
>  
>  	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
>  	host->version = (host->version & SDHCI_SPEC_VER_MASK)
> @@ -1829,6 +1855,9 @@ int sdhci_add_host(struct sdhci_host *host)
>  	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
>  		mmc->caps |= MMC_CAP_NEEDS_POLL;
>  
> +	if (host->ops->set_caps)
> +		host->ops->set_caps(host);
> +
>  	mmc->ocr_avail = 0;
>  	if (caps & SDHCI_CAN_VDD_330)
>  		mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
> @@ -1881,7 +1910,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	} else {
>  		mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >>
>  				SDHCI_MAX_BLOCK_SHIFT;
> -		if (mmc->max_blk_size >= 3) {
> +		if (mmc->max_blk_size > 3) {

Why this change? Not mentioned in the changelog. And wrong according to
the simplified standard v2. Is it V3 material?

>  			printk(KERN_WARNING "%s: Invalid maximum block size, "
>  				"assuming 512 bytes\n", mmc_hostname(mmc));
>  			mmc->max_blk_size = 0;
> @@ -1952,7 +1981,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  
>  #ifdef SDHCI_USE_LEDS_CLASS
>  reset:
> -	sdhci_reset(host, SDHCI_RESET_ALL);
> +	sdhci_reset_all(host, 1);
>  	free_irq(host->irq, host);
>  #endif
>  untasklet:
> @@ -1993,7 +2022,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
>  #endif
>  
>  	if (!dead)
> -		sdhci_reset(host, SDHCI_RESET_ALL);
> +		sdhci_reset_all(host, 1);
>  
>  	free_irq(host->irq, host);
>  
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index d316bc7..182fcc3 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -323,6 +323,17 @@ struct sdhci_ops {
>  	unsigned int	(*get_max_clock)(struct sdhci_host *host);
>  	unsigned int	(*get_min_clock)(struct sdhci_host *host);
>  	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
> +
> +	/* Interface hooks to allow drivers to override standard behaviour */
> +	void	(*reset)(struct sdhci_host *host, u8 mask);
> +	void	(*reset_all)(struct sdhci_host *host, int down);
> +	void	(*init)(struct sdhci_host *host, int soft);
> +	void 	(*write_command)(struct sdhci_host *host,
> +				struct mmc_command *cmd, int flags);
> +	void	(*set_ios)(struct sdhci_host *host,
> +				struct mmc_ios *ios, u8 ctrl);
> +	void	(*set_caps)(struct sdhci_host *host);
> +	void	(*unexpected_cmd_irq)(struct sdhci_host *host, u32 intmask);

That looks quite much on a first view. Might need to dig in deeper...

>  };
>  
>  #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
> @@ -427,4 +438,13 @@ extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
>  extern int sdhci_resume_host(struct sdhci_host *host);
>  #endif
>  
> +extern void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set);
> +extern int sdhci_pci_enable_dma(struct sdhci_host *host);
> +extern void sdhci_dumpregs(struct sdhci_host *host);
> +extern void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
> +
> +/* Host function sets from driver support files */
> +extern struct sdhci_ops sdhci_intel_mrst_hc;
> +
> +
>  #endif /* __SDHCI_H */
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 9438660..674316e 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2410,6 +2410,8 @@
>  #define PCI_DEVICE_ID_INTEL_82375	0x0482
>  #define PCI_DEVICE_ID_INTEL_82424	0x0483
>  #define PCI_DEVICE_ID_INTEL_82378	0x0484
> +#define PCI_DEVICE_ID_INTEL_MRST_SD0	0x0807
> +#define PCI_DEVICE_ID_INTEL_MRST_SD1	0x0808
>  #define PCI_DEVICE_ID_INTEL_I960	0x0960
>  #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
>  #define PCI_DEVICE_ID_INTEL_8257X_SOL	0x1062
> 
> --
> 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

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

Attachment: signature.asc
Description: Digital signature


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

  Powered by Linux