diff options
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.patch | 299 |
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); + } + |