1 /* 2 * pata_piccolo.c - Toshiba Piccolo PATA/SATA controller driver. 3 * 4 * This is basically an update to ata_generic.c to add Toshiba Piccolo support 5 * then split out to keep ata_generic "clean". 6 * 7 * Copyright 2005 Red Hat Inc, all rights reserved. 8 * 9 * Elements from ide/pci/generic.c 10 * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> 11 * Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com> 12 * 13 * May be copied or modified under the terms of the GNU General Public License 14 * 15 * The timing data tables/programming info are courtesy of the NetBSD driver 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/pci.h> 21 #include <linux/blkdev.h> 22 #include <linux/delay.h> 23 #include <scsi/scsi_host.h> 24 #include <linux/libata.h> 25 26 #define DRV_NAME "pata_piccolo" 27 #define DRV_VERSION "0.0.1" 28 29 30 31 static void tosh_set_piomode(struct ata_port *ap, struct ata_device *adev) 32 { 33 static const u16 pio[6] = { /* For reg 0x50 low word & E088 */ 34 0x0566, 0x0433, 0x0311, 0x0201, 0x0200, 0x0100 35 }; 36 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 37 u16 conf; 38 pci_read_config_word(pdev, 0x50, &conf); 39 conf &= 0xE088; 40 conf |= pio[adev->pio_mode - XFER_PIO_0]; 41 pci_write_config_word(pdev, 0x50, conf); 42 } 43 44 static void tosh_set_dmamode(struct ata_port *ap, struct ata_device *adev) 45 { 46 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 47 u32 conf; 48 pci_read_config_dword(pdev, 0x5C, &conf); 49 conf &= 0x78FFE088; /* Keep the other bits */ 50 if (adev->dma_mode >= XFER_UDMA_0) { 51 int udma = adev->dma_mode - XFER_UDMA_0; 52 conf |= 0x80000000; 53 conf |= (udma + 2) << 28; 54 conf |= (2 - udma) * 0x111; /* spread into three nibbles */ 55 } else { 56 static const u32 mwdma[4] = { 57 0x0655, 0x0200, 0x0200, 0x0100 58 }; 59 conf |= mwdma[adev->dma_mode - XFER_MW_DMA_0]; 60 } 61 pci_write_config_dword(pdev, 0x5C, conf); 62 } 63 64 65 static struct scsi_host_template tosh_sht = { 66 ATA_BMDMA_SHT(DRV_NAME), 67 }; 68 69 static struct ata_port_operations tosh_port_ops = { 70 .inherits = &ata_bmdma_port_ops, 71 .cable_detect = ata_cable_unknown, 72 .set_piomode = tosh_set_piomode, 73 .set_dmamode = tosh_set_dmamode 74 }; 75 76 /** 77 * ata_tosh_init - attach generic IDE 78 * @dev: PCI device found 79 * @id: match entry 80 * 81 * Called each time a matching IDE interface is found. We check if the 82 * interface is one we wish to claim and if so we perform any chip 83 * specific hacks then let the ATA layer do the heavy lifting. 84 */ 85 86 static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id) 87 { 88 static const struct ata_port_info info = { 89 .flags = ATA_FLAG_SLAVE_POSS, 90 .pio_mask = ATA_PIO5, 91 .mwdma_mask = ATA_MWDMA2, 92 .udma_mask = ATA_UDMA2, 93 .port_ops = &tosh_port_ops 94 }; 95 const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; 96 /* Just one port for the moment */ 97 return ata_pci_bmdma_init_one(dev, ppi, &tosh_sht, NULL, 0); 98 } 99 100 static struct pci_device_id ata_tosh[] = { 101 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, 102 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, 103 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3), }, 104 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), }, 105 { 0, }, 106 }; 107 108 static struct pci_driver ata_tosh_pci_driver = { 109 .name = DRV_NAME, 110 .id_table = ata_tosh, 111 .probe = ata_tosh_init_one, 112 .remove = ata_pci_remove_one, 113 #ifdef CONFIG_PM_SLEEP 114 .suspend = ata_pci_device_suspend, 115 .resume = ata_pci_device_resume, 116 #endif 117 }; 118 119 module_pci_driver(ata_tosh_pci_driver); 120 121 MODULE_AUTHOR("Alan Cox"); 122 MODULE_DESCRIPTION("Low level driver for Toshiba Piccolo ATA"); 123 MODULE_LICENSE("GPL"); 124 MODULE_DEVICE_TABLE(pci, ata_tosh); 125 MODULE_VERSION(DRV_VERSION); 126