diff options
Diffstat (limited to 'drivers/ide/tx4938ide.c')
-rw-r--r-- | drivers/ide/tx4938ide.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index fa660f931a11..9120063e8f87 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -26,12 +26,13 @@ static void tx4938ide_tune_ebusc(unsigned int ebus_ch, | |||
26 | unsigned int sp = (cr >> 4) & 3; | 26 | unsigned int sp = (cr >> 4) & 3; |
27 | unsigned int clock = gbus_clock / (4 - sp); | 27 | unsigned int clock = gbus_clock / (4 - sp); |
28 | unsigned int cycle = 1000000000 / clock; | 28 | unsigned int cycle = 1000000000 / clock; |
29 | unsigned int wt, shwt; | 29 | unsigned int shwt; |
30 | int wt; | ||
30 | 31 | ||
31 | /* Minimum DIOx- active time */ | 32 | /* Minimum DIOx- active time */ |
32 | wt = DIV_ROUND_UP(t->act8b, cycle) - 2; | 33 | wt = DIV_ROUND_UP(t->act8b, cycle) - 2; |
33 | /* IORDY setup time: 35ns */ | 34 | /* IORDY setup time: 35ns */ |
34 | wt = max(wt, DIV_ROUND_UP(35, cycle)); | 35 | wt = max_t(int, wt, DIV_ROUND_UP(35, cycle)); |
35 | /* actual wait-cycle is max(wt & ~1, 1) */ | 36 | /* actual wait-cycle is max(wt & ~1, 1) */ |
36 | if (wt > 2 && (wt & 1)) | 37 | if (wt > 2 && (wt & 1)) |
37 | wt++; | 38 | wt++; |
@@ -39,10 +40,17 @@ static void tx4938ide_tune_ebusc(unsigned int ebus_ch, | |||
39 | /* Address-valid to DIOR/DIOW setup */ | 40 | /* Address-valid to DIOR/DIOW setup */ |
40 | shwt = DIV_ROUND_UP(t->setup, cycle); | 41 | shwt = DIV_ROUND_UP(t->setup, cycle); |
41 | 42 | ||
43 | /* -DIOx recovery time (SHWT * 4) and cycle time requirement */ | ||
44 | while ((shwt * 4 + wt + (wt ? 2 : 3)) * cycle < t->cycle) | ||
45 | shwt++; | ||
46 | if (shwt > 7) { | ||
47 | pr_warning("tx4938ide: SHWT violation (%d)\n", shwt); | ||
48 | shwt = 7; | ||
49 | } | ||
42 | pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d\n", | 50 | pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d\n", |
43 | ebus_ch, cycle, wt, shwt); | 51 | ebus_ch, cycle, wt, shwt); |
44 | 52 | ||
45 | __raw_writeq((cr & ~(0x3f007ull)) | (wt << 12) | shwt, | 53 | __raw_writeq((cr & ~0x3f007ull) | (wt << 12) | shwt, |
46 | &tx4938_ebuscptr->cr[ebus_ch]); | 54 | &tx4938_ebuscptr->cr[ebus_ch]); |
47 | } | 55 | } |
48 | 56 | ||
@@ -228,7 +236,7 @@ static int __init tx4938ide_probe(struct platform_device *pdev) | |||
228 | struct resource *res; | 236 | struct resource *res; |
229 | struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; | 237 | struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; |
230 | int irq, ret, i; | 238 | int irq, ret, i; |
231 | unsigned long mapbase; | 239 | unsigned long mapbase, mapctl; |
232 | struct ide_port_info d = tx4938ide_port_info; | 240 | struct ide_port_info d = tx4938ide_port_info; |
233 | 241 | ||
234 | irq = platform_get_irq(pdev, 0); | 242 | irq = platform_get_irq(pdev, 0); |
@@ -242,38 +250,43 @@ static int __init tx4938ide_probe(struct platform_device *pdev) | |||
242 | res->end - res->start + 1, "tx4938ide")) | 250 | res->end - res->start + 1, "tx4938ide")) |
243 | return -EBUSY; | 251 | return -EBUSY; |
244 | mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, | 252 | mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, |
245 | res->end - res->start + 1); | 253 | 8 << pdata->ioport_shift); |
246 | if (!mapbase) | 254 | mapctl = (unsigned long)devm_ioremap(&pdev->dev, |
255 | res->start + 0x10000 + | ||
256 | (6 << pdata->ioport_shift), | ||
257 | 1 << pdata->ioport_shift); | ||
258 | if (!mapbase || !mapctl) | ||
247 | return -EBUSY; | 259 | return -EBUSY; |
248 | 260 | ||
249 | memset(&hw, 0, sizeof(hw)); | 261 | memset(&hw, 0, sizeof(hw)); |
250 | if (pdata->ioport_shift) { | 262 | if (pdata->ioport_shift) { |
251 | unsigned long port = mapbase; | 263 | unsigned long port = mapbase; |
264 | unsigned long ctl = mapctl; | ||
252 | 265 | ||
253 | hw.io_ports_array[0] = port; | 266 | hw.io_ports_array[0] = port; |
254 | #ifdef __BIG_ENDIAN | 267 | #ifdef __BIG_ENDIAN |
255 | port++; | 268 | port++; |
269 | ctl++; | ||
256 | #endif | 270 | #endif |
257 | for (i = 1; i <= 7; i++) | 271 | for (i = 1; i <= 7; i++) |
258 | hw.io_ports_array[i] = | 272 | hw.io_ports_array[i] = |
259 | port + (i << pdata->ioport_shift); | 273 | port + (i << pdata->ioport_shift); |
260 | hw.io_ports.ctl_addr = | 274 | hw.io_ports.ctl_addr = ctl; |
261 | port + 0x10000 + (6 << pdata->ioport_shift); | ||
262 | } else | 275 | } else |
263 | ide_std_init_ports(&hw, mapbase, mapbase + 0x10006); | 276 | ide_std_init_ports(&hw, mapbase, mapctl); |
264 | hw.irq = irq; | 277 | hw.irq = irq; |
265 | hw.dev = &pdev->dev; | 278 | hw.dev = &pdev->dev; |
266 | 279 | ||
267 | pr_info("TX4938 IDE interface (base %#lx, irq %d)\n", mapbase, hw.irq); | 280 | pr_info("TX4938 IDE interface (base %#lx, ctl %#lx, irq %d)\n", |
281 | mapbase, mapctl, hw.irq); | ||
268 | if (pdata->gbus_clock) | 282 | if (pdata->gbus_clock) |
269 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); | 283 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); |
270 | else | 284 | else |
271 | d.port_ops = NULL; | 285 | d.port_ops = NULL; |
272 | ret = ide_host_add(&d, hws, &host); | 286 | ret = ide_host_add(&d, hws, &host); |
273 | if (ret) | 287 | if (!ret) |
274 | return ret; | 288 | platform_set_drvdata(pdev, host); |
275 | platform_set_drvdata(pdev, host); | 289 | return ret; |
276 | return 0; | ||
277 | } | 290 | } |
278 | 291 | ||
279 | static int __exit tx4938ide_remove(struct platform_device *pdev) | 292 | static int __exit tx4938ide_remove(struct platform_device *pdev) |