lkml.org 
[lkml]   [2011]   [Feb]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 18/20] ata_piix: add RDC support
    From 4cc4234e2049fa6e97d5a2d3643bb5499e52f838 Mon Sep 17 00:00:00 2001
    From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
    Date: Tue, 8 Feb 2011 12:39:28 +0100
    Subject: [PATCH 18/20] ata_piix: add RDC support

    Add RDC PATA support to ata_piix and remove no longer
    needed pata_rdc driver.

    Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
    ---
    drivers/ata/Kconfig | 1 +
    drivers/ata/Makefile | 1 -
    drivers/ata/ata_piix.c | 14 ++-
    drivers/ata/pata_rdc.c | 384 ------------------------------------------------
    4 files changed, 13 insertions(+), 387 deletions(-)
    delete mode 100644 drivers/ata/pata_rdc.c

    diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
    index 5a92f24..dc9038d 100644
    --- a/drivers/ata/Kconfig
    +++ b/drivers/ata/Kconfig
    @@ -567,6 +567,7 @@ config PATA_RADISYS
    config PATA_RDC
    tristate "RDC PATA support"
    depends on PCI
    + select ATA_PIIX
    help
    This option enables basic support for the later RDC PATA controllers
    controllers via the new ATA layer. For the RDC 1010, you need to
    diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
    index 7e78491..e627f6d 100644
    --- a/drivers/ata/Makefile
    +++ b/drivers/ata/Makefile
    @@ -58,7 +58,6 @@ obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
    obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
    obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
    obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
    -obj-$(CONFIG_PATA_RDC) += pata_rdc.o
    obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
    obj-$(CONFIG_PATA_SCC) += pata_scc.o
    obj-$(CONFIG_PATA_SCH) += pata_sch.o
    diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
    index deb7c96..86d12c2 100644
    --- a/drivers/ata/ata_piix.c
    +++ b/drivers/ata/ata_piix.c
    @@ -1,6 +1,9 @@
    /*
    * ata_piix.c - Intel PATA/SATA controllers
    *
    + * This is actually a driver for hardware meeting
    + * INCITS 370-2004 (1510D): ATA Host Adapter Standards
    + *
    * Maintained by: Jeff Garzik <jgarzik@pobox.com>
    * Please ALWAYS copy linux-ide@vger.kernel.org
    * on emails.
    @@ -249,6 +252,10 @@ static const struct pci_device_id piix_pci_tbl[] = {
    /* IT8213 */
    { 0x1283, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, it8213_pata },

    + /* RDC is ICH like */
    + { 0x17F3, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
    + { 0x17F3, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
    +
    /* SATA ports */

    /* 82801EB (ICH5) */
    @@ -665,6 +672,7 @@ MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
    MODULE_VERSION(DRV_VERSION);
    MODULE_ALIAS("pata_efar");
    MODULE_ALIAS("pata_it8213");
    +MODULE_ALIAS("pata_rdc");

    struct ich_laptop {
    u16 device;
    @@ -1670,7 +1678,8 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
    * because some ACPI implementations mess up cable related
    * bits on _STM. Reported on kernel bz#11879.
    */
    - if (pdev->vendor == PCI_VENDOR_ID_INTEL)
    + if (pdev->vendor == PCI_VENDOR_ID_INTEL ||
    + pdev->vendor == PCI_VENDOR_ID_RDC)
    pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg);

    /* ICH6R may be driven by either ata_piix or ahci driver
    @@ -1735,7 +1744,8 @@ static void piix_remove_one(struct pci_dev *pdev)
    struct ata_host *host = dev_get_drvdata(&pdev->dev);
    struct piix_host_priv *hpriv = host->private_data;

    - if (pdev->vendor == PCI_VENDOR_ID_INTEL)
    + if (pdev->vendor == PCI_VENDOR_ID_INTEL ||
    + pdev->vendor == PCI_VENDOR_ID_RDC)
    pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg);

    ata_pci_remove_one(pdev);
    diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
    deleted file mode 100644
    index a4a0d88..0000000
    --- a/drivers/ata/pata_rdc.c
    +++ /dev/null
    @@ -1,384 +0,0 @@
    -/*
    - * pata_rdc - Driver for later RDC PATA controllers
    - *
    - * This is actually a driver for hardware meeting
    - * INCITS 370-2004 (1510D): ATA Host Adapter Standards
    - *
    - * Based on ata_piix.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2, or (at your option)
    - * any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; see the file COPYING. If not, write to
    - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    - */
    -
    -#include <linux/kernel.h>
    -#include <linux/module.h>
    -#include <linux/pci.h>
    -#include <linux/init.h>
    -#include <linux/blkdev.h>
    -#include <linux/delay.h>
    -#include <linux/device.h>
    -#include <linux/gfp.h>
    -#include <scsi/scsi_host.h>
    -#include <linux/libata.h>
    -#include <linux/dmi.h>
    -
    -#define DRV_NAME "pata_rdc"
    -#define DRV_VERSION "0.01"
    -
    -struct rdc_host_priv {
    - u32 saved_iocfg;
    -};
    -
    -/**
    - * rdc_pata_cable_detect - Probe host controller cable detect info
    - * @ap: Port for which cable detect info is desired
    - *
    - * Read 80c cable indicator from ATA PCI device's PCI config
    - * register. This register is normally set by firmware (BIOS).
    - *
    - * LOCKING:
    - * None (inherited from caller).
    - */
    -
    -static int rdc_pata_cable_detect(struct ata_port *ap)
    -{
    - struct rdc_host_priv *hpriv = ap->host->private_data;
    - u8 mask;
    -
    - /* check BIOS cable detect results */
    - mask = 0x30 << (2 * ap->port_no);
    - if ((hpriv->saved_iocfg & mask) == 0)
    - return ATA_CBL_PATA40;
    - return ATA_CBL_PATA80;
    -}
    -
    -/**
    - * rdc_pata_prereset - prereset for PATA host controller
    - * @link: Target link
    - * @deadline: deadline jiffies for the operation
    - *
    - * LOCKING:
    - * None (inherited from caller).
    - */
    -static int rdc_pata_prereset(struct ata_link *link, unsigned long deadline)
    -{
    - struct ata_port *ap = link->ap;
    - struct pci_dev *pdev = to_pci_dev(ap->host->dev);
    -
    - static const struct pci_bits rdc_enable_bits[] = {
    - { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
    - { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */
    - };
    -
    - if (!pci_test_config_bits(pdev, &rdc_enable_bits[ap->port_no]))
    - return -ENOENT;
    - return ata_sff_prereset(link, deadline);
    -}
    -
    -static DEFINE_SPINLOCK(rdc_lock);
    -
    -static void rdc_set_timings(struct ata_port *ap, struct ata_device *adev,
    - u8 pio, bool use_mwdma)
    -{
    - struct pci_dev *dev = to_pci_dev(ap->host->dev);
    - unsigned long flags;
    - unsigned int is_slave = (adev->devno != 0);
    - unsigned int master_port= ap->port_no ? 0x42 : 0x40;
    - unsigned int slave_port = 0x44;
    - u16 master_data;
    - u8 slave_data;
    - u8 udma_enable;
    - int control = 0;
    -
    - static const /* ISP RTC */
    - u8 timings[][2] = { { 0, 0 },
    - { 0, 0 },
    - { 1, 0 },
    - { 2, 1 },
    - { 2, 3 }, };
    -
    - if (pio >= 2 || use_mwdma)
    - control |= 1; /* TIME1 enable */
    - if (ata_pio_need_iordy(adev) || use_mwdma)
    - control |= 2; /* IE enable */
    - if (adev->class == ATA_DEV_ATA)
    - control |= 4; /* PPE enable */
    - /* If the drive MWDMA is faster than it can do PIO then
    - we must force PIO into PIO0 */
    - if (use_mwdma && adev->pio_mode < (XFER_PIO_0 + pio))
    - /* Enable DMA timing only */
    - control |= 8; /* PIO cycles in PIO0 */
    -
    - spin_lock_irqsave(&rdc_lock, flags);
    -
    - /* PIO configuration clears DTE unconditionally. It will be
    - * programmed in set_dmamode which is guaranteed to be called
    - * after set_piomode if any DMA mode is available.
    - */
    - pci_read_config_word(dev, master_port, &master_data);
    - if (is_slave) {
    - /* clear TIME1|IE1|PPE1|DTE1 */
    - master_data &= 0xff0f;
    - /* Enable SITRE (separate slave timing register) */
    - master_data |= 0x4000;
    - /* enable PPE1, IE1 and TIME1 as needed */
    - master_data |= (control << 4);
    - pci_read_config_byte(dev, slave_port, &slave_data);
    - slave_data &= (ap->port_no ? 0x0f : 0xf0);
    - /* Load the timing nibble for this slave */
    - slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
    - << (ap->port_no ? 4 : 0);
    - } else {
    - /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
    - master_data &= 0xccf0;
    - /* Enable PPE, IE and TIME as appropriate */
    - master_data |= control;
    - /* load ISP and RCT */
    - master_data |=
    - (timings[pio][0] << 12) |
    - (timings[pio][1] << 8);
    - }
    - pci_write_config_word(dev, master_port, master_data);
    - if (is_slave)
    - pci_write_config_byte(dev, slave_port, slave_data);
    -
    - /* Ensure the UDMA bit is off - it will be turned back on if
    - UDMA is selected */
    -
    - pci_read_config_byte(dev, 0x48, &udma_enable);
    - udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
    - pci_write_config_byte(dev, 0x48, udma_enable);
    -
    - spin_unlock_irqrestore(&rdc_lock, flags);
    -}
    -
    -/**
    - * rdc_set_piomode - Initialize host controller PATA PIO timings
    - * @ap: Port whose timings we are configuring
    - * @adev: Drive in question
    - *
    - * Set PIO mode for device, in host controller PCI config space.
    - *
    - * LOCKING:
    - * None (inherited from caller).
    - */
    -
    -static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
    -{
    - rdc_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0, 0);
    -}
    -
    -/**
    - * rdc_set_dmamode - Initialize host controller PATA PIO timings
    - * @ap: Port whose timings we are configuring
    - * @adev: Drive in question
    - *
    - * Set UDMA mode for device, in host controller PCI config space.
    - *
    - * LOCKING:
    - * None (inherited from caller).
    - */
    -
    -static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
    -{
    - struct pci_dev *dev = to_pci_dev(ap->host->dev);
    - unsigned long flags;
    - u8 speed = adev->dma_mode;
    - int devid = adev->devno + 2 * ap->port_no;
    - u8 udma_enable = 0;
    -
    - if (speed >= XFER_UDMA_0) {
    - unsigned int udma = speed - XFER_UDMA_0;
    - u16 udma_timing;
    - u16 ideconf;
    - int u_clock, u_speed;
    -
    - spin_lock_irqsave(&rdc_lock, flags);
    -
    - pci_read_config_byte(dev, 0x48, &udma_enable);
    -
    - /*
    - * UDMA is handled by a combination of clock switching and
    - * selection of dividers
    - *
    - * Handy rule: Odd modes are UDMATIMx 01, even are 02
    - * except UDMA0 which is 00
    - */
    - u_speed = min(2 - (udma & 1), udma);
    - if (udma == 5)
    - u_clock = 0x1000; /* 100Mhz */
    - else if (udma > 2)
    - u_clock = 1; /* 66Mhz */
    - else
    - u_clock = 0; /* 33Mhz */
    -
    - udma_enable |= (1 << devid);
    -
    - /* Load the CT/RP selection */
    - pci_read_config_word(dev, 0x4A, &udma_timing);
    - udma_timing &= ~(3 << (4 * devid));
    - udma_timing |= u_speed << (4 * devid);
    - pci_write_config_word(dev, 0x4A, udma_timing);
    -
    - /* Select a 33/66/100Mhz clock */
    - pci_read_config_word(dev, 0x54, &ideconf);
    - ideconf &= ~(0x1001 << devid);
    - ideconf |= u_clock << devid;
    - pci_write_config_word(dev, 0x54, ideconf);
    -
    - pci_write_config_byte(dev, 0x48, udma_enable);
    -
    - spin_unlock_irqrestore(&rdc_lock, flags);
    - } else {
    - /* MWDMA is driven by the PIO timings. */
    - unsigned int mwdma = speed - XFER_MW_DMA_0;
    - const unsigned int needed_pio[3] = {
    - XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
    - };
    - int pio = needed_pio[mwdma] - XFER_PIO_0;
    -
    - rdc_set_timings(ap, adev, pio, 1);
    - }
    -}
    -
    -static struct ata_port_operations rdc_pata_ops = {
    - .inherits = &ata_bmdma32_port_ops,
    - .cable_detect = rdc_pata_cable_detect,
    - .set_piomode = rdc_set_piomode,
    - .set_dmamode = rdc_set_dmamode,
    - .prereset = rdc_pata_prereset,
    -};
    -
    -static struct ata_port_info rdc_port_info = {
    -
    - .flags = ATA_FLAG_SLAVE_POSS,
    - .pio_mask = ATA_PIO4,
    - .mwdma_mask = ATA_MWDMA12_ONLY,
    - .udma_mask = ATA_UDMA5,
    - .port_ops = &rdc_pata_ops,
    -};
    -
    -static struct scsi_host_template rdc_sht = {
    - ATA_BMDMA_SHT(DRV_NAME),
    -};
    -
    -/**
    - * rdc_init_one - Register PIIX ATA PCI device with kernel services
    - * @pdev: PCI device to register
    - * @ent: Entry in rdc_pci_tbl matching with @pdev
    - *
    - * Called from kernel PCI layer. We probe for combined mode (sigh),
    - * and then hand over control to libata, for it to do the rest.
    - *
    - * LOCKING:
    - * Inherited from PCI layer (may sleep).
    - *
    - * RETURNS:
    - * Zero on success, or -ERRNO value.
    - */
    -
    -static int __devinit rdc_init_one(struct pci_dev *pdev,
    - const struct pci_device_id *ent)
    -{
    - static int printed_version;
    - struct device *dev = &pdev->dev;
    - struct ata_port_info port_info[2];
    - const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
    - unsigned long port_flags;
    - struct ata_host *host;
    - struct rdc_host_priv *hpriv;
    - int rc;
    -
    - if (!printed_version++)
    - dev_printk(KERN_DEBUG, &pdev->dev,
    - "version " DRV_VERSION "\n");
    -
    - port_info[0] = rdc_port_info;
    - port_info[1] = rdc_port_info;
    -
    - port_flags = port_info[0].flags;
    -
    - /* enable device and prepare host */
    - rc = pcim_enable_device(pdev);
    - if (rc)
    - return rc;
    -
    - hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
    - if (!hpriv)
    - return -ENOMEM;
    -
    - /* Save IOCFG, this will be used for cable detection, quirk
    - * detection and restoration on detach.
    - */
    - pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg);
    -
    - rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
    - if (rc)
    - return rc;
    - host->private_data = hpriv;
    -
    - pci_intx(pdev, 1);
    -
    - host->flags |= ATA_HOST_PARALLEL_SCAN;
    -
    - pci_set_master(pdev);
    - return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht);
    -}
    -
    -static void rdc_remove_one(struct pci_dev *pdev)
    -{
    - struct ata_host *host = dev_get_drvdata(&pdev->dev);
    - struct rdc_host_priv *hpriv = host->private_data;
    -
    - pci_write_config_dword(pdev, 0x54, hpriv->saved_iocfg);
    -
    - ata_pci_remove_one(pdev);
    -}
    -
    -static const struct pci_device_id rdc_pci_tbl[] = {
    - { PCI_DEVICE(0x17F3, 0x1011), },
    - { PCI_DEVICE(0x17F3, 0x1012), },
    - { } /* terminate list */
    -};
    -
    -static struct pci_driver rdc_pci_driver = {
    - .name = DRV_NAME,
    - .id_table = rdc_pci_tbl,
    - .probe = rdc_init_one,
    - .remove = rdc_remove_one,
    -#ifdef CONFIG_PM
    - .suspend = ata_pci_device_suspend,
    - .resume = ata_pci_device_resume,
    -#endif
    -};
    -
    -
    -static int __init rdc_init(void)
    -{
    - return pci_register_driver(&rdc_pci_driver);
    -}
    -
    -static void __exit rdc_exit(void)
    -{
    - pci_unregister_driver(&rdc_pci_driver);
    -}
    -
    -module_init(rdc_init);
    -module_exit(rdc_exit);
    -
    -MODULE_AUTHOR("Alan Cox (based on ata_piix)");
    -MODULE_DESCRIPTION("SCSI low-level driver for RDC PATA controllers");
    -MODULE_LICENSE("GPL");
    -MODULE_DEVICE_TABLE(pci, rdc_pci_tbl);
    -MODULE_VERSION(DRV_VERSION);
    --
    1.7.1


    \
     
     \ /
      Last update: 2011-02-08 13:29    [W:0.050 / U:0.076 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site