diff options
Diffstat (limited to 'drivers/ide/pci/sc1200.c')
-rw-r--r-- | drivers/ide/pci/sc1200.c | 172 |
1 files changed, 55 insertions, 117 deletions
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 707d5ff66b03..fef20bd4aa78 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c | |||
@@ -135,59 +135,29 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) | |||
135 | unsigned short pci_clock; | 135 | unsigned short pci_clock; |
136 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; | 136 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; |
137 | 137 | ||
138 | static const u32 udma_timing[3][3] = { | ||
139 | { 0x00921250, 0x00911140, 0x00911030 }, | ||
140 | { 0x00932470, 0x00922260, 0x00922140 }, | ||
141 | { 0x009436a1, 0x00933481, 0x00923261 }, | ||
142 | }; | ||
143 | |||
144 | static const u32 mwdma_timing[3][3] = { | ||
145 | { 0x00077771, 0x00012121, 0x00002020 }, | ||
146 | { 0x000bbbb2, 0x00024241, 0x00013131 }, | ||
147 | { 0x000ffff3, 0x00035352, 0x00015151 }, | ||
148 | }; | ||
149 | |||
138 | pci_clock = sc1200_get_pci_clock(); | 150 | pci_clock = sc1200_get_pci_clock(); |
139 | 151 | ||
140 | /* | 152 | /* |
141 | * Note that each DMA mode has several timings associated with it. | 153 | * Note that each DMA mode has several timings associated with it. |
142 | * The correct timing depends on the fast PCI clock freq. | 154 | * The correct timing depends on the fast PCI clock freq. |
143 | */ | 155 | */ |
144 | timings = 0; | 156 | |
145 | switch (mode) { | 157 | if (mode >= XFER_UDMA_0) |
146 | case XFER_UDMA_0: | 158 | timings = udma_timing[pci_clock][mode - XFER_UDMA_0]; |
147 | switch (pci_clock) { | 159 | else |
148 | case PCI_CLK_33: timings = 0x00921250; break; | 160 | timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0]; |
149 | case PCI_CLK_48: timings = 0x00932470; break; | ||
150 | case PCI_CLK_66: timings = 0x009436a1; break; | ||
151 | } | ||
152 | break; | ||
153 | case XFER_UDMA_1: | ||
154 | switch (pci_clock) { | ||
155 | case PCI_CLK_33: timings = 0x00911140; break; | ||
156 | case PCI_CLK_48: timings = 0x00922260; break; | ||
157 | case PCI_CLK_66: timings = 0x00933481; break; | ||
158 | } | ||
159 | break; | ||
160 | case XFER_UDMA_2: | ||
161 | switch (pci_clock) { | ||
162 | case PCI_CLK_33: timings = 0x00911030; break; | ||
163 | case PCI_CLK_48: timings = 0x00922140; break; | ||
164 | case PCI_CLK_66: timings = 0x00923261; break; | ||
165 | } | ||
166 | break; | ||
167 | case XFER_MW_DMA_0: | ||
168 | switch (pci_clock) { | ||
169 | case PCI_CLK_33: timings = 0x00077771; break; | ||
170 | case PCI_CLK_48: timings = 0x000bbbb2; break; | ||
171 | case PCI_CLK_66: timings = 0x000ffff3; break; | ||
172 | } | ||
173 | break; | ||
174 | case XFER_MW_DMA_1: | ||
175 | switch (pci_clock) { | ||
176 | case PCI_CLK_33: timings = 0x00012121; break; | ||
177 | case PCI_CLK_48: timings = 0x00024241; break; | ||
178 | case PCI_CLK_66: timings = 0x00035352; break; | ||
179 | } | ||
180 | break; | ||
181 | case XFER_MW_DMA_2: | ||
182 | switch (pci_clock) { | ||
183 | case PCI_CLK_33: timings = 0x00002020; break; | ||
184 | case PCI_CLK_48: timings = 0x00013131; break; | ||
185 | case PCI_CLK_66: timings = 0x00015151; break; | ||
186 | } | ||
187 | break; | ||
188 | default: | ||
189 | return; | ||
190 | } | ||
191 | 161 | ||
192 | if (unit == 0) { /* are we configuring drive0? */ | 162 | if (unit == 0) { /* are we configuring drive0? */ |
193 | pci_read_config_dword(hwif->pci_dev, basereg+4, ®); | 163 | pci_read_config_dword(hwif->pci_dev, basereg+4, ®); |
@@ -260,66 +230,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
260 | } | 230 | } |
261 | 231 | ||
262 | #ifdef CONFIG_PM | 232 | #ifdef CONFIG_PM |
263 | static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) | 233 | struct sc1200_saved_state { |
264 | { | 234 | u32 regs[8]; |
265 | int h; | 235 | }; |
266 | |||
267 | for (h = 0; h < MAX_HWIFS; h++) { | ||
268 | ide_hwif_t *hwif = &ide_hwifs[h]; | ||
269 | if (prev) { | ||
270 | if (hwif == prev) | ||
271 | prev = NULL; // found previous, now look for next match | ||
272 | } else { | ||
273 | if (hwif && hwif->pci_dev == dev) | ||
274 | return hwif; // found next match | ||
275 | } | ||
276 | } | ||
277 | return NULL; // not found | ||
278 | } | ||
279 | |||
280 | typedef struct sc1200_saved_state_s { | ||
281 | __u32 regs[4]; | ||
282 | } sc1200_saved_state_t; | ||
283 | |||
284 | 236 | ||
285 | static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) | 237 | static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) |
286 | { | 238 | { |
287 | ide_hwif_t *hwif = NULL; | ||
288 | |||
289 | printk("SC1200: suspend(%u)\n", state.event); | 239 | printk("SC1200: suspend(%u)\n", state.event); |
290 | 240 | ||
241 | /* | ||
242 | * we only save state when going from full power to less | ||
243 | */ | ||
291 | if (state.event == PM_EVENT_ON) { | 244 | if (state.event == PM_EVENT_ON) { |
292 | // we only save state when going from full power to less | 245 | struct sc1200_saved_state *ss; |
293 | 246 | unsigned int r; | |
294 | // | 247 | |
295 | // Loop over all interfaces that are part of this PCI device: | 248 | /* |
296 | // | 249 | * allocate a permanent save area, if not already allocated |
297 | while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { | 250 | */ |
298 | sc1200_saved_state_t *ss; | 251 | ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); |
299 | unsigned int basereg, r; | 252 | if (ss == NULL) { |
300 | // | 253 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); |
301 | // allocate a permanent save area, if not already allocated | 254 | if (ss == NULL) |
302 | // | 255 | return -ENOMEM; |
303 | ss = (sc1200_saved_state_t *)hwif->config_data; | 256 | pci_set_drvdata(dev, ss); |
304 | if (ss == NULL) { | ||
305 | ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); | ||
306 | if (ss == NULL) | ||
307 | return -ENOMEM; | ||
308 | hwif->config_data = (unsigned long)ss; | ||
309 | } | ||
310 | ss = (sc1200_saved_state_t *)hwif->config_data; | ||
311 | // | ||
312 | // Save timing registers: this may be unnecessary if | ||
313 | // BIOS also does it | ||
314 | // | ||
315 | basereg = hwif->channel ? 0x50 : 0x40; | ||
316 | for (r = 0; r < 4; ++r) { | ||
317 | pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); | ||
318 | } | ||
319 | } | 257 | } |
320 | } | ||
321 | 258 | ||
322 | /* You don't need to iterate over disks -- sysfs should have done that for you already */ | 259 | /* |
260 | * save timing registers | ||
261 | * (this may be unnecessary if BIOS also does it) | ||
262 | */ | ||
263 | for (r = 0; r < 8; r++) | ||
264 | pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); | ||
265 | } | ||
323 | 266 | ||
324 | pci_disable_device(dev); | 267 | pci_disable_device(dev); |
325 | pci_set_power_state(dev, pci_choose_state(dev, state)); | 268 | pci_set_power_state(dev, pci_choose_state(dev, state)); |
@@ -328,30 +271,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state) | |||
328 | 271 | ||
329 | static int sc1200_resume (struct pci_dev *dev) | 272 | static int sc1200_resume (struct pci_dev *dev) |
330 | { | 273 | { |
331 | ide_hwif_t *hwif = NULL; | 274 | struct sc1200_saved_state *ss; |
332 | int i; | 275 | unsigned int r; |
276 | int i; | ||
333 | 277 | ||
334 | i = pci_enable_device(dev); | 278 | i = pci_enable_device(dev); |
335 | if (i) | 279 | if (i) |
336 | return i; | 280 | return i; |
337 | 281 | ||
338 | // | 282 | ss = (struct sc1200_saved_state *)pci_get_drvdata(dev); |
339 | // loop over all interfaces that are part of this pci device: | 283 | |
340 | // | 284 | /* |
341 | while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { | 285 | * restore timing registers |
342 | unsigned int basereg, r; | 286 | * (this may be unnecessary if BIOS also does it) |
343 | sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; | 287 | */ |
344 | 288 | if (ss) { | |
345 | // | 289 | for (r = 0; r < 8; r++) |
346 | // Restore timing registers: this may be unnecessary if BIOS also does it | 290 | pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); |
347 | // | ||
348 | basereg = hwif->channel ? 0x50 : 0x40; | ||
349 | if (ss != NULL) { | ||
350 | for (r = 0; r < 4; ++r) { | ||
351 | pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); | ||
352 | } | ||
353 | } | ||
354 | } | 291 | } |
292 | |||
355 | return 0; | 293 | return 0; |
356 | } | 294 | } |
357 | #endif | 295 | #endif |