From: Bartlomiej Zolnierkiewicz <bzolnier@xxxxxxxxx> Subject: [PATCH] pata_sil680: move code to be re-used by ide2libata to pata_sil680.h Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@xxxxxxxxx> --- drivers/ata/pata_sil680.c | 236 ---------------------------------------------- drivers/ata/pata_sil680.h | 235 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 235 deletions(-) Index: b/drivers/ata/pata_sil680.c =================================================================== --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -36,160 +36,7 @@ #define SIL680_MMIO_BAR 5 -/** - * sil680_selreg - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * Thankfully this is a configuration operation so isnt performance - * criticial. - */ - -static unsigned long sil680_selreg(struct ata_port *ap, int r) -{ - unsigned long base = 0xA0 + r; - base += (ap->port_no << 4); - return base; -} - -/** - * sil680_seldev - return register base - * @hwif: interface - * @r: config offset - * - * Turn a config register offset into the right address in either - * PCI space or MMIO space to access the control register in question - * including accounting for the unit shift. - */ - -static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) -{ - unsigned long base = 0xA0 + r; - base += (ap->port_no << 4); - base |= adev->devno ? 2 : 0; - return base; -} - - -/** - * sil680_cable_detect - cable detection - * @ap: ATA port - * - * Perform cable detection. The SIL680 stores this in PCI config - * space for us. - */ - -static int sil680_cable_detect(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long addr = sil680_selreg(ap, 0); - u8 ata66; - pci_read_config_byte(pdev, addr, &ata66); - if (ata66 & 1) - return ATA_CBL_PATA80; - else - return ATA_CBL_PATA40; -} - -/** - * sil680_set_piomode - set initial PIO mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the SIL680 registers for PIO mode. Note that the task speed - * registers are shared between the devices so we must pick the lowest - * mode for command work. - */ - -static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; - static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 }; - - unsigned long tfaddr = sil680_selreg(ap, 0x02); - unsigned long addr = sil680_seldev(ap, adev, 0x04); - unsigned long addr_mask = 0x80 + 4 * ap->port_no; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - int pio = adev->pio_mode - XFER_PIO_0; - int lowest_pio = pio; - int port_shift = 4 * adev->devno; - u16 reg; - u8 mode; - - struct ata_device *pair = ata_dev_pair(adev); - - if (pair != NULL && adev->pio_mode > pair->pio_mode) - lowest_pio = pair->pio_mode - XFER_PIO_0; - - pci_write_config_word(pdev, addr, speed_p[pio]); - pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]); - - pci_read_config_word(pdev, tfaddr-2, ®); - pci_read_config_byte(pdev, addr_mask, &mode); - - reg &= ~0x0200; /* Clear IORDY */ - mode &= ~(3 << port_shift); /* Clear IORDY and DMA bits */ - - if (ata_pio_need_iordy(adev)) { - reg |= 0x0200; /* Enable IORDY */ - mode |= 1 << port_shift; - } - pci_write_config_word(pdev, tfaddr-2, reg); - pci_write_config_byte(pdev, addr_mask, mode); -} - -/** - * sil680_set_dmamode - set initial DMA mode data - * @ap: ATA interface - * @adev: ATA device - * - * Program the MWDMA/UDMA modes for the sil680 k - * chipset. The MWDMA mode values are pulled from a lookup table - * while the chipset uses mode number for UDMA. - */ - -static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - static u8 ultra_table[2][7] = { - { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ - { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ - }; - static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; - - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long ma = sil680_seldev(ap, adev, 0x08); - unsigned long ua = sil680_seldev(ap, adev, 0x0C); - unsigned long addr_mask = 0x80 + 4 * ap->port_no; - int port_shift = adev->devno * 4; - u8 scsc, mode; - u16 multi, ultra; - - pci_read_config_byte(pdev, 0x8A, &scsc); - pci_read_config_byte(pdev, addr_mask, &mode); - pci_read_config_word(pdev, ma, &multi); - pci_read_config_word(pdev, ua, &ultra); - - /* Mask timing bits */ - ultra &= ~0x3F; - mode &= ~(0x03 << port_shift); - - /* Extract scsc */ - scsc = (scsc & 0x30) ? 1 : 0; - - if (adev->dma_mode >= XFER_UDMA_0) { - multi = 0x10C1; - ultra |= ultra_table[scsc][adev->dma_mode - XFER_UDMA_0]; - mode |= (0x03 << port_shift); - } else { - multi = dma_table[adev->dma_mode - XFER_MW_DMA_0]; - mode |= (0x02 << port_shift); - } - pci_write_config_byte(pdev, addr_mask, mode); - pci_write_config_word(pdev, ma, multi); - pci_write_config_word(pdev, ua, ultra); -} +#include "pata_sil680.h" static struct scsi_host_template sil680_sht = { ATA_BMDMA_SHT(DRV_NAME), @@ -202,87 +49,6 @@ static struct ata_port_operations sil680 .set_dmamode = sil680_set_dmamode, }; -/** - * sil680_init_chip - chip setup - * @pdev: PCI device - * - * Perform all the chip setup which must be done both when the device - * is powered up on boot and when we resume in case we resumed from RAM. - * Returns the final clock settings. - */ - -static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) -{ - u8 tmpbyte = 0; - - /* FIXME: double check */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, - pdev->revision ? 1 : 255); - - pci_write_config_byte(pdev, 0x80, 0x00); - pci_write_config_byte(pdev, 0x84, 0x00); - - pci_read_config_byte(pdev, 0x8A, &tmpbyte); - - dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); - - *try_mmio = 0; -#ifdef CONFIG_PPC - if (machine_is(cell)) - *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); -#endif - - switch (tmpbyte & 0x30) { - case 0x00: - /* 133 clock attempt to force it on */ - pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); - break; - case 0x30: - /* if clocking is disabled */ - /* 133 clock attempt to force it on */ - pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); - break; - case 0x10: - /* 133 already */ - break; - case 0x20: - /* BIOS set PCI x2 clocking */ - break; - } - - pci_read_config_byte(pdev, 0x8A, &tmpbyte); - dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); - - pci_write_config_byte(pdev, 0xA1, 0x72); - pci_write_config_word(pdev, 0xA2, 0x328A); - pci_write_config_dword(pdev, 0xA4, 0x62DD62DD); - pci_write_config_dword(pdev, 0xA8, 0x43924392); - pci_write_config_dword(pdev, 0xAC, 0x40094009); - pci_write_config_byte(pdev, 0xB1, 0x72); - pci_write_config_word(pdev, 0xB2, 0x328A); - pci_write_config_dword(pdev, 0xB4, 0x62DD62DD); - pci_write_config_dword(pdev, 0xB8, 0x43924392); - pci_write_config_dword(pdev, 0xBC, 0x40094009); - - switch (tmpbyte & 0x30) { - case 0x00: - printk(KERN_INFO "sil680: 100MHz clock.\n"); - break; - case 0x10: - printk(KERN_INFO "sil680: 133MHz clock.\n"); - break; - case 0x20: - printk(KERN_INFO "sil680: Using PCI clock.\n"); - break; - /* This last case is _NOT_ ok */ - case 0x30: - printk(KERN_ERR "sil680: Clock disabled ?\n"); - } - return tmpbyte & 0x30; -} - static int __devinit sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { Index: b/drivers/ata/pata_sil680.h =================================================================== --- /dev/null +++ b/drivers/ata/pata_sil680.h @@ -0,0 +1,235 @@ +/** + * sil680_selreg - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * Thankfully this is a configuration operation so isnt performance + * criticial. + */ + +static unsigned long sil680_selreg(struct ata_port *ap, int r) +{ + unsigned long base = 0xA0 + r; + base += (ap->port_no << 4); + return base; +} + +/** + * sil680_seldev - return register base + * @hwif: interface + * @r: config offset + * + * Turn a config register offset into the right address in either + * PCI space or MMIO space to access the control register in question + * including accounting for the unit shift. + */ + +static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) +{ + unsigned long base = 0xA0 + r; + base += (ap->port_no << 4); + base |= adev->devno ? 2 : 0; + return base; +} + + +/** + * sil680_cable_detect - cable detection + * @ap: ATA port + * + * Perform cable detection. The SIL680 stores this in PCI config + * space for us. + */ + +static int sil680_cable_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + unsigned long addr = sil680_selreg(ap, 0); + u8 ata66; + pci_read_config_byte(pdev, addr, &ata66); + if (ata66 & 1) + return ATA_CBL_PATA80; + else + return ATA_CBL_PATA40; +} + +/** + * sil680_set_piomode - set initial PIO mode data + * @ap: ATA interface + * @adev: ATA device + * + * Program the SIL680 registers for PIO mode. Note that the task speed + * registers are shared between the devices so we must pick the lowest + * mode for command work. + */ + +static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; + static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 }; + + unsigned long tfaddr = sil680_selreg(ap, 0x02); + unsigned long addr = sil680_seldev(ap, adev, 0x04); + unsigned long addr_mask = 0x80 + 4 * ap->port_no; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + int pio = adev->pio_mode - XFER_PIO_0; + int lowest_pio = pio; + int port_shift = 4 * adev->devno; + u16 reg; + u8 mode; + + struct ata_device *pair = ata_dev_pair(adev); + + if (pair != NULL && adev->pio_mode > pair->pio_mode) + lowest_pio = pair->pio_mode - XFER_PIO_0; + + pci_write_config_word(pdev, addr, speed_p[pio]); + pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]); + + pci_read_config_word(pdev, tfaddr-2, ®); + pci_read_config_byte(pdev, addr_mask, &mode); + + reg &= ~0x0200; /* Clear IORDY */ + mode &= ~(3 << port_shift); /* Clear IORDY and DMA bits */ + + if (ata_pio_need_iordy(adev)) { + reg |= 0x0200; /* Enable IORDY */ + mode |= 1 << port_shift; + } + pci_write_config_word(pdev, tfaddr-2, reg); + pci_write_config_byte(pdev, addr_mask, mode); +} + +/** + * sil680_set_dmamode - set initial DMA mode data + * @ap: ATA interface + * @adev: ATA device + * + * Program the MWDMA/UDMA modes for the sil680 k + * chipset. The MWDMA mode values are pulled from a lookup table + * while the chipset uses mode number for UDMA. + */ + +static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ + static u8 ultra_table[2][7] = { + { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ + { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ + }; + static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; + + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + unsigned long ma = sil680_seldev(ap, adev, 0x08); + unsigned long ua = sil680_seldev(ap, adev, 0x0C); + unsigned long addr_mask = 0x80 + 4 * ap->port_no; + int port_shift = adev->devno * 4; + u8 scsc, mode; + u16 multi, ultra; + + pci_read_config_byte(pdev, 0x8A, &scsc); + pci_read_config_byte(pdev, addr_mask, &mode); + pci_read_config_word(pdev, ma, &multi); + pci_read_config_word(pdev, ua, &ultra); + + /* Mask timing bits */ + ultra &= ~0x3F; + mode &= ~(0x03 << port_shift); + + /* Extract scsc */ + scsc = (scsc & 0x30) ? 1 : 0; + + if (adev->dma_mode >= XFER_UDMA_0) { + multi = 0x10C1; + ultra |= ultra_table[scsc][adev->dma_mode - XFER_UDMA_0]; + mode |= (0x03 << port_shift); + } else { + multi = dma_table[adev->dma_mode - XFER_MW_DMA_0]; + mode |= (0x02 << port_shift); + } + pci_write_config_byte(pdev, addr_mask, mode); + pci_write_config_word(pdev, ma, multi); + pci_write_config_word(pdev, ua, ultra); +} + +/** + * sil680_init_chip - chip setup + * @pdev: PCI device + * + * Perform all the chip setup which must be done both when the device + * is powered up on boot and when we resume in case we resumed from RAM. + * Returns the final clock settings. + */ + +static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) +{ + u8 tmpbyte = 0; + + /* FIXME: double check */ + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + pdev->revision ? 1 : 255); + + pci_write_config_byte(pdev, 0x80, 0x00); + pci_write_config_byte(pdev, 0x84, 0x00); + + pci_read_config_byte(pdev, 0x8A, &tmpbyte); + + dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", + tmpbyte & 1, tmpbyte & 0x30); + + *try_mmio = 0; +#ifdef CONFIG_PPC + if (machine_is(cell)) + *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); +#endif + + switch (tmpbyte & 0x30) { + case 0x00: + /* 133 clock attempt to force it on */ + pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); + break; + case 0x30: + /* if clocking is disabled */ + /* 133 clock attempt to force it on */ + pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); + break; + case 0x10: + /* 133 already */ + break; + case 0x20: + /* BIOS set PCI x2 clocking */ + break; + } + + pci_read_config_byte(pdev, 0x8A, &tmpbyte); + dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", + tmpbyte & 1, tmpbyte & 0x30); + + pci_write_config_byte(pdev, 0xA1, 0x72); + pci_write_config_word(pdev, 0xA2, 0x328A); + pci_write_config_dword(pdev, 0xA4, 0x62DD62DD); + pci_write_config_dword(pdev, 0xA8, 0x43924392); + pci_write_config_dword(pdev, 0xAC, 0x40094009); + pci_write_config_byte(pdev, 0xB1, 0x72); + pci_write_config_word(pdev, 0xB2, 0x328A); + pci_write_config_dword(pdev, 0xB4, 0x62DD62DD); + pci_write_config_dword(pdev, 0xB8, 0x43924392); + pci_write_config_dword(pdev, 0xBC, 0x40094009); + + switch (tmpbyte & 0x30) { + case 0x00: + printk(KERN_INFO "sil680: 100MHz clock.\n"); + break; + case 0x10: + printk(KERN_INFO "sil680: 133MHz clock.\n"); + break; + case 0x20: + printk(KERN_INFO "sil680: Using PCI clock.\n"); + break; + /* This last case is _NOT_ ok */ + case 0x30: + printk(KERN_ERR "sil680: Clock disabled ?\n"); + } + return tmpbyte & 0x30; +} -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html