--- drivers/mmc/host/ricoh_mmc.c 2008-01-24 23:58:37.000000000 +0100 +++ drivers/mmc/host/ricoh_mmc_update.c 2008-03-25 17:33:30.000000000 +0100 @@ -41,10 +41,91 @@ 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 @@ 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 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, }; /*****************************************************************************\