Bläddra i källkod

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (26 commits)
  mmc: sdio_ops.c should #include "sdio_ops.h"
  mmc: proper prototypes for mmc_attach_*()
  mmc: make __mmc_release_bus() static
  sdhci: improve no card, no reset quirk
  MMC: OMAP: Do not busy wait for end of command for ever
  MMC: OMAP: Start new commands from work queue instead of irq
  MMC: OMAP: Lazy clock shutdown
  MMC: OMAP: Move failing command abortion to workqueue
  MMC: OMAP: Use tasklet instead of workqueue for cover switch notification
  MMC: OMAP: Check the get_cover_state function pointer if not set
  MMC: OMAP: Using setup_timer instead of init_timer
  MMC: OMAP: Abort stuck commands
  MMC: OMAP: General cleanup for MMC multislot support
  MMC: OMAP: Power functions modified to MMC multislot support
  MMC: OMAP: Fix timeout calculation for MMC multislot support
  MMC: OMAP: New release dma and abort xfer functions
  MMC: OMAP: Add back cover switch support
  MMC: OMAP: Introduce new multislot structure and change driver to use it
  MMC: OMAP: Remove cover switch handling to allow adding multislot support
  MMC: OMAP: Fix the BYTEBLOCK capability removal
  ...
Linus Torvalds 17 år sedan
förälder
incheckning
135cedad74

+ 1 - 5
drivers/mmc/core/core.c

@@ -35,10 +35,6 @@
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
-extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
-extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
-extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
-
 static struct workqueue_struct *workqueue;
 
 /*
@@ -516,7 +512,7 @@ static void mmc_power_off(struct mmc_host *host)
 /*
  * Cleanup when the last reference to the bus operator is dropped.
  */
-void __mmc_release_bus(struct mmc_host *host)
+static void __mmc_release_bus(struct mmc_host *host)
 {
 	BUG_ON(!host);
 	BUG_ON(host->bus_refs);

+ 4 - 0
drivers/mmc/core/core.h

@@ -46,6 +46,10 @@ void mmc_rescan(struct work_struct *work);
 void mmc_start_host(struct mmc_host *host);
 void mmc_stop_host(struct mmc_host *host);
 
+int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
+
 extern int use_spi_crc;
 
 #endif

+ 22 - 17
drivers/mmc/core/host.c

@@ -2,7 +2,7 @@
  *  linux/drivers/mmc/core/host.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
- *  Copyright (C) 2007 Pierre Ossman
+ *  Copyright (C) 2007-2008 Pierre Ossman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -57,12 +57,25 @@ static DEFINE_SPINLOCK(mmc_host_lock);
  */
 struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 {
+	int err;
 	struct mmc_host *host;
 
+	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+		return NULL;
+
 	host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
 	if (!host)
 		return NULL;
 
+	spin_lock(&mmc_host_lock);
+	err = idr_get_new(&mmc_host_idr, host, &host->index);
+	spin_unlock(&mmc_host_lock);
+	if (err)
+		goto free;
+
+	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+		 "mmc%d", host->index);
+
 	host->parent = dev;
 	host->class_dev.parent = dev;
 	host->class_dev.class = &mmc_host_class;
@@ -85,6 +98,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 	host->max_blk_count = PAGE_CACHE_SIZE / 512;
 
 	return host;
+
+free:
+	kfree(host);
+	return NULL;
 }
 
 EXPORT_SYMBOL(mmc_alloc_host);
@@ -104,18 +121,6 @@ int mmc_add_host(struct mmc_host *host)
 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
 		!host->ops->enable_sdio_irq);
 
-	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
-		return -ENOMEM;
-
-	spin_lock(&mmc_host_lock);
-	err = idr_get_new(&mmc_host_idr, host, &host->index);
-	spin_unlock(&mmc_host_lock);
-	if (err)
-		return err;
-
-	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
-		 "mmc%d", host->index);
-
 	led_trigger_register_simple(host->class_dev.bus_id, &host->led);
 
 	err = device_add(&host->class_dev);
@@ -144,10 +149,6 @@ void mmc_remove_host(struct mmc_host *host)
 	device_del(&host->class_dev);
 
 	led_trigger_unregister_simple(host->led);
-
-	spin_lock(&mmc_host_lock);
-	idr_remove(&mmc_host_idr, host->index);
-	spin_unlock(&mmc_host_lock);
 }
 
 EXPORT_SYMBOL(mmc_remove_host);
@@ -160,6 +161,10 @@ EXPORT_SYMBOL(mmc_remove_host);
  */
 void mmc_free_host(struct mmc_host *host)
 {
+	spin_lock(&mmc_host_lock);
+	idr_remove(&mmc_host_idr, host->index);
+	spin_unlock(&mmc_host_lock);
+
 	put_device(&host->class_dev);
 }
 

+ 2 - 2
drivers/mmc/core/sdio_irq.c

@@ -128,12 +128,12 @@ static int sdio_irq_thread(void *_host)
 			}
 		}
 
-		set_task_state(current, TASK_INTERRUPTIBLE);
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (host->caps & MMC_CAP_SDIO_IRQ)
 			host->ops->enable_sdio_irq(host, 1);
 		if (!kthread_should_stop())
 			schedule_timeout(period);
-		set_task_state(current, TASK_RUNNING);
+		set_current_state(TASK_RUNNING);
 	} while (!kthread_should_stop());
 
 	if (host->caps & MMC_CAP_SDIO_IRQ)

+ 1 - 0
drivers/mmc/core/sdio_ops.c

@@ -17,6 +17,7 @@
 #include <linux/mmc/sdio.h>
 
 #include "core.h"
+#include "sdio_ops.h"
 
 int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
 {

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 592 - 193
drivers/mmc/host/omap.c


+ 70 - 30
drivers/mmc/host/sdhci.c

@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 
+#include <linux/leds.h>
+
 #include <linux/mmc/host.h>
 
 #include "sdhci.h"
@@ -30,10 +32,6 @@
 
 static unsigned int debug_quirks = 0;
 
-/* For multi controllers in one platform case */
-static u16 chip_index = 0;
-static spinlock_t index_lock;
-
 /*
  * Different quirks to handle when the hardware deviates from a strict
  * interpretation of the SDHCI specification.
@@ -43,7 +41,7 @@ static spinlock_t index_lock;
 #define SDHCI_QUIRK_CLOCK_BEFORE_RESET			(1<<0)
 /* Controller has bad caps bits, but really supports DMA */
 #define SDHCI_QUIRK_FORCE_DMA				(1<<1)
-/* Controller doesn't like some resets when there is no card inserted. */
+/* Controller doesn't like to be reset when there is no card inserted. */
 #define SDHCI_QUIRK_NO_CARD_NO_RESET			(1<<2)
 /* Controller doesn't like clearing the power reg before a change */
 #define SDHCI_QUIRK_SINGLE_POWER_WRITE			(1<<3)
@@ -71,12 +69,20 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 	{
 		.vendor		= PCI_VENDOR_ID_RICOH,
 		.device		= PCI_DEVICE_ID_RICOH_R5C822,
-		.subvendor	= PCI_ANY_ID,
+		.subvendor	= PCI_VENDOR_ID_SAMSUNG,
 		.subdevice	= PCI_ANY_ID,
 		.driver_data	= SDHCI_QUIRK_FORCE_DMA |
 				  SDHCI_QUIRK_NO_CARD_NO_RESET,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_RICOH,
+		.device		= PCI_DEVICE_ID_RICOH_R5C822,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= SDHCI_QUIRK_FORCE_DMA,
+	},
+
 	{
 		.vendor		= PCI_VENDOR_ID_TI,
 		.device		= PCI_DEVICE_ID_TI_XX21_XX11_SD,
@@ -256,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
 }
 
+#ifdef CONFIG_LEDS_CLASS
+static void sdhci_led_control(struct led_classdev *led,
+	enum led_brightness brightness)
+{
+	struct sdhci_host *host = container_of(led, struct sdhci_host, led);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (brightness == LED_OFF)
+		sdhci_deactivate_led(host);
+	else
+		sdhci_activate_led(host);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+#endif
+
 /*****************************************************************************\
  *                                                                           *
  * Core functions                                                            *
@@ -773,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	WARN_ON(host->mrq != NULL);
 
+#ifndef CONFIG_LEDS_CLASS
 	sdhci_activate_led(host);
+#endif
 
 	host->mrq = mrq;
 
@@ -965,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param)
 	host->cmd = NULL;
 	host->data = NULL;
 
+#ifndef CONFIG_LEDS_CLASS
 	sdhci_deactivate_led(host);
+#endif
 
 	mmiowb();
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -1105,7 +1133,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		goto out;
 	}
 
-	DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
+	DBG("*** %s got interrupt: 0x%08x\n",
+		mmc_hostname(host->mmc), intmask);
 
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
 		writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
@@ -1235,7 +1264,7 @@ static int sdhci_resume (struct pci_dev *pdev)
 		if (chip->hosts[i]->flags & SDHCI_USE_DMA)
 			pci_set_master(pdev);
 		ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
-			IRQF_SHARED, chip->hosts[i]->slot_descr,
+			IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc),
 			chip->hosts[i]);
 		if (ret)
 			return ret;
@@ -1324,9 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
 	DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
 
-	snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
-
-	ret = pci_request_region(pdev, host->bar, host->slot_descr);
+	ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc));
 	if (ret)
 		goto free;
 
@@ -1343,7 +1370,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
 	if (version > 1) {
 		printk(KERN_ERR "%s: Unknown controller version (%d). "
-			"You may experience problems.\n", host->slot_descr,
+			"You may experience problems.\n", mmc_hostname(mmc),
 			version);
 	}
 
@@ -1366,13 +1393,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 		(host->flags & SDHCI_USE_DMA)) {
 		printk(KERN_WARNING "%s: Will use DMA "
 			"mode even though HW doesn't fully "
-			"claim to support it.\n", host->slot_descr);
+			"claim to support it.\n", mmc_hostname(mmc));
 	}
 
 	if (host->flags & SDHCI_USE_DMA) {
 		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 			printk(KERN_WARNING "%s: No suitable DMA available. "
-				"Falling back to PIO.\n", host->slot_descr);
+				"Falling back to PIO.\n", mmc_hostname(mmc));
 			host->flags &= ~SDHCI_USE_DMA;
 		}
 	}
@@ -1386,7 +1413,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 		(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
 	if (host->max_clk == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't specify base clock "
-			"frequency.\n", host->slot_descr);
+			"frequency.\n", mmc_hostname(mmc));
 		ret = -ENODEV;
 		goto unmap;
 	}
@@ -1396,7 +1423,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 		(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
 	if (host->timeout_clk == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
-			"frequency.\n", host->slot_descr);
+			"frequency.\n", mmc_hostname(mmc));
 		ret = -ENODEV;
 		goto unmap;
 	}
@@ -1424,7 +1451,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
 	if (mmc->ocr_avail == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't report any "
-			"support voltages.\n", host->slot_descr);
+			"support voltages.\n", mmc_hostname(mmc));
 		ret = -ENODEV;
 		goto unmap;
 	}
@@ -1458,8 +1485,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	 */
 	mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
 	if (mmc->max_blk_size >= 3) {
-		printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
-			host->slot_descr);
+		printk(KERN_WARNING "%s: Invalid maximum block size, "
+			"assuming 512 bytes\n", mmc_hostname(mmc));
 		mmc->max_blk_size = 512;
 	} else
 		mmc->max_blk_size = 512 << mmc->max_blk_size;
@@ -1480,7 +1507,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
 
 	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-		host->slot_descr, host);
+		mmc_hostname(mmc), host);
 	if (ret)
 		goto untasklet;
 
@@ -1490,16 +1517,32 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 	sdhci_dumpregs(host);
 #endif
 
+#ifdef CONFIG_LEDS_CLASS
+	host->led.name = mmc_hostname(mmc);
+	host->led.brightness = LED_OFF;
+	host->led.default_trigger = mmc_hostname(mmc);
+	host->led.brightness_set = sdhci_led_control;
+
+	ret = led_classdev_register(&pdev->dev, &host->led);
+	if (ret)
+		goto reset;
+#endif
+
 	mmiowb();
 
 	mmc_add_host(mmc);
 
-	printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
-		host->addr, host->irq,
+	printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n",
+		mmc_hostname(mmc), host->addr, host->irq,
 		(host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
 
 	return 0;
 
+#ifdef CONFIG_LEDS_CLASS
+reset:
+	sdhci_reset(host, SDHCI_RESET_ALL);
+	free_irq(host->irq, host);
+#endif
 untasklet:
 	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->finish_tasklet);
@@ -1527,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
 
 	mmc_remove_host(mmc);
 
+#ifdef CONFIG_LEDS_CLASS
+	led_classdev_unregister(&host->led);
+#endif
+
 	sdhci_reset(host, SDHCI_RESET_ALL);
 
 	free_irq(host->irq, host);
@@ -1589,11 +1636,6 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
 	chip->num_slots = slots;
 	pci_set_drvdata(pdev, chip);
 
-	/* Add for multi controller case */
-	spin_lock(&index_lock);
-	chip->index = chip_index++;
-	spin_unlock(&index_lock);
-
 	for (i = 0;i < slots;i++) {
 		ret = sdhci_probe_slot(pdev, i);
 		if (ret) {
@@ -1654,8 +1696,6 @@ static int __init sdhci_drv_init(void)
 		": Secure Digital Host Controller Interface driver\n");
 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
-	spin_lock_init(&index_lock);
-
 	return pci_register_driver(&sdhci_driver);
 }
 

+ 5 - 4
drivers/mmc/host/sdhci.h

@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -168,6 +168,10 @@ struct sdhci_host {
 	struct sdhci_chip	*chip;
 	struct mmc_host		*mmc;		/* MMC structure */
 
+#ifdef CONFIG_LEDS_CLASS
+	struct led_classdev	led;		/* LED control */
+#endif
+
 	spinlock_t		lock;		/* Mutex */
 
 	int			flags;		/* Host attributes */
@@ -190,8 +194,6 @@ struct sdhci_host {
 	int			offset;		/* Offset into current sg */
 	int			remain;		/* Bytes left in current */
 
-	char			slot_descr[20];	/* Name for reservations */
-
 	int			irq;		/* Device IRQ */
 	int			bar;		/* PCI BAR index */
 	unsigned long		addr;		/* Bus address */
@@ -208,7 +210,6 @@ struct sdhci_chip {
 
 	unsigned long		quirks;
 
-	int			index;		/* Index for chip0, chip1 ...*/
 	int			num_slots;	/* Slots on controller */
 	struct sdhci_host	*hosts[0];	/* Pointers to hosts */
 };

+ 2 - 0
include/asm-arm/arch-omap/mmc.h

@@ -18,6 +18,8 @@
 #define OMAP_MMC_MAX_SLOTS	2
 
 struct omap_mmc_platform_data {
+	struct omap_mmc_conf	conf;
+
 	unsigned enabled:1;
 	/* number of slots on board */
 	unsigned nr_slots:2;

Vissa filer visades inte eftersom för många filer har ändrats