Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753209AbXJBEpy (ORCPT ); Tue, 2 Oct 2007 00:45:54 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750988AbXJBEpq (ORCPT ); Tue, 2 Oct 2007 00:45:46 -0400 Received: from gate.crashing.org ([63.228.1.57]:34076 "EHLO gate.crashing.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750803AbXJBEpp (ORCPT ); Tue, 2 Oct 2007 00:45:45 -0400 Subject: Re: [PATCH] mmc: Disabler for Ricoh MMC controller From: Benjamin Herrenschmidt Reply-To: benh@kernel.crashing.org To: Philip Langdale Cc: Pierre Ossman , sdhci-devel@list.drzeus.cx, LKML In-Reply-To: <1191300236.6310.60.camel@pasglop> References: <4701B9AB.5070308@overt.org> <1191300236.6310.60.camel@pasglop> Content-Type: text/plain Date: Tue, 02 Oct 2007 14:45:34 +1000 Message-Id: <1191300334.6310.62.camel@pasglop> Mime-Version: 1.0 X-Mailer: Evolution 2.12.0 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8596 Lines: 229 On Tue, 2007-10-02 at 14:44 +1000, Benjamin Herrenschmidt wrote: > On Mon, 2007-10-01 at 20:23 -0700, Philip Langdale wrote: > > Thanks to Matt Domsch and Rezwanul Kabir at Dell, we know how to disable the > > MMC controller on the multi-function Ricoh R5C832. The MMC controller needs > > to be disabled or it will steal MMC cards from the SD controller where they > > would otherwise be supported by the Linux SDHCI driver. > > Why can't that be a quirk instead ? That is, a global quirk or a quirk in the SDHCI driver... > > Signed-off-by: Philipl Langdale > > > > --- linux-2.6.22/drivers/mmc/host/Kconfig 2007-07-08 16:32:17.000000000 -0700 > > +++ linux-ricoh/drivers/mmc/host/Kconfig 2007-09-15 12:32:10.000000000 -0700 > > @@ -35,6 +35,23 @@ > > > > If unsure, say N. > > > > +config MMC_RICOH_MMC > > + tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)" > > + depends on PCI && EXPERIMENTAL && MMC_SDHCI > > + help > > + This selects the disabler for the Ricoh MMC Controller. This > > + proprietary controller is unnecessary because the SDHCI driver > > + supports MMC cards on the SD controller, but if it is not > > + disabled, it will steal the MMC cards away - rendering them > > + useless. It is safe to select this driver even if you don't > > + have a Ricoh based card reader. > > + > > + > > + To compile this driver as a module, choose M here: > > + the module will be called ricoh_mmc. > > + > > + If unsure, say Y. > > + > > config MMC_OMAP > > tristate "TI OMAP Multimedia Card Interface support" > > depends on ARCH_OMAP > > --- linux-2.6.22/drivers/mmc/host/Makefile 2007-07-08 16:32:17.000000000 -0700 > > +++ linux-ricoh/drivers/mmc/host/Makefile 2007-09-15 12:28:49.000000000 -0700 > > @@ -15,4 +15,5 @@ > > obj-$(CONFIG_MMC_OMAP) += omap.o > > obj-$(CONFIG_MMC_AT91) += at91_mci.o > > obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o > > +obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o > > > > --- linux-2.6.22/drivers/mmc/host/ricoh_mmc.c 1969-12-31 16:00:00.000000000 -0800 > > +++ linux-ricoh/drivers/mmc/host/ricoh_mmc.c 2007-09-15 12:29:05.000000000 -0700 > > @@ -0,0 +1,156 @@ > > +/* > > + * ricoh_mmc.c - Dummy driver to disable the Rioch MMC controller. > > + * > > + * Copyright (C) 2007 Philip Langdale, 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 > > + * the Free Software Foundation; either version 2 of the License, or (at > > + * your option) any later version. > > + */ > > + > > +/* > > + * This is a conceptually ridiculous driver, but it is required by the way > > + * the Ricoh multi-function R5C832 works. This chip implements firewire > > + * and four different memory card controllers. Two of those controllers are > > + * an SDHCI controller and a proprietary MMC controller. The linux SDHCI > > + * driver supports MMC cards but the chip detects MMC cards in hardware > > + * and directs them to the MMC controller - so the SDHCI driver never sees > > + * them. To get around this, we must disable the useless MMC controller. > > + * At that point, the SDHCI controller will start seeing them. As a bonus, > > + * a detection event occurs immediately, even if the MMC card is already > > + * in the reader. > > + * > > + * The relevant registers live on the firewire function, so this is unavoidably > > + * ugly. Such is life. > > + */ > > + > > +#include > > + > > +#define DRIVER_NAME "ricoh-mmc" > > + > > +#define DBG(f, x...) \ > > + pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) > > + > > +static const struct pci_device_id pci_ids[] __devinitdata = { > > + { > > + .vendor = PCI_VENDOR_ID_RICOH, > > + .device = PCI_DEVICE_ID_RICOH_R5C843, > > + .subvendor = PCI_ANY_ID, > > + .subdevice = PCI_ANY_ID, > > + }, > > + { /* end: all zeroes */ }, > > +}; > > + > > +MODULE_DEVICE_TABLE(pci, pci_ids); > > + > > +static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, > > + const struct pci_device_id *ent) > > +{ > > + u8 rev; > > + > > + struct pci_dev *fw_dev = NULL; > > + > > + BUG_ON(pdev == NULL); > > + BUG_ON(ent == NULL); > > + > > + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev); > > + > > + printk(KERN_INFO DRIVER_NAME > > + ": Ricoh MMC controller found at %s [%04x:%04x] (rev %x)\n", > > + 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))) { > > + 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"); > > + 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"); > > + > > + break; > > + } > > + } > > + > > + if (pci_get_drvdata(pdev) == NULL) { > > + printk(KERN_WARNING DRIVER_NAME > > + ": Main firewire function not found. Cannot disable controller.\n"); > > + return -ENODEV; > > + } > > + > > + return 0; > > +} > > + > > +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"); > > + > > + pci_set_drvdata(pdev, NULL); > > +} > > + > > +static struct pci_driver ricoh_mmc_driver = { > > + .name = DRIVER_NAME, > > + .id_table = pci_ids, > > + .probe = ricoh_mmc_probe, > > + .remove = __devexit_p(ricoh_mmc_remove), > > +}; > > + > > +/*****************************************************************************\ > > + * * > > + * Driver init/exit * > > + * * > > +\*****************************************************************************/ > > + > > +static int __init ricoh_mmc_drv_init(void) > > +{ > > + printk(KERN_INFO DRIVER_NAME > > + ": Ricoh MMC Controller disabling driver\n"); > > + printk(KERN_INFO DRIVER_NAME ": Copyright(c) Philip Langdale\n"); > > + > > + return pci_register_driver(&ricoh_mmc_driver); > > +} > > + > > +static void __exit ricoh_mmc_drv_exit(void) > > +{ > > + DBG("Exiting\n"); > > + > > + pci_unregister_driver(&ricoh_mmc_driver); > > +} > > + > > +module_init(ricoh_mmc_drv_init); > > +module_exit(ricoh_mmc_drv_exit); > > + > > +MODULE_AUTHOR("Philip Langdale "); > > +MODULE_DESCRIPTION("Ricoh MMC Controller disabling driver"); > > +MODULE_LICENSE("GPL"); > > + > > --- linux-2.6.22/include/linux/pci_ids.h 2007-09-02 00:14:25.000000000 -0700 > > +++ linux-ricoh/include/linux/pci_ids.h 2007-09-15 12:27:36.000000000 -0700 > > @@ -1485,6 +1485,8 @@ > > #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 > > #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 > > #define PCI_DEVICE_ID_RICOH_R5C822 0x0822 > > +#define PCI_DEVICE_ID_RICOH_R5C832 0x0832 > > +#define PCI_DEVICE_ID_RICOH_R5C843 0x0843 > > > > #define PCI_VENDOR_ID_DLINK 0x1186 > > #define PCI_DEVICE_ID_DLINK_DGE510T 0x4c00 > > - > > 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/ - 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/