1 /* 2 * Marvell PATA driver. 3 * 4 * For the moment we drive the PATA port in legacy mode. That 5 * isn't making full use of the device functionality but it is 6 * easy to get working. 7 * 8 * (c) 2006 Red Hat <alan@redhat.com> 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/pci.h> 14 #include <linux/init.h> 15 #include <linux/blkdev.h> 16 #include <linux/delay.h> 17 #include <linux/device.h> 18 #include <scsi/scsi_host.h> 19 #include <linux/libata.h> 20 #include <linux/ata.h> 21 22 #define DRV_NAME "pata_marvell" 23 #define DRV_VERSION "0.1.4" 24 25 /** 26 * marvell_pre_reset - check for 40/80 pin 27 * @link: link 28 * @deadline: deadline jiffies for the operation 29 * 30 * Perform the PATA port setup we need. 31 */ 32 33 static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) 34 { 35 struct ata_port *ap = link->ap; 36 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 37 u32 devices; 38 void __iomem *barp; 39 int i; 40 41 /* Check if our port is enabled */ 42 43 barp = pci_iomap(pdev, 5, 0x10); 44 if (barp == NULL) 45 return -ENOMEM; 46 printk("BAR5:"); 47 for(i = 0; i <= 0x0F; i++) 48 printk("%02X:%02X ", i, ioread8(barp + i)); 49 printk("\n"); 50 51 devices = ioread32(barp + 0x0C); 52 pci_iounmap(pdev, barp); 53 54 if ((pdev->device == 0x6145) && (ap->port_no == 0) && 55 (!(devices & 0x10))) /* PATA enable ? */ 56 return -ENOENT; 57 58 return ata_sff_prereset(link, deadline); 59 } 60 61 static int marvell_cable_detect(struct ata_port *ap) 62 { 63 /* Cable type */ 64 switch(ap->port_no) 65 { 66 case 0: 67 if (ioread8(ap->ioaddr.bmdma_addr + 1) & 1) 68 return ATA_CBL_PATA40; 69 return ATA_CBL_PATA80; 70 case 1: /* Legacy SATA port */ 71 return ATA_CBL_SATA; 72 } 73 74 BUG(); 75 return 0; /* Our BUG macro needs the right markup */ 76 } 77 78 /* No PIO or DMA methods needed for this device */ 79 80 static struct scsi_host_template marvell_sht = { 81 ATA_BMDMA_SHT(DRV_NAME), 82 }; 83 84 static struct ata_port_operations marvell_ops = { 85 .inherits = &ata_bmdma_port_ops, 86 .cable_detect = marvell_cable_detect, 87 .prereset = marvell_pre_reset, 88 }; 89 90 91 /** 92 * marvell_init_one - Register Marvell ATA PCI device with kernel services 93 * @pdev: PCI device to register 94 * @ent: Entry in marvell_pci_tbl matching with @pdev 95 * 96 * Called from kernel PCI layer. 97 * 98 * LOCKING: 99 * Inherited from PCI layer (may sleep). 100 * 101 * RETURNS: 102 * Zero on success, or -ERRNO value. 103 */ 104 105 static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id) 106 { 107 static const struct ata_port_info info = { 108 .flags = ATA_FLAG_SLAVE_POSS, 109 110 .pio_mask = 0x1f, 111 .mwdma_mask = 0x07, 112 .udma_mask = ATA_UDMA5, 113 114 .port_ops = &marvell_ops, 115 }; 116 static const struct ata_port_info info_sata = { 117 /* Slave possible as its magically mapped not real */ 118 .flags = ATA_FLAG_SLAVE_POSS, 119 120 .pio_mask = 0x1f, 121 .mwdma_mask = 0x07, 122 .udma_mask = ATA_UDMA6, 123 124 .port_ops = &marvell_ops, 125 }; 126 const struct ata_port_info *ppi[] = { &info, &info_sata }; 127 128 if (pdev->device == 0x6101) 129 ppi[1] = &ata_dummy_port_info; 130 131 return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL); 132 } 133 134 static const struct pci_device_id marvell_pci_tbl[] = { 135 { PCI_DEVICE(0x11AB, 0x6101), }, 136 { PCI_DEVICE(0x11AB, 0x6121), }, 137 { PCI_DEVICE(0x11AB, 0x6123), }, 138 { PCI_DEVICE(0x11AB, 0x6145), }, 139 { } /* terminate list */ 140 }; 141 142 static struct pci_driver marvell_pci_driver = { 143 .name = DRV_NAME, 144 .id_table = marvell_pci_tbl, 145 .probe = marvell_init_one, 146 .remove = ata_pci_remove_one, 147 #ifdef CONFIG_PM 148 .suspend = ata_pci_device_suspend, 149 .resume = ata_pci_device_resume, 150 #endif 151 }; 152 153 static int __init marvell_init(void) 154 { 155 return pci_register_driver(&marvell_pci_driver); 156 } 157 158 static void __exit marvell_exit(void) 159 { 160 pci_unregister_driver(&marvell_pci_driver); 161 } 162 163 module_init(marvell_init); 164 module_exit(marvell_exit); 165 166 MODULE_AUTHOR("Alan Cox"); 167 MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode"); 168 MODULE_LICENSE("GPL"); 169 MODULE_DEVICE_TABLE(pci, marvell_pci_tbl); 170 MODULE_VERSION(DRV_VERSION); 171 172