diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/host/ricoh_mmc.c | 101 |
1 files changed, 80 insertions, 21 deletions
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c index 898e7991caef..a16d7609e4ee 100644 --- a/drivers/mmc/host/ricoh_mmc.c +++ b/drivers/mmc/host/ricoh_mmc.c | |||
| @@ -44,19 +44,43 @@ MODULE_DEVICE_TABLE(pci, pci_ids); | |||
| 44 | static int ricoh_mmc_disable(struct pci_dev *fw_dev) | 44 | static int ricoh_mmc_disable(struct pci_dev *fw_dev) |
| 45 | { | 45 | { |
| 46 | u8 write_enable; | 46 | u8 write_enable; |
| 47 | u8 write_target; | ||
| 47 | u8 disable; | 48 | u8 disable; |
| 48 | 49 | ||
| 49 | pci_read_config_byte(fw_dev, 0xCB, &disable); | 50 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { |
| 50 | if (disable & 0x02) { | 51 | /* via RL5C476 */ |
| 51 | printk(KERN_INFO DRIVER_NAME | ||
| 52 | ": Controller already disabled. Nothing to do.\n"); | ||
| 53 | return -ENODEV; | ||
| 54 | } | ||
| 55 | 52 | ||
| 56 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | 53 | pci_read_config_byte(fw_dev, 0xB7, &disable); |
| 57 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | 54 | if (disable & 0x02) { |
| 58 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | 55 | printk(KERN_INFO DRIVER_NAME |
| 59 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | 56 | ": Controller already disabled. " \ |
| 57 | "Nothing to do.\n"); | ||
| 58 | return -ENODEV; | ||
| 59 | } | ||
| 60 | |||
| 61 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); | ||
| 62 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); | ||
| 63 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 64 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 65 | pci_write_config_byte(fw_dev, 0xB7, disable | 0x02); | ||
| 66 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 67 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 68 | } else { | ||
| 69 | /* via R5C832 */ | ||
| 70 | |||
| 71 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 72 | if (disable & 0x02) { | ||
| 73 | printk(KERN_INFO DRIVER_NAME | ||
| 74 | ": Controller already disabled. " \ | ||
| 75 | "Nothing to do.\n"); | ||
| 76 | return -ENODEV; | ||
| 77 | } | ||
| 78 | |||
| 79 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 80 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 81 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
| 82 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 83 | } | ||
| 60 | 84 | ||
| 61 | printk(KERN_INFO DRIVER_NAME | 85 | printk(KERN_INFO DRIVER_NAME |
| 62 | ": Controller is now disabled.\n"); | 86 | ": Controller is now disabled.\n"); |
| @@ -67,13 +91,29 @@ static int ricoh_mmc_disable(struct pci_dev *fw_dev) | |||
| 67 | static int ricoh_mmc_enable(struct pci_dev *fw_dev) | 91 | static int ricoh_mmc_enable(struct pci_dev *fw_dev) |
| 68 | { | 92 | { |
| 69 | u8 write_enable; | 93 | u8 write_enable; |
| 94 | u8 write_target; | ||
| 70 | u8 disable; | 95 | u8 disable; |
| 71 | 96 | ||
| 72 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | 97 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { |
| 73 | pci_read_config_byte(fw_dev, 0xCB, &disable); | 98 | /* via RL5C476 */ |
| 74 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | 99 | |
| 75 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | 100 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); |
| 76 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | 101 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); |
| 102 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 103 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 104 | pci_read_config_byte(fw_dev, 0xB7, &disable); | ||
| 105 | pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02); | ||
| 106 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 107 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 108 | } else { | ||
| 109 | /* via R5C832 */ | ||
| 110 | |||
| 111 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 112 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 113 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 114 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
| 115 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 116 | } | ||
| 77 | 117 | ||
| 78 | printk(KERN_INFO DRIVER_NAME | 118 | printk(KERN_INFO DRIVER_NAME |
| 79 | ": Controller is now re-enabled.\n"); | 119 | ": Controller is now re-enabled.\n"); |
| @@ -85,6 +125,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
| 85 | const struct pci_device_id *ent) | 125 | const struct pci_device_id *ent) |
| 86 | { | 126 | { |
| 87 | u8 rev; | 127 | u8 rev; |
| 128 | u8 ctrlfound = 0; | ||
| 88 | 129 | ||
| 89 | struct pci_dev *fw_dev = NULL; | 130 | struct pci_dev *fw_dev = NULL; |
| 90 | 131 | ||
| @@ -98,20 +139,38 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
| 98 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, | 139 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, |
| 99 | (int)rev); | 140 | (int)rev); |
| 100 | 141 | ||
| 101 | while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | 142 | while ((fw_dev = |
| 143 | pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 144 | PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) { | ||
| 102 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | 145 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && |
| 103 | pdev->bus == fw_dev->bus) { | 146 | pdev->bus == fw_dev->bus) { |
| 104 | if (ricoh_mmc_disable(fw_dev) != 0) { | 147 | if (ricoh_mmc_disable(fw_dev) != 0) |
| 105 | return -ENODEV; | 148 | return -ENODEV; |
| 106 | } | ||
| 107 | 149 | ||
| 108 | pci_set_drvdata(pdev, fw_dev); | 150 | pci_set_drvdata(pdev, fw_dev); |
| 109 | 151 | ||
| 152 | ++ctrlfound; | ||
| 110 | break; | 153 | break; |
| 111 | } | 154 | } |
| 112 | } | 155 | } |
| 113 | 156 | ||
| 114 | if (pci_get_drvdata(pdev) == NULL) { | 157 | fw_dev = NULL; |
| 158 | |||
| 159 | while (!ctrlfound && | ||
| 160 | (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 161 | PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | ||
| 162 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | ||
| 163 | pdev->bus == fw_dev->bus) { | ||
| 164 | if (ricoh_mmc_disable(fw_dev) != 0) | ||
| 165 | return -ENODEV; | ||
| 166 | |||
| 167 | pci_set_drvdata(pdev, fw_dev); | ||
| 168 | |||
| 169 | ++ctrlfound; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | if (!ctrlfound) { | ||
| 115 | printk(KERN_WARNING DRIVER_NAME | 174 | printk(KERN_WARNING DRIVER_NAME |
| 116 | ": Main firewire function not found. Cannot disable controller.\n"); | 175 | ": Main firewire function not found. Cannot disable controller.\n"); |
| 117 | return -ENODEV; | 176 | return -ENODEV; |
| @@ -132,7 +191,7 @@ static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) | |||
| 132 | pci_set_drvdata(pdev, NULL); | 191 | pci_set_drvdata(pdev, NULL); |
| 133 | } | 192 | } |
| 134 | 193 | ||
| 135 | static int ricoh_mmc_suspend (struct pci_dev *pdev, pm_message_t state) | 194 | static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) |
| 136 | { | 195 | { |
| 137 | struct pci_dev *fw_dev = NULL; | 196 | struct pci_dev *fw_dev = NULL; |
| 138 | 197 | ||
| @@ -146,7 +205,7 @@ static int ricoh_mmc_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 146 | return 0; | 205 | return 0; |
| 147 | } | 206 | } |
| 148 | 207 | ||
| 149 | static int ricoh_mmc_resume (struct pci_dev *pdev) | 208 | static int ricoh_mmc_resume(struct pci_dev *pdev) |
| 150 | { | 209 | { |
| 151 | struct pci_dev *fw_dev = NULL; | 210 | struct pci_dev *fw_dev = NULL; |
| 152 | 211 | ||
