diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2011-10-13 09:39:10 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2011-10-14 13:37:36 -0400 |
commit | 6a94a746fb2572c03c664acece101ee03dae7a17 (patch) | |
tree | 08362472bd03ce67d30955cb4caa5310ab9f31b7 | |
parent | ce986690d9bfabb8c61fd8fe785fce5d95210b66 (diff) |
ata_piix: unify code for programming PIO and MWDMA timings
Besides making things noticably simpler it results in ~2% decrease in
the driver LOC count and also ~2% decrease in the driver binary size
(as measured on x86-32).
Fix piix_set_piomode() documentation while at it.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/ata_piix.c | 111 |
1 files changed, 38 insertions, 73 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 75fdd026a997..69ac373c72ab 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -731,22 +731,11 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline) | |||
731 | 731 | ||
732 | static DEFINE_SPINLOCK(piix_lock); | 732 | static DEFINE_SPINLOCK(piix_lock); |
733 | 733 | ||
734 | /** | 734 | static void piix_set_timings(struct ata_port *ap, struct ata_device *adev, |
735 | * piix_set_piomode - Initialize host controller PATA PIO timings | 735 | u8 pio) |
736 | * @ap: Port whose timings we are configuring | ||
737 | * @adev: um | ||
738 | * | ||
739 | * Set PIO mode for device, in host controller PCI config space. | ||
740 | * | ||
741 | * LOCKING: | ||
742 | * None (inherited from caller). | ||
743 | */ | ||
744 | |||
745 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) | ||
746 | { | 736 | { |
747 | struct pci_dev *dev = to_pci_dev(ap->host->dev); | 737 | struct pci_dev *dev = to_pci_dev(ap->host->dev); |
748 | unsigned long flags; | 738 | unsigned long flags; |
749 | unsigned int pio = adev->pio_mode - XFER_PIO_0; | ||
750 | unsigned int is_slave = (adev->devno != 0); | 739 | unsigned int is_slave = (adev->devno != 0); |
751 | unsigned int master_port= ap->port_no ? 0x42 : 0x40; | 740 | unsigned int master_port= ap->port_no ? 0x42 : 0x40; |
752 | unsigned int slave_port = 0x44; | 741 | unsigned int slave_port = 0x44; |
@@ -771,10 +760,16 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
771 | control |= 1; /* TIME1 enable */ | 760 | control |= 1; /* TIME1 enable */ |
772 | if (ata_pio_need_iordy(adev)) | 761 | if (ata_pio_need_iordy(adev)) |
773 | control |= 2; /* IE enable */ | 762 | control |= 2; /* IE enable */ |
774 | |||
775 | /* Intel specifies that the PPE functionality is for disk only */ | 763 | /* Intel specifies that the PPE functionality is for disk only */ |
776 | if (adev->class == ATA_DEV_ATA) | 764 | if (adev->class == ATA_DEV_ATA) |
777 | control |= 4; /* PPE enable */ | 765 | control |= 4; /* PPE enable */ |
766 | /* | ||
767 | * If the drive MWDMA is faster than it can do PIO then | ||
768 | * we must force PIO into PIO0 | ||
769 | */ | ||
770 | if (adev->pio_mode < XFER_PIO_0 + pio) | ||
771 | /* Enable DMA timing only */ | ||
772 | control |= 8; /* PIO cycles in PIO0 */ | ||
778 | 773 | ||
779 | spin_lock_irqsave(&piix_lock, flags); | 774 | spin_lock_irqsave(&piix_lock, flags); |
780 | 775 | ||
@@ -823,6 +818,22 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
823 | } | 818 | } |
824 | 819 | ||
825 | /** | 820 | /** |
821 | * piix_set_piomode - Initialize host controller PATA PIO timings | ||
822 | * @ap: Port whose timings we are configuring | ||
823 | * @adev: Drive in question | ||
824 | * | ||
825 | * Set PIO mode for device, in host controller PCI config space. | ||
826 | * | ||
827 | * LOCKING: | ||
828 | * None (inherited from caller). | ||
829 | */ | ||
830 | |||
831 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) | ||
832 | { | ||
833 | piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0); | ||
834 | } | ||
835 | |||
836 | /** | ||
826 | * do_pata_set_dmamode - Initialize host controller PATA PIO timings | 837 | * do_pata_set_dmamode - Initialize host controller PATA PIO timings |
827 | * @ap: Port whose timings we are configuring | 838 | * @ap: Port whose timings we are configuring |
828 | * @adev: Drive in question | 839 | * @adev: Drive in question |
@@ -838,31 +849,20 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in | |||
838 | { | 849 | { |
839 | struct pci_dev *dev = to_pci_dev(ap->host->dev); | 850 | struct pci_dev *dev = to_pci_dev(ap->host->dev); |
840 | unsigned long flags; | 851 | unsigned long flags; |
841 | u8 master_port = ap->port_no ? 0x42 : 0x40; | ||
842 | u16 master_data; | ||
843 | u8 speed = adev->dma_mode; | 852 | u8 speed = adev->dma_mode; |
844 | int devid = adev->devno + 2 * ap->port_no; | 853 | int devid = adev->devno + 2 * ap->port_no; |
845 | u8 udma_enable = 0; | 854 | u8 udma_enable = 0; |
846 | 855 | ||
847 | static const /* ISP RTC */ | ||
848 | u8 timings[][2] = { { 0, 0 }, | ||
849 | { 0, 0 }, | ||
850 | { 1, 0 }, | ||
851 | { 2, 1 }, | ||
852 | { 2, 3 }, }; | ||
853 | |||
854 | spin_lock_irqsave(&piix_lock, flags); | ||
855 | |||
856 | pci_read_config_word(dev, master_port, &master_data); | ||
857 | if (ap->udma_mask) | ||
858 | pci_read_config_byte(dev, 0x48, &udma_enable); | ||
859 | |||
860 | if (speed >= XFER_UDMA_0) { | 856 | if (speed >= XFER_UDMA_0) { |
861 | unsigned int udma = adev->dma_mode - XFER_UDMA_0; | 857 | unsigned int udma = speed - XFER_UDMA_0; |
862 | u16 udma_timing; | 858 | u16 udma_timing; |
863 | u16 ideconf; | 859 | u16 ideconf; |
864 | int u_clock, u_speed; | 860 | int u_clock, u_speed; |
865 | 861 | ||
862 | spin_lock_irqsave(&piix_lock, flags); | ||
863 | |||
864 | pci_read_config_byte(dev, 0x48, &udma_enable); | ||
865 | |||
866 | /* | 866 | /* |
867 | * UDMA is handled by a combination of clock switching and | 867 | * UDMA is handled by a combination of clock switching and |
868 | * selection of dividers | 868 | * selection of dividers |
@@ -895,56 +895,21 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in | |||
895 | performance (WR_PingPong_En) */ | 895 | performance (WR_PingPong_En) */ |
896 | pci_write_config_word(dev, 0x54, ideconf); | 896 | pci_write_config_word(dev, 0x54, ideconf); |
897 | } | 897 | } |
898 | |||
899 | pci_write_config_byte(dev, 0x48, udma_enable); | ||
900 | |||
901 | spin_unlock_irqrestore(&piix_lock, flags); | ||
898 | } else { | 902 | } else { |
899 | /* | 903 | /* MWDMA is driven by the PIO timings. */ |
900 | * MWDMA is driven by the PIO timings. We must also enable | 904 | unsigned int mwdma = speed - XFER_MW_DMA_0; |
901 | * IORDY unconditionally along with TIME1. PPE has already | ||
902 | * been set when the PIO timing was set. | ||
903 | */ | ||
904 | unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; | ||
905 | unsigned int control; | ||
906 | u8 slave_data; | ||
907 | const unsigned int needed_pio[3] = { | 905 | const unsigned int needed_pio[3] = { |
908 | XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 | 906 | XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 |
909 | }; | 907 | }; |
910 | int pio = needed_pio[mwdma] - XFER_PIO_0; | 908 | int pio = needed_pio[mwdma] - XFER_PIO_0; |
911 | 909 | ||
912 | control = 3; /* IORDY|TIME1 */ | 910 | /* XFER_PIO_0 is never used currently */ |
913 | 911 | piix_set_timings(ap, adev, pio); | |
914 | /* If the drive MWDMA is faster than it can do PIO then | ||
915 | we must force PIO into PIO0 */ | ||
916 | |||
917 | if (adev->pio_mode < needed_pio[mwdma]) | ||
918 | /* Enable DMA timing only */ | ||
919 | control |= 8; /* PIO cycles in PIO0 */ | ||
920 | |||
921 | if (adev->devno) { /* Slave */ | ||
922 | master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ | ||
923 | master_data |= control << 4; | ||
924 | pci_read_config_byte(dev, 0x44, &slave_data); | ||
925 | slave_data &= (ap->port_no ? 0x0f : 0xf0); | ||
926 | /* Load the matching timing */ | ||
927 | slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); | ||
928 | pci_write_config_byte(dev, 0x44, slave_data); | ||
929 | } else { /* Master */ | ||
930 | master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY | ||
931 | and master timing bits */ | ||
932 | master_data |= control; | ||
933 | master_data |= | ||
934 | (timings[pio][0] << 12) | | ||
935 | (timings[pio][1] << 8); | ||
936 | } | ||
937 | |||
938 | if (ap->udma_mask) | ||
939 | udma_enable &= ~(1 << devid); | ||
940 | |||
941 | pci_write_config_word(dev, master_port, master_data); | ||
942 | } | 912 | } |
943 | /* Don't scribble on 0x48 if the controller does not support UDMA */ | ||
944 | if (ap->udma_mask) | ||
945 | pci_write_config_byte(dev, 0x48, udma_enable); | ||
946 | |||
947 | spin_unlock_irqrestore(&piix_lock, flags); | ||
948 | } | 913 | } |
949 | 914 | ||
950 | /** | 915 | /** |