diff options
Diffstat (limited to 'drivers/mmc/host/ricoh_mmc.c')
-rw-r--r-- | drivers/mmc/host/ricoh_mmc.c | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c index 1e8704533bc5..898e7991caef 100644 --- a/drivers/mmc/host/ricoh_mmc.c +++ b/drivers/mmc/host/ricoh_mmc.c | |||
@@ -41,6 +41,46 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
41 | 41 | ||
42 | MODULE_DEVICE_TABLE(pci, pci_ids); | 42 | MODULE_DEVICE_TABLE(pci, pci_ids); |
43 | 43 | ||
44 | static int ricoh_mmc_disable(struct pci_dev *fw_dev) | ||
45 | { | ||
46 | u8 write_enable; | ||
47 | u8 disable; | ||
48 | |||
49 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
50 | if (disable & 0x02) { | ||
51 | printk(KERN_INFO DRIVER_NAME | ||
52 | ": Controller already disabled. Nothing to do.\n"); | ||
53 | return -ENODEV; | ||
54 | } | ||
55 | |||
56 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
57 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
58 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
59 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
60 | |||
61 | printk(KERN_INFO DRIVER_NAME | ||
62 | ": Controller is now disabled.\n"); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int ricoh_mmc_enable(struct pci_dev *fw_dev) | ||
68 | { | ||
69 | u8 write_enable; | ||
70 | u8 disable; | ||
71 | |||
72 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
73 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
74 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
75 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
76 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
77 | |||
78 | printk(KERN_INFO DRIVER_NAME | ||
79 | ": Controller is now re-enabled.\n"); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
44 | static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | 84 | static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, |
45 | const struct pci_device_id *ent) | 85 | const struct pci_device_id *ent) |
46 | { | 86 | { |
@@ -61,26 +101,12 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
61 | while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | 101 | while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { |
62 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | 102 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && |
63 | pdev->bus == fw_dev->bus) { | 103 | pdev->bus == fw_dev->bus) { |
64 | u8 write_enable; | 104 | if (ricoh_mmc_disable(fw_dev) != 0) { |
65 | u8 disable; | ||
66 | |||
67 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
68 | if (disable & 0x02) { | ||
69 | printk(KERN_INFO DRIVER_NAME | ||
70 | ": Controller already disabled. Nothing to do.\n"); | ||
71 | return -ENODEV; | 105 | return -ENODEV; |
72 | } | 106 | } |
73 | 107 | ||
74 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
75 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
76 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
77 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
78 | |||
79 | pci_set_drvdata(pdev, fw_dev); | 108 | pci_set_drvdata(pdev, fw_dev); |
80 | 109 | ||
81 | printk(KERN_INFO DRIVER_NAME | ||
82 | ": Controller is now disabled.\n"); | ||
83 | |||
84 | break; | 110 | break; |
85 | } | 111 | } |
86 | } | 112 | } |
@@ -96,30 +122,51 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
96 | 122 | ||
97 | static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) | 123 | static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) |
98 | { | 124 | { |
99 | u8 write_enable; | ||
100 | u8 disable; | ||
101 | struct pci_dev *fw_dev = NULL; | 125 | struct pci_dev *fw_dev = NULL; |
102 | 126 | ||
103 | fw_dev = pci_get_drvdata(pdev); | 127 | fw_dev = pci_get_drvdata(pdev); |
104 | BUG_ON(fw_dev == NULL); | 128 | BUG_ON(fw_dev == NULL); |
105 | 129 | ||
106 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | 130 | ricoh_mmc_enable(fw_dev); |
107 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
108 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
109 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
110 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
111 | |||
112 | printk(KERN_INFO DRIVER_NAME | ||
113 | ": Controller is now re-enabled.\n"); | ||
114 | 131 | ||
115 | pci_set_drvdata(pdev, NULL); | 132 | pci_set_drvdata(pdev, NULL); |
116 | } | 133 | } |
117 | 134 | ||
135 | static int ricoh_mmc_suspend (struct pci_dev *pdev, pm_message_t state) | ||
136 | { | ||
137 | struct pci_dev *fw_dev = NULL; | ||
138 | |||
139 | fw_dev = pci_get_drvdata(pdev); | ||
140 | BUG_ON(fw_dev == NULL); | ||
141 | |||
142 | printk(KERN_INFO DRIVER_NAME ": Suspending.\n"); | ||
143 | |||
144 | ricoh_mmc_enable(fw_dev); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int ricoh_mmc_resume (struct pci_dev *pdev) | ||
150 | { | ||
151 | struct pci_dev *fw_dev = NULL; | ||
152 | |||
153 | fw_dev = pci_get_drvdata(pdev); | ||
154 | BUG_ON(fw_dev == NULL); | ||
155 | |||
156 | printk(KERN_INFO DRIVER_NAME ": Resuming.\n"); | ||
157 | |||
158 | ricoh_mmc_disable(fw_dev); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
118 | static struct pci_driver ricoh_mmc_driver = { | 163 | static struct pci_driver ricoh_mmc_driver = { |
119 | .name = DRIVER_NAME, | 164 | .name = DRIVER_NAME, |
120 | .id_table = pci_ids, | 165 | .id_table = pci_ids, |
121 | .probe = ricoh_mmc_probe, | 166 | .probe = ricoh_mmc_probe, |
122 | .remove = __devexit_p(ricoh_mmc_remove), | 167 | .remove = __devexit_p(ricoh_mmc_remove), |
168 | .suspend = ricoh_mmc_suspend, | ||
169 | .resume = ricoh_mmc_resume, | ||
123 | }; | 170 | }; |
124 | 171 | ||
125 | /*****************************************************************************\ | 172 | /*****************************************************************************\ |