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/init.h> 22 #include <linux/blkdev.h> 23 #include <linux/delay.h> 24 #include <scsi/scsi_host.h> 25 #include <linux/libata.h> 26 27 #define DRV_NAME "pata_piccolo" 28 #define DRV_VERSION "0.0.1" 29 30 31 32 static void tosh_set_piomode(struct ata_port *ap, struct ata_device *adev) 33 { 34 static const u16 pio[6] = { /* For reg 0x50 low word & E088 */ 35 0x0566, 0x0433, 0x0311, 0x0201, 0x0200, 0x0100 36 }; 37 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 38 u16 conf; 39 pci_read_config_word(pdev, 0x50, &conf); 40 conf &= 0xE088; 41 conf |= pio[adev->pio_mode - XFER_PIO_0]; 42 pci_write_config_word(pdev, 0x50, conf); 43 } 44 45 static void tosh_set_dmamode(struct ata_port *ap, struct ata_device *adev) 46 { 47 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 48 u32 conf; 49 pci_read_config_dword(pdev, 0x5C, &conf); 50 conf &= 0x78FFE088; /* Keep the other bits */ 51 if (adev->dma_mode >= XFER_UDMA_0) { 52 int udma = adev->dma_mode - XFER_UDMA_0; 53 conf |= 0x80000000; 54 conf |= (udma + 2) << 28; 55 conf |= (2 - udma) * 0x111; /* spread into three nibbles */ 56 } else { 57 static const u32 mwdma[4] = { 58 0x0655, 0x0200, 0x0200, 0x0100 59 }; 60 conf |= mwdma[adev->dma_mode - XFER_MW_DMA_0]; 61 } 62 pci_write_config_dword(pdev, 0x5C, conf); 63 } 64 65 66 static struct scsi_host_template tosh_sht = { 67 ATA_BMDMA_SHT(DRV_NAME), 68 }; 69 70 static struct ata_port_operations tosh_port_ops = { 71 .inherits = &ata_bmdma_port_ops, 72 .cable_detect = ata_cable_unknown, 73 .set_piomode = tosh_set_piomode, 74 .set_dmamode = tosh_set_dmamode 75 }; 76 77 /** 78 * ata_tosh_init - attach generic IDE 79 * @dev: PCI device found 80 * @id: match entry 81 * 82 * Called each time a matching IDE interface is found. We check if the 83 * interface is one we wish to claim and if so we perform any chip 84 * specific hacks then let the ATA layer do the heavy lifting. 85 */ 86 87 static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id) 88 { 89 static const struct ata_port_info info = { 90 .flags = ATA_FLAG_SLAVE_POSS, 91 .pio_mask = ATA_PIO5, 92 .mwdma_mask = ATA_MWDMA2, 93 .udma_mask = ATA_UDMA2, 94 .port_ops = &tosh_port_ops 95 }; 96 const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; 97 /* Just one port for the moment */ 98 return ata_pci_bmdma_init_one(dev, ppi, &tosh_sht, NULL, 0); 99 } 100 101 static struct pci_device_id ata_tosh[] = { 102 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, 103 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, 104 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3), }, 105 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), }, 106 { 0, }, 107 }; 108 109 static struct pci_driver ata_tosh_pci_driver = { 110 .name = DRV_NAME, 111 .id_table = ata_tosh, 112 .probe = ata_tosh_init_one, 113 .remove = ata_pci_remove_one, 114 #ifdef CONFIG_PM 115 .suspend = ata_pci_device_suspend, 116 .resume = ata_pci_device_resume, 117 #endif 118 }; 119 120 module_pci_driver(ata_tosh_pci_driver); 121 122 MODULE_AUTHOR("Alan Cox"); 123 MODULE_DESCRIPTION("Low level driver for Toshiba Piccolo ATA"); 124 MODULE_LICENSE("GPL"); 125 MODULE_DEVICE_TABLE(pci, ata_tosh); 126 MODULE_VERSION(DRV_VERSION); 127