libata: introduce sff_set_devctl() method
authorSergei Shtylyov <sshtylyov@ru.mvista.com>
Fri, 7 May 2010 18:47:50 +0000 (22:47 +0400)
committerJeff Garzik <jgarzik@redhat.com>
Fri, 14 May 2010 21:35:52 +0000 (17:35 -0400)
The set of libata's taskfile access methods is clearly incomplete as
it lacks a method to write to the device control register -- which
forces drivers like 'pata_bf54x' and 'pata_scc' to implement more
"high level" (and more weighty) methods like freeze() and postreset().

So, introduce the optional sff_set_devctl() method which the drivers
only have to implement if the standard iowrite8() can't be used (just
like the existing sff_check_altstatus() method) and make use of it
in the freeze() and postreset() method implementations (I could also
have used it in softreset() method but it also reads other taskfile
registers without using tf_read() making that quite pointless);
this makes freeze() method implementations in the 'pata_bf54x' and
'pata_scc' methods virtually identical to ata_sff_freeze(), so we
can get rid of them completely.

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Documentation/DocBook/libata.tmpl
drivers/ata/libata-sff.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_scc.c
include/linux/libata.h

index 70b811e9f2cabc062cb7e16e475ae6bad3079192..828748c4e78d1c10fb195dd449497616b2e7f2a1 100644 (file)
@@ -225,6 +225,18 @@ u8   (*sff_check_altstatus)(struct ata_port *ap);
 
        </sect2>
 
+       <sect2><title>Write specific ATA shadow register</title>
+       <programlisting>
+void (*sff_set_devctl)(struct ata_port *ap, u8 ctl);
+       </programlisting>
+
+       <para>
+       Write the device control ATA shadow register to the hardware.
+       Most drivers don't need to define this.
+       </para>
+
+       </sect2>
+
        <sect2><title>Select ATA device on bus</title>
        <programlisting>
 void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
index b31389605beec6a32de54c5cf8ed7a50923ebc05..31b495fcd969fc33e9d3864c76a34d787106c9f5 100644 (file)
@@ -445,6 +445,27 @@ int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
 }
 EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
 
+/**
+ *     ata_sff_set_devctl - Write device control reg
+ *     @ap: port where the device is
+ *     @ctl: value to write
+ *
+ *     Writes ATA taskfile device control register.
+ *
+ *     Note: may NOT be used as the sff_set_devctl() entry in
+ *     ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+static void ata_sff_set_devctl(struct ata_port *ap, u8 ctl)
+{
+       if (ap->ops->sff_set_devctl)
+               ap->ops->sff_set_devctl(ap, ctl);
+       else
+               iowrite8(ctl, ap->ioaddr.ctl_addr);
+}
+
 /**
  *     ata_sff_dev_select - Select device 0/1 on ATA bus
  *     @ap: ATA channel to manipulate
@@ -1895,13 +1916,11 @@ EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
  */
 void ata_sff_freeze(struct ata_port *ap)
 {
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
        ap->ctl |= ATA_NIEN;
        ap->last_ctl = ap->ctl;
 
-       if (ioaddr->ctl_addr)
-               iowrite8(ap->ctl, ioaddr->ctl_addr);
+       if (ap->ops->sff_set_devctl || ap->ioaddr.ctl_addr)
+               ata_sff_set_devctl(ap, ap->ctl);
 
        /* Under certain circumstances, some controllers raise IRQ on
         * ATA_NIEN manipulation.  Also, many controllers fail to mask
@@ -2301,8 +2320,8 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
        }
 
        /* set up device control */
-       if (ap->ioaddr.ctl_addr) {
-               iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+       if (ap->ops->sff_set_devctl || ap->ioaddr.ctl_addr) {
+               ata_sff_set_devctl(ap, ap->ctl);
                ap->last_ctl = ap->ctl;
        }
 }
index 02c81f12c702a7a02546a595937ae353c7a3290d..198307534d90d3554c019f55b745ddffb9969dfb 100644 (file)
@@ -820,6 +820,18 @@ static void bfin_dev_select(struct ata_port *ap, unsigned int device)
        ata_sff_pause(ap);
 }
 
+/**
+ *     bfin_set_devctl - Write device control reg
+ *     @ap: port where the device is
+ *     @ctl: value to write
+ */
+
+static u8 bfin_set_devctl(struct ata_port *ap, u8 ctl)
+{
+       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+       write_atapi_register(base, ATA_REG_CTRL, ctl);
+}
+
 /**
  *     bfin_bmdma_setup - Set up IDE DMA transaction
  *     @qc: Info associated with this ATA transaction.
@@ -1239,32 +1251,6 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
        return tmp;
 }
 
-/**
- *     bfin_freeze - Freeze DMA controller port
- *     @ap: port to freeze
- *
- *     Note: Original code is ata_sff_freeze().
- */
-
-static void bfin_freeze(struct ata_port *ap)
-{
-       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-
-       dev_dbg(ap->dev, "in atapi dma freeze\n");
-       ap->ctl |= ATA_NIEN;
-       ap->last_ctl = ap->ctl;
-
-       write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
-
-       /* Under certain circumstances, some controllers raise IRQ on
-        * ATA_NIEN manipulation.  Also, many controllers fail to mask
-        * previously pending IRQ on ATA_NIEN assertion.  Clear it.
-        */
-       ap->ops->sff_check_status(ap);
-
-       bfin_irq_clear(ap);
-}
-
 /**
  *     bfin_thaw - Thaw DMA controller port
  *     @ap: port to thaw
@@ -1476,6 +1462,7 @@ static struct ata_port_operations bfin_pata_ops = {
        .sff_check_status       = bfin_check_status,
        .sff_check_altstatus    = bfin_check_altstatus,
        .sff_dev_select         = bfin_dev_select,
+       .sff_set_devctl         = bfin_set_devctl,
 
        .bmdma_setup            = bfin_bmdma_setup,
        .bmdma_start            = bfin_bmdma_start,
@@ -1485,7 +1472,6 @@ static struct ata_port_operations bfin_pata_ops = {
 
        .qc_prep                = ata_noop_qc_prep,
 
-       .freeze                 = bfin_freeze,
        .thaw                   = bfin_thaw,
        .softreset              = bfin_softreset,
        .postreset              = bfin_postreset,
index 77ff829af176b76725ed4f1be6e3ebeca6571b1c..86b25fef34a9bb9c88fbb702ba3ad3c7f0b57cef 100644 (file)
@@ -415,6 +415,17 @@ static void scc_dev_select (struct ata_port *ap, unsigned int device)
        ata_sff_pause(ap);
 }
 
+/**
+ *     scc_set_devctl - Write device control reg
+ *     @ap: port where the device is
+ *     @ctl: value to write
+ */
+
+static void scc_set_devctl(struct ata_port *ap, u8 ctl)
+{
+       out_be32(ap->ioaddr.ctl_addr, ctl);
+}
+
 /**
  *     scc_bmdma_setup - Set up PCI IDE BMDMA transaction
  *     @qc: Info associated with this ATA transaction.
@@ -839,31 +850,6 @@ static u8 scc_irq_on (struct ata_port *ap)
        return tmp;
 }
 
-/**
- *     scc_freeze - Freeze BMDMA controller port
- *     @ap: port to freeze
- *
- *     Note: Original code is ata_sff_freeze().
- */
-
-static void scc_freeze (struct ata_port *ap)
-{
-       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-       ap->ctl |= ATA_NIEN;
-       ap->last_ctl = ap->ctl;
-
-       out_be32(ioaddr->ctl_addr, ap->ctl);
-
-       /* Under certain circumstances, some controllers raise IRQ on
-        * ATA_NIEN manipulation.  Also, many controllers fail to mask
-        * previously pending IRQ on ATA_NIEN assertion.  Clear it.
-        */
-       ap->ops->sff_check_status(ap);
-
-       ap->ops->sff_irq_clear(ap);
-}
-
 /**
  *     scc_pata_prereset - prepare for reset
  *     @ap: ATA port to be reset
@@ -977,6 +963,7 @@ static struct ata_port_operations scc_pata_ops = {
        .sff_check_status       = scc_check_status,
        .sff_check_altstatus    = scc_check_altstatus,
        .sff_dev_select         = scc_dev_select,
+       .sff_set_devctl         = scc_set_devctl,
 
        .bmdma_setup            = scc_bmdma_setup,
        .bmdma_start            = scc_bmdma_start,
@@ -984,7 +971,6 @@ static struct ata_port_operations scc_pata_ops = {
        .bmdma_status           = scc_bmdma_status,
        .sff_data_xfer          = scc_data_xfer,
 
-       .freeze                 = scc_freeze,
        .prereset               = scc_pata_prereset,
        .softreset              = scc_softreset,
        .postreset              = scc_postreset,
index 242eb2646101a6d1fa4807f9e1410602a8c2e6e0..6207ec60072272b1cfe5eaf119b302cf60cd18bb 100644 (file)
@@ -850,6 +850,7 @@ struct ata_port_operations {
         * SFF / taskfile oriented ops
         */
        void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
+       void (*sff_set_devctl)(struct ata_port *ap, u8 ctl);
        u8   (*sff_check_status)(struct ata_port *ap);
        u8   (*sff_check_altstatus)(struct ata_port *ap);
        void (*sff_tf_load)(struct ata_port *ap, const struct ata_taskfile *tf);