summaryrefslogtreecommitdiff
path: root/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch')
-rw-r--r--packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch299
1 files changed, 299 insertions, 0 deletions
diff --git a/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch b/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch
new file mode 100644
index 0000000000..1c08150c45
--- /dev/null
+++ b/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch
@@ -0,0 +1,299 @@
+---
+ drivers/scsi/Kconfig | 11 +-
+ drivers/scsi/Makefile | 1
+ drivers/scsi/libata-core.c | 4
+ drivers/scsi/pata_ixp4xx.c | 242 +++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 255 insertions(+), 3 deletions(-)
+
+--- linux-ixp4xx.orig/drivers/scsi/Kconfig 2006-02-24 18:13:55.000000000 +0100
++++ linux-ixp4xx/drivers/scsi/Kconfig 2006-02-24 18:50:19.000000000 +0100
+@@ -903,11 +903,20 @@ config SCSI_PATA_WINBOND
+ tristate "Winbond SL82C105 PATA support"
+ depends on SCSI_SATA && PCI
+ help
+- This option enables support for SL82C105 PATA devices found in the
++ This option enables support for SL82C105 PATAll devices found in the
+ Netwinder and some other systems
+
+ If unsure, say N.
+
++config SCSI_PATA_IXP4XX
++ tristate "IXP4XX Compact FLash support"
++ depends on SCSI_SATA && PCI
++ help
++ This option enables support for a Compact Flash connected on
++ the ixp4xx expansion bus.
++
++ If unsure, say N.
++
+
+ config SCSI_BUSLOGIC
+ tristate "BusLogic SCSI support"
+--- linux-ixp4xx.orig/drivers/scsi/Makefile 2006-02-24 18:13:55.000000000 +0100
++++ linux-ixp4xx/drivers/scsi/Makefile 2006-02-24 18:16:46.000000000 +0100
+@@ -174,6 +174,7 @@ obj-$(CONFIG_SCSI_PATA_VIA) += libata.o
+ obj-$(CONFIG_SCSI_PATA_WINBOND) += libata.o pata_sl82c105.o
+ obj-$(CONFIG_SCSI_ATA_GENERIC) += libata.o ata_generic.o
+ obj-$(CONFIG_SCSI_PATA_LEGACY) += libata.o pata_legacy.o
++obj-$(CONFIG_SCSI_PATA_IXP4XX) += libata.o pata_ixp4xx.o
+
+ obj-$(CONFIG_ARM) += arm/
+
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-ixp4xx/drivers/scsi/pata_ixp4xx.c 2006-02-24 18:43:02.000000000 +0100
+@@ -0,0 +1,242 @@
++/*
++ * pata-ixp4xx.c - Legacy port PATA/SATA controller driver.
++ * Copyright (c) 2006 Tower Technologies
++ *
++ * An ATA driver to handle a Compact Flash connected
++ * to the ixp4xx expansion bus.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/libata.h>
++#include <scsi/scsi_host.h>
++
++#define DRV_NAME "ixp4xx"
++#define DRV_VERSION "0.0.2"
++
++/* XXX remove when converting to platform driver */
++#define IXP4XX_IDE_BASE IXP4XX_EXP_BUS_BASE(1)
++#define IXP4XX_IDE_IRQ IRQ_IXP4XX_GPIO12
++#define IXP4XX_IDE_CONTROL 0x1e
++#define IXP4XX_IDE_INT 12
++#define IXP4XX_IDE_CS1_BITS 0xbfff0043
++#define IXP4XX_IDE_PIO_MASK 0x1f
++
++#ifdef __ARMEB__
++#define ixp4xx_writew(data,addr) writew(data,addr)
++#define ixp4xx_readw(addr) readw(addr)
++#else
++#define ixp4xx_writew(data,addr) writew(le16_to_cpu(data),addr)
++#define ixp4xx_readw(addr) cpu_to_le16(readw(addr))
++#endif
++
++static struct ata_host_set *ixp4xx_host;
++
++static unsigned int ixp4xx_mode_filter(const struct ata_port *ap,
++ struct ata_device *adev, unsigned int mask, int shift)
++{
++ if (shift != ATA_SHIFT_PIO)
++ return 0;
++ return mask;
++}
++
++static void ixp4xx_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_present(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 ixp4xx_phy_reset(struct ata_port *ap)
++{
++ ap->cbl = ATA_CBL_PATA40;
++ ata_port_probe(ap);
++ ata_bus_reset(ap);
++}
++
++void ixp4xx_mmio_data_xfer(struct ata_port *ap, 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;
++ void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
++
++ /* set the expansion bus in 16bit mode and restore
++ * 8 bit mode after the transaction.
++ */
++ *IXP4XX_EXP_CS1 &= ~(0x00000001);
++
++ /* Transfer multiple of 2 bytes */
++ if (write_data) {
++ for (i = 0; i < words; i++)
++ writew(buf16[i], mmio);
++ } else {
++ for (i = 0; i < words; i++)
++ buf16[i] = 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);
++ writew(le16_to_cpu(align_buf[0]), mmio);
++ } else {
++ align_buf[0] = cpu_to_le16(readw(mmio));
++ memcpy(trailing_buf, align_buf, 1);
++ }
++ }
++
++ *IXP4XX_EXP_CS1 |= 0x00000001;
++}
++
++void ixp4xx_host_stop(struct ata_host_set *host_set)
++{
++ ata_host_stop(host_set);
++ release_region(IXP4XX_IDE_BASE, 0x1000);
++}
++
++static struct scsi_host_template ixp4xx_sht = {
++ .module = THIS_MODULE,
++ .name = DRV_NAME,
++ .ioctl = ata_scsi_ioctl,
++ .queuecommand = ata_scsi_queuecmd,
++ .eh_strategy_handler = ata_scsi_error,
++ .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,
++// .ordered_flush = 1,
++};
++
++static struct ata_port_operations ixp4xx_port_ops = {
++ .set_mode = ixp4xx_set_mode,
++ .mode_filter = ixp4xx_mode_filter,
++
++ .port_disable = ata_port_disable,
++ .tf_load = ata_tf_load,
++ .tf_read = ata_tf_read,
++ .check_status = ata_check_status,
++ .exec_command = ata_exec_command,
++ .dev_select = ata_std_dev_select,
++
++ .qc_prep = ata_qc_prep,
++ .qc_issue = ata_qc_issue_prot,
++ .eng_timeout = ata_eng_timeout,
++ .data_xfer = ixp4xx_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 = ixp4xx_host_stop,
++
++ .phy_reset = ixp4xx_phy_reset,
++};
++
++/* adjust the addresses to handle the address swizzling of the
++ * ixp4xx in little endian mode.
++ */
++#ifndef __ARMEB__
++void ixp4xx_fix_le_ports(struct ata_ioports *ioaddr)
++{
++ ioaddr->data_addr ^= 0x02;
++ ioaddr->cmd_addr ^= 0x03;
++ ioaddr->altstatus_addr ^= 0x03;
++ ioaddr->ctl_addr ^= 0x03;
++ ioaddr->error_addr ^= 0x03;
++ ioaddr->feature_addr ^= 0x03;
++ ioaddr->nsect_addr ^= 0x03;
++ ioaddr->lbal_addr ^= 0x03;
++ ioaddr->lbam_addr ^= 0x03;
++ ioaddr->lbah_addr ^= 0x03;
++ ioaddr->device_addr ^= 0x03;
++ ioaddr->status_addr ^= 0x03;
++ ioaddr->command_addr ^= 0x03;
++}
++#endif
++
++static __init int ixp4xx_init_one(unsigned long base, unsigned int irq)
++{
++ int ret;
++ struct ata_probe_ent ae;
++
++ memset(&ae, 0, sizeof(struct ata_probe_ent));
++ INIT_LIST_HEAD(&ae.node);
++
++ ae.mmio_base = ioremap(base, 0x1000);
++ if (ae.mmio_base == NULL)
++ return -ENOMEM;
++
++ if (request_region(base, 0x1000, "pata_ixp4xx") == NULL)
++ return -EBUSY;
++
++ ae.dev = NULL;
++ ae.port_ops = &ixp4xx_port_ops;
++ ae.sht = &ixp4xx_sht;
++ ae.n_ports = 1;
++ ae.pio_mask = IXP4XX_IDE_PIO_MASK;
++ ae.irq = irq;
++ ae.irq_flags = 0;
++ ae.host_flags = ATA_FLAG_IRQ_MASK | ATA_FLAG_MMIO;
++
++ ae.port[0].cmd_addr = (unsigned long) ae.mmio_base;
++ ae.port[0].altstatus_addr = (unsigned long) ae.mmio_base + IXP4XX_IDE_CONTROL;
++ ae.port[0].ctl_addr = (unsigned long) ae.mmio_base + IXP4XX_IDE_CONTROL;
++ ata_std_ports(&ae.port[0]);
++
++#ifndef __ARMEB__
++ ixp4xx_fix_le_ports(&ae.port[0]);
++#endif
++ ret = ata_device_add(&ae);
++ if (ret == 0)
++ return -ENODEV;
++
++ ixp4xx_host = ae.host_set;
++ return 0;
++}
++
++static __init int ixp4xx_init(void)
++{
++ gpio_line_config(IXP4XX_IDE_INT, IXP4XX_GPIO_IN | IXP4XX_GPIO_STYLE_ACTIVE_HIGH);
++
++ *IXP4XX_EXP_CS1 |= IXP4XX_IDE_CS1_BITS;
++
++ if (ixp4xx_init_one(IXP4XX_IDE_BASE, IXP4XX_IDE_INT) == 0)
++ return 0;
++
++ return -ENODEV;
++}
++
++static __exit void ixp4xx_exit(void)
++{
++ if (ixp4xx_host)
++ ata_host_set_remove(ixp4xx_host);
++}
++
++MODULE_AUTHOR("Alessandro Zummo");
++MODULE_DESCRIPTION("low-level driver for ixp4xx CF/ATA");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(ixp4xx_init);
++module_exit(ixp4xx_exit);
+--- linux-ixp4xx.orig/drivers/scsi/libata-core.c 2006-02-24 18:13:55.000000000 +0100
++++ linux-ixp4xx/drivers/scsi/libata-core.c 2006-02-24 18:16:46.000000000 +0100
+@@ -2513,8 +2513,8 @@ static void ata_dev_set_xfermode(struct
+ tf.nsect = dev->xfer_mode;
+
+ if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+- printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+- ap->id);
++ printk(KERN_ERR "ata%u: failed to set xfermode (0x%02x), disabled\n",
++ ap->id, dev->xfer_mode);
+ ata_port_disable(ap);
+ }
+