Re: [PATCH] mmc: sdhci: Correct ADMA_DESC_LEN to 12

2024-05-02 Thread Judith Mendez

Hi,

On 5/1/24 1:53 PM, A. Sverdlin wrote:

From: Alexander Sverdlin 

Commit 37cb626da25d0d ("mmc: sdhci: Add Support for ADMA2") introduced
ADMA_DESC_LEN == 16 (64 bit case), but it was never used before commit
74755c1fed1b0 ("mmc: sdhci: introduce adma_write_desc() hook to struct 
sdhci_ops").

"sizeof(struct sdhci_adma_desc)" (== 12 for 64bit case) was used instead.

Confusion probably originates from Linux commit 685e444bbaa0
("mmc: sdhci: Add ADMA2 64-bit addressing support for V4 mode"), but
the latter "V4 mode" was never ported to U-Boot.

Fixes: 74755c1fed1b0 ("mmc: sdhci: introduce adma_write_desc() hook to struct 
sdhci_ops")
Signed-off-by: Alexander Sverdlin 
---
  include/sdhci.h | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/sdhci.h b/include/sdhci.h
index d73a725609be3..810ef56e4be66 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -300,7 +300,7 @@ struct sdhci_ops {
  
  #define ADMA_MAX_LEN	65532

  #ifdef CONFIG_DMA_ADDR_T_64BIT
-#define ADMA_DESC_LEN  16
+#define ADMA_DESC_LEN  12
  #else
  #define ADMA_DESC_LEN 8
  #endif


on TI AM62 platform:

Tested-by: Judith Mendez 



Re: [GIT PULL] Please pull u-boot-mmc master

2024-05-02 Thread Judith Mendez

Hi Greg,

On 5/1/24 9:40 PM, Greg Malysa wrote:

On Tue, Apr 30, 2024 at 3:42 AM Francesco Dolcini  wrote:


On Mon, Apr 29, 2024 at 03:39:53PM -0500, Judith Mendez wrote:

A patch in this series caused a regression for AM62x SK with the
following error:


+1, this affects also Verdin AM62.


Hi, please try 
https://patchwork.ozlabs.org/project/uboot/patch/20240501185331.1189647-1-alexander.sverd...@siemens.com/
as this should explain the issue and also fix it.


The fix fixes my issuu on AM62x, thanks.

~ Judith


[PATCH] configs: am62x_evm_r5: Increase size of malloc_simple heap after relocation

2024-04-29 Thread Judith Mendez
On AM62x SK we can see a boot failure with signature "alloc space
exhausted", so fix by increasing size of SPL_STACK_R_MALLOC_SIMPLE_LEN.

Fixes: 128f81290b ("arm: dts: k3: binman: am625: add support for signing 
TIFSSTUB Images")
Signed-off-by: Judith Mendez 
---
 configs/am62x_evm_r5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/am62x_evm_r5_defconfig b/configs/am62x_evm_r5_defconfig
index 4b2e57b13a0..648241488ed 100644
--- a/configs/am62x_evm_r5_defconfig
+++ b/configs/am62x_evm_r5_defconfig
@@ -26,6 +26,7 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
 CONFIG_SPL_BSS_START_ADDR=0x43c3b000
 CONFIG_SPL_BSS_MAX_SIZE=0x3000
 CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x20
 CONFIG_SPL_SIZE_LIMIT=0x3A7F0
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x3500
 CONFIG_SPL_FS_FAT=y

base-commit: 174ac987655c888017c82df1883c0c2ea0dc2495
-- 
2.43.2



Re: [GIT PULL] Please pull u-boot-mmc master

2024-04-29 Thread Judith Mendez

Hi all,

On 4/26/24 10:51 AM, Tom Rini wrote:

On Fri, Apr 26, 2024 at 07:38:30PM +0900, Jaehoon Chung wrote:


Dear Tom,

Please pull u-boot-mmc master into u-boot master branch.
If there is any problem, let me know, plz

Best Regards,
Jaehoon Chung

CI: https://source.denx.de/u-boot/custodians/u-boot-mmc/-/pipelines/20547

The following changes since commit d097f9e1299a3bdb7de468f0d9bbc63932f461cd:

   Merge tag 'fsl-qoriq-2024-4-24' of 
https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq (2024-04-23 17:53:06 
-0600)

are available in the Git repository at:

   g...@source.denx.de:u-boot/custodians/u-boot-mmc.git master

for you to fetch changes up to 1776213dadef4b578f98bcf18beb152f8975a8bf:

   mmc: arm_pl180: Limit data transfer to U16_MAX (2024-04-26 15:32:06 +0900)



Applied to u-boot/master, thanks!




A patch in this series caused a regression for AM62x SK with the
following error:

Error reading cluster
spl_load_image_fat: error reading image u-boot.img, err - -22
SPL: failed to boot from all boot devices (err=-6)
### ERROR ### Please RESET the board ###

Git bisect showed "mmc: sdhci: introduce adma_write_desc() hook to
struct sdhci_ops" to be the offending commit.

Could someone point me to the next steps to fix this issue?

regards,
Judith


[PATCH v2 4/5] mmc: am654_sdhci: Set ENDLL=1 for DDR52 mode

2024-04-18 Thread Judith Mendez
According to the device datasheet [0], ENDLL=1 for
DDR52 mode, so call am654_sdhci_setup_dll() and write
itapdly after since we do not carry out tuning.

[0] https://www.ti.com/lit/ds/symlink/am62p.pdf
Fixes: c964447ea3d6 ("mmc: am654_sdhci: Add support for input tap delay")
Signed-off-by: Judith Mendez 
Reviewed-by: Jaehoon Chung 
---
Changes since v1:
- Add Reviewed-by
---
 drivers/mmc/am654_sdhci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 62007ebd0f4..e1047812fa8 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -289,12 +289,14 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
 
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
 
-   if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) {
+   if ((mode > UHS_SDR25 || mode == MMC_DDR_52) && speed >= 
CLOCK_TOO_SLOW_HZ) {
ret = am654_sdhci_setup_dll(plat, speed);
if (ret)
return ret;
 
plat->dll_enable = true;
+   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
+ plat->itap_del_ena[mode]);
} else {
am654_sdhci_setup_delay_chain(plat, mode);
plat->dll_enable = false;
-- 
2.43.2



[PATCH v2 5/5] mmc: am654_sdhci: Fix ITAPDLY for HS400 timing

2024-04-18 Thread Judith Mendez
At HS400 mode the ITAPDLY value is that from High Speed mode
which is incorrect and may cause boot failures.

The ITAPDLY for HS400 speed mode should be the same as ITAPDLY
as HS200 timing after tuning is executed. Add the functionality
to save ITAPDLY from HS200 tuning and save as HS400 ITAPDLY.

Fixes: c964447ea3d6 ("mmc: am654_sdhci: Add support for input tap delay")
Signed-off-by: Judith Mendez 
---
Changes since v1:
- Use ENABLE macro instead of 0x1
---
 drivers/mmc/am654_sdhci.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index e1047812fa8..fadab7d40bb 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -295,6 +295,11 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
return ret;
 
plat->dll_enable = true;
+   if (mode == MMC_HS_400) {
+   plat->itap_del_ena[mode] = ENABLE;
+   plat->itap_del_sel[mode] = plat->itap_del_sel[mode - 1];
+   }
+
am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
  plat->itap_del_ena[mode]);
} else {
@@ -486,6 +491,9 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
  plat->dll_enable);
 
+   /* Save ITAPDLY */
+   plat->itap_del_sel[mode] = itap;
+
am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
return 0;
-- 
2.43.2



[PATCH v2 1/5] mmc: am654_sdhci: Add tuning algorithm for delay chain

2024-04-18 Thread Judith Mendez
Currently the sdhci_am654 driver only supports one tuning
algorithm which should be used only when DLL is enabled. The
ITAPDLY is selected from the largest passing window and the
buffer is viewed as a circular buffer.

The new tuning algorithm should be used when the delay chain
is enabled; the ITAPDLY is selected from the largest passing
window and the buffer is not viewed as a circular buffer.

This implementation is based off of the following paper: [1].

Also add support for multiple failing windows.

[1] https://www.ti.com/lit/an/spract9/spract9.pdf

Fixes: a759abf569d4 ("mmc: am654_sdhci: Add support for software tuning")
Signed-off-by: Judith Mendez 
---
Changes since v1:
- Remove extra param from mmc_send_tunning() call
---
 drivers/mmc/am654_sdhci.c | 107 +++---
 1 file changed, 89 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 2139fea04d5..7e41dd91f8e 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -97,6 +97,7 @@ struct am654_sdhci_plat {
u32 strb_sel;
u32 clkbuf_sel;
u32 flags;
+   bool dll_enable;
 #define DLL_PRESENTBIT(0)
 #define IOMUX_PRESENT  BIT(1)
 #define FREQSEL_2_BIT  BIT(2)
@@ -110,6 +111,12 @@ struct timing_data {
u32 capability;
 };
 
+struct window {
+   u8 start;
+   u8 end;
+   u8 length;
+};
+
 static const struct timing_data td[] = {
[MMC_LEGACY]= {"ti,otap-del-sel-legacy",
   "ti,itap-del-sel-legacy",
@@ -280,8 +287,11 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
ret = am654_sdhci_setup_dll(plat, speed);
if (ret)
return ret;
+
+   plat->dll_enable = true;
} else {
am654_sdhci_setup_delay_chain(plat, mode);
+   plat->dll_enable = false;
}
 
regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
@@ -375,38 +385,99 @@ static void am654_sdhci_write_b(struct sdhci_host *host, 
u8 val, int reg)
writeb(val, host->ioaddr + reg);
 }
 #ifdef MMC_SUPPORTS_TUNING
-#define ITAP_MAX   32
+#define ITAPDLY_LENGTH 32
+#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
+
+static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window
+ *fail_window, u8 num_fails, bool circular_buffer)
+{
+   u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
+   u8 first_fail_start = 0, last_fail_end = 0;
+   struct window pass_window = {0, 0, 0};
+   int prev_fail_end = -1;
+   u8 i;
+
+   if (!num_fails)
+   return ITAPDLY_LAST_INDEX >> 1;
+
+   if (fail_window->length == ITAPDLY_LENGTH) {
+   dev_err(dev, "No passing ITAPDLY, return 0\n");
+   return 0;
+   }
+
+   first_fail_start = fail_window->start;
+   last_fail_end = fail_window[num_fails - 1].end;
+
+   for (i = 0; i < num_fails; i++) {
+   start_fail = fail_window[i].start;
+   end_fail = fail_window[i].end;
+   pass_length = start_fail - (prev_fail_end + 1);
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = prev_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+   prev_fail_end = end_fail;
+   }
+
+   if (!circular_buffer)
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
+   else
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end + 
first_fail_start;
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = last_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+
+   if (!circular_buffer)
+   itap = pass_window.start + (pass_window.length >> 1);
+   else
+   itap = (pass_window.start + (pass_window.length >> 1)) % 
ITAPDLY_LENGTH;
+
+   return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
+}
+
 static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 {
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len;
-   u32 itap;
+   struct window fail_window[ITAPDLY_LENGTH];
+   u8 curr_pass, itap;
+   u8 fail_index = 0;
+   u8 prev_pass = 1;
+
+   memset(fail_window, 0, sizeof(fail_window));
 
/* Enable ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
   1 << ITAPDLYENA_SHIFT);
 
-   for (itap = 0; itap < ITAP_MAX; itap++) {
+   for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
am654_sdhci_write_itapdly(plat, itap);
 
-   cur_val = !mm

[PATCH v2 3/5] mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena bit

2024-04-18 Thread Judith Mendez
Set itap_del_ena if ITAPDLY is found in DT or if the tuning
algorithm was executed and found the optimal ITAPDLY. Add the
functionality to save ITAPDLYENA that can be referenced later
by storing the bit in array itap_del_ena[].

Signed-off-by: Judith Mendez 
---
Changes since v1:
- Use ENABLE macro instead of 0x1
---
 drivers/mmc/am654_sdhci.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index becb3550899..62007ebd0f4 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -85,6 +85,8 @@
 #define AM654_SDHCI_MIN_FREQ   40
 #define CLOCK_TOO_SLOW_HZ  5000
 
+#define ENABLE 0x1
+
 struct am654_sdhci_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -92,6 +94,7 @@ struct am654_sdhci_plat {
bool non_removable;
u32 otap_del_sel[MMC_MODES_END];
u32 itap_del_sel[MMC_MODES_END];
+   u32 itap_del_ena[MMC_MODES_END];
u32 trm_icp;
u32 drv_strength;
u32 strb_sel;
@@ -223,8 +226,10 @@ static int am654_sdhci_setup_dll(struct am654_sdhci_plat 
*plat,
 }
 
 static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
- u32 itapdly)
+ u32 itapdly, u32 enable)
 {
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
+  enable << ITAPDLYENA_SHIFT);
/* Set ITAPCHGWIN before writing to ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
   1 << ITAPCHGWIN_SHIFT);
@@ -242,7 +247,8 @@ static void am654_sdhci_setup_delay_chain(struct 
am654_sdhci_plat *plat,
mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
 
-   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
+   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
+ plat->itap_del_ena[mode]);
 }
 
 static int am654_sdhci_set_ios_post(struct sdhci_host *host)
@@ -443,6 +449,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
struct window fail_window[ITAPDLY_LENGTH];
+   int mode = mmc->selected_mode;
u8 curr_pass, itap;
u8 fail_index = 0;
u8 prev_pass = 1;
@@ -450,11 +457,10 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
memset(fail_window, 0, sizeof(fail_window));
 
/* Enable ITAPDLY */
-   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
-  1 << ITAPDLYENA_SHIFT);
+   plat->itap_del_ena[mode] = ENABLE;
 
for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
curr_pass = !mmc_send_tuning(mmc, opcode);
 
@@ -478,7 +484,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
  plat->dll_enable);
 
-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
return 0;
 }
@@ -515,6 +521,7 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host 
*host)
struct am654_sdhci_plat *plat = dev_get_plat(dev);
int mode = host->mmc->selected_mode;
u32 otap_del_sel;
+   u32 itap_del_ena;
u32 itap_del_sel;
u32 mask, val;
 
@@ -524,10 +531,11 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
val = (1 << OTAPDLYENA_SHIFT) |
  (otap_del_sel << OTAPDLYSEL_SHIFT);
 
+   itap_del_ena = plat->itap_del_ena[mode];
itap_del_sel = plat->itap_del_sel[mode];
 
mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
-   val |= (1 << ITAPDLYENA_SHIFT) |
+   val |= (itap_del_ena << ITAPDLYENA_SHIFT) |
   (itap_del_sel << ITAPDLYSEL_SHIFT);
 
regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
@@ -599,9 +607,13 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
cfg->host_caps &= ~td[i].capability;
}
 
-   if (td[i].itap_binding)
-   dev_read_u32(dev, td[i].itap_binding,
->itap_del_sel[i]);
+   if (td[i].itap_binding) {
+   ret = dev_read_u32(dev, td[i].itap_binding,
+  >itap_del_sel[i]);
+
+   if (!ret)
+   plat->itap_del_ena[i] = ENABLE;
+   }
}
 
return 0;
-- 
2.43.2



[PATCH v2 0/5] Fix MMC tuning algorithm

2024-04-18 Thread Judith Mendez
The following patch series includes a MMC tuning algorithm
fix according to the following published paper [0].

This seris also includes fixes for OTAP/ITAP delay values
in j721e_4bit_sdhci_set_ios_post and for HS400 mode.

For DDR52 mode, also set ENDLL=1 and call am654_sdhci_setup_dll()
instead of am654_sdhci_setup_delay_chain() according to
device datasheet[1].

[0] https://www.ti.com/lit/an/spract9/spract9.pdf
[1] https://www.ti.com/lit/ds/symlink/am62p.pdf

Link to v1:
https://lore.kernel.org/u-boot/20240415212747.2678974-1...@ti.com/

Changes since v1:
- Use ENABLE macro instead of 0x1
- Fix assignment to val variable in j721e_4bit_sdhci_set_ios_post()
- Remove extra param from mmc_send_tunning() call
- Add Reviewed by

Judith Mendez (4):
  mmc: am654_sdhci: Add tuning algorithm for delay chain
  mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena bit
  mmc: am654_sdhci: Set ENDLL=1 for DDR52 mode
  mmc: am654_sdhci: Fix ITAPDLY for HS400 timing

Nitin Yadav (1):
  mmc: am654_sdhci: Fix OTAP/ITAP delay values

 drivers/mmc/am654_sdhci.c | 172 +++---
 1 file changed, 140 insertions(+), 32 deletions(-)


base-commit: 3434b88d2c2fdad3cc947f9e9b03dabfdd3feb5c
-- 
2.43.2



[PATCH v2 2/5] mmc: am654_sdhci: Fix OTAP/ITAP delay values

2024-04-18 Thread Judith Mendez
From: Nitin Yadav 

U-Boot is failing to boot class U1 UHS SD cards due to incorrect
OTAP and ITAP delay select values. Update OTAP and ITAP delay select
values from DT.

Fixes: c7d106b4eb3 ("mmc: am654_sdhci: Update output tap delay writes")
Signed-off-by: Nitin Yadav 
Signed-off-by: Judith Mendez 
---
Changes since v1:
- Fix assignment to val variable in j721e_4bit_sdhci_set_ios_post()
---
 drivers/mmc/am654_sdhci.c | 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 7e41dd91f8e..becb3550899 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -513,12 +513,27 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
 {
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   u32 otap_del_sel, mask, val;
+   int mode = host->mmc->selected_mode;
+   u32 otap_del_sel;
+   u32 itap_del_sel;
+   u32 mask, val;
+
+   otap_del_sel = plat->otap_del_sel[mode];
 
-   otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
-   val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
+   val = (1 << OTAPDLYENA_SHIFT) |
+ (otap_del_sel << OTAPDLYSEL_SHIFT);
+
+   itap_del_sel = plat->itap_del_sel[mode];
+
+   mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
+   val |= (1 << ITAPDLYENA_SHIFT) |
+  (itap_del_sel << ITAPDLYSEL_SHIFT);
+
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+  1 << ITAPCHGWIN_SHIFT);
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
 
regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
   plat->clkbuf_sel);
@@ -572,7 +587,7 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
 * Remove the corresponding capability if an otap-del-sel
 * value is not found
 */
-   for (i = MMC_HS; i <= MMC_HS_400; i++) {
+   for (i = MMC_LEGACY; i <= MMC_HS_400; i++) {
ret = dev_read_u32(dev, td[i].otap_binding,
   >otap_del_sel[i]);
if (ret) {
-- 
2.43.2



Re: [PATCH 3/5] mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena bit

2024-04-18 Thread Judith Mendez

On 4/17/24 6:34 AM, Jaehoon Chung wrote:

Hi,


-Original Message-
From: Judith Mendez 
Sent: Tuesday, April 16, 2024 6:28 AM
To: Peng Fan ; Jaehoon Chung ; Tom Rini 

Cc: Nitin Yadav ; Simon Glass ; 
u-boot@lists.denx.de
Subject: [PATCH 3/5] mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena 
bit

Set itap_del_ena if ITAPDLY is found in DT or if the tuning
algorithm was executed and found the optimal ITAPDLY. Add the
functionality to save ITAPDLYENA that can be referenced later
by storing the bit in array itap_del_ena[].

Signed-off-by: Judith Mendez 
---
  drivers/mmc/am654_sdhci.c | 30 --
  1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 1dd032e1e36..38f1ad28ec4 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -92,6 +92,7 @@ struct am654_sdhci_plat {
bool non_removable;
u32 otap_del_sel[MMC_MODES_END];
u32 itap_del_sel[MMC_MODES_END];
+   u32 itap_del_ena[MMC_MODES_END];
u32 trm_icp;
u32 drv_strength;
u32 strb_sel;
@@ -223,8 +224,10 @@ static int am654_sdhci_setup_dll(struct am654_sdhci_plat 
*plat,
  }

  static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
- u32 itapdly)
+ u32 itapdly, u32 enable)
  {
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
+  enable << ITAPDLYENA_SHIFT);
/* Set ITAPCHGWIN before writing to ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
   1 << ITAPCHGWIN_SHIFT);
@@ -242,7 +245,8 @@ static void am654_sdhci_setup_delay_chain(struct 
am654_sdhci_plat *plat,
mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
regmap_update_bits(plat->base, PHY_CTRL5, mask, val);

-   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
+   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
+ plat->itap_del_ena[mode]);
  }

  static int am654_sdhci_set_ios_post(struct sdhci_host *host)
@@ -443,6 +447,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
struct window fail_window[ITAPDLY_LENGTH];
+   int mode = mmc->selected_mode;
u8 curr_pass, itap;
u8 fail_index = 0;
u8 prev_pass = 1;
@@ -450,11 +455,10 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
memset(fail_window, 0, sizeof(fail_window));

/* Enable ITAPDLY */
-   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
-  1 << ITAPDLYENA_SHIFT);
+   plat->itap_del_ena[mode] = 0x1;


0x1 means "enable"? I want to use a macro with meaning.


Sure, can do for V2, thanks.
~ Judith





for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);

curr_pass = !mmc_send_tuning(mmc, opcode, NULL);

@@ -478,7 +482,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
  plat->dll_enable);

-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);

return 0;
  }
@@ -515,6 +519,7 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host 
*host)
struct am654_sdhci_plat *plat = dev_get_plat(dev);
int mode = host->mmc->selected_mode;
u32 otap_del_sel;
+   u32 itap_del_ena;
u32 itap_del_sel;
u32 mask, val;

@@ -524,10 +529,11 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
val = (1 << OTAPDLYENA_SHIFT) |
  (otap_del_sel << OTAPDLYSEL_SHIFT);

+   itap_del_ena = plat->itap_del_ena[mode];
itap_del_sel = plat->itap_del_sel[mode];

mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
-   val = (1 << ITAPDLYENA_SHIFT) |
+   val = (itap_del_ena << ITAPDLYENA_SHIFT) |
  (itap_del_sel << ITAPDLYSEL_SHIFT);

regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
@@ -599,9 +605,13 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
cfg->host_caps &= ~td[i].capability;
}

-   if (td[i].itap_binding)
-   dev_read_u32(dev, td[i].itap_binding,
->itap_del_sel[i]);
+   if (td[i].itap_binding) {
+   ret = dev_read_u32(dev, td[i].itap_binding,
+

Re: [PATCH 2/5] mmc: am654_sdhci: Fix OTAP/ITAP delay values

2024-04-18 Thread Judith Mendez

On 4/17/24 6:28 AM, Jaehoon Chung wrote:

Hi Judith,


-Original Message-
From: Judith Mendez 
Sent: Tuesday, April 16, 2024 6:28 AM
To: Peng Fan ; Jaehoon Chung ; Tom Rini 

Cc: Nitin Yadav ; Simon Glass ; 
u-boot@lists.denx.de
Subject: [PATCH 2/5] mmc: am654_sdhci: Fix OTAP/ITAP delay values

From: Nitin Yadav 

U-Boot is failing to boot class U1 UHS SD cards due to incorrect
OTAP and ITAP delay select values. Update OTAP and ITAP delay select
values from DT.

Fixes: c7d106b4eb3 ("mmc: am654_sdhci: Update output tap delay writes")
Signed-off-by: Nitin Yadav 
Signed-off-by: Judith Mendez 
---
  drivers/mmc/am654_sdhci.c | 23 +++
  1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index e5ad00e2531..1dd032e1e36 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -513,12 +513,27 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
  {
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   u32 otap_del_sel, mask, val;
+   int mode = host->mmc->selected_mode;
+   u32 otap_del_sel;
+   u32 itap_del_sel;
+   u32 mask, val;
+
+   otap_del_sel = plat->otap_del_sel[mode];

-   otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
-   val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
+   val = (1 << OTAPDLYENA_SHIFT) |
+ (otap_del_sel << OTAPDLYSEL_SHIFT);


Is there any reason to touch this? And I can't understood this, this val 
doesn’t use anywhere.
Because val is resetting the below. It seems same value, right?


This change is syncing with upstream kernel driver.

The second val assignment is supposed to be val |=,
will fix for v2.




+
+   itap_del_sel = plat->itap_del_sel[mode];
+
+   mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;


Can it be set at above?

mask |= OTAPDLYENA_MASK | OTAPDLYSEL_MASK |
ITAPDLYENA_MASK | ITAPDLYSEL_MASK;


This is also syncing with upstream. I am hoping
to leave this as is.

~ Judith



Best Regards,
Jaehoon Chung




+   val = (1 << ITAPDLYENA_SHIFT) |
+ (itap_del_sel << ITAPDLYSEL_SHIFT);
+
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+  1 << ITAPCHGWIN_SHIFT);
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);

regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
   plat->clkbuf_sel);
@@ -572,7 +587,7 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
 * Remove the corresponding capability if an otap-del-sel
 * value is not found
 */
-   for (i = MMC_HS; i <= MMC_HS_400; i++) {
+   for (i = MMC_LEGACY; i <= MMC_HS_400; i++) {
ret = dev_read_u32(dev, td[i].otap_binding,
   >otap_del_sel[i]);
if (ret) {
--
2.43.2








Re: [PATCH 1/5] mmc: am654_sdhci: Add tuning algorithm for delay chain

2024-04-18 Thread Judith Mendez

Hi,

On 4/17/24 6:23 AM, Jaehoon Chung wrote:




-Original Message-
From: Judith Mendez 
Sent: Tuesday, April 16, 2024 6:28 AM
To: Peng Fan ; Jaehoon Chung ; Tom Rini 

Cc: Nitin Yadav ; Simon Glass ; 
u-boot@lists.denx.de
Subject: [PATCH 1/5] mmc: am654_sdhci: Add tuning algorithm for delay chain

Currently the sdhci_am654 driver only supports one tuning
algorithm which should be used only when DLL is enabled. The
ITAPDLY is selected from the largest passing window and the
buffer is viewed as a circular buffer.

The new tuning algorithm should be used when the delay chain
is enabled; the ITAPDLY is selected from the largest passing
window and the buffer is not viewed as a circular buffer.

This implementation is based off of the following paper: [1].

Also add support for multiple failing windows.

[1] https://www.ti.com/lit/an/spract9/spract9.pdf

Fixes: a759abf569d4 ("mmc: am654_sdhci: Add support for software tuning")
Signed-off-by: Judith Mendez 
---
  drivers/mmc/am654_sdhci.c | 107 +++---
  1 file changed, 89 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 05595bdac39..e5ad00e2531 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -97,6 +97,7 @@ struct am654_sdhci_plat {
u32 strb_sel;
u32 clkbuf_sel;
u32 flags;
+   bool dll_enable;
  #define DLL_PRESENT   BIT(0)
  #define IOMUX_PRESENT BIT(1)
  #define FREQSEL_2_BIT BIT(2)
@@ -110,6 +111,12 @@ struct timing_data {
u32 capability;
  };

+struct window {
+   u8 start;
+   u8 end;
+   u8 length;
+};
+
  static const struct timing_data td[] = {
[MMC_LEGACY]= {"ti,otap-del-sel-legacy",
   "ti,itap-del-sel-legacy",
@@ -280,8 +287,11 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
ret = am654_sdhci_setup_dll(plat, speed);
if (ret)
return ret;
+
+   plat->dll_enable = true;
} else {
am654_sdhci_setup_delay_chain(plat, mode);
+   plat->dll_enable = false;
}

regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
@@ -375,38 +385,99 @@ static void am654_sdhci_write_b(struct sdhci_host *host, 
u8 val, int reg)
writeb(val, host->ioaddr + reg);
  }
  #ifdef MMC_SUPPORTS_TUNING
-#define ITAP_MAX   32
+#define ITAPDLY_LENGTH 32
+#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
+
+static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window
+ *fail_window, u8 num_fails, bool circular_buffer)
+{
+   u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
+   u8 first_fail_start = 0, last_fail_end = 0;
+   struct window pass_window = {0, 0, 0};
+   int prev_fail_end = -1;
+   u8 i;
+
+   if (!num_fails)
+   return ITAPDLY_LAST_INDEX >> 1;
+
+   if (fail_window->length == ITAPDLY_LENGTH) {
+   dev_err(dev, "No passing ITAPDLY, return 0\n");
+   return 0;
+   }
+
+   first_fail_start = fail_window->start;
+   last_fail_end = fail_window[num_fails - 1].end;
+
+   for (i = 0; i < num_fails; i++) {
+   start_fail = fail_window[i].start;
+   end_fail = fail_window[i].end;
+   pass_length = start_fail - (prev_fail_end + 1);
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = prev_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+   prev_fail_end = end_fail;
+   }
+
+   if (!circular_buffer)
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
+   else
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end + 
first_fail_start;
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = last_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+
+   if (!circular_buffer)
+   itap = pass_window.start + (pass_window.length >> 1);
+   else
+   itap = (pass_window.start + (pass_window.length >> 1)) % 
ITAPDLY_LENGTH;
+
+   return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
+}
+
  static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
  {
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len;
-   u32 itap;
+   struct window fail_window[ITAPDLY_LENGTH];
+   u8 curr_pass, itap;
+   u8 fail_index = 0;
+   u8 prev_pass = 1;
+
+   memset(fail_window, 0, sizeof(fail_window));

/* Enable ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
   

Re: [PATCH] configs: am62px_evm_a53_defconfig: Enable MMC UHS config option

2024-04-16 Thread Judith Mendez

Hi all,

On 4/8/24 11:01 AM, Judith Mendez wrote:

Enable MMC UHS support for to allow to enter the UHS
modes for MMC0.



I have sent v2 for this patch since there was a typo in
the patch description.

~ Judith



[PATCH v2] configs: am62px_evm_a53_defconfig: Enable MMC UHS config option

2024-04-16 Thread Judith Mendez
Enable MMC UHS support for to allow to enter the UHS
modes for MMC1.

Signed-off-by: Judith Mendez 
---
Changes since v1:
- Fix typo in patch description
---

 configs/am62px_evm_a53_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/am62px_evm_a53_defconfig b/configs/am62px_evm_a53_defconfig
index 2621abb8ce1..d1ae18bedf6 100644
--- a/configs/am62px_evm_a53_defconfig
+++ b/configs/am62px_evm_a53_defconfig
@@ -115,6 +115,8 @@ CONFIG_FS_LOADER=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_SPL_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_SPL_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_SPL_MMC_HS400_SUPPORT=y
 CONFIG_MMC_SDHCI=y

base-commit: bc39e06778168a34bb4e0a34fbee4edbde4414d8
-- 
2.43.2



[PATCH 2/5] mmc: am654_sdhci: Fix OTAP/ITAP delay values

2024-04-15 Thread Judith Mendez
From: Nitin Yadav 

U-Boot is failing to boot class U1 UHS SD cards due to incorrect
OTAP and ITAP delay select values. Update OTAP and ITAP delay select
values from DT.

Fixes: c7d106b4eb3 ("mmc: am654_sdhci: Update output tap delay writes")
Signed-off-by: Nitin Yadav 
Signed-off-by: Judith Mendez 
---
 drivers/mmc/am654_sdhci.c | 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index e5ad00e2531..1dd032e1e36 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -513,12 +513,27 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
 {
struct udevice *dev = host->mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   u32 otap_del_sel, mask, val;
+   int mode = host->mmc->selected_mode;
+   u32 otap_del_sel;
+   u32 itap_del_sel;
+   u32 mask, val;
+
+   otap_del_sel = plat->otap_del_sel[mode];
 
-   otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
-   val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
+   val = (1 << OTAPDLYENA_SHIFT) |
+ (otap_del_sel << OTAPDLYSEL_SHIFT);
+
+   itap_del_sel = plat->itap_del_sel[mode];
+
+   mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
+   val = (1 << ITAPDLYENA_SHIFT) |
+ (itap_del_sel << ITAPDLYSEL_SHIFT);
+
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+  1 << ITAPCHGWIN_SHIFT);
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
 
regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
   plat->clkbuf_sel);
@@ -572,7 +587,7 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
 * Remove the corresponding capability if an otap-del-sel
 * value is not found
 */
-   for (i = MMC_HS; i <= MMC_HS_400; i++) {
+   for (i = MMC_LEGACY; i <= MMC_HS_400; i++) {
ret = dev_read_u32(dev, td[i].otap_binding,
   >otap_del_sel[i]);
if (ret) {
-- 
2.43.2



[PATCH 4/5] mmc: am654_sdhci: Set ENDLL=1 for DDR52 mode

2024-04-15 Thread Judith Mendez
According to the device datasheet [0], ENDLL=1 for
DDR52 mode, so call am654_sdhci_setup_dll() and write
itapdly after since we do not carry out tuning.

[0] https://www.ti.com/lit/ds/symlink/am62p.pdf
Fixes: c964447ea3d6 ("mmc: am654_sdhci: Add support for input tap delay")
Signed-off-by: Judith Mendez 
---
 drivers/mmc/am654_sdhci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 38f1ad28ec4..dee56dfdbaa 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -287,12 +287,14 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
 
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
 
-   if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) {
+   if ((mode > UHS_SDR25 || mode == MMC_DDR_52) && speed >= 
CLOCK_TOO_SLOW_HZ) {
ret = am654_sdhci_setup_dll(plat, speed);
if (ret)
return ret;
 
plat->dll_enable = true;
+   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
+ plat->itap_del_ena[mode]);
} else {
am654_sdhci_setup_delay_chain(plat, mode);
plat->dll_enable = false;
-- 
2.43.2



[PATCH 1/5] mmc: am654_sdhci: Add tuning algorithm for delay chain

2024-04-15 Thread Judith Mendez
Currently the sdhci_am654 driver only supports one tuning
algorithm which should be used only when DLL is enabled. The
ITAPDLY is selected from the largest passing window and the
buffer is viewed as a circular buffer.

The new tuning algorithm should be used when the delay chain
is enabled; the ITAPDLY is selected from the largest passing
window and the buffer is not viewed as a circular buffer.

This implementation is based off of the following paper: [1].

Also add support for multiple failing windows.

[1] https://www.ti.com/lit/an/spract9/spract9.pdf

Fixes: a759abf569d4 ("mmc: am654_sdhci: Add support for software tuning")
Signed-off-by: Judith Mendez 
---
 drivers/mmc/am654_sdhci.c | 107 +++---
 1 file changed, 89 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 05595bdac39..e5ad00e2531 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -97,6 +97,7 @@ struct am654_sdhci_plat {
u32 strb_sel;
u32 clkbuf_sel;
u32 flags;
+   bool dll_enable;
 #define DLL_PRESENTBIT(0)
 #define IOMUX_PRESENT  BIT(1)
 #define FREQSEL_2_BIT  BIT(2)
@@ -110,6 +111,12 @@ struct timing_data {
u32 capability;
 };
 
+struct window {
+   u8 start;
+   u8 end;
+   u8 length;
+};
+
 static const struct timing_data td[] = {
[MMC_LEGACY]= {"ti,otap-del-sel-legacy",
   "ti,itap-del-sel-legacy",
@@ -280,8 +287,11 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
ret = am654_sdhci_setup_dll(plat, speed);
if (ret)
return ret;
+
+   plat->dll_enable = true;
} else {
am654_sdhci_setup_delay_chain(plat, mode);
+   plat->dll_enable = false;
}
 
regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
@@ -375,38 +385,99 @@ static void am654_sdhci_write_b(struct sdhci_host *host, 
u8 val, int reg)
writeb(val, host->ioaddr + reg);
 }
 #ifdef MMC_SUPPORTS_TUNING
-#define ITAP_MAX   32
+#define ITAPDLY_LENGTH 32
+#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
+
+static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window
+ *fail_window, u8 num_fails, bool circular_buffer)
+{
+   u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
+   u8 first_fail_start = 0, last_fail_end = 0;
+   struct window pass_window = {0, 0, 0};
+   int prev_fail_end = -1;
+   u8 i;
+
+   if (!num_fails)
+   return ITAPDLY_LAST_INDEX >> 1;
+
+   if (fail_window->length == ITAPDLY_LENGTH) {
+   dev_err(dev, "No passing ITAPDLY, return 0\n");
+   return 0;
+   }
+
+   first_fail_start = fail_window->start;
+   last_fail_end = fail_window[num_fails - 1].end;
+
+   for (i = 0; i < num_fails; i++) {
+   start_fail = fail_window[i].start;
+   end_fail = fail_window[i].end;
+   pass_length = start_fail - (prev_fail_end + 1);
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = prev_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+   prev_fail_end = end_fail;
+   }
+
+   if (!circular_buffer)
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
+   else
+   pass_length = ITAPDLY_LAST_INDEX - last_fail_end + 
first_fail_start;
+
+   if (pass_length > pass_window.length) {
+   pass_window.start = last_fail_end + 1;
+   pass_window.length = pass_length;
+   }
+
+   if (!circular_buffer)
+   itap = pass_window.start + (pass_window.length >> 1);
+   else
+   itap = (pass_window.start + (pass_window.length >> 1)) % 
ITAPDLY_LENGTH;
+
+   return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
+}
+
 static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 {
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
-   int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len;
-   u32 itap;
+   struct window fail_window[ITAPDLY_LENGTH];
+   u8 curr_pass, itap;
+   u8 fail_index = 0;
+   u8 prev_pass = 1;
+
+   memset(fail_window, 0, sizeof(fail_window));
 
/* Enable ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
   1 << ITAPDLYENA_SHIFT);
 
-   for (itap = 0; itap < ITAP_MAX; itap++) {
+   for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
am654_sdhci_write_itapdly(plat, itap);
 
-   cur_val = !mmc_send_tuning(mmc, opcode, NULL);
-   if (cur_val &&am

[PATCH 0/5] Fix MMC tuning algorithm

2024-04-15 Thread Judith Mendez
The following patch series includes a MMC tuning algorithm
fix according to the following published paper [0].

This seris also includes fixes for OTAP/ITAP delay values
in j721e_4bit_sdhci_set_ios_post and for HS400 mode.

For DDR52 mode, also set ENDLL=1 and call am654_sdhci_setup_dll()
instead of am654_sdhci_setup_delay_chain() according to
device datasheet[1].

[0] https://www.ti.com/lit/an/spract9/spract9.pdf
[1] https://www.ti.com/lit/ds/symlink/am62p.pdf

Judith Mendez (4):
  mmc: am654_sdhci: Add tuning algorithm for delay chain
  mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena bit
  mmc: am654_sdhci: Set ENDLL=1 for DDR52 mode
  mmc: am654_sdhci: Fix ITAPDLY for HS400 timing

Nitin Yadav (1):
  mmc: am654_sdhci: Fix OTAP/ITAP delay values

 drivers/mmc/am654_sdhci.c | 170 +++---
 1 file changed, 138 insertions(+), 32 deletions(-)


base-commit: 27795dd717dadc73091e1b4d6c50952b93aaa819
-- 
2.43.2



[PATCH 5/5] mmc: am654_sdhci: Fix ITAPDLY for HS400 timing

2024-04-15 Thread Judith Mendez
At HS400 mode the ITAPDLY value is that from High Speed mode
which is incorrect and may cause boot failures.

The ITAPDLY for HS400 speed mode should be the same as ITAPDLY
as HS200 timing after tuning is executed. Add the functionality
to save ITAPDLY from HS200 tuning and save as HS400 ITAPDLY.

Fixes: c964447ea3d6 ("mmc: am654_sdhci: Add support for input tap delay")
Signed-off-by: Judith Mendez 
---
 drivers/mmc/am654_sdhci.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index dee56dfdbaa..ce3813ea3d0 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -293,6 +293,11 @@ static int am654_sdhci_set_ios_post(struct sdhci_host 
*host)
return ret;
 
plat->dll_enable = true;
+   if (mode == MMC_HS_400) {
+   plat->itap_del_ena[mode] = 0x1;
+   plat->itap_del_sel[mode] = plat->itap_del_sel[mode - 1];
+   }
+
am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
  plat->itap_del_ena[mode]);
} else {
@@ -484,6 +489,9 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
  plat->dll_enable);
 
+   /* Save ITAPDLY */
+   plat->itap_del_sel[mode] = itap;
+
am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
return 0;
-- 
2.43.2



[PATCH 3/5] mmc: am654_sdhci: Add itap_del_ena[] to store itapdlyena bit

2024-04-15 Thread Judith Mendez
Set itap_del_ena if ITAPDLY is found in DT or if the tuning
algorithm was executed and found the optimal ITAPDLY. Add the
functionality to save ITAPDLYENA that can be referenced later
by storing the bit in array itap_del_ena[].

Signed-off-by: Judith Mendez 
---
 drivers/mmc/am654_sdhci.c | 30 --
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 1dd032e1e36..38f1ad28ec4 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -92,6 +92,7 @@ struct am654_sdhci_plat {
bool non_removable;
u32 otap_del_sel[MMC_MODES_END];
u32 itap_del_sel[MMC_MODES_END];
+   u32 itap_del_ena[MMC_MODES_END];
u32 trm_icp;
u32 drv_strength;
u32 strb_sel;
@@ -223,8 +224,10 @@ static int am654_sdhci_setup_dll(struct am654_sdhci_plat 
*plat,
 }
 
 static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
- u32 itapdly)
+ u32 itapdly, u32 enable)
 {
+   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
+  enable << ITAPDLYENA_SHIFT);
/* Set ITAPCHGWIN before writing to ITAPDLY */
regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
   1 << ITAPCHGWIN_SHIFT);
@@ -242,7 +245,8 @@ static void am654_sdhci_setup_delay_chain(struct 
am654_sdhci_plat *plat,
mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
 
-   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
+   am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
+ plat->itap_del_ena[mode]);
 }
 
 static int am654_sdhci_set_ios_post(struct sdhci_host *host)
@@ -443,6 +447,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
struct udevice *dev = mmc->dev;
struct am654_sdhci_plat *plat = dev_get_plat(dev);
struct window fail_window[ITAPDLY_LENGTH];
+   int mode = mmc->selected_mode;
u8 curr_pass, itap;
u8 fail_index = 0;
u8 prev_pass = 1;
@@ -450,11 +455,10 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
memset(fail_window, 0, sizeof(fail_window));
 
/* Enable ITAPDLY */
-   regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
-  1 << ITAPDLYENA_SHIFT);
+   plat->itap_del_ena[mode] = 0x1;
 
for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
curr_pass = !mmc_send_tuning(mmc, opcode, NULL);
 
@@ -478,7 +482,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 
opcode)
itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
  plat->dll_enable);
 
-   am654_sdhci_write_itapdly(plat, itap);
+   am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
 
return 0;
 }
@@ -515,6 +519,7 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host 
*host)
struct am654_sdhci_plat *plat = dev_get_plat(dev);
int mode = host->mmc->selected_mode;
u32 otap_del_sel;
+   u32 itap_del_ena;
u32 itap_del_sel;
u32 mask, val;
 
@@ -524,10 +529,11 @@ static int j721e_4bit_sdhci_set_ios_post(struct 
sdhci_host *host)
val = (1 << OTAPDLYENA_SHIFT) |
  (otap_del_sel << OTAPDLYSEL_SHIFT);
 
+   itap_del_ena = plat->itap_del_ena[mode];
itap_del_sel = plat->itap_del_sel[mode];
 
mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
-   val = (1 << ITAPDLYENA_SHIFT) |
+   val = (itap_del_ena << ITAPDLYENA_SHIFT) |
  (itap_del_sel << ITAPDLYSEL_SHIFT);
 
regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
@@ -599,9 +605,13 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
cfg->host_caps &= ~td[i].capability;
}
 
-   if (td[i].itap_binding)
-   dev_read_u32(dev, td[i].itap_binding,
->itap_del_sel[i]);
+   if (td[i].itap_binding) {
+   ret = dev_read_u32(dev, td[i].itap_binding,
+  >itap_del_sel[i]);
+
+   if (!ret)
+   plat->itap_del_ena[i] = 0x1;
+   }
}
 
return 0;
-- 
2.43.2



[PATCH] configs: am64x_evm_*_defconfig: Increase offsets for eMMC raw boot

2024-04-10 Thread Judith Mendez
EMMC boot can fail due to the size of R5 SPL image growing beyond the
500KB of memory allocated in eMMC. Update offsets for eMMMC raw boot
to load each binary from the correct address in eMMC according to the
following eMMC layout:

boot0/1 partition
0x0+--+
   | tiboot3.bin (1 MB)   |
  0x800+--+
   |   tispl.bin (2 MB)   |
0x1800+---+
   |   u-boot.img (4 MB)  |
0x3800+---+
   |  environment (128 KB)|
0x3900+---+

Signed-off-by: Judith Mendez 
---
 configs/am64x_evm_a53_defconfig | 2 +-
 configs/am64x_evm_r5_defconfig  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig
index b7057be3d65..86740559905 100644
--- a/configs/am64x_evm_a53_defconfig
+++ b/configs/am64x_evm_a53_defconfig
@@ -44,7 +44,7 @@ CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SYS_MALLOC=y
 CONFIG_SPL_SYS_MALLOC_SIZE=0x80
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1800
 CONFIG_SPL_DMA=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_ETH=y
diff --git a/configs/am64x_evm_r5_defconfig b/configs/am64x_evm_r5_defconfig
index 555d69bb117..4a3780ce660 100644
--- a/configs/am64x_evm_r5_defconfig
+++ b/configs/am64x_evm_r5_defconfig
@@ -51,7 +51,7 @@ CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x8400
 CONFIG_SPL_SYS_MALLOC_SIZE=0x100
 CONFIG_SPL_EARLY_BSS=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x800
 CONFIG_SPL_DMA=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_ETH=y

base-commit: bc39e06778168a34bb4e0a34fbee4edbde4414d8
-- 
2.43.2



[PATCH] configs: am62px_evm_a53_defconfig: Enable MMC UHS config option

2024-04-08 Thread Judith Mendez
Enable MMC UHS support for to allow to enter the UHS
modes for MMC0.

Signed-off-by: Judith Mendez 
---
 configs/am62px_evm_a53_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/am62px_evm_a53_defconfig b/configs/am62px_evm_a53_defconfig
index 2621abb8ce1..d1ae18bedf6 100644
--- a/configs/am62px_evm_a53_defconfig
+++ b/configs/am62px_evm_a53_defconfig
@@ -115,6 +115,8 @@ CONFIG_FS_LOADER=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_SPL_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_SPL_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_SPL_MMC_HS400_SUPPORT=y
 CONFIG_MMC_SDHCI=y

base-commit: bc39e06778168a34bb4e0a34fbee4edbde4414d8
-- 
2.43.2



[PATCH] configs: am6*_evm_a53_defconfig: Enable config to support mmc rescan

2024-03-19 Thread Judith Mendez
Enable MMC_SPEED_MODE_SET config option in defconfig to enable
mmc rescan for various Sitara devices.

Signed-off-by: Judith Mendez 
---
 configs/am62px_evm_a53_defconfig | 1 +
 configs/am62x_evm_a53_defconfig  | 1 +
 configs/am64x_evm_a53_defconfig  | 1 +
 configs/am65x_evm_a53_defconfig  | 1 +
 4 files changed, 4 insertions(+)

diff --git a/configs/am62px_evm_a53_defconfig b/configs/am62px_evm_a53_defconfig
index 2621abb8ce..6dbdd427ec 100644
--- a/configs/am62px_evm_a53_defconfig
+++ b/configs/am62px_evm_a53_defconfig
@@ -73,6 +73,7 @@ CONFIG_CMD_TIME=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_UBI=y
+CONFIG_MMC_SPEED_MODE_SET=y
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_MULTI_DTB_FIT=y
diff --git a/configs/am62x_evm_a53_defconfig b/configs/am62x_evm_a53_defconfig
index 4c1e4d7cc4..a25f7b2223 100644
--- a/configs/am62x_evm_a53_defconfig
+++ b/configs/am62x_evm_a53_defconfig
@@ -50,6 +50,7 @@ CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x28
 CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_CMD_MMC=y
+CONFIG_MMC_SPEED_MODE_SET=y
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_MULTI_DTB_FIT=y
diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig
index b7057be3d6..179c42a544 100644
--- a/configs/am64x_evm_a53_defconfig
+++ b/configs/am64x_evm_a53_defconfig
@@ -72,6 +72,7 @@ CONFIG_CMD_USB=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
+CONFIG_MMC_SPEED_MODE_SET=y
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_LIST="ti/k3-am642-evm ti/k3-am642-sk"
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index 500335f7e6..3afa80f45a 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -73,6 +73,7 @@ CONFIG_CMD_TIME=y
 CONFIG_MTDIDS_DEFAULT="nor0=4704.spi.0"
 
CONFIG_MTDPARTS_DEFAULT="mtdparts=4704.spi.0:512k(ospi.tiboot3),2m(ospi.tispl),4m(ospi.u-boot),128k(ospi.env),128k(ospi.env.backup),1m(ospi.sysfw),-@8m(ospi.rootfs)"
 CONFIG_CMD_UBI=y
+CONFIG_MMC_SPEED_MODE_SET=y
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y

base-commit: b145877c22b391a4872c875145a8f86f6ffebaba
-- 
2.43.2



[PATCH v3] doc: ti: Add switch setting for boot modes on AM62 SK

2023-04-06 Thread Judith Mendez
List some common boot modes and their corresponding switch
settings for AM62 SK.

List in a ASCII-style table.

Signed-off-by: Judith Mendez 
---

Changes from v1: Change table format from ascii-art to list-table
Changes from v2: Change table format to ASCII style

 doc/board/ti/am62x_sk.rst | 29 +
 1 file changed, 29 insertions(+)

diff --git a/doc/board/ti/am62x_sk.rst b/doc/board/ti/am62x_sk.rst
index b1b7d99befb..7adbdac7ca9 100644
--- a/doc/board/ti/am62x_sk.rst
+++ b/doc/board/ti/am62x_sk.rst
@@ -229,3 +229,32 @@ Image formats:
 | |   SPL DTB 1...N   | |
 | +---+ |
 +---+
+
+Switch Setting for Boot Mode
+
+
+Boot Mode pins provide means to select the boot mode and options before the
+device is powered up. After every POR, they are the main source to populate
+the Boot Parameter Tables.
+
+The following table shows some common boot modes used on AM62 platform. More
+details can be found in the Technical Reference Manual:
+https://www.ti.com/lit/pdf/spruiv7 under the `Boot Mode Pins` section.
+
+*Boot Modes*
+
+++-+-+
+|  Switch Label  |  SW2: 12345678  |  SW3: 12345678  |
+++=+=+
+| SD |  0100   |  1110   |
+++-+-+
+| OSPI   |     |  11001110   |
+++-+-+
+| EMMC   |     |  11010010   |
+++-+-+
+| UART   |     |  11011100   |
+++-+-+
+| USB DFU|     |  11001010   |
+++-+-+
+
+For SW2 and SW1, the switch state in the "ON" position = 1.
-- 
2.17.1



[PATCH] doc: ti: Add switch setting for boot modes on AM62 SK

2023-03-31 Thread Judith Mendez
List some common boot modes and their corresponding switch
settings for AM62 SK.

Signed-off-by: Judith Mendez 
---

Changes from v1: Change table format from ascii-art to list-table

 doc/board/ti/am62x_sk.rst | 36 
 1 file changed, 36 insertions(+)

diff --git a/doc/board/ti/am62x_sk.rst b/doc/board/ti/am62x_sk.rst
index b1b7d99befb..3d85400b1a1 100644
--- a/doc/board/ti/am62x_sk.rst
+++ b/doc/board/ti/am62x_sk.rst
@@ -229,3 +229,39 @@ Image formats:
 | |   SPL DTB 1...N   | |
 | +---+ |
 +---+
+
+Switch Setting for Boot Mode
+
+
+Boot Mode pins provide means to select the boot mode and options before the
+device is powered up. After every POR, they are the main source to populate
+the Boot Parameter Tables.
+
+The following table shows some common boot modes used on AM62 platform. More
+details can be found in the Technical Reference Manual:
+https://www.ti.com/lit/pdf/spruiv7 under the `Boot Mode Pins` section.
+
+.. list-table:: Boot Modes
+   :widths: 32 32 32
+   :header-rows: 1
+
+   * - Switch Label
+ - SW2: 12345678
+ - SW3: 12345678
+   * - SD
+ - 0100
+ - 1110
+   * - OSPI
+ - 
+ - 11001110
+   * - EMMC
+ - 
+ - 11010010
+   * - UART
+ - 
+ - 11011100
+   * - USB DFU
+ - 
+ - 11001010
+
+For SW2 and SW1, the switch state in the "ON" position = 1.
-- 
2.17.1



[PATCH] doc: ti: Add switch setting for boot modes on AM62 SK

2023-03-27 Thread Judith Mendez
List some common boot modes and their corresponding switch
settings for AM62 SK.

Signed-off-by: Judith Mendez 
---
 doc/board/ti/am62x_sk.rst | 29 +
 1 file changed, 29 insertions(+)

diff --git a/doc/board/ti/am62x_sk.rst b/doc/board/ti/am62x_sk.rst
index b1b7d99befb..40d58ea8bfa 100644
--- a/doc/board/ti/am62x_sk.rst
+++ b/doc/board/ti/am62x_sk.rst
@@ -229,3 +229,32 @@ Image formats:
 | |   SPL DTB 1...N   | |
 | +---+ |
 +---+
+
+Switch Setting for Boot Mode
+
+
+Boot Mode pins provide means to select the boot mode and options before the
+device is powered up. After every POR, they are the main source to populate
+the Boot Parameter Tables.
+
+The following table shows some common boot modes used on AM62 platform. More
+details can be found in the Technical Reference Manual:
+https://www.ti.com/lit/pdf/spruiv7 under the `Boot Mode Pins` section.
+
++--+++
+|*Boot Mode*   | *SW2*  | *SW1*  |
++--+++
+| Switch label | 12345678   | 12345678   |
++==+++
+| SD   | 0100   | 1110   |
++--+++
+| OSPI |    | 11001110   |
++--+++
+| EMMC |    | 11010010   |
++--+++
+| UART |    | 11011100   |
++--+++
+| USB DFU  |    | 11001010   |
++--+++
+
+For SW2 and SW1, the switch state in the "ON" position = 1.
-- 
2.17.1