* [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
@ 2006-11-16 22:12 Sylvain Munaut
2006-11-16 23:46 ` Alan
2006-11-17 18:49 ` Jarno Manninen
0 siblings, 2 replies; 8+ messages in thread
From: Sylvain Munaut @ 2006-11-16 22:12 UTC (permalink / raw)
To: Linux PPC Embedded, Linux IDE; +Cc: Sylvain Munaut, Sven Luther
This is the first attempt at a libata driver for this controller.
The two main issues :
* The manual states we should check for the TIP bit before all
PIO transaction. That's not really supported by libata and requires
reimplementing almost all the hooks. But after talking to Freescale,
it turnsout it's not really necessary. So this driver doesn't implement
that check. I noticed no problem so far ...
* This driver doesn't use the standard function to compute timing
because the 5200 needs more timing parameters that are not handled
by the generic call (ta and t4).
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
Hi everyone,
This is a request for comments, I'd like to get that driver clean enough
for the 2.6.20 merge window ;)
It has been tested on my system (but not stressed to the limits ...). I'd
appreciate if someone could test it as well on other platforms.
Sylvain
---
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1
drivers/ata/pata_mpc52xx.c | 510 ++++++++++++++++++++++++++++++++++++++++++++
drivers/ata/pata_mpc52xx.h | 107 +++++++++
4 files changed, 627 insertions(+), 0 deletions(-)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 03f6338..be01ddf 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -328,6 +328,15 @@ config PATA_TRIFLEX
If unsure, say N.
+config PATA_MPC52xx
+ tristate "Freescale MPC52xx SoC internal IDE"
+ depends on PPC_MPC52xx
+ help
+ This option enables support for integrated IDE controller
+ of the Freescale MPC52xx SoC.
+
+ If unsure, say N.
+
config PATA_MPIIX
tristate "Intel PATA MPIIX support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 72243a6..e3a741c 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netce
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
+obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
new file mode 100644
index 0000000..c75d4c9
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.c
@@ -0,0 +1,510 @@
+/*
+ * drivers/ata/pata_mpc52xx.c
+ *
+ * libata driver for the Freescale MPC52xx on-chip IDE interface
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/libata.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_platform.h>
+#include <asm/mpc52xx.h>
+
+#include "pata_mpc52xx.h"
+
+
+#define DRV_NAME "mpc52xx_ata"
+#define DRV_VERSION "0.1.0"
+
+
+/* Private structures used by the driver */
+struct mpc52xx_ata_timings {
+ u32 pio1;
+ u32 pio2;
+};
+
+struct mpc52xx_ata_priv {
+ unsigned int ipb_period;
+ struct mpc52xx_ata __iomem * ata_regs;
+ int ata_irq;
+ struct mpc52xx_ata_timings timings[2];
+ int csel;
+};
+
+
+/* ATAPI-4 PIO specs (in ns) */
+static const int ataspec_t0[5] = {600, 383, 240, 180, 120};
+static const int ataspec_t1[5] = { 70, 50, 30, 30, 25};
+static const int ataspec_t2_8[5] = {290, 290, 290, 80, 70};
+static const int ataspec_t2_16[5] = {165, 125, 100, 80, 70};
+static const int ataspec_t2i[5] = { 0, 0, 0, 70, 25};
+static const int ataspec_t4[5] = { 30, 20, 15, 10, 10};
+static const int ataspec_ta[5] = { 35, 35, 35, 35, 35};
+
+#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
+
+
+/* ======================================================================== */
+/* Aux fns */
+/* ======================================================================== */
+
+
+/* OF device tree */
+
+static unsigned int
+mpc52xx_find_ipb_freq(struct device_node *on)
+{
+ struct device_node *onp;
+ const unsigned int *p_ipb_freq = NULL;
+
+ of_node_get(on);
+ while (on) {
+ p_ipb_freq = get_property(on, "bus-frequency", NULL);
+
+ if (p_ipb_freq)
+ break;
+
+ onp = of_get_parent(on);
+ of_node_put(on);
+ on = onp;
+ }
+
+ if (on)
+ of_node_put(on);
+
+ return p_ipb_freq ? *p_ipb_freq : 0;
+}
+
+
+/* MPC52xx low level hw control */
+
+static int
+mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
+{
+ struct mpc52xx_ata_timings *timing = &priv->timings[dev];
+ unsigned int ipb_period = priv->ipb_period;
+ unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta;
+
+ if ((pio<0) || (pio>4))
+ return -EINVAL;
+
+ t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]);
+ t1 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t1[pio]);
+ t2_8 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_8[pio]);
+ t2_16 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_16[pio]);
+ t2i = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2i[pio]);
+ t4 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t4[pio]);
+ ta = CALC_CLKCYC(ipb_period, 1000 * ataspec_ta[pio]);
+
+ timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
+ timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+ return 0;
+}
+
+static void
+mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
+{
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+ struct mpc52xx_ata_timings *timing = &priv->timings[device];
+
+ out_be32(®s->pio1, timing->pio1);
+ out_be32(®s->pio2, timing->pio2);
+ out_be32(®s->mdma1, 0);
+ out_be32(®s->mdma2, 0);
+ out_be32(®s->udma1, 0);
+ out_be32(®s->udma2, 0);
+ out_be32(®s->udma3, 0);
+ out_be32(®s->udma4, 0);
+ out_be32(®s->udma5, 0);
+
+ priv->csel = device;
+}
+
+static int
+mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv)
+{
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+ int tslot;
+
+ /* Clear share_cnt (all sample code do this ...) */
+ out_be32(®s->share_cnt, 0);
+
+ /* Configure and reset host */
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY |
+ MPC52xx_ATA_HOSTCONF_SMR |
+ MPC52xx_ATA_HOSTCONF_FR);
+
+ udelay(10);
+
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY);
+
+ /* Set the time slot to 1us */
+ tslot = CALC_CLKCYC(priv->ipb_period, 1000000);
+ out_be32(®s->share_cnt, tslot << 16 );
+
+ /* Init timings to PIO0 */
+ memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
+
+ mpc52xx_ata_compute_pio_timings(priv, 0, 0);
+ mpc52xx_ata_compute_pio_timings(priv, 1, 0);
+
+ mpc52xx_ata_apply_timings(priv, 0);
+
+ return 0;
+}
+
+
+/* ======================================================================== */
+/* libata driver */
+/* ======================================================================== */
+
+static void
+mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct mpc52xx_ata_priv *priv = ap->host->private_data;
+ int pio, rv;
+
+ pio = adev->pio_mode - XFER_PIO_0;
+
+ rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio);
+
+ if (rv) {
+ printk(KERN_ERR DRV_NAME
+ ": Trying to select invalid PIO mode %d\n", pio);
+ return;
+ }
+
+ mpc52xx_ata_apply_timings(priv, adev->devno);
+}
+static void
+mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+{
+ struct mpc52xx_ata_priv *priv = ap->host->private_data;
+
+ if (device != priv->csel)
+ mpc52xx_ata_apply_timings(priv, device);
+
+ ata_std_dev_select(ap,device);
+}
+
+static void
+mpc52xx_ata_error_handler(struct ata_port *ap)
+{
+ ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+ ata_std_postreset);
+}
+
+
+
+static struct scsi_host_template mpc52xx_ata_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 mpc52xx_ata_port_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = mpc52xx_ata_set_piomode,
+ .dev_select = mpc52xx_ata_dev_select,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = mpc52xx_ata_error_handler,
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .data_xfer = ata_mmio_data_xfer,
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
+};
+
+static struct ata_probe_ent mpc52xx_ata_probe_ent = {
+ .port_ops = &mpc52xx_ata_port_ops,
+ .sht = &mpc52xx_ata_sht,
+ .n_ports = 1,
+ .pio_mask = 0x1f, /* Up to PIO4 */
+ .mwdma_mask = 0x00, /* No MWDMA */
+ .udma_mask = 0x00, /* No UDMA */
+ .port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_MMIO,
+ .irq_flags = 0,
+};
+
+static int __devinit
+mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
+{
+ struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent;
+ struct ata_ioports *aio = &ae->port[0];
+ int rv;
+
+ INIT_LIST_HEAD(&ae->node);
+ ae->dev = dev;
+ ae->irq = priv->ata_irq;
+
+ aio->cmd_addr = 0; /* Don't have a classic reg block */
+ aio->altstatus_addr = (unsigned long)&priv->ata_regs->tf_control;
+ aio->ctl_addr = (unsigned long)&priv->ata_regs->tf_control;
+ aio->data_addr = (unsigned long)&priv->ata_regs->tf_data;
+ aio->error_addr = (unsigned long)&priv->ata_regs->tf_features;
+ aio->feature_addr = (unsigned long)&priv->ata_regs->tf_features;
+ aio->nsect_addr = (unsigned long)&priv->ata_regs->tf_sec_count;
+ aio->lbal_addr = (unsigned long)&priv->ata_regs->tf_sec_num;
+ aio->lbam_addr = (unsigned long)&priv->ata_regs->tf_cyl_low;
+ aio->lbah_addr = (unsigned long)&priv->ata_regs->tf_cyl_high;
+ aio->device_addr = (unsigned long)&priv->ata_regs->tf_dev_head;
+ aio->status_addr = (unsigned long)&priv->ata_regs->tf_command;
+ aio->command_addr = (unsigned long)&priv->ata_regs->tf_command;
+
+ ae->private_data = priv;
+
+ rv = ata_device_add(ae);
+
+ return rv ? 0 : -EINVAL;
+}
+
+static struct mpc52xx_ata_priv *
+mpc52xx_ata_remove_one(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct mpc52xx_ata_priv *priv = host->private_data;
+
+ ata_host_remove(host);
+
+ return priv;
+}
+
+
+/* ======================================================================== */
+/* OF Platform driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
+{
+ unsigned int ipb_freq;
+ struct resource res_mem;
+ int ata_irq = NO_IRQ;
+ struct mpc52xx_ata __iomem *ata_regs = NULL;
+ struct mpc52xx_ata_priv *priv = NULL;
+ int rv;
+
+ /* Get ipb frequency */
+ ipb_freq = mpc52xx_find_ipb_freq(op->node);
+ if (!ipb_freq) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Unable to find IPB Bus frequency\n" );
+ return -ENODEV;
+ }
+
+ /* Get IRQ and register */
+ rv = of_address_to_resource(op->node, 0, &res_mem);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while parsing device node resource\n" );
+ return rv;
+ }
+
+ ata_irq = irq_of_parse_and_map(op->node, 0);
+ if (ata_irq == NO_IRQ) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while mapping the irq\n");
+ return -EINVAL;
+ }
+
+ /* Request mem region */
+ if (!request_mem_region(res_mem.start,
+ sizeof(struct mpc52xx_ata), DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while requesting mem region\n");
+ irq_dispose_mapping(ata_irq);
+ return -EBUSY;
+ }
+
+ /* Remap registers */
+ ata_regs = ioremap(res_mem.start, sizeof(struct mpc52xx_ata));
+ if (!ata_regs) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while mapping register set\n");
+ rv = -ENOMEM;
+ goto err;
+ }
+
+ /* Prepare our private structure */
+ priv = kmalloc(sizeof(struct mpc52xx_ata_priv), GFP_ATOMIC);
+ if (!priv) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while allocating private structure\n");
+ rv = -ENOMEM;
+ goto err;
+ }
+
+ priv->ipb_period = 1000000000 / (ipb_freq / 1000);
+ priv->ata_regs = ata_regs;
+ priv->ata_irq = ata_irq;
+ priv->csel = -1;
+
+ /* Init the hw */
+ rv = mpc52xx_ata_hw_init(priv);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+ goto err;
+ }
+
+ /* Register ourselves to libata */
+ rv = mpc52xx_ata_init_one(&op->dev, priv);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while registering to ATA layer\n");
+ return rv;
+ }
+
+ /* Done */
+ return 0;
+
+ /* Error path */
+err:
+ kfree(priv);
+
+ if (ata_regs)
+ iounmap(ata_regs);
+
+ release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
+
+ irq_dispose_mapping(ata_irq);
+
+ return rv;
+}
+
+static int
+mpc52xx_ata_remove(struct of_device *op)
+{
+ struct mpc52xx_ata_priv *priv;
+ struct resource res_mem;
+ int rv;
+
+ /* Unregister */
+ priv = mpc52xx_ata_remove_one(&op->dev);
+
+ /* Free everything */
+ iounmap(priv->ata_regs);
+
+ rv = of_address_to_resource(op->node, 0, &res_mem);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": "
+ "Error while parsing device node resource\n");
+ printk(KERN_ERR DRV_NAME ": "
+ "Zone may not be properly released\n");
+ } else
+ release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
+
+ irq_dispose_mapping(priv->ata_irq);
+
+ kfree(priv);
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_ata_resume(struct of_device *op)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+
+#endif
+
+
+static struct of_device_id mpc52xx_ata_of_match[] = {
+ {
+ .compatible = "mpc5200-ata",
+ },
+ {
+ .compatible = "mpc52xx-ata",
+ },
+ {},
+};
+
+
+static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .match_table = mpc52xx_ata_of_match,
+ .probe = mpc52xx_ata_probe,
+ .remove = mpc52xx_ata_remove,
+#ifdef CONFIG_PM
+ .suspend = mpc52xx_ata_suspend,
+ .resume = mpc52xx_ata_resume,
+#endif
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ata_init(void)
+{
+ printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
+ return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_ata_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+module_init(mpc52xx_ata_init);
+module_exit(mpc52xx_ata_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_mpc52xx.h b/drivers/ata/pata_mpc52xx.h
new file mode 100644
index 0000000..2430ae2
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.h
@@ -0,0 +1,107 @@
+/*
+ * drivers/ata/pata_mpc52xx.h
+ *
+ * Definitions for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __PATA_MPC52xx_H__
+#define __PATA_MPC52xx_H__
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+
+/* Bit definitions inside the registers */
+
+#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+ /* Host interface registers */
+ u32 config; /* ATA + 0x00 Host configuration */
+ u32 host_status; /* ATA + 0x04 Host controller status */
+ u32 pio1; /* ATA + 0x08 PIO Timing 1 */
+ u32 pio2; /* ATA + 0x0c PIO Timing 2 */
+ u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
+ u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
+ u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
+ u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
+ u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
+ u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
+ u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
+ u32 share_cnt; /* ATA + 0x2c ATA share counter */
+ u32 reserved0[3];
+
+ /* FIFO registers */
+ u32 fifo_data; /* ATA + 0x3c */
+ u8 fifo_status_frame; /* ATA + 0x40 */
+ u8 fifo_status; /* ATA + 0x41 */
+ u16 reserved7[1];
+ u8 fifo_control; /* ATA + 0x44 */
+ u8 reserved8[5];
+ u16 fifo_alarm; /* ATA + 0x4a */
+ u16 reserved9;
+ u16 fifo_rdp; /* ATA + 0x4e */
+ u16 reserved10;
+ u16 fifo_wrp; /* ATA + 0x52 */
+ u16 reserved11;
+ u16 fifo_lfrdp; /* ATA + 0x56 */
+ u16 reserved12;
+ u16 fifo_lfwrp; /* ATA + 0x5a */
+
+ /* Drive TaskFile registers */
+ u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
+ u8 reserved13[3];
+ u16 tf_data; /* ATA + 0x60 TASKFILE Data */
+ u16 reserved14;
+ u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
+ u8 reserved15[3];
+ u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
+ u8 reserved16[3];
+ u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */
+ u8 reserved17[3];
+ u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */
+ u8 reserved18[3];
+ u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */
+ u8 reserved19[3];
+ u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */
+ u8 reserved20[3];
+ u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */
+ u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */
+ u8 reserved21[2];
+};
+
+#endif /* __PATA_MPC52xx_H__ */
+
--
1.4.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-16 22:12 [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata Sylvain Munaut
@ 2006-11-16 23:46 ` Alan
2006-11-17 19:12 ` Sylvain Munaut
2006-11-17 18:49 ` Jarno Manninen
1 sibling, 1 reply; 8+ messages in thread
From: Alan @ 2006-11-16 23:46 UTC (permalink / raw)
To: Sylvain Munaut
Cc: Benjamin, Sylvain Munaut, Linux PPC Embedded, Sven Luther,
Linux IDE
On Thu, 16 Nov 2006 23:12:19 +0100
Sylvain Munaut <tnt@246tNt.com> wrote:
> * The manual states we should check for the TIP bit before all
> PIO transaction. That's not really supported by libata and requires
> reimplementing almost all the hooks. But after talking to Freescale,
> it turnsout it's not really necessary. So this driver doesn't implement
> that check. I noticed no problem so far ...
>
All PIO transactions meaning each PIO command sequence or each register
read/write ? In the former case is it not enough just to wrap the command
write ?
> * This driver doesn't use the standard function to compute timing
> because the 5200 needs more timing parameters that are not handled
> by the generic call (ta and t4).
I'd rather the generic code was taught to compute any extra times you
need but it seems clean enough.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-16 23:46 ` Alan
@ 2006-11-17 19:12 ` Sylvain Munaut
0 siblings, 0 replies; 8+ messages in thread
From: Sylvain Munaut @ 2006-11-17 19:12 UTC (permalink / raw)
To: Alan; +Cc: Linux PPC Embedded, Sven Luther, Linux IDE
Alan wrote:
> On Thu, 16 Nov 2006 23:12:19 +0100
> Sylvain Munaut <tnt@246tNt.com> wrote:
>
>
>> * The manual states we should check for the TIP bit before all
>> PIO transaction. That's not really supported by libata and requires
>> reimplementing almost all the hooks. But after talking to Freescale,
>> it turnsout it's not really necessary. So this driver doesn't implement
>> that check. I noticed no problem so far ...
>>
>>
>
> All PIO transactions meaning each PIO command sequence or each register
> read/write ? In the former case is it not enough just to wrap the command
> write ?
>
Each register write apparently.
>> * This driver doesn't use the standard function to compute timing
>> because the 5200 needs more timing parameters that are not handled
>> by the generic call (ta and t4).
>>
>
> I'd rather the generic code was taught to compute any extra times you
> need but it seems clean enough.
>
Well, I can do that as well. It should be simple enough and not
interfere with
the existing drivers.
Sylvain
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-16 22:12 [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata Sylvain Munaut
2006-11-16 23:46 ` Alan
@ 2006-11-17 18:49 ` Jarno Manninen
2006-11-17 19:09 ` Sylvain Munaut
1 sibling, 1 reply; 8+ messages in thread
From: Jarno Manninen @ 2006-11-17 18:49 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Linux IDE, Sven Luther
On Friday 17 November 2006 00:12, Sylvain Munaut wrote:
> * The manual states we should check for the TIP bit before all
> PIO transaction. That's not really supported by libata and requires
> reimplementing almost all the hooks. But after talking to Freescale,
> it turnsout it's not really necessary. So this driver doesn't implement
> that check. I noticed no problem so far ...
I've had some bad experiences with 2.4 line kernel when using BAPI 2.2 on Rev.
A 5200 while imposing heavy I/O load. Problems manifested as hanging XLB-bus
and so on. Funny thing is that combinations like Rev.A + BAPI 2.1 and Rev.B +
BAPI 2.[12] seem to be immune while doing similar stress tests.
Problems went away after wrapping PIO access like this:
1. Stop XLB-pipelining
2. Wait for TIP bit to go down.
3. Do the access
4. Restore XLB-pipelining.
Just polling for the TIP bit is not enough due to errata on Rev. A if the
pipelining is enabled.
Just in case if someone else is having mysterious hangs on Rev.A:s with newer
microcode. :)
- Jarno
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-17 18:49 ` Jarno Manninen
@ 2006-11-17 19:09 ` Sylvain Munaut
2006-11-17 22:41 ` Jeff Garzik
0 siblings, 1 reply; 8+ messages in thread
From: Sylvain Munaut @ 2006-11-17 19:09 UTC (permalink / raw)
To: Jarno Manninen; +Cc: Linux IDE, Sven Luther, linuxppc-embedded
Jarno Manninen wrote:
> On Friday 17 November 2006 00:12, Sylvain Munaut wrote:
>
>
>> * The manual states we should check for the TIP bit before all
>> PIO transaction. That's not really supported by libata and requires
>> reimplementing almost all the hooks. But after talking to Freescale,
>> it turnsout it's not really necessary. So this driver doesn't implement
>> that check. I noticed no problem so far ...
>>
>
> I've had some bad experiences with 2.4 line kernel when using BAPI 2.2 on Rev.
> A 5200 while imposing heavy I/O load. Problems manifested as hanging XLB-bus
> and so on. Funny thing is that combinations like Rev.A + BAPI 2.1 and Rev.B +
> BAPI 2.[12] seem to be immune while doing similar stress tests.
>
> Problems went away after wrapping PIO access like this:
>
> 1. Stop XLB-pipelining
> 2. Wait for TIP bit to go down.
> 3. Do the access
> 4. Restore XLB-pipelining.
>
> Just polling for the TIP bit is not enough due to errata on Rev. A if the
> pipelining is enabled.
>
> Just in case if someone else is having mysterious hangs on Rev.A:s with newer
> microcode. :)
>
Thanks for the info ! I'll certainly try to remember that.
The currentl kernel doesn't handle DMA so far so there is no problem and
we deactivate
XLB pipelining.
Since the current libata doesn't really support overriding IO accessors,
I'd keep it like
that for now. Apparently some other architecture needs special IO stuff
so we could see
a way to hook io accessor soon, and then we can change it if we notice
big problems.
Sylvain
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-17 19:09 ` Sylvain Munaut
@ 2006-11-17 22:41 ` Jeff Garzik
2006-11-17 23:21 ` Sylvain Munaut
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2006-11-17 22:41 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: Linux IDE, Sven Luther, linuxppc-embedded
Sylvain Munaut wrote:
> Since the current libata doesn't really support overriding IO accessors,
> I'd keep it like
> that for now. Apparently some other architecture needs special IO stuff
> so we could see
> a way to hook io accessor soon, and then we can change it if we notice
> big problems.
Sure it does... there are no individual outb etc. hooks, but you can
override every available bitbang function. This is intentional, so that
arches have more power to control when and how a set of registers is
blasted to the hardware.
Jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-17 22:41 ` Jeff Garzik
@ 2006-11-17 23:21 ` Sylvain Munaut
2006-11-19 19:14 ` Nicolas DET
0 siblings, 1 reply; 8+ messages in thread
From: Sylvain Munaut @ 2006-11-17 23:21 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Linux IDE, Sven Luther, linuxppc-embedded
Jeff Garzik wrote:
> Sylvain Munaut wrote:
>> Since the current libata doesn't really support overriding IO accessors,
>> I'd keep it like
>> that for now. Apparently some other architecture needs special IO stuff
>> so we could see
>> a way to hook io accessor soon, and then we can change it if we notice
>> big problems.
>
> Sure it does... there are no individual outb etc. hooks, but you can
> override every available bitbang function. This is intentional, so
> that arches have more power to control when and how a set of registers
> is blasted to the hardware.
That why I said "really" but in english that doesn't quite mean what I
meant.
I have a version that does it and it's not pretty, it needs to reimplement
every hook where I basically just cut & pasted the standard libata ones
and changed the outb to mpc52xx_ata_outb ...
I agree that this gives more flexibility when you need more than just change
IO accessors. But this also means than when you just need to replace IO
access, you need to do more work ... IMHO it would have made sense to
add hooks for just inb and outb (not for all the possible io stuff like in
driver/ide), but heh, I'm kind of biased ;)
So it's possible but as in the current state of thing since it doesn't
matter
if we do it or not, I'd rather not. If it becomes necessary (when doing DMA
or ...), then we can always add it. But for the moment, I would keep it
as clean as possible.
Aside from that, does the driver looks ok ? It has been tested ok on another
5200b platform as well. I'd like to include it in a patch set I'll probably
send next weekend. I'll try to add the timing computation to the generic
call and make use of those.
Thanks,
Sylvain
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata
2006-11-17 23:21 ` Sylvain Munaut
@ 2006-11-19 19:14 ` Nicolas DET
0 siblings, 0 replies; 8+ messages in thread
From: Nicolas DET @ 2006-11-19 19:14 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: Linux IDE, Sven Luther, Jeff Garzik, linuxppc-embedded
On Sat, 18 Nov 2006 00:21:42 +0100
Sylvain Munaut <tnt@246tNt.com> wrote:
> Aside from that, does the driver looks ok ? It has been tested ok on another
> 5200b platform as well. I'd like to include it in a patch set I'll probably
> send next weekend. I'll try to add the timing computation to the generic
> call and make use of those.
>
>
I succefully tested the driver on Efika 5k2: I booted my root fs and did 2 min badblocks. No problems.
Regards,
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-11-19 19:15 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-16 22:12 [PATCH/RFC] ata: Add support for the MPC52xx ATA controller using libata Sylvain Munaut
2006-11-16 23:46 ` Alan
2006-11-17 19:12 ` Sylvain Munaut
2006-11-17 18:49 ` Jarno Manninen
2006-11-17 19:09 ` Sylvain Munaut
2006-11-17 22:41 ` Jeff Garzik
2006-11-17 23:21 ` Sylvain Munaut
2006-11-19 19:14 ` Nicolas DET
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).