ep93xx pata problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi !

I am new on the list. I try to get ep93xx pata driver from Alessandro Zummo 
running on 2.6.20-rc1. The driver supports for now no DMA but i think PIO or 
MMIO, what is the difference? You see I am a newbe to ata ... sorry

The problem is that ata_interrupt comes always and the system hangs:  

I have added some printks to ata_interrupt:

ep93xx_pata_probe: : ioremap to 0xc685a000 
pata_ep93xx pata_ep93xx: version 0.1
ata_device_add: ENTER
ata_port_add: ENTER
ata_port_start: prd alloc, virt ffc97000, dma 5d9a000
ata1: PATA max PIO4 cmd 0xC685A002 ctl 0xC685A019 bmdma 0x0 irq 40
ata_device_add: probe begin
scsi0 : pata_ep93xx
ata_device_add: ata1: bus probe begin
ata_bus_reset: ENTER, host 1, port 0
ata_bus_softreset: ata1: bus reset via SRST
ata_dev_classify: found ATA device by sig
ata_bus_reset: EXIT
ata1: ata_dev_select: ENTER, ata1: device 0, wait 1
ata1: ata_dev_select: ENTER, ata1: device 0, wait 1
ep93xx_exec_command: ata1: cmd 0xEC
ATA INTERRUPT 1 
ATA INTERRUPT 2 
 ** ap->flags 18 
ATA INTERRUPT 3 
if (qc)
(qc->tf.flags & ATA_TFLAG_POLLING) qc->tf.flags 40 
(qc->flags & ATA_QCFLAG_ACTIVE)

--> It looks like that the ATA_TFLAG_POLLING is alsways set. So Interrupt 
alsways returns 0 because it is not handled.

--> Does someone have any information about that for me what i can do or is 
there a problem in the driver ?

Thanks a lot for help, happy x-mas, regards manfred

attached is the driver:

-- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/ata/pata_ep93xx.c	2006-12-20 16:51:02.192065229 +0100
@@ -0,0 +1,378 @@
+/*
+ * EP93XX PATA controller driver.
+ * Copyright (c) 2006 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@xxxxxxxxxxxx>
+ *
+ * An ATA driver to handle the embedded IDE controller
+ * of the Cirrus Logic EP93XX.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/libata.h>
+#include <linux/irq.h>
+#include <scsi/scsi_host.h>
+#include <linux/platform_device.h>
+
+#define DRV_NAME	"pata_ep93xx"
+#define DRV_VERSION	"0.1"
+
+struct ep93xx_pata_data {
+	void __iomem *mem;
+	int irq;
+};
+
+struct ata_host *ep93xx_host;
+
+static inline void ep93xx_toggle_wr(register u32 ctrl)
+{
+	ctrl &= ~(EP93XX_IDE_CTRL_DIOWn);
+	__raw_writel(ctrl, EP93XX_IDE_CTRL);
+
+	ctrl |= EP93XX_IDE_CTRL_DIOWn;
+	__raw_writel(ctrl, EP93XX_IDE_CTRL);
+}
+
+static inline void ep93xx_toggle_rd(register u32 ctrl)
+{
+	ctrl &= ~(EP93XX_IDE_CTRL_DIORn);
+	__raw_writel(ctrl, EP93XX_IDE_CTRL);
+
+	ctrl |= EP93XX_IDE_CTRL_DIORn;
+	__raw_writel(ctrl, EP93XX_IDE_CTRL);
+}
+
+#define ep93xx_write_addr(ctrl,addr) { \
+	ctrl = (ctrl & ~(EP93XX_IDE_CTRL_DA_CS_MASK)) | EP93XX_IDE_CTRL_DA_CS(addr); 
\
+	__raw_writel(ctrl, EP93XX_IDE_CTRL); }
+
+static inline void ep93xx_writew(register u16 value, volatile void __iomem 
*p)
+{
+	register u32 ctrl = __raw_readl(EP93XX_IDE_CTRL);
+	ep93xx_write_addr(ctrl, (unsigned long) p);
+	__raw_writel(value, EP93XX_IDE_DATAOUT);
+	ep93xx_toggle_wr(ctrl);
+}
+
+#define ep93xx_writeb(value,addr) ep93xx_writew(value,addr)
+
+static inline unsigned short ep93xx_readw(volatile void __iomem *p)
+{
+	register u32 ctrl = __raw_readl(EP93XX_IDE_CTRL);
+
+	ep93xx_write_addr(ctrl, (unsigned long) p);
+	ep93xx_toggle_rd(ctrl);
+	return __raw_readl(EP93XX_IDE_DATAIN);
+}
+
+#define ep93xx_readb(addr) ep93xx_readw(addr)
+
+static unsigned long ep93xx_mode_filter(const struct ata_port *ap,
+				 struct ata_device *adev, unsigned long mask)
+{
+	return mask;
+}
+
+static void ep93xx_set_mode(struct ata_port *ap)
+{
+	int i;
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_enabled(dev)) {
+			dev->pio_mode = XFER_PIO_0;
+			dev->xfer_mode = XFER_PIO_0;
+			dev->xfer_shift = ATA_SHIFT_PIO;
+			dev->flags |= ATA_DFLAG_PIO;
+		}
+	}
+}
+
+static void ep93xx_phy_reset(struct ata_port *ap)
+{
+	ap->cbl = ATA_CBL_PATA40;
+	ata_port_probe(ap);
+	ata_bus_reset(ap);
+}
+
+static void ep93xx_irq_clear(struct ata_port *ap)
+{
+}
+
+static void ep93xx_tf_load(struct ata_port *ap, const struct ata_taskfile 
*tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		ep93xx_writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		ep93xx_writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
+		ep93xx_writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
+		ep93xx_writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
+		ep93xx_writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
+		ep93xx_writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
+		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+			tf->hob_feature,
+			tf->hob_nsect,
+			tf->hob_lbal,
+			tf->hob_lbam,
+			tf->hob_lbah);
+	}
+
+	if (is_addr) {
+		ep93xx_writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
+		ep93xx_writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+		ep93xx_writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+		ep93xx_writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+		ep93xx_writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
+		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+			tf->feature,
+			tf->nsect,
+			tf->lbal,
+			tf->lbam,
+			tf->lbah);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		ep93xx_writeb(tf->device, (void __iomem *) ioaddr->device_addr);
+		VPRINTK("device 0x%X\n", tf->device);
+	}
+
+	ata_wait_idle(ap);
+}
+
+static void ep93xx_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ap->ops->check_status(ap);
+	tf->feature = ep93xx_readb((void __iomem *)ioaddr->error_addr);
+	tf->nsect = ep93xx_readb((void __iomem *)ioaddr->nsect_addr);
+	tf->lbal = ep93xx_readb((void __iomem *)ioaddr->lbal_addr);
+	tf->lbam = ep93xx_readb((void __iomem *)ioaddr->lbam_addr);
+	tf->lbah = ep93xx_readb((void __iomem *)ioaddr->lbah_addr);
+	tf->device = ep93xx_readb((void __iomem *)ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		ep93xx_writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
+		tf->hob_feature = ep93xx_readb((void __iomem *)ioaddr->error_addr);
+		tf->hob_nsect = ep93xx_readb((void __iomem *)ioaddr->nsect_addr);
+		tf->hob_lbal = ep93xx_readb((void __iomem *)ioaddr->lbal_addr);
+		tf->hob_lbam = ep93xx_readb((void __iomem *)ioaddr->lbam_addr);
+		tf->hob_lbah = ep93xx_readb((void __iomem *)ioaddr->lbah_addr);
+	}
+}
+
+static u8 ep93xx_check_status(struct ata_port *ap)
+{
+	return ep93xx_readb((void __iomem *) ap->ioaddr.status_addr);
+}
+
+static u8 ep93xx_check_altstatus(struct ata_port *ap)
+{
+	return ep93xx_readb((void __iomem *)ap->ioaddr.altstatus_addr);
+}
+
+static void ep93xx_exec_command(struct ata_port *ap, const struct 
ata_taskfile *tf)
+{
+	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+	ep93xx_writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
+	ata_pause(ap);
+}
+
+static void ep93xx_data_xfer(struct ata_device *adev, unsigned char *buf,
+			     unsigned int buflen, int write_data)
+{
+	unsigned int i;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *) buf;
+	struct ata_port *ap = adev->ap;
+	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+
+	/* Transfer multiple of 2 bytes */
+	if (write_data) {
+		for (i = 0; i < words; i++)
+			ep93xx_writew(le16_to_cpu(buf16[i]), mmio);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(ep93xx_readw(mmio));
+	}
+
+	/* Transfer trailing 1 byte, if any. */
+	if (unlikely(buflen & 0x01)) {
+		u16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (write_data) {
+			memcpy(align_buf, trailing_buf, 1);
+			ep93xx_writew(le16_to_cpu(align_buf[0]), mmio);
+		} else {
+			align_buf[0] = cpu_to_le16(ep93xx_readw(mmio));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
+}
+
+static struct scsi_host_template ep93xx_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations ep93xx_port_ops = {
+	.set_mode		= ep93xx_set_mode,
+	.mode_filter		= ep93xx_mode_filter,
+
+	.port_disable		= ata_port_disable,
+	.tf_load		= ep93xx_tf_load,
+	.tf_read		= ep93xx_tf_read,
+	.check_status 		= ep93xx_check_status,
+	.check_altstatus	= ep93xx_check_altstatus,
+	.exec_command		= ep93xx_exec_command,
+	.data_xfer		= ep93xx_data_xfer,
+
+	.dev_select 		= ata_std_dev_select,
+
+	.qc_prep 		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.eng_timeout		= ata_eng_timeout,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ep93xx_irq_clear,
+
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
+
+	.phy_reset		= ep93xx_phy_reset,
+};
+
+/* Setup the addresses and encode CSx within them */
+static void ep93xx_ports(struct ata_ioports *ioaddr,struct ep93xx_pata_data 
*data)
+{
+    ioaddr->cmd_addr        = data->mem + 2;
+    ioaddr->altstatus_addr  = data->mem + (0x06 << 2) + 1;
+    ioaddr->ctl_addr        = data->mem + (0x06 << 2) + 1;
+
+    ioaddr->data_addr       = data->mem + (ATA_REG_DATA << 2) + 2;
+    ioaddr->error_addr      = data->mem + (ATA_REG_ERR << 2) + 2;
+    ioaddr->feature_addr    = data->mem + (ATA_REG_FEATURE << 2) + 2;
+    ioaddr->nsect_addr      = data->mem + (ATA_REG_NSECT << 2) + 2;
+    ioaddr->lbal_addr       = data->mem + (ATA_REG_LBAL << 2) + 2;
+    ioaddr->lbam_addr       = data->mem + (ATA_REG_LBAM << 2) + 2;
+    ioaddr->lbah_addr       = data->mem + (ATA_REG_LBAH << 2) + 2;
+    ioaddr->device_addr     = data->mem + (ATA_REG_DEVICE << 2) + 2;
+    ioaddr->status_addr     = data->mem + (ATA_REG_STATUS << 2) + 2;
+    ioaddr->command_addr    = data->mem + (ATA_REG_CMD << 2) + 2;
+}
+
+static __devinit int ep93xx_pata_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct ata_probe_ent ae;
+	struct resource *res;
+	struct ep93xx_pata_data *data;
+
+	memset(&ae, 0, sizeof(struct ata_probe_ent));
+	INIT_LIST_HEAD(&ae.node);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	data->mem = ioremap(res->start,0x1000);
+	if (data->mem == NULL) {
+                dev_err(&pdev->dev, "Failed to ioremap pata registers\n");
+                return -EIO;
+        } else {
+	    DPRINTK(": ioremap to 0x%x \n",(unsigned int) data->mem);
+	}
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq)
+		set_irq_type(data->irq, IRQT_HIGH);
+
+	ae.dev		= &pdev->dev;
+	ae.port_ops	= &ep93xx_port_ops;
+	ae.sht		= &ep93xx_sht;
+	ae.n_ports	= 1;
+	ae.pio_mask	= 0x1f; /* PIO4 */
+	ae.irq		= data->irq;
+	ae.irq_flags	= 0;
+	ae.port_flags	= ATA_FLAG_MMIO | ATA_FLAG_SRST;
+
+	ep93xx_ports(&ae.port[0], data);
+
+	/* enable ide and set pio mode 4 */
+	__raw_writel(EP93XX_IDE_CFG_IDEEN | EP93XX_IDE_CFG_PIO |
+			EP93XX_IDE_CFG_WST(0) | EP93XX_IDE_CFG_MODE(4),
+			EP93XX_IDE_CFG);
+
+	/* run in polling mode if no irq has been assigned */
+	if (!data->irq)
+		ae.port_flags |= ATA_FLAG_PIO_POLLING;
+
+	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+	ret = ata_device_add(&ae);
+	if (ret == 0)
+		return -ENODEV;
+
+	return 0;
+}
+
+static __devexit int ep93xx_pata_remove(struct platform_device *dev)
+{
+	struct ata_host *host = platform_get_drvdata(dev);
+
+	ata_host_remove(host);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver ep93xx_pata_platform_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+	},
+	.probe		= ep93xx_pata_probe,
+	.remove		= __devexit_p(ep93xx_pata_remove),
+};
+
+
+static int __init ep93xx_pata_init(void)
+{
+	return platform_driver_register(&ep93xx_pata_platform_driver);
+}
+
+static void __exit ep93xx_pata_exit(void)
+{
+	platform_driver_unregister(&ep93xx_pata_platform_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@xxxxxxxxxxxx>");
+MODULE_DESCRIPTION("low-level driver for ep93xx ATA");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ep93xx_pata_init);
+module_exit(ep93xx_pata_exit);
 

-- 
mfg
Manfred Gruber
==========================================
Contec Steuerungstechnik & Automation GmbH
Manfred Gruber
Wildbichler Straße 2e
6341 Ebbs / Austria
AUSTRIA
------------------------------------------
http://www.contec.at/
manfred.gruber@xxxxxxxxx

phone: 0043 / (0) 5373 / 43143 - 511
fax:   0043 / (0) 5373 / 43143 - 888
==========================================
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux