@@ -1423,6 +1423,307 @@ static int adjust_tuning(struct mmc_host *mmc, struct adj *adj, u32 opcode)
1423
1423
return 0 ;
1424
1424
}
1425
1425
1426
+ static const u8 octeontx_hs400_tuning_block [512 ] = {
1427
+ 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0x00 ,
1428
+ 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc , 0xcc ,
1429
+ 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff , 0xff ,
1430
+ 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee , 0xff ,
1431
+ 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd , 0xdd ,
1432
+ 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff , 0xbb ,
1433
+ 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff , 0xff ,
1434
+ 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee , 0xff ,
1435
+ 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 ,
1436
+ 0x00 , 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc ,
1437
+ 0xcc , 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff ,
1438
+ 0xff , 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee ,
1439
+ 0xff , 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd ,
1440
+ 0xdd , 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff ,
1441
+ 0xbb , 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff ,
1442
+ 0xff , 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee ,
1443
+ 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0x00 ,
1444
+ 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc , 0xcc ,
1445
+ 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff , 0xff ,
1446
+ 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee , 0xff ,
1447
+ 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd , 0xdd ,
1448
+ 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff , 0xbb ,
1449
+ 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff , 0xff ,
1450
+ 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee , 0xff ,
1451
+ 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 ,
1452
+ 0x00 , 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc ,
1453
+ 0xcc , 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff ,
1454
+ 0xff , 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee ,
1455
+ 0xff , 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd ,
1456
+ 0xdd , 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff ,
1457
+ 0xbb , 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff ,
1458
+ 0xff , 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee ,
1459
+ 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0x00 ,
1460
+ 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc , 0xcc ,
1461
+ 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff , 0xff ,
1462
+ 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee , 0xff ,
1463
+ 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd , 0xdd ,
1464
+ 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff , 0xbb ,
1465
+ 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff , 0xff ,
1466
+ 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee , 0xff ,
1467
+ 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 ,
1468
+ 0x00 , 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc ,
1469
+ 0xcc , 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff ,
1470
+ 0xff , 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee ,
1471
+ 0xff , 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd ,
1472
+ 0xdd , 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff ,
1473
+ 0xbb , 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff ,
1474
+ 0xff , 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee ,
1475
+ 0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0xff , 0x00 ,
1476
+ 0x00 , 0xff , 0x00 , 0xff , 0x55 , 0xaa , 0x55 , 0xaa ,
1477
+ 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff , 0xff ,
1478
+ 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee , 0xff ,
1479
+ 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd , 0xdd ,
1480
+ 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff , 0xbb ,
1481
+ 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff , 0xff ,
1482
+ 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee , 0xff ,
1483
+ 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 ,
1484
+ 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff , 0x00 , 0xff ,
1485
+ 0x01 , 0xfe , 0x01 , 0xfe , 0xcc , 0xcc , 0xcc , 0xff ,
1486
+ 0xff , 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee ,
1487
+ 0xff , 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd ,
1488
+ 0xdd , 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff ,
1489
+ 0xbb , 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff ,
1490
+ 0xff , 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee ,
1491
+
1492
+ };
1493
+
1494
+ /* Initialization for single block read/write operation for tuning */
1495
+ static void hs400_prepare_mrq (const struct cvm_mmc_slot * slot ,
1496
+ struct mmc_request * mrq , struct mmc_command * cmd ,
1497
+ struct mmc_data * data , struct scatterlist * sg ,
1498
+ const void * dat_buf , u32 size , bool write )
1499
+ {
1500
+ struct mmc_host * mmc = slot -> mmc ;
1501
+
1502
+ memset (data , 0 , sizeof (* data ));
1503
+ memset (cmd , 0 , sizeof (* cmd ));
1504
+ memset (mrq , 0 , sizeof (* mrq ));
1505
+
1506
+ mrq -> cmd = cmd ;
1507
+ mrq -> data = data ;
1508
+ cmd -> opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK ;
1509
+ cmd -> arg = slot -> hs400_tuning_block ;
1510
+ cmd -> flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC ;
1511
+ data -> blksz = size ;
1512
+ data -> blocks = 1 ;
1513
+ data -> sg = sg ;
1514
+ data -> sg_len = 1 ;
1515
+ data -> flags = write ? MMC_DATA_WRITE : MMC_DATA_READ ;
1516
+ init_completion (& (mrq -> completion ));
1517
+ if (mmc -> card )
1518
+ mmc_set_data_timeout (data , mmc -> card );
1519
+ else
1520
+ data -> timeout_ns = (write ? 80 : 10 ) * NSEC_PER_MSEC ;
1521
+ sg_init_one (sg , dat_buf , size );
1522
+ }
1523
+
1524
+ static int access_hs400_tuning_block (struct cvm_mmc_slot * slot , bool write )
1525
+ {
1526
+ struct mmc_request mrq = {};
1527
+ struct mmc_command cmd = {};
1528
+ struct mmc_data data = {};
1529
+ struct scatterlist sg ;
1530
+ struct mmc_host * mmc = slot -> mmc ;
1531
+ const int size = mmc -> max_blk_size ;
1532
+ u8 * data_buf ;
1533
+
1534
+ data_buf = kzalloc (size , GFP_KERNEL );
1535
+ if (!data_buf )
1536
+ return - ENOMEM ;
1537
+ if (write )
1538
+ memcpy (data_buf , octeontx_hs400_tuning_block , size );
1539
+
1540
+ hs400_prepare_mrq (slot , & mrq , & cmd , & data , & sg , data_buf , size , write );
1541
+
1542
+ mmc_wait_for_req (mmc , & mrq );
1543
+
1544
+ if (!write ) {
1545
+ if (memcmp (data_buf , octeontx_hs400_tuning_block ,
1546
+ sizeof (octeontx_hs400_tuning_block ))) {
1547
+ kfree (data_buf );
1548
+ return - EILSEQ ;
1549
+ }
1550
+ }
1551
+ kfree (data_buf );
1552
+
1553
+ if (cmd .error || data .error )
1554
+ dev_dbg (slot -> host -> dev , "%s op failed, cmd: %d, data: %d\n" ,
1555
+ write ? "write" : "read" , cmd .error , data .error );
1556
+ return (cmd .error || data .error ) ? - ENODATA : 0 ;
1557
+ }
1558
+
1559
+ /* Check for and write if necessary the tuning block for HS4000 tuning */
1560
+ static int check_and_write_hs400_tuning_block (struct cvm_mmc_slot * slot )
1561
+ {
1562
+ int err ;
1563
+
1564
+ if (slot -> hs400_tuning_block == -1 ||
1565
+ slot -> hs400_tuning_block_present )
1566
+ return 0 ;
1567
+
1568
+ /* Read the tuning block first and see if it's already set */
1569
+ err = access_hs400_tuning_block (slot , false);
1570
+ if (err == - ENODATA ) {
1571
+ dev_warn (slot -> host -> dev ,
1572
+ "Could not access HS400 tuning block %d in HS200 mode, err: %d\n" ,
1573
+ slot -> hs400_tuning_block , err );
1574
+ return err ;
1575
+ } else if (!err ) {
1576
+ /* Everything is good, data matches, we're done */
1577
+ goto done ;
1578
+ }
1579
+
1580
+ /* Attempt to write the tuning block */
1581
+ err = access_hs400_tuning_block (slot , true);
1582
+ if (err ) {
1583
+ dev_warn (slot -> host -> dev ,
1584
+ "err: %d, Could not write HS400 tuning block in HS200 mode\n" ,
1585
+ err );
1586
+ goto done ;
1587
+ }
1588
+
1589
+ /* Read after write, this should pass */
1590
+ err = access_hs400_tuning_block (slot , false);
1591
+ if (err )
1592
+ dev_warn (slot -> host -> dev ,
1593
+ "Could not read HS400 tuning block after write, err: %d\n" ,
1594
+ err );
1595
+
1596
+ done :
1597
+ /* Disable HS400 tuning if we can't access the tuning block */
1598
+ if (err )
1599
+ slot -> hs400_tuning_block = -1 ;
1600
+
1601
+ slot -> hs400_tuning_block_present = !err ;
1602
+
1603
+ return err ;
1604
+ }
1605
+
1606
+ static int tune_hs400 (struct cvm_mmc_slot * slot )
1607
+ {
1608
+ int err = 0 , start_run = -1 , best_run = 0 , best_start = -1 ;
1609
+ int last_good = -1 ;
1610
+ bool prev_ok = false;
1611
+ u64 timing ;
1612
+ int tap ;
1613
+ const int size = sizeof (octeontx_hs400_tuning_block );
1614
+ struct mmc_host * mmc = slot -> mmc ;
1615
+ struct cvm_mmc_host * host = slot -> host ;
1616
+ struct mmc_request mrq ;
1617
+ struct mmc_command cmd ;
1618
+ struct mmc_data data ;
1619
+ struct scatterlist sg ;
1620
+ u8 * data_buf ;
1621
+ char how [MAX_NO_OF_TAPS + 1 ] = "" ;
1622
+
1623
+ if (slot -> hs400_tuning_block == -1 )
1624
+ return 0 ;
1625
+
1626
+ /*
1627
+ * Unfortunately, in their infinite wisdom, the eMMC standard does
1628
+ * not allow for tuning in HS400 mode. The problem is that what
1629
+ * makes a good tuning point for HS200 often does not work in HS400
1630
+ * mode. In order to tune HS400 mode, a block (usually block 1) is
1631
+ * set aside for tuning. U-Boot is responsible for writing a data
1632
+ * pattern designed to generate a worst case signal. Most of this
1633
+ * pattern is based off of the HS200 pattern.
1634
+ *
1635
+ * Each data in tap is tested by a read of this block and the center
1636
+ * tap of the longest run of good reads is chosen. This code is
1637
+ * largely similar to adjust_tuning() above.
1638
+ */
1639
+ data_buf = kmalloc (size , GFP_KERNEL );
1640
+ if (!data_buf )
1641
+ return - ENOMEM ;
1642
+
1643
+ hs400_prepare_mrq (slot , & mrq , & cmd , & data , & sg , data_buf , size , false);
1644
+
1645
+ /* loop over range+1 to simplify processing */
1646
+ for (tap = 0 ; tap <= MAX_NO_OF_TAPS ; tap ++ , prev_ok = !err ) {
1647
+ if (tap < MAX_NO_OF_TAPS ) {
1648
+ cvm_mmc_clk_config (host , CLK_OFF );
1649
+ timing = readq (host -> base + MIO_EMM_TIMING (host ));
1650
+ timing = FIELD_PREP (MIO_EMM_TIMING_DATA_IN , tap );
1651
+ writeq (timing , host -> base + MIO_EMM_TIMING (host ));
1652
+ cvm_mmc_clk_config (host , CLK_ON );
1653
+
1654
+ dev_dbg (host -> dev , "HS400 testing data in tap %d\n" ,
1655
+ tap );
1656
+ mmc_wait_for_req (mmc , & mrq );
1657
+ if (cmd .error | data .error ) {
1658
+ err = cmd .error ? cmd .error : data .error ;
1659
+ how [tap ] = '-' ;
1660
+ dev_dbg (host -> dev ,
1661
+ "HS400 tuning cmd err: %d, data error: %d\n" ,
1662
+ cmd .error , data .error );
1663
+ } else { /* Validate data */
1664
+ err = memcmp (data_buf ,
1665
+ octeontx_hs400_tuning_block , size );
1666
+
1667
+ how [tap ] = "d+" [!err ];
1668
+ dev_dbg (host -> dev ,
1669
+ "HS400 read OK at tap %d, data %s\n" ,
1670
+ tap , err ? "mismatch" : "ok" );
1671
+ }
1672
+
1673
+ if (!err )
1674
+ last_good = tap ;
1675
+ } else {
1676
+ /*
1677
+ * putting the end+1 case in loop simplifies
1678
+ * logic, allowing 'prev_ok' to process a
1679
+ * sweet spot in tuning which extends to wall.
1680
+ */
1681
+ err = - EILSEQ ;
1682
+ }
1683
+
1684
+ if (!err ) {
1685
+ /*
1686
+ * If no CRC/etc errors in response, but previous
1687
+ * failed, note the start of a new run
1688
+ */
1689
+ if (!prev_ok )
1690
+ start_run = tap ;
1691
+ } else if (prev_ok ) {
1692
+ int run = tap - 1 - start_run ;
1693
+
1694
+ /* did we just exit a wider sweet spot? */
1695
+ if (start_run >= 0 && run > best_run ) {
1696
+ best_start = start_run ;
1697
+ best_run = run ;
1698
+ }
1699
+ }
1700
+ }
1701
+
1702
+ kfree (data_buf );
1703
+ if (best_start < 0 ) {
1704
+ dev_warn (host -> dev , "%s %lldMHz tuning HS400 data in failed\n" ,
1705
+ mmc_hostname (mmc ), slot -> clock / 1000000 );
1706
+ return - EINVAL ;
1707
+ }
1708
+
1709
+ tap = best_start + best_run / 2 ;
1710
+ how [tap ] = '@' ;
1711
+ if (tapdance ) {
1712
+ tap = last_good - tapdance ;
1713
+ how [tap ] = 'X' ;
1714
+ }
1715
+ dev_dbg (host -> dev , "%s/HS400 data in %d/%d/%d %s\n" ,
1716
+ mmc_hostname (mmc ), best_start , tap ,
1717
+ best_start + best_run , how );
1718
+ slot -> taps &= ~MIO_EMM_TIMING_DATA_IN ;
1719
+ slot -> taps |= FIELD_PREP (MIO_EMM_TIMING_DATA_IN , tap );
1720
+ dev_dbg (host -> dev , "HS400 data input tap: %d\n" , tap );
1721
+ dev_dbg (host -> dev , "%s\n" , how );
1722
+ cvm_mmc_set_timing (slot );
1723
+
1724
+ return 0 ;
1725
+ }
1726
+
1426
1727
static u32 max_supported_frequency (struct cvm_mmc_host * host )
1427
1728
{
1428
1729
/* Default maximum freqeuncey is 52000000 for chip prior to 9X */
@@ -1572,6 +1873,10 @@ static void cvm_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1572
1873
cvm_mmc_configure_delay (slot );
1573
1874
out :
1574
1875
host -> release_bus (host );
1876
+ if (ios -> timing == MMC_TIMING_MMC_HS )
1877
+ check_and_write_hs400_tuning_block (slot );
1878
+ else if (ios -> timing == MMC_TIMING_MMC_HS400 )
1879
+ tune_hs400 (slot );
1575
1880
}
1576
1881
1577
1882
static struct adj adj [] = {
@@ -1600,6 +1905,8 @@ static int cvm_scan_tuning(struct mmc_host *mmc, u32 opcode)
1600
1905
}
1601
1906
1602
1907
cvm_mmc_set_timing (slot );
1908
+ if (!slot -> hs400_tuning_block_present )
1909
+ check_and_write_hs400_tuning_block (slot );
1603
1910
return 0 ;
1604
1911
}
1605
1912
@@ -1768,6 +2075,9 @@ static int cvm_mmc_of_parse(struct device *dev, struct cvm_mmc_slot *slot)
1768
2075
if (ret )
1769
2076
return ret ;
1770
2077
2078
+ slot -> hs400_tuning_block = -1U ;
2079
+ of_property_read_u32 (node , "marvell,hs400-tuning-block" ,
2080
+ & slot -> hs400_tuning_block );
1771
2081
/* Set bus width from obsolete properties, if unset */
1772
2082
if (!(mmc -> caps & (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA ))) {
1773
2083
of_property_read_u32 (node , "cavium,bus-max-width" , & bus_width );
0 commit comments