Re: [PATCH] mmc: Disabler for Ricoh MMC controller

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

 



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 ?

> Signed-off-by: Philipl Langdale <[email protected]>
> 
> --- 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 <linux/pci.h>
> +
> +#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 <[email protected]>");
> +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 [email protected]
> 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux