[PATCH v2 1/3] PATA host controller driver for ep93xx

H Hartley Sweeten hartleys at visionengravers.com
Tue Apr 3 14:55:17 EDT 2012


On Tuesday, April 03, 2012 7:45 AM, Rafal Prylowski wrote:
<snip>

> +static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
> +{
> +	const struct platform_device *pdev = drv_data->pdev;
> +	dma_cap_mask_t mask;
> +	struct dma_slave_config conf;
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(DMA_SLAVE, mask);
> +
> +	/*
> +	 * Request two channels for IDE. Another possibility would be
> +	 * to request only one channel, and reprogram it's direction at
> +	 * start of new transfer.
> +	 */
> +	drv_data->dma_rx_data.port = EP93XX_DMA_IDE;
> +	drv_data->dma_rx_data.direction = DMA_FROM_DEVICE;
> +	drv_data->dma_rx_data.name = "ep93xx-pata-rx";
> +	drv_data->dma_rx_channel = dma_request_channel(mask,
> +		ep93xx_pata_dma_filter, &drv_data->dma_rx_data);
> +	if (!drv_data->dma_rx_channel)
> +		return;
> +
> +	drv_data->dma_tx_data.port = EP93XX_DMA_IDE;
> +	drv_data->dma_tx_data.direction = DMA_TO_DEVICE;
> +	drv_data->dma_tx_data.name = "ep93xx-pata-tx";
> +	drv_data->dma_tx_channel = dma_request_channel(mask,
> +		ep93xx_pata_dma_filter, &drv_data->dma_tx_data);
> +	if (!drv_data->dma_tx_channel) {
> +		dma_release_channel(drv_data->dma_rx_channel);
> +		return;
> +	}
> +
> +	/* Configure receive channel direction and source address */
> +	memset(&conf, 0, sizeof(conf));
> +	conf.direction = DMA_FROM_DEVICE;
> +	conf.src_addr = drv_data->udma_in_phys;
> +	conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +	if (dmaengine_slave_config(drv_data->dma_rx_channel, &conf)) {
> +		dev_err(&pdev->dev, "failed to configure rx dma channel\n");
> +		ep93xx_pata_release_dma(drv_data);
> +		return;
> +	}
> +
> +	/* Configure transmit channel direction and destination address */
> +	memset(&conf, 0, sizeof(conf));
> +	conf.direction = DMA_TO_DEVICE;
> +	conf.dst_addr = drv_data->udma_out_phys;
> +	conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +	if (dmaengine_slave_config(drv_data->dma_tx_channel, &conf)) {
> +		dev_err(&pdev->dev, "failed to configure tx dma channel\n");
> +		ep93xx_pata_release_dma(drv_data);
> +	}
> +}

If the dma init fails does the driver fall back to pio mode correctly?

<snip>

> +static struct ata_port_operations ep93xx_pata_port_ops = {
> +	.inherits		= &ata_bmdma_port_ops,
> +
> +	.qc_prep		= ata_noop_qc_prep,
> +
> +	.softreset		= ep93xx_pata_softreset,
> +	.hardreset		= ATA_OP_NULL,
> +
> +	.sff_dev_select		= ep93xx_pata_dev_select,
> +	.sff_set_devctl		= ep93xx_pata_set_devctl,
> +	.sff_check_status	= ep93xx_pata_check_status,
> +	.sff_check_altstatus	= ep93xx_pata_check_altstatus,
> +	.sff_tf_load		= ep93xx_pata_tf_load,
> +	.sff_tf_read		= ep93xx_pata_tf_read,
> +	.sff_exec_command	= ep93xx_pata_exec_command,
> +	.sff_data_xfer		= ep93xx_pata_data_xfer,
> +	.sff_drain_fifo		= ep93xx_pata_drain_fifo,
> +	.sff_irq_clear		= ATA_OP_NULL,
> +
> +	.set_piomode		= ep93xx_pata_set_piomode,
> +
> +	.bmdma_setup		= ep93xx_pata_dma_setup,
> +	.bmdma_start		= ep93xx_pata_dma_start,
> +	.bmdma_stop		= ep93xx_pata_dma_stop,
> +	.bmdma_status		= ep93xx_pata_dma_status,

The bmdma ops pointers are still set if the dma init failed. Should they
be set to NULL?

> +
> +	.cable_detect		= ata_cable_unknown,
> +	.port_start		= ep93xx_pata_port_start,
> +};
> +
> +static int __devinit ep93xx_pata_probe(struct platform_device *pdev)
> +{
> +	struct ep93xx_pata_data *drv_data;
> +	struct ata_host *host;
> +	struct ata_port *ap;
> +	unsigned int irq;
> +	struct resource *mem_res;
> +	void __iomem *ide_base;
> +	int err;
> +
> +	err = ep93xx_ide_acquire_gpio(pdev);
> +	if (err)
> +		return err;
> +
> +	/* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {
> +		err = -ENXIO;
> +		goto err_rel_gpio;
> +	}
> +
> +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem_res) {
> +		err = -ENXIO;
> +		goto err_rel_gpio;
> +	}
> +
> +	ide_base = devm_request_and_ioremap(&pdev->dev, mem_res);
> +	if (!ide_base) {
> +		err = -ENXIO;
> +		goto err_rel_gpio;
> +	}
> +
> +	drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL);
> +	if (!drv_data) {
> +		err = -ENXIO;
> +		goto err_rel_gpio;
> +	}
> +
> +	platform_set_drvdata(pdev, drv_data);
> +	drv_data->pdev = pdev;
> +	drv_data->ide_base = ide_base;
> +	drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN;
> +	drv_data->udma_out_phys = mem_res->start + IDEUDMADATAOUT;
> +	ep93xx_pata_dma_init(drv_data);
> +
> +	/* allocate host */
> +	host = ata_host_alloc(&pdev->dev, 1);
> +	if (!host) {
> +		err = -ENXIO;
> +		goto err_rel_dma;
> +	}
> +
> +	ep93xx_pata_clear_regs(ide_base);
> +
> +	host->n_ports = 1;
> +	host->private_data = drv_data;
> +
> +	ap = host->ports[0];
> +	ap->dev = &pdev->dev;
> +	ap->ops = &ep93xx_pata_port_ops;
> +	ap->flags |= ATA_FLAG_SLAVE_POSS;
> +	ap->pio_mask = ATA_PIO4;
> +
> +	/*
> +	 * Maximum UDMA modes:
> +	 * EP931x rev.E0 - UDMA2
> +	 * EP931x rev.E1 - UDMA3
> +	 * EP931x rev.E2 - UDMA4
> +	 *
> +	 * MWDMA support was removed from EP931x rev.E2,
> +	 * so this driver supports only UDMA modes.
> +	 */
> +	if (drv_data->dma_rx_channel && drv_data->dma_tx_channel) {
> +		int chip_rev = ep93xx_chip_revision();
> +
> +		if (chip_rev == EP93XX_CHIP_REV_E1)
> +			ap->udma_mask = ATA_UDMA3;
> +		else if (chip_rev == EP93XX_CHIP_REV_E2)
> +			ap->udma_mask = ATA_UDMA4;
> +		else
> +			ap->udma_mask = ATA_UDMA2;
> +	}
> +
> +	/* defaults, pio 0 */
> +	ep93xx_pata_enable_pio(ide_base, 0);
> +
> +	dev_info(&pdev->dev, "version " DRV_VERSION "\n");
> +
> +	/* activate host */
> +	err = ata_host_activate(host, irq, ata_bmdma_interrupt, 0,
> +		&ep93xx_pata_sht);
> +	if (err == 0)
> +		return 0;
> +
> +err_rel_dma:
> +	ep93xx_pata_release_dma(drv_data);
> +err_rel_gpio:
> +	ep93xx_ide_release_gpio(pdev);
> +	return err;
> +}

There are only two m2m dma channels on the ep93xx. They could be already in
use by the spi driver. I just want to make sure that the ide driver will fall back to
pio mode if they are not available.

Regards,
Hartley





More information about the linux-arm-kernel mailing list