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:
  mmc: extend ricoh_mmc to support Ricoh RL5c476
  at91_mci: use generic GPIO calls
  sdhci: add num index for multi controllers case
  MAINTAINERS: remove non-existant URLs
  mmc: remove sdhci and mmc_spi experimental markers
  mmc: Handle suspend/resume in Ricoh MMC disabler
This commit is contained in:
Linus Torvalds 2008-02-09 11:12:15 -08:00
commit 5b39dba502
6 changed files with 231 additions and 70 deletions

View File

@ -2682,7 +2682,6 @@ MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
P: Pavel Pisa
M: ppisa@pikron.com
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
S: Maintained
MOUSE AND MISC DEVICES [GENERAL]
@ -3716,7 +3715,6 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
P: Pierre Ossman
M: drzeus-sdhci@drzeus.cx
L: sdhci-devel@list.drzeus.cx
W: http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci
S: Maintained
SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
@ -4286,7 +4284,6 @@ W83L51xD SD/MMC CARD INTERFACE DRIVER
P: Pierre Ossman
M: drzeus-wbsd@drzeus.cx
L: linux-kernel@vger.kernel.org
W: http://projects.drzeus.cx/wbsd
S: Maintained
WATCHDOG DEVICE DRIVERS

View File

@ -25,8 +25,8 @@ config MMC_PXA
If unsure, say N.
config MMC_SDHCI
tristate "Secure Digital Host Controller Interface support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
tristate "Secure Digital Host Controller Interface support"
depends on PCI
help
This select the generic Secure Digital Host Controller Interface.
It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@ -118,8 +118,8 @@ config MMC_TIFM_SD
module will be called tifm_sd.
config MMC_SPI
tristate "MMC/SD over SPI (EXPERIMENTAL)"
depends on MMC && SPI_MASTER && !HIGHMEM && EXPERIMENTAL
tristate "MMC/SD over SPI"
depends on MMC && SPI_MASTER && !HIGHMEM
select CRC7
select CRC_ITU_T
help

View File

@ -70,10 +70,11 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/gpio.h>
#include <asm/mach/mmc.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91_mci.h>
#define DRIVER_NAME "at91_mci"
@ -659,11 +660,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->board->vcc_pin) {
switch (ios->power_mode) {
case MMC_POWER_OFF:
at91_set_gpio_value(host->board->vcc_pin, 0);
gpio_set_value(host->board->vcc_pin, 0);
break;
case MMC_POWER_UP:
case MMC_POWER_ON:
at91_set_gpio_value(host->board->vcc_pin, 1);
gpio_set_value(host->board->vcc_pin, 1);
break;
}
}
@ -768,7 +769,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
{
struct at91mci_host *host = _host;
int present = !at91_get_gpio_value(irq);
int present = !gpio_get_value(irq_to_gpio(irq));
/*
* we expect this irq on both insert and remove,
@ -793,7 +794,7 @@ static int at91_mci_get_ro(struct mmc_host *mmc)
struct at91mci_host *host = mmc_priv(mmc);
if (host->board->wp_pin) {
read_only = at91_get_gpio_value(host->board->wp_pin);
read_only = gpio_get_value(host->board->wp_pin);
printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
(read_only ? "read-only" : "read-write") );
}
@ -820,8 +821,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
struct resource *res;
int ret;
pr_debug("Probe MCI devices\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
@ -831,9 +830,9 @@ static int __init at91_mci_probe(struct platform_device *pdev)
mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
if (!mmc) {
pr_debug("Failed to allocate mmc host\n");
release_mem_region(res->start, res->end - res->start + 1);
return -ENOMEM;
ret = -ENOMEM;
dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
goto fail6;
}
mmc->ops = &at91_mci_ops;
@ -853,19 +852,44 @@ static int __init at91_mci_probe(struct platform_device *pdev)
if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
mmc->caps |= MMC_CAP_4_BIT_DATA;
else
printk("AT91 MMC: 4 wire bus mode not supported"
dev_warn(&pdev->dev, "4 wire bus mode not supported"
" - using 1 wire\n");
}
/*
* Reserve GPIOs ... board init code makes sure these pins are set
* up as GPIOs with the right direction (input, except for vcc)
*/
if (host->board->det_pin) {
ret = gpio_request(host->board->det_pin, "mmc_detect");
if (ret < 0) {
dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
goto fail5;
}
}
if (host->board->wp_pin) {
ret = gpio_request(host->board->wp_pin, "mmc_wp");
if (ret < 0) {
dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
goto fail4;
}
}
if (host->board->vcc_pin) {
ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
if (ret < 0) {
dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
goto fail3;
}
}
/*
* Get Clock
*/
host->mci_clk = clk_get(&pdev->dev, "mci_clk");
if (IS_ERR(host->mci_clk)) {
printk(KERN_ERR "AT91 MMC: no clock defined.\n");
mmc_free_host(mmc);
release_mem_region(res->start, res->end - res->start + 1);
return -ENODEV;
ret = -ENODEV;
dev_dbg(&pdev->dev, "no mci_clk?\n");
goto fail2;
}
/*
@ -873,10 +897,8 @@ static int __init at91_mci_probe(struct platform_device *pdev)
*/
host->baseaddr = ioremap(res->start, res->end - res->start + 1);
if (!host->baseaddr) {
clk_put(host->mci_clk);
mmc_free_host(mmc);
release_mem_region(res->start, res->end - res->start + 1);
return -ENOMEM;
ret = -ENOMEM;
goto fail1;
}
/*
@ -890,15 +912,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
* Allocate the MCI interrupt
*/
host->irq = platform_get_irq(pdev, 0);
ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
mmc_hostname(mmc), host);
if (ret) {
printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
clk_disable(host->mci_clk);
clk_put(host->mci_clk);
mmc_free_host(mmc);
iounmap(host->baseaddr);
release_mem_region(res->start, res->end - res->start + 1);
return ret;
dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
goto fail0;
}
platform_set_drvdata(pdev, mmc);
@ -907,8 +925,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
* Add host to MMC layer
*/
if (host->board->det_pin) {
host->present = !at91_get_gpio_value(host->board->det_pin);
device_init_wakeup(&pdev->dev, 1);
host->present = !gpio_get_value(host->board->det_pin);
}
else
host->present = -1;
@ -919,15 +936,38 @@ static int __init at91_mci_probe(struct platform_device *pdev)
* monitor card insertion/removal if we can
*/
if (host->board->det_pin) {
ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
0, DRIVER_NAME, host);
ret = request_irq(gpio_to_irq(host->board->det_pin),
at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
if (ret)
printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
dev_warn(&pdev->dev, "request MMC detect irq failed\n");
else
device_init_wakeup(&pdev->dev, 1);
}
pr_debug("Added MCI driver\n");
return 0;
fail0:
clk_disable(host->mci_clk);
iounmap(host->baseaddr);
fail1:
clk_put(host->mci_clk);
fail2:
if (host->board->vcc_pin)
gpio_free(host->board->vcc_pin);
fail3:
if (host->board->wp_pin)
gpio_free(host->board->wp_pin);
fail4:
if (host->board->det_pin)
gpio_free(host->board->det_pin);
fail5:
mmc_free_host(mmc);
fail6:
release_mem_region(res->start, res->end - res->start + 1);
dev_err(&pdev->dev, "probe failed, err %d\n", ret);
return ret;
}
/*
@ -945,9 +985,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
host = mmc_priv(mmc);
if (host->board->det_pin) {
if (device_can_wakeup(&pdev->dev))
free_irq(gpio_to_irq(host->board->det_pin), host);
device_init_wakeup(&pdev->dev, 0);
free_irq(host->board->det_pin, host);
cancel_delayed_work(&host->mmc->detect);
gpio_free(host->board->det_pin);
}
at91_mci_disable(host);
@ -957,6 +998,11 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
clk_disable(host->mci_clk); /* Disable the peripheral clock */
clk_put(host->mci_clk);
if (host->board->vcc_pin)
gpio_free(host->board->vcc_pin);
if (host->board->wp_pin)
gpio_free(host->board->wp_pin);
iounmap(host->baseaddr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, res->end - res->start + 1);

View File

@ -41,10 +41,91 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, pci_ids);
static int ricoh_mmc_disable(struct pci_dev *fw_dev)
{
u8 write_enable;
u8 write_target;
u8 disable;
if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
/* via RL5C476 */
pci_read_config_byte(fw_dev, 0xB7, &disable);
if (disable & 0x02) {
printk(KERN_INFO DRIVER_NAME
": Controller already disabled. " \
"Nothing to do.\n");
return -ENODEV;
}
pci_read_config_byte(fw_dev, 0x8E, &write_enable);
pci_write_config_byte(fw_dev, 0x8E, 0xAA);
pci_read_config_byte(fw_dev, 0x8D, &write_target);
pci_write_config_byte(fw_dev, 0x8D, 0xB7);
pci_write_config_byte(fw_dev, 0xB7, disable | 0x02);
pci_write_config_byte(fw_dev, 0x8E, write_enable);
pci_write_config_byte(fw_dev, 0x8D, write_target);
} else {
/* via R5C832 */
pci_read_config_byte(fw_dev, 0xCB, &disable);
if (disable & 0x02) {
printk(KERN_INFO DRIVER_NAME
": Controller already disabled. " \
"Nothing to do.\n");
return -ENODEV;
}
pci_read_config_byte(fw_dev, 0xCA, &write_enable);
pci_write_config_byte(fw_dev, 0xCA, 0x57);
pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
pci_write_config_byte(fw_dev, 0xCA, write_enable);
}
printk(KERN_INFO DRIVER_NAME
": Controller is now disabled.\n");
return 0;
}
static int ricoh_mmc_enable(struct pci_dev *fw_dev)
{
u8 write_enable;
u8 write_target;
u8 disable;
if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
/* via RL5C476 */
pci_read_config_byte(fw_dev, 0x8E, &write_enable);
pci_write_config_byte(fw_dev, 0x8E, 0xAA);
pci_read_config_byte(fw_dev, 0x8D, &write_target);
pci_write_config_byte(fw_dev, 0x8D, 0xB7);
pci_read_config_byte(fw_dev, 0xB7, &disable);
pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02);
pci_write_config_byte(fw_dev, 0x8E, write_enable);
pci_write_config_byte(fw_dev, 0x8D, write_target);
} else {
/* via R5C832 */
pci_read_config_byte(fw_dev, 0xCA, &write_enable);
pci_read_config_byte(fw_dev, 0xCB, &disable);
pci_write_config_byte(fw_dev, 0xCA, 0x57);
pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
pci_write_config_byte(fw_dev, 0xCA, write_enable);
}
printk(KERN_INFO DRIVER_NAME
": Controller is now re-enabled.\n");
return 0;
}
static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u8 rev;
u8 ctrlfound = 0;
struct pci_dev *fw_dev = NULL;
@ -58,34 +139,38 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
(int)rev);
while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
while ((fw_dev =
pci_get_device(PCI_VENDOR_ID_RICOH,
PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
pdev->bus == fw_dev->bus) {
u8 write_enable;
u8 disable;
pci_read_config_byte(fw_dev, 0xCB, &disable);
if (disable & 0x02) {
printk(KERN_INFO DRIVER_NAME
": Controller already disabled. Nothing to do.\n");
if (ricoh_mmc_disable(fw_dev) != 0)
return -ENODEV;
}
pci_read_config_byte(fw_dev, 0xCA, &write_enable);
pci_write_config_byte(fw_dev, 0xCA, 0x57);
pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
pci_write_config_byte(fw_dev, 0xCA, write_enable);
pci_set_drvdata(pdev, fw_dev);
printk(KERN_INFO DRIVER_NAME
": Controller is now disabled.\n");
++ctrlfound;
break;
}
}
if (pci_get_drvdata(pdev) == NULL) {
fw_dev = NULL;
while (!ctrlfound &&
(fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
pdev->bus == fw_dev->bus) {
if (ricoh_mmc_disable(fw_dev) != 0)
return -ENODEV;
pci_set_drvdata(pdev, fw_dev);
++ctrlfound;
}
}
if (!ctrlfound) {
printk(KERN_WARNING DRIVER_NAME
": Main firewire function not found. Cannot disable controller.\n");
return -ENODEV;
@ -96,30 +181,51 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
{
u8 write_enable;
u8 disable;
struct pci_dev *fw_dev = NULL;
fw_dev = pci_get_drvdata(pdev);
BUG_ON(fw_dev == NULL);
pci_read_config_byte(fw_dev, 0xCA, &write_enable);
pci_read_config_byte(fw_dev, 0xCB, &disable);
pci_write_config_byte(fw_dev, 0xCA, 0x57);
pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
pci_write_config_byte(fw_dev, 0xCA, write_enable);
printk(KERN_INFO DRIVER_NAME
": Controller is now re-enabled.\n");
ricoh_mmc_enable(fw_dev);
pci_set_drvdata(pdev, NULL);
}
static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct pci_dev *fw_dev = NULL;
fw_dev = pci_get_drvdata(pdev);
BUG_ON(fw_dev == NULL);
printk(KERN_INFO DRIVER_NAME ": Suspending.\n");
ricoh_mmc_enable(fw_dev);
return 0;
}
static int ricoh_mmc_resume(struct pci_dev *pdev)
{
struct pci_dev *fw_dev = NULL;
fw_dev = pci_get_drvdata(pdev);
BUG_ON(fw_dev == NULL);
printk(KERN_INFO DRIVER_NAME ": Resuming.\n");
ricoh_mmc_disable(fw_dev);
return 0;
}
static struct pci_driver ricoh_mmc_driver = {
.name = DRIVER_NAME,
.id_table = pci_ids,
.probe = ricoh_mmc_probe,
.remove = __devexit_p(ricoh_mmc_remove),
.suspend = ricoh_mmc_suspend,
.resume = ricoh_mmc_resume,
};
/*****************************************************************************\

View File

@ -30,6 +30,10 @@
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.
@ -1320,7 +1324,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, "sdhci:slot%d", slot);
snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
ret = pci_request_region(pdev, host->bar, host->slot_descr);
if (ret)
@ -1585,6 +1589,11 @@ 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) {
@ -1645,6 +1654,8 @@ 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);
}

View File

@ -208,6 +208,7 @@ 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 */
};