summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-05-15 02:32:40 +0200
committerCástor Muñoz <cmvidal@gmail.com>2016-05-15 22:57:12 +0200
commit52a6db3a363e915b1af7eb37778baaee81306c48 (patch)
tree0987c86a4f429f32b0ec236eba23d5b88ac65a3b /firmware/target
parent201f57171a67530a288f2a29a7a7060293e93bf2 (diff)
downloadrockbox-52a6db3a363e915b1af7eb37778baaee81306c48.tar.gz
rockbox-52a6db3a363e915b1af7eb37778baaee81306c48.zip
iPod Classic: optimize UDMA timming for ATA drives
This patch optimizes UDMA timings to increase write transfer rate on ATA bus, these transfers are clocked by HCLK, tDVS+tDVH is modified to decrease Tcyctyp (typical write cycle period). This is not overclocking, we meet the ATA standar, the settings used by OF are not well optimized for each UDMA mode, we will never know but probably this was due some documentation issue. ATA_UDMA_TIME register is documented on s3c6400 datasheet, information included in s5l8700 datasheet is wrong or not valid for s5l8702. From ATA specs, (Minimum, Maximum) values in nanoseconds: UDMA 0 UDMA 1 UDMA 2 UDMA 3 UDMA 4 tACKENV (20, 70) (20, 70) (20, 70) (20, 55) (20, 55) tRP (160, --) (125, --) (100, --) (100, --) (100, --) tSS (50, --) (50, --) (50, --) (50, --) (50, --) tDVS (70, --) (48, --) (31, --) (20, --) (6.7, --) tDVH (6.2, --) (6.2, --) (6.2, --) (6.2, --) (6.2, --) tDVS+tDVH (120, --) (80, --) (60, --) (45, --) (30, --) Tcyc = tDVS+tDVH WR[bytes/s] = 1/Tcyc[s] * 2[bytes] On Classic (boosted): HClk = 108 MHz. -> T = ~9.26 ns. Old values (used by OF): UDMA ATA_UDMA_TIME tACK tRP tSS tDVS tDVH Tcyc WR(MB/s) 0 0x5071152 27.8 166.7 55.6 74.1 55.6 129.7 15.4 1 0x3050a52 27.8 101.8 55.6 55.6 37 92.6 21.6 2 0x3030a52 27.8 101.8 55.6 37 37 74 27 3 0x2020a52 27.8 101.8 55.6 27.8 27.8 55.6 36 4 0x2010a52 27.8 101.8 55.6 18.5 27.8 46.3 43.2 New values: UDMA ATA_UDMA_TIME tACK tRP tSS tDVS tDVH Tcyc WR(MB/s) 0 0x4071152 27.8 166.7 55.6 74.1 46.3 120.4 16.6 1 0x2050d52 27.8 129.6 55.6 55.6 27.8 83.4 24 2 0x2030a52 27.8 101.8 55.6 37 27.8 64.8 30.9 3 0x1020a52 27.8 101.8 55.6 27.8 18.5 46.3 43.2 4 0x1010a52 27.8 101.8 55.6 18.5 18.5 37 54 To verify that the settings are correct, a write-to-cache test was performed using emCORE, the measured transfer rate (WRm) is compared against the theoric transfer rate (WR) at 108 Mhz for the old and the new UDMA4 settings (iPod 160, HDD Toshiba MK1634GAL): UDMA ATA_UDMA_TIME Tcyc(ns) WR(MB/s) WRm(MB/s) RDm(MB/s) 4 0x2010a52 46.3 43.2 42.9 59.8 4 0x1010a52 37 54 53.5 59.8 Notes: - The new UDMA4 settings increases ~25% the ATA transfer rate for cached-writes. The real HDD write speed is limited by the internal transfer rate (depends on cilinder, for the MK1634GAL it is 276 to 573 Mbits/s). Sequential write benchmark using diskdump on USB are ~8% faster. - Read transfers are clocked by the device, it depends on UDMA mode selected and are not affected by HClk or ATA_UDMA_TIME settings. Read-from-cache tests results (RDm) using HClk=108 and HClk=54 for UDMA4 are 59.8 MB/s on MK1634GAL. - Minimum HClk is limited by tACKENV specs, using current settings it is 54 MHz for UDMA4,UDMA3 and 43 MHz for UDMA2,UDMA1,UDMA0. Change-Id: I61d67060410752518a59e1ff08072b21747ca997
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
index 98efa33c84..5b0ab3e22a 100644
--- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
@@ -537,6 +537,25 @@ static int ata_set_feature(uint32_t feature, uint32_t param)
537 return 0; 537 return 0;
538} 538}
539 539
540/*
541 * ATA_UDMA_TIME register is documented on s3c6400 datasheet, information
542 * included in s5l8700 datasheet is wrong or not valid for s5l8702.
543 *
544 * On Classic (boosted):
545 * HClk = 108 MHz. -> T = ~9.26 ns.
546 *
547 * Configured values (in nanoseconds):
548 *
549 * UDMA ATA_UDMA_TIME tACK tRP tSS tDVS tDVH Tcyc WR(MB/s)
550 * 0 0x4071152 27.8 166.7 55.6 74.1 46.3 120.4 16.6
551 * 1 0x2050d52 27.8 129.6 55.6 55.6 27.8 83.4 24
552 * 2 0x2030a52 27.8 101.8 55.6 37 27.8 64.8 30.9
553 * 3 0x1020a52 27.8 101.8 55.6 27.8 18.5 46.3 43.2
554 * 4 0x1010a52 27.8 101.8 55.6 18.5 18.5 37 54
555 *
556 * Tcyc = tDVS+tDVH
557 * WR[bytes/s] = 1/Tcyc[s] * 2[bytes]
558 */
540static int ata_power_up(void) 559static int ata_power_up(void)
541{ 560{
542 ata_set_active(); 561 ata_set_active();
@@ -592,7 +611,7 @@ static int ata_power_up(void)
592 PASS_RC(ata_identify(ata_identify_data), 3, 3); 611 PASS_RC(ata_identify(ata_identify_data), 3, 3);
593 uint32_t piotime = 0x11f3; 612 uint32_t piotime = 0x11f3;
594 uint32_t mdmatime = 0x1c175; 613 uint32_t mdmatime = 0x1c175;
595 uint32_t udmatime = 0x5071152; 614 uint32_t udmatime = 0x4071152;
596 uint32_t param = 0; 615 uint32_t param = 0;
597 ata_dma_flags = 0; 616 ata_dma_flags = 0;
598 ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false; 617 ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false;
@@ -620,22 +639,22 @@ static int ata_power_up(void)
620 { 639 {
621 if (ata_identify_data[88] & BIT(4)) 640 if (ata_identify_data[88] & BIT(4))
622 { 641 {
623 udmatime = 0x2010a52; 642 udmatime = 0x1010a52;
624 param = 0x44; 643 param = 0x44;
625 } 644 }
626 else if (ata_identify_data[88] & BIT(3)) 645 else if (ata_identify_data[88] & BIT(3))
627 { 646 {
628 udmatime = 0x2020a52; 647 udmatime = 0x1020a52;
629 param = 0x43; 648 param = 0x43;
630 } 649 }
631 else if (ata_identify_data[88] & BIT(2)) 650 else if (ata_identify_data[88] & BIT(2))
632 { 651 {
633 udmatime = 0x3030a52; 652 udmatime = 0x2030a52;
634 param = 0x42; 653 param = 0x42;
635 } 654 }
636 else if (ata_identify_data[88] & BIT(1)) 655 else if (ata_identify_data[88] & BIT(1))
637 { 656 {
638 udmatime = 0x3050a52; 657 udmatime = 0x2050d52;
639 param = 0x41; 658 param = 0x41;
640 } 659 }
641 else if (ata_identify_data[88] & BIT(0)) 660 else if (ata_identify_data[88] & BIT(0))