Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757185AbYBDS0S (ORCPT ); Mon, 4 Feb 2008 13:26:18 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756716AbYBDSZv (ORCPT ); Mon, 4 Feb 2008 13:25:51 -0500 Received: from cantor2.suse.de ([195.135.220.15]:60816 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756656AbYBDSZt (ORCPT ); Mon, 4 Feb 2008 13:25:49 -0500 From: Frank Seidel Organization: SUSE LINUX Products GmbH To: Philip Langdale Subject: [PATCH v2] mmc: extend ricoh_mmc to support Ricoh RL5c476 Date: Mon, 4 Feb 2008 19:25:42 +0100 User-Agent: KMail/1.9.6 (enterprise 20071221.751182) Cc: sdhci-devel@list.drzeus.cx, linux-kernel@vger.kernel.org, Pierre Ossman , Andrew de Quincey References: <200801311838.24743.fseidel@suse.de> <47A418E0.6040205@overt.org> In-Reply-To: <47A418E0.6040205@overt.org> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200802041925.43081.fseidel@suse.de> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5778 Lines: 179 From: Frank Seidel This patch (base on current linus git tree plus Philip Langdales suspend/resume patch) adds support for the Ricoh RL5c476 chip: with this the mmc adapter that needs this disabler (R5C843) can also be handled correctly when it sits on a RL5c476. (+ minor style changes (removed spaces between function names and open parenthesis .. checkpatch warned from previos patch)) Signed-off-by: Frank Seidel --- drivers/mmc/host/ricoh_mmc.c | 101 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 80 insertions(+), 21 deletions(-) --- a/drivers/mmc/host/ricoh_mmc.c +++ b/drivers/mmc/host/ricoh_mmc.c @@ -44,19 +44,43 @@ MODULE_DEVICE_TABLE(pci, pci_ids); static int ricoh_mmc_disable(struct pci_dev *fw_dev) { u8 write_enable; + u8 write_target; 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"); - return -ENODEV; - } + 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); + 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"); @@ -67,13 +91,29 @@ static int ricoh_mmc_disable(struct pci_ static int ricoh_mmc_enable(struct pci_dev *fw_dev) { u8 write_enable; + u8 write_target; u8 disable; - 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); + 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"); @@ -85,6 +125,7 @@ static int __devinit ricoh_mmc_probe(str const struct pci_device_id *ent) { u8 rev; + u8 ctrlfound = 0; struct pci_dev *fw_dev = NULL; @@ -98,20 +139,38 @@ static int __devinit ricoh_mmc_probe(str 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) { - if (ricoh_mmc_disable(fw_dev) != 0) { + if (ricoh_mmc_disable(fw_dev) != 0) return -ENODEV; - } pci_set_drvdata(pdev, fw_dev); + ++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; @@ -132,7 +191,7 @@ static void __devexit ricoh_mmc_remove(s pci_set_drvdata(pdev, NULL); } -static int ricoh_mmc_suspend (struct pci_dev *pdev, pm_message_t state) +static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) { struct pci_dev *fw_dev = NULL; @@ -146,7 +205,7 @@ static int ricoh_mmc_suspend (struct pci return 0; } -static int ricoh_mmc_resume (struct pci_dev *pdev) +static int ricoh_mmc_resume(struct pci_dev *pdev) { struct pci_dev *fw_dev = NULL; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/