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 <[EMAIL PROTECTED]>
+ *
+ * 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 <[EMAIL PROTECTED]>");
+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/
[EMAIL PROTECTED]
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 [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html