diff options
author | Frank Seidel <fseidel@suse.de> | 2008-02-04 13:25:42 -0500 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-02-08 03:02:47 -0500 |
commit | 882c49164d72c45f37d7fa1bb3de7c31cf1a5fab (patch) | |
tree | 2db5b00ad700c31999fc5e3eecd5d8a28b84fad4 | |
parent | 6e996ee8e730a50eef51cdb072b166fe8f80831e (diff) |
mmc: extend ricoh_mmc to support Ricoh RL5c476
This 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.
Signed-off-by: Frank Seidel <fseidel@suse.de>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-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 | ||