Lines Matching +full:ep9312 +full:- +full:pata

1 // SPDX-License-Identifier: GPL-2.0-only
3 * EP93XX PATA controller driver.
9 * PATA driver by Lennert Buytenhek and Alessandro Zummo.
12 * DMA engine support based on spi-ep93xx.c by Mika Westerberg.
16 * Support for Cirrus Logic's EP93xx (EP9312, EP9315) CPUs
17 * PATA host controller driver.
21 * Heavily based on the ep93xx-ide.c driver:
26 * EP93XX PATA controller driver.
29 * An ATA driver for the Cirrus Logic EP93xx PATA controller.
51 #define DRV_NAME "ep93xx-ide"
199 * Based on delay loop found in mach-pxa/mp900.c.
222 * tA = 35ns after activation of DIOR-/DIOW-. Maximum IORDY pulse in ep93xx_pata_wait_for_iordy()
226 * DIOR-/DIOW-, so we set timeout to (1250 + 35) / 25 - t2 additional in ep93xx_pata_wait_for_iordy()
229 unsigned long start = (1250 + 35) / 25 - t2; in ep93xx_pata_wait_for_iordy()
232 while (!ep93xx_pata_check_iordy(base) && counter--) in ep93xx_pata_wait_for_iordy()
234 return start - counter; in ep93xx_pata_wait_for_iordy()
255 if (t0 > t2 && t0 - t2 > t2i) in ep93xx_pata_rw_end()
256 ep93xx_pata_delay(t0 - t2); in ep93xx_pata_rw_end()
265 void __iomem *base = drv_data->ide_base; in ep93xx_pata_read()
266 const struct ata_timing *t = &drv_data->t; in ep93xx_pata_read()
267 unsigned long t0 = reg ? t->cyc8b : t->cycle; in ep93xx_pata_read()
268 unsigned long t2 = reg ? t->act8b : t->active; in ep93xx_pata_read()
269 unsigned long t2i = reg ? t->rec8b : t->recover; in ep93xx_pata_read()
271 ep93xx_pata_rw_begin(base, addr, t->setup); in ep93xx_pata_read()
275 * edge of the DIORN signal. (EP93xx UG p27-14) in ep93xx_pata_read()
277 ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i); in ep93xx_pata_read()
299 void __iomem *base = drv_data->ide_base; in ep93xx_pata_write()
300 const struct ata_timing *t = &drv_data->t; in ep93xx_pata_write()
301 unsigned long t0 = reg ? t->cyc8b : t->cycle; in ep93xx_pata_write()
302 unsigned long t2 = reg ? t->act8b : t->active; in ep93xx_pata_write()
303 unsigned long t2i = reg ? t->rec8b : t->recover; in ep93xx_pata_write()
305 ep93xx_pata_rw_begin(base, addr, t->setup); in ep93xx_pata_write()
308 * DIOWN is low. (EP93xx UG p27-13) in ep93xx_pata_write()
312 ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i); in ep93xx_pata_write()
332 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_set_piomode()
343 ata_timing_compute(adev, adev->pio_mode, &drv_data->t, T, 0); in ep93xx_pata_set_piomode()
344 if (pair && pair->pio_mode) { in ep93xx_pata_set_piomode()
346 ata_timing_compute(pair, pair->pio_mode, &t, T, 0); in ep93xx_pata_set_piomode()
347 ata_timing_merge(&t, &drv_data->t, &drv_data->t, in ep93xx_pata_set_piomode()
350 drv_data->iordy = ata_pio_need_iordy(adev); in ep93xx_pata_set_piomode()
352 ep93xx_pata_enable_pio(drv_data->ide_base, in ep93xx_pata_set_piomode()
353 adev->pio_mode - XFER_PIO_0); in ep93xx_pata_set_piomode()
359 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_check_status()
366 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_check_altstatus()
375 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_tf_load()
376 unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; in ep93xx_pata_tf_load()
378 if (tf->ctl != ap->last_ctl) { in ep93xx_pata_tf_load()
379 ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL); in ep93xx_pata_tf_load()
380 ap->last_ctl = tf->ctl; in ep93xx_pata_tf_load()
384 if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { in ep93xx_pata_tf_load()
385 ep93xx_pata_write_reg(drv_data, tf->hob_feature, in ep93xx_pata_tf_load()
387 ep93xx_pata_write_reg(drv_data, tf->hob_nsect, in ep93xx_pata_tf_load()
389 ep93xx_pata_write_reg(drv_data, tf->hob_lbal, in ep93xx_pata_tf_load()
391 ep93xx_pata_write_reg(drv_data, tf->hob_lbam, in ep93xx_pata_tf_load()
393 ep93xx_pata_write_reg(drv_data, tf->hob_lbah, in ep93xx_pata_tf_load()
398 ep93xx_pata_write_reg(drv_data, tf->feature, in ep93xx_pata_tf_load()
400 ep93xx_pata_write_reg(drv_data, tf->nsect, IDECTRL_ADDR_NSECT); in ep93xx_pata_tf_load()
401 ep93xx_pata_write_reg(drv_data, tf->lbal, IDECTRL_ADDR_LBAL); in ep93xx_pata_tf_load()
402 ep93xx_pata_write_reg(drv_data, tf->lbam, IDECTRL_ADDR_LBAM); in ep93xx_pata_tf_load()
403 ep93xx_pata_write_reg(drv_data, tf->lbah, IDECTRL_ADDR_LBAH); in ep93xx_pata_tf_load()
406 if (tf->flags & ATA_TFLAG_DEVICE) in ep93xx_pata_tf_load()
407 ep93xx_pata_write_reg(drv_data, tf->device, in ep93xx_pata_tf_load()
416 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_tf_read()
418 tf->status = ep93xx_pata_check_status(ap); in ep93xx_pata_tf_read()
419 tf->error = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_FEATURE); in ep93xx_pata_tf_read()
420 tf->nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT); in ep93xx_pata_tf_read()
421 tf->lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL); in ep93xx_pata_tf_read()
422 tf->lbam = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAM); in ep93xx_pata_tf_read()
423 tf->lbah = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAH); in ep93xx_pata_tf_read()
424 tf->device = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_DEVICE); in ep93xx_pata_tf_read()
426 if (tf->flags & ATA_TFLAG_LBA48) { in ep93xx_pata_tf_read()
427 ep93xx_pata_write_reg(drv_data, tf->ctl | ATA_HOB, in ep93xx_pata_tf_read()
429 tf->hob_feature = ep93xx_pata_read_reg(drv_data, in ep93xx_pata_tf_read()
431 tf->hob_nsect = ep93xx_pata_read_reg(drv_data, in ep93xx_pata_tf_read()
433 tf->hob_lbal = ep93xx_pata_read_reg(drv_data, in ep93xx_pata_tf_read()
435 tf->hob_lbam = ep93xx_pata_read_reg(drv_data, in ep93xx_pata_tf_read()
437 tf->hob_lbah = ep93xx_pata_read_reg(drv_data, in ep93xx_pata_tf_read()
439 ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL); in ep93xx_pata_tf_read()
440 ap->last_ctl = tf->ctl; in ep93xx_pata_tf_read()
448 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_exec_command()
450 ep93xx_pata_write_reg(drv_data, tf->command, in ep93xx_pata_exec_command()
458 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_dev_select()
471 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_set_devctl()
481 struct ata_port *ap = qc->dev->link->ap; in ep93xx_pata_data_xfer()
482 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_data_xfer()
487 while (words--) in ep93xx_pata_data_xfer()
500 buf += buflen - 1; in ep93xx_pata_data_xfer()
522 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_device_is_present()
525 ap->ops->sff_dev_select(ap, device); in ep93xx_pata_device_is_present()
550 struct ata_port *ap = link->ap; in ep93xx_pata_wait_after_reset()
551 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_wait_after_reset()
561 * -ENODEV means the odd clown forgot the D7 pulldown resistor in ep93xx_pata_wait_after_reset()
574 ap->ops->sff_dev_select(ap, 1); in ep93xx_pata_wait_after_reset()
595 if (rc != -ENODEV) in ep93xx_pata_wait_after_reset()
601 ap->ops->sff_dev_select(ap, 0); in ep93xx_pata_wait_after_reset()
603 ap->ops->sff_dev_select(ap, 1); in ep93xx_pata_wait_after_reset()
605 ap->ops->sff_dev_select(ap, 0); in ep93xx_pata_wait_after_reset()
614 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_bus_softreset()
616 ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL); in ep93xx_pata_bus_softreset()
618 ep93xx_pata_write_reg(drv_data, ap->ctl | ATA_SRST, IDECTRL_ADDR_CTL); in ep93xx_pata_bus_softreset()
620 ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL); in ep93xx_pata_bus_softreset()
621 ap->last_ctl = ap->ctl; in ep93xx_pata_bus_softreset()
623 return ep93xx_pata_wait_after_reset(&ap->link, devmask, deadline); in ep93xx_pata_bus_softreset()
628 if (drv_data->dma_rx_channel) { in ep93xx_pata_release_dma()
629 dma_release_channel(drv_data->dma_rx_channel); in ep93xx_pata_release_dma()
630 drv_data->dma_rx_channel = NULL; in ep93xx_pata_release_dma()
632 if (drv_data->dma_tx_channel) { in ep93xx_pata_release_dma()
633 dma_release_channel(drv_data->dma_tx_channel); in ep93xx_pata_release_dma()
634 drv_data->dma_tx_channel = NULL; in ep93xx_pata_release_dma()
640 struct platform_device *pdev = drv_data->pdev; in ep93xx_pata_dma_init()
641 struct device *dev = &pdev->dev; in ep93xx_pata_dma_init()
654 drv_data->dma_rx_channel = dma_request_chan(dev, "rx"); in ep93xx_pata_dma_init()
655 if (IS_ERR(drv_data->dma_rx_channel)) in ep93xx_pata_dma_init()
656 return dev_err_probe(dev, PTR_ERR(drv_data->dma_rx_channel), in ep93xx_pata_dma_init()
659 drv_data->dma_tx_channel = dma_request_chan(&pdev->dev, "tx"); in ep93xx_pata_dma_init()
660 if (IS_ERR(drv_data->dma_tx_channel)) { in ep93xx_pata_dma_init()
661 ret = dev_err_probe(dev, PTR_ERR(drv_data->dma_tx_channel), in ep93xx_pata_dma_init()
669 conf.src_addr = drv_data->udma_in_phys; in ep93xx_pata_dma_init()
671 ret = dmaengine_slave_config(drv_data->dma_rx_channel, &conf); in ep93xx_pata_dma_init()
680 conf.dst_addr = drv_data->udma_out_phys; in ep93xx_pata_dma_init()
682 ret = dmaengine_slave_config(drv_data->dma_tx_channel, &conf); in ep93xx_pata_dma_init()
691 dma_release_channel(drv_data->dma_rx_channel); in ep93xx_pata_dma_init()
701 struct ep93xx_pata_data *drv_data = qc->ap->host->private_data; in ep93xx_pata_dma_start()
702 void __iomem *base = drv_data->ide_base; in ep93xx_pata_dma_start()
703 struct ata_device *adev = qc->dev; in ep93xx_pata_dma_start()
704 u32 v = qc->dma_dir == DMA_TO_DEVICE ? IDEUDMAOP_RWOP : 0; in ep93xx_pata_dma_start()
705 struct dma_chan *channel = qc->dma_dir == DMA_TO_DEVICE in ep93xx_pata_dma_start()
706 ? drv_data->dma_tx_channel : drv_data->dma_rx_channel; in ep93xx_pata_dma_start()
708 txd = dmaengine_prep_slave_sg(channel, qc->sg, qc->n_elem, qc->dma_dir, in ep93xx_pata_dma_start()
711 dev_err(qc->ap->dev, "failed to prepare slave for sg dma\n"); in ep93xx_pata_dma_start()
714 txd->callback = NULL; in ep93xx_pata_dma_start()
715 txd->callback_param = NULL; in ep93xx_pata_dma_start()
718 dev_err(qc->ap->dev, "failed to submit dma transfer\n"); in ep93xx_pata_dma_start()
735 ((adev->xfer_mode - XFER_UDMA_0) << IDECFG_MODE_SHIFT), in ep93xx_pata_dma_start()
741 struct ep93xx_pata_data *drv_data = qc->ap->host->private_data; in ep93xx_pata_dma_stop()
742 void __iomem *base = drv_data->ide_base; in ep93xx_pata_dma_stop()
745 dmaengine_terminate_all(drv_data->dma_rx_channel); in ep93xx_pata_dma_stop()
746 dmaengine_terminate_all(drv_data->dma_tx_channel); in ep93xx_pata_dma_stop()
749 * To properly stop IDE-DMA, IDEUDMAOP register must to be cleared in ep93xx_pata_dma_stop()
756 ep93xx_pata_enable_pio(drv_data->ide_base, in ep93xx_pata_dma_stop()
757 qc->dev->pio_mode - XFER_PIO_0); in ep93xx_pata_dma_stop()
759 ata_sff_dma_pause(qc->ap); in ep93xx_pata_dma_stop()
764 qc->ap->ops->sff_exec_command(qc->ap, &qc->tf); in ep93xx_pata_dma_setup()
769 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_dma_status()
770 u32 val = readl(drv_data->ide_base + IDEUDMASTS); in ep93xx_pata_dma_status()
775 * DMAIDE - DMA request signal from UDMA state machine, in ep93xx_pata_dma_status()
776 * INTIDE - INT line generated by UDMA because of errors in the in ep93xx_pata_dma_status()
778 * SBUSY - UDMA state machine busy, not in idle state, in ep93xx_pata_dma_status()
779 * NDO - error for data-out not completed, in ep93xx_pata_dma_status()
780 * NDI - error for data-in not completed, in ep93xx_pata_dma_status()
781 * N4X - error for data transferred not multiplies of four in ep93xx_pata_dma_status()
782 * 32-bit words. in ep93xx_pata_dma_status()
783 * (EP93xx UG p27-17) in ep93xx_pata_dma_status()
790 if (readl(drv_data->ide_base + IDECTRL) & IDECTRL_INTRQ) in ep93xx_pata_dma_status()
803 struct ata_port *ap = al->ap; in ep93xx_pata_softreset()
804 unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; in ep93xx_pata_softreset()
816 ap->ops->sff_dev_select(al->ap, 0); in ep93xx_pata_softreset()
820 /* if link is ocuppied, -ENODEV too is an error */ in ep93xx_pata_softreset()
821 if (rc && (rc != -ENODEV || sata_scr_valid(al))) { in ep93xx_pata_softreset()
827 classes[0] = ata_sff_dev_classify(&al->device[0], devmask & (1 << 0), in ep93xx_pata_softreset()
830 classes[1] = ata_sff_dev_classify(&al->device[1], in ep93xx_pata_softreset()
844 if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) in ep93xx_pata_drain_fifo()
847 ap = qc->ap; in ep93xx_pata_drain_fifo()
848 drv_data = ap->host->private_data; in ep93xx_pata_drain_fifo()
850 for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) in ep93xx_pata_drain_fifo()
861 struct ep93xx_pata_data *drv_data = ap->host->private_data; in ep93xx_pata_port_start()
867 drv_data->t = *ata_timing_find_mode(XFER_PIO_0); in ep93xx_pata_port_start()
932 drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL); in ep93xx_pata_probe()
934 return -ENOMEM; in ep93xx_pata_probe()
936 drv_data->pdev = pdev; in ep93xx_pata_probe()
937 drv_data->ide_base = ide_base; in ep93xx_pata_probe()
938 drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN; in ep93xx_pata_probe()
939 drv_data->udma_out_phys = mem_res->start + IDEUDMADATAOUT; in ep93xx_pata_probe()
945 host = ata_host_alloc(&pdev->dev, 1); in ep93xx_pata_probe()
947 err = -ENOMEM; in ep93xx_pata_probe()
953 host->private_data = drv_data; in ep93xx_pata_probe()
955 ap = host->ports[0]; in ep93xx_pata_probe()
956 ap->dev = &pdev->dev; in ep93xx_pata_probe()
957 ap->ops = &ep93xx_pata_port_ops; in ep93xx_pata_probe()
958 ap->flags |= ATA_FLAG_SLAVE_POSS; in ep93xx_pata_probe()
959 ap->pio_mask = ATA_PIO4; in ep93xx_pata_probe()
963 * EP931x rev.E0 - UDMA2 in ep93xx_pata_probe()
964 * EP931x rev.E1 - UDMA3 in ep93xx_pata_probe()
965 * EP931x rev.E2 - UDMA4 in ep93xx_pata_probe()
970 if (drv_data->dma_rx_channel && drv_data->dma_tx_channel) { in ep93xx_pata_probe()
975 ap->udma_mask = (unsigned int) match->data; in ep93xx_pata_probe()
977 ap->udma_mask = ATA_UDMA2; in ep93xx_pata_probe()
983 dev_info(&pdev->dev, "version " DRV_VERSION "\n"); in ep93xx_pata_probe()
999 struct ep93xx_pata_data *drv_data = host->private_data; in ep93xx_pata_remove()
1003 ep93xx_pata_clear_regs(drv_data->ide_base); in ep93xx_pata_remove()
1007 { .compatible = "cirrus,ep9312-pata" },
1025 MODULE_DESCRIPTION("low-level driver for cirrus ep93xx IDE controller");