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) |
