From 75742cb41e4b5c7913f385b9688aad69c9fa7ada Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:40:06 +0100 Subject: [PATCH] pata_marvell: Marvell 6101/6145 PATA driver This is a legacy mode PATA driver for the 6101/45 and will also drive the SATA ports 1 & 2 in legacy mode as well if desired. Tested and confirmed working by users. The chip supports AHCI type behaviour for SATA and has a more advanced PATA interface as well so this driver will get it working but not get best performance for now. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_marvell.c | 221 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 drivers/ata/pata_marvell.c (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c new file mode 100644 index 000000000000..2b8e00cb7b9b --- /dev/null +++ b/drivers/ata/pata_marvell.c @@ -0,0 +1,221 @@ +/* + * Marvell PATA driver. + * + * For the moment we drive the PATA port in legacy mode. That + * isn't making full use of the device functionality but it is + * easy to get working. + * + * (c) 2006 Red Hat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pata_marvell" +#define DRV_VERSION "0.0.4t" + +/** + * marvell_pre_reset - check for 40/80 pin + * @ap: Port + * + * Perform the PATA port setup we need. + */ + +static int marvell_pre_reset(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u32 devices; + unsigned long bar5; + void __iomem *barp; + int i; + + /* Check if our port is enabled */ + + bar5 = pci_resource_start(pdev, 5); + barp = ioremap(bar5, 0x10); + if (barp == NULL) + return -ENOMEM; + printk("BAR5:"); + for(i = 0; i <= 0x0F; i++) + printk("%02X:%02X ", i, readb(barp + i)); + printk("\n"); + + devices = readl(barp + 0x0C); + iounmap(barp); + + if (pdev->device == 0x6145 && ap->port_no == 0 && !(devices & 0x10)) /* PATA enable ? */ + return -ENOENT; + + /* Cable type */ + switch(ap->port_no) + { + case 0: + /* Might be backward, docs unclear */ + if(inb(ap->ioaddr.bmdma_addr + 1) & 1) + ap->cbl = ATA_CBL_PATA80; + else + ap->cbl = ATA_CBL_PATA40; + + case 1: /* Legacy SATA port */ + ap->cbl = ATA_CBL_SATA; + break; + } + return ata_std_prereset(ap); +} + +/** + * marvell_error_handler - Setup and error handler + * @ap: Port to handle + * + * LOCKING: + * None (inherited from caller). + */ + +static void marvell_error_handler(struct ata_port *ap) +{ + return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL, ata_std_postreset); +} + +/* No PIO or DMA methods needed for this device */ + +static struct scsi_host_template marvell_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, + /* Use standard CHS mapping rules */ + .bios_param = ata_std_bios_param, +}; + +static const struct ata_port_operations marvell_ops = { + .port_disable = ata_port_disable, + + /* Task file is PCI ATA format, use helpers */ + .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, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = marvell_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + /* BMDMA handling is PCI ATA format, use helpers */ + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, + + /* Timeout handling */ + .eng_timeout = ata_eng_timeout, + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + /* Generic PATA PCI ATA helpers */ + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + + +/** + * marvell_init_one - Register Marvell ATA PCI device with kernel services + * @pdev: PCI device to register + * @ent: Entry in marvell_pci_tbl matching with @pdev + * + * Called from kernel PCI layer. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, or -ERRNO value. + */ + +static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id) +{ + static struct ata_port_info info = { + .sht = &marvell_sht, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x3f, + + .port_ops = &marvell_ops, + }; + static struct ata_port_info info_sata = { + .sht = &marvell_sht, + /* Slave possible as its magically mapped not real */ + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x7f, + + .port_ops = &marvell_ops, + }; + struct ata_port_info *port_info[2] = { &info, &info_sata }; + int n_port = 2; + + if (pdev->device == 0x6101) + n_port = 1; + + return ata_pci_init_one(pdev, port_info, n_port); +} + +static const struct pci_device_id marvell_pci_tbl[] = { + { PCI_DEVICE(0x11AB, 0x6101), }, + { PCI_DEVICE(0x11AB, 0x6145), }, + { } /* terminate list */ +}; + +static struct pci_driver marvell_pci_driver = { + .name = DRV_NAME, + .id_table = marvell_pci_tbl, + .probe = marvell_init_one, + .remove = ata_pci_remove_one, +}; + +static int __init marvell_init(void) +{ + return pci_register_driver(&marvell_pci_driver); +} + +static void __exit marvell_exit(void) +{ + pci_unregister_driver(&marvell_pci_driver); +} + +module_init(marvell_init); +module_exit(marvell_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, marvell_pci_tbl); +MODULE_VERSION(DRV_VERSION); + -- cgit v1.2.3 From 6e9d8629b5503175a4425722a1ef13eed232c650 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 21 Oct 2006 15:54:13 -0400 Subject: [libata] pata_marvell: minor and trivial cleanups - use pci_iomap() [Alan, version 0.0.5t] - fix Alan's version 0.0.5t change - line length, trailing whitespace, case indentation cleanups - don't use deprecated ->eng_timeout() in a driver that uses new EH Signed-off-by: Jeff Garzik --- drivers/ata/pata_marvell.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 2b8e00cb7b9b..1ea64075c783 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -20,7 +20,7 @@ #include #define DRV_NAME "pata_marvell" -#define DRV_VERSION "0.0.4t" +#define DRV_VERSION "0.0.5u" /** * marvell_pre_reset - check for 40/80 pin @@ -33,14 +33,12 @@ static int marvell_pre_reset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 devices; - unsigned long bar5; void __iomem *barp; int i; /* Check if our port is enabled */ - bar5 = pci_resource_start(pdev, 5); - barp = ioremap(bar5, 0x10); + barp = pci_iomap(pdev, 5, 0x10); if (barp == NULL) return -ENOMEM; printk("BAR5:"); @@ -49,24 +47,25 @@ static int marvell_pre_reset(struct ata_port *ap) printk("\n"); devices = readl(barp + 0x0C); - iounmap(barp); + pci_iounmap(pdev, barp); - if (pdev->device == 0x6145 && ap->port_no == 0 && !(devices & 0x10)) /* PATA enable ? */ + if ((pdev->device == 0x6145) && (ap->port_no == 0) && + (!(devices & 0x10))) /* PATA enable ? */ return -ENOENT; /* Cable type */ switch(ap->port_no) { - case 0: - /* Might be backward, docs unclear */ - if(inb(ap->ioaddr.bmdma_addr + 1) & 1) - ap->cbl = ATA_CBL_PATA80; - else - ap->cbl = ATA_CBL_PATA40; - - case 1: /* Legacy SATA port */ - ap->cbl = ATA_CBL_SATA; - break; + case 0: + /* Might be backward, docs unclear */ + if (inb(ap->ioaddr.bmdma_addr + 1) & 1) + ap->cbl = ATA_CBL_PATA80; + else + ap->cbl = ATA_CBL_PATA40; + + case 1: /* Legacy SATA port */ + ap->cbl = ATA_CBL_SATA; + break; } return ata_std_prereset(ap); } @@ -81,7 +80,8 @@ static int marvell_pre_reset(struct ata_port *ap) static void marvell_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL, ata_std_postreset); + return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, + NULL, ata_std_postreset); } /* No PIO or DMA methods needed for this device */ @@ -130,7 +130,6 @@ static const struct ata_port_operations marvell_ops = { .data_xfer = ata_pio_data_xfer, /* Timeout handling */ - .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -159,7 +158,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i { static struct ata_port_info info = { .sht = &marvell_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -170,7 +169,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i static struct ata_port_info info_sata = { .sht = &marvell_sht, /* Slave possible as its magically mapped not real */ - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, @@ -180,10 +179,10 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i }; struct ata_port_info *port_info[2] = { &info, &info_sata }; int n_port = 2; - + if (pdev->device == 0x6101) n_port = 1; - + return ata_pci_init_one(pdev, port_info, n_port); } -- cgit v1.2.3 From 30ced0f0d211999f316930eff7287aa5a9995bef Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 22 Nov 2006 16:57:36 +0000 Subject: [PATCH] PATA libata: suspend/resume simple cases This patch adds the suspend/resume callbacks for drivers which don't need any additional help (beyond the pci resume quirk patch I posted earlier anyway). Also bring version numbers back inline with master copies. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_marvell.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 1ea64075c783..a5953c389264 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -20,7 +20,7 @@ #include #define DRV_NAME "pata_marvell" -#define DRV_VERSION "0.0.5u" +#define DRV_VERSION "0.1.1" /** * marvell_pre_reset - check for 40/80 pin @@ -103,6 +103,8 @@ static struct scsi_host_template marvell_sht = { .slave_configure = ata_scsi_slave_config, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, }; static const struct ata_port_operations marvell_ops = { @@ -197,6 +199,8 @@ static struct pci_driver marvell_pci_driver = { .id_table = marvell_pci_tbl, .probe = marvell_init_one, .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, }; static int __init marvell_init(void) -- cgit v1.2.3 From 099156db555aabf54dc80b40abb628ce35d90065 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 27 Nov 2006 16:37:52 +0000 Subject: [PATCH] pata_marvell: merge Mandriva patches Correct and complete the Marvell PATA cable detection logic. From: Arnaud Patard Signed-off-by: Arnaud Patard Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_marvell.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index a5953c389264..25f7a79a8e25 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -57,11 +57,11 @@ static int marvell_pre_reset(struct ata_port *ap) switch(ap->port_no) { case 0: - /* Might be backward, docs unclear */ if (inb(ap->ioaddr.bmdma_addr + 1) & 1) - ap->cbl = ATA_CBL_PATA80; - else ap->cbl = ATA_CBL_PATA40; + else + ap->cbl = ATA_CBL_PATA80; + break; case 1: /* Legacy SATA port */ ap->cbl = ATA_CBL_SATA; -- cgit v1.2.3 From c972b60bf167a3d2c3da23df2af1eac93229e7cc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 29 Nov 2006 12:10:46 +0900 Subject: [PATCH] libata: add missing sht->slave_destroy Add missing sht->slave_destroy. Most drivers received this fix in didn't. Fix those four drives. Signed-off-by: Tejun Heo --- drivers/ata/pata_marvell.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 25f7a79a8e25..3f53be4607a0 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -101,6 +101,7 @@ static struct scsi_host_template marvell_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, .resume = ata_scsi_device_resume, -- cgit v1.2.3 From 2eab80ac0c96fb98267afeb12a4899801564c75b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 29 Nov 2006 12:20:26 +0900 Subject: [PATCH] libata: kill unnecessary sht->max_sectors initializations sht->max_sectors is overrided unconditionally in ->slave_configure. There's no reason to set it to any value. Signed-off-by: Tejun Heo --- drivers/ata/pata_marvell.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ata/pata_marvell.c') diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 3f53be4607a0..1c810ea00253 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -94,7 +94,6 @@ static struct scsi_host_template marvell_sht = { .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, -- cgit v1.2.3