diff mbox series

[RFC,u-boot-mvebu,4/6] arm: mvebu: Define all options for A38x BOOT_FROM_* macros

Message ID 20230304105036.19189-5-pali@kernel.org
State Superseded
Delegated to: Stefan Roese
Headers show
Series arm: mvebu: Fix boot mode detection | expand

Commit Message

Pali Rohár March 4, 2023, 10:50 a.m. UTC
Disassembling A385 BootROM binary reveal how BootROM interprets strapping
pins for Boot Device Mode. All possible options are:

0x00..0x07 -> Parallel NOR
0x08..0x15 -> Parallel NAND
0x16..0x17 -> Parallel NOR
0x18..0x25 -> Parallel NAND
0x26..0x27 -> SPI NAND
0x28..0x29 -> UART xmodem
0x2a..0x2b -> SATA
0x2c..0x2d -> PCI Express
0x2e..0x2f -> Parallel NOR
0x30..0x31 -> SD / eMMC
0x32..0x39 -> SPI NOR
0x3a..0x3c -> Parallel NOR
0x3d..0x3e -> UART debug console
0x3f       -> Invalid

Note that Boot Device Mode Options in A38x Hardware Specifications is
incomplete.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/mach-mvebu/include/mach/soc.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

Comments

Pali Rohár March 4, 2023, 11:20 a.m. UTC | #1
On Saturday 04 March 2023 11:50:34 Pali Rohár wrote:
> Disassembling A385 BootROM binary reveal how BootROM interprets strapping
> pins for Boot Device Mode. All possible options are:
> 
> 0x00..0x07 -> Parallel NOR
> 0x08..0x15 -> Parallel NAND
> 0x16..0x17 -> Parallel NOR
> 0x18..0x25 -> Parallel NAND
> 0x26..0x27 -> SPI NAND
> 0x28..0x29 -> UART xmodem
> 0x2a..0x2b -> SATA
> 0x2c..0x2d -> PCI Express
> 0x2e..0x2f -> Parallel NOR
> 0x30..0x31 -> SD / eMMC
> 0x32..0x39 -> SPI NOR
> 0x3a..0x3c -> Parallel NOR
> 0x3d..0x3e -> UART debug console
> 0x3f       -> Invalid

Clearfog has 5-bit DIP switch and seems that it is directly mapped to
the Boot Device mode with most significant bit of boot mode pulled to
high (sixth bit not present on the switch) and flipped second, third and
fifth bits of the boot mode.

Based on documentation Clearfog DIP switch should be set to 11100 for
SATA booting, by flipping bits it is 01010, by adding MSB it is 101010,
which is hex 0x2a --> matches A385 SATA boot mode.

Can somebody check if UART debug console boot mode works on Clearfog?
It is boot mode when BootROM enters into simple debug console with few
commands. Via kwboot it is possible to enter into this mode (it sends
magic sequence) but from this information it looks like that it should
be possible also without magic sequence, just by configuring boot mode.

> Note that Boot Device Mode Options in A38x Hardware Specifications is
> incomplete.
> 
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  arch/arm/mach-mvebu/include/mach/soc.h | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
> index aa42db36a1ee..698b70339436 100644
> --- a/arch/arm/mach-mvebu/include/mach/soc.h
> +++ b/arch/arm/mach-mvebu/include/mach/soc.h
> @@ -160,11 +160,14 @@
>  #define BOOT_DEV_SEL_OFFS	4
>  #define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
>  
> -#define BOOT_FROM_NAND(x)	(x == 0x0A)
> -#define BOOT_FROM_SATA(x)	(x == 0x2A)
> -#define BOOT_FROM_UART(x)	(x == 0x28)
> -#define BOOT_FROM_SPI(x)	(x == 0x32)
> +#define BOOT_FROM_NOR(x)	((x >= 0x00 && x <= 0x07) || x == 0x16 || x == 0x17 || x == 0x2E || x == 0x2F || (x >= 0x3A && x <= 0x3C))
> +#define BOOT_FROM_NAND(x)	((x >= 0x08 && x <= 0x15) || (x >= 0x18 && x <= 0x25))
> +#define BOOT_FROM_SPINAND(x)	(x == 0x26 || x == 0x27)
> +#define BOOT_FROM_UART(x)	(x == 0x28 || x == 0x29)
> +#define BOOT_FROM_SATA(x)	(x == 0x2A || x == 0x2B)
> +#define BOOT_FROM_PEX(x)	(x == 0x2C || x == 0x2D)
>  #define BOOT_FROM_MMC(x)	(x == 0x30 || x == 0x31)
> +#define BOOT_FROM_SPI(x)	(x >= 0x32 && x <= 0x39)
>  
>  #define CONFIG_SYS_TCLK		((readl(CONFIG_SAR_REG) & BIT(15)) ? \
>  				 200000000 : 250000000)
> -- 
> 2.20.1
>
Martin Rowe March 5, 2023, 12:06 a.m. UTC | #2
On Sat, 4 Mar 2023 at 11:20, Pali Rohár <pali@kernel.org> wrote:

> On Saturday 04 March 2023 11:50:34 Pali Rohár wrote:
> > Disassembling A385 BootROM binary reveal how BootROM interprets strapping
> > pins for Boot Device Mode. All possible options are:
> >
> > 0x00..0x07 -> Parallel NOR
> > 0x08..0x15 -> Parallel NAND
> > 0x16..0x17 -> Parallel NOR
> > 0x18..0x25 -> Parallel NAND
> > 0x26..0x27 -> SPI NAND
> > 0x28..0x29 -> UART xmodem
> > 0x2a..0x2b -> SATA
> > 0x2c..0x2d -> PCI Express
> > 0x2e..0x2f -> Parallel NOR
> > 0x30..0x31 -> SD / eMMC
> > 0x32..0x39 -> SPI NOR
> > 0x3a..0x3c -> Parallel NOR
> > 0x3d..0x3e -> UART debug console
> > 0x3f       -> Invalid
>
> Clearfog has 5-bit DIP switch and seems that it is directly mapped to
> the Boot Device mode with most significant bit of boot mode pulled to
> high (sixth bit not present on the switch) and flipped second, third and
> fifth bits of the boot mode.
>
> Based on documentation Clearfog DIP switch should be set to 11100 for
> SATA booting, by flipping bits it is 01010, by adding MSB it is 101010,
> which is hex 0x2a --> matches A385 SATA boot mode.
>

The Clearfog schematics indicate the switch is internally pulled to 0x36 /
110110. 110110 XOR 11100 = 101010 = 0x2a. The math checks out and
corresponds to the documented modes as well as the enumeration I did a few
years ago:
00000 nothing [0x36]
00001 nothing [0x37]
00010 SPI [0x34] (documented SPI)
00011 SPI [0x35]
00100 SPI [0x32]
00101 SPI [0x33]
00110 MMC (Card did not respond to voltage select!) [0x30]
00111 MMC [0x31] (documented SD/eMMC)
01000 nothing [0x3e]
01001 UART [0x3f] (documented UART)
01010 NOR [0x3c]
01011 nothing [0x3d]
01100 NOR [0x3a]
01101 NOR [0x3b]
01110 nothing [0x38]
01111 nothing [0x39]
10000 nothing [0x26]
10001 nothing [0x27]
10010 NAND [0x24]
10011 NAND [0x25]
10100 NAND [0x22]
10101 NAND [0x23]
10110 NAND [0x20]
10111 NAND [0x21]
11000 NOR [0x2e]
11001 nothing [0x2f]
11010 PEX0 (00) [0x2c]
11011 PEX0 (1A) [0x2d]
11100 nothing [0x2a] (I don't think I had a SATA card attached, but this is
documented SATA)
11101 nothing [0x2b]
11110 nothing [0x28]
11111 nothing [0x29]
Where "nothing" indicates no BootROM output


> Can somebody check if UART debug console boot mode works on Clearfog?
> It is boot mode when BootROM enters into simple debug console with few
> commands. Via kwboot it is possible to enter into this mode (it sends
> magic sequence) but from this information it looks like that it should
> be possible also without magic sequence, just by configuring boot mode.
>

I didn't know about this before. I tried with the magic sequence and it
works (though it needs the A38x output workaround mentioned here [1]. The
boot mode is the one set by 0x3d / 111101 or 0x3e / 111110, right?
0x3d: 111101 XOR 110110 = 01011
0x3e: 111110 XOR 110110 = 01000
Neither of those gives an interactive serial console, and even if the
output workaround is entered there is never anything that appears in the
console. It doesn't even echo the data I type in.

[1] https://manpages.debian.org/testing/u-boot-tools/kwboot.1.en.html


> > Note that Boot Device Mode Options in A38x Hardware Specifications is
> > incomplete.
> >
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  arch/arm/mach-mvebu/include/mach/soc.h | 11 +++++++----
> >  1 file changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/mach-mvebu/include/mach/soc.h
> b/arch/arm/mach-mvebu/include/mach/soc.h
> > index aa42db36a1ee..698b70339436 100644
> > --- a/arch/arm/mach-mvebu/include/mach/soc.h
> > +++ b/arch/arm/mach-mvebu/include/mach/soc.h
> > @@ -160,11 +160,14 @@
> >  #define BOOT_DEV_SEL_OFFS    4
> >  #define BOOT_DEV_SEL_MASK    (0x3f << BOOT_DEV_SEL_OFFS)
> >
> > -#define BOOT_FROM_NAND(x)    (x == 0x0A)
> > -#define BOOT_FROM_SATA(x)    (x == 0x2A)
> > -#define BOOT_FROM_UART(x)    (x == 0x28)
> > -#define BOOT_FROM_SPI(x)     (x == 0x32)
> > +#define BOOT_FROM_NOR(x)     ((x >= 0x00 && x <= 0x07) || x == 0x16 ||
> x == 0x17 || x == 0x2E || x == 0x2F || (x >= 0x3A && x <= 0x3C))
> > +#define BOOT_FROM_NAND(x)    ((x >= 0x08 && x <= 0x15) || (x >= 0x18 &&
> x <= 0x25))
> > +#define BOOT_FROM_SPINAND(x) (x == 0x26 || x == 0x27)
> > +#define BOOT_FROM_UART(x)    (x == 0x28 || x == 0x29)
> > +#define BOOT_FROM_SATA(x)    (x == 0x2A || x == 0x2B)
> > +#define BOOT_FROM_PEX(x)     (x == 0x2C || x == 0x2D)
> >  #define BOOT_FROM_MMC(x)     (x == 0x30 || x == 0x31)
> > +#define BOOT_FROM_SPI(x)     (x >= 0x32 && x <= 0x39)
> >
> >  #define CONFIG_SYS_TCLK              ((readl(CONFIG_SAR_REG) & BIT(15))
> ? \
> >                                200000000 : 250000000)
> > --
> > 2.20.1
> >
>
Pali Rohár March 5, 2023, 1 a.m. UTC | #3
On Sunday 05 March 2023 00:06:05 Martin Rowe wrote:
> On Sat, 4 Mar 2023 at 11:20, Pali Rohár <pali@kernel.org> wrote:
> 
> > On Saturday 04 March 2023 11:50:34 Pali Rohár wrote:
> > > Disassembling A385 BootROM binary reveal how BootROM interprets strapping
> > > pins for Boot Device Mode. All possible options are:
> > >
> > > 0x00..0x07 -> Parallel NOR
> > > 0x08..0x15 -> Parallel NAND
> > > 0x16..0x17 -> Parallel NOR
> > > 0x18..0x25 -> Parallel NAND
> > > 0x26..0x27 -> SPI NAND
> > > 0x28..0x29 -> UART xmodem
> > > 0x2a..0x2b -> SATA
> > > 0x2c..0x2d -> PCI Express
> > > 0x2e..0x2f -> Parallel NOR
> > > 0x30..0x31 -> SD / eMMC
> > > 0x32..0x39 -> SPI NOR
> > > 0x3a..0x3c -> Parallel NOR
> > > 0x3d..0x3e -> UART debug console
> > > 0x3f       -> Invalid
> >
> > Clearfog has 5-bit DIP switch and seems that it is directly mapped to
> > the Boot Device mode with most significant bit of boot mode pulled to
> > high (sixth bit not present on the switch) and flipped second, third and
> > fifth bits of the boot mode.
> >
> > Based on documentation Clearfog DIP switch should be set to 11100 for
> > SATA booting, by flipping bits it is 01010, by adding MSB it is 101010,
> > which is hex 0x2a --> matches A385 SATA boot mode.
> >
> 
> The Clearfog schematics indicate the switch is internally pulled to 0x36 /
> 110110. 110110 XOR 11100 = 101010 = 0x2a. The math checks out and
> corresponds to the documented modes as well as the enumeration I did a few
> years ago:
> 00000 nothing [0x36]
> 00001 nothing [0x37]
> 00010 SPI [0x34] (documented SPI)
> 00011 SPI [0x35]
> 00100 SPI [0x32]
> 00101 SPI [0x33]
> 00110 MMC (Card did not respond to voltage select!) [0x30]
> 00111 MMC [0x31] (documented SD/eMMC)
> 01000 nothing [0x3e]
> 01001 UART [0x3f] (documented UART)
> 01010 NOR [0x3c]
> 01011 nothing [0x3d]
> 01100 NOR [0x3a]
> 01101 NOR [0x3b]
> 01110 nothing [0x38]
> 01111 nothing [0x39]
> 10000 nothing [0x26]
> 10001 nothing [0x27]
> 10010 NAND [0x24]
> 10011 NAND [0x25]
> 10100 NAND [0x22]
> 10101 NAND [0x23]
> 10110 NAND [0x20]
> 10111 NAND [0x21]
> 11000 NOR [0x2e]
> 11001 nothing [0x2f]
> 11010 PEX0 (00) [0x2c]
> 11011 PEX0 (1A) [0x2d]
> 11100 nothing [0x2a] (I don't think I had a SATA card attached, but this is
> documented SATA)
> 11101 nothing [0x2b]
> 11110 nothing [0x28]
> 11111 nothing [0x29]
> Where "nothing" indicates no BootROM output
> 
> 
> > Can somebody check if UART debug console boot mode works on Clearfog?
> > It is boot mode when BootROM enters into simple debug console with few
> > commands. Via kwboot it is possible to enter into this mode (it sends
> > magic sequence) but from this information it looks like that it should
> > be possible also without magic sequence, just by configuring boot mode.
> >
> 
> I didn't know about this before. I tried with the magic sequence and it
> works (though it needs the A38x output workaround mentioned here [1]. The
> boot mode is the one set by 0x3d / 111101 or 0x3e / 111110, right?
> 0x3d: 111101 XOR 110110 = 01011
> 0x3e: 111110 XOR 110110 = 01000
> Neither of those gives an interactive serial console, and even if the
> output workaround is entered there is never anything that appears in the
> console. It doesn't even echo the data I type in.
> 
> [1] https://manpages.debian.org/testing/u-boot-tools/kwboot.1.en.html
> 

Different options for the same boot source use different configuration
of the source. E.g. different MPP pins or different ECC NAND schema, ...
It is hardcoded in the BootROM but figure it out is kind hard
(executable code refers to the data blocks). 0x28 and 0x3d should use
UART0, while 0x29 and 0x3e UART1.

This explains why 0x30 MMC does not work for you and 0x31 MMC works.

There is erratum Ref #: FE-482008 that boot option 0x27 is not supported
and erratum Ref #: FE-9360355 that boot option 0x28 is non functional.

UART1 as boot source is completely undocumented and I suspect that
because there is errata for 0x28 (UART0), UART in normal mode is somehow
completely broken in BootROM.

You wrote that UART debug console mode does not work, so maybe it just
proves brokenness and reason why it is undocumented.

I have not fully understood BootROM code, I was just able to decode
tables and functions which read strapping pins and decide which boot
code calls.

Magic sequence for putting into UART debug console is triggered
independently of the strapping pins and (my) workaround with rewriting
variable stored in L2/SRAM is always needed when on default location is
stored valid image. Also sending magic sequence is not simple because if
too many bytes are send then magic sequence cause buffer overflow in the
BootROM and CPU reset occurs. So if magic sequence is working for you
via kwboot then I'm happy as I when I wrote that kwboot code it was too
fragile to stabilize it.

Anyway, I see that BootROM debug console has undocumented command 't'
which listen for a short period for the UART magic pattern -- either
xmodem or debug console. So maybe via this undocumented command it could
be possible to enter into UART xmodem boot mode once UART debug console
was activated. If it really works I can image that it could be useful
for configuring higher UART speeds (via debug console 'w' commands)
before starting xmodem transfer...

Note about 0x3F boot mode. I have not found any A385 documentation for
it and BootROM maps this to unknown configuration (not even to UART),
which always fails. I suspect that this is something unfinished or
another out-of-bound array read and looks like a nice hack to jump to
UART booting mode, via fallback mechanism (as the primary way is
documented via errata as broken).

> > > Note that Boot Device Mode Options in A38x Hardware Specifications is
> > > incomplete.
> > >
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  arch/arm/mach-mvebu/include/mach/soc.h | 11 +++++++----
> > >  1 file changed, 7 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/arm/mach-mvebu/include/mach/soc.h
> > b/arch/arm/mach-mvebu/include/mach/soc.h
> > > index aa42db36a1ee..698b70339436 100644
> > > --- a/arch/arm/mach-mvebu/include/mach/soc.h
> > > +++ b/arch/arm/mach-mvebu/include/mach/soc.h
> > > @@ -160,11 +160,14 @@
> > >  #define BOOT_DEV_SEL_OFFS    4
> > >  #define BOOT_DEV_SEL_MASK    (0x3f << BOOT_DEV_SEL_OFFS)
> > >
> > > -#define BOOT_FROM_NAND(x)    (x == 0x0A)
> > > -#define BOOT_FROM_SATA(x)    (x == 0x2A)
> > > -#define BOOT_FROM_UART(x)    (x == 0x28)
> > > -#define BOOT_FROM_SPI(x)     (x == 0x32)
> > > +#define BOOT_FROM_NOR(x)     ((x >= 0x00 && x <= 0x07) || x == 0x16 ||
> > x == 0x17 || x == 0x2E || x == 0x2F || (x >= 0x3A && x <= 0x3C))
> > > +#define BOOT_FROM_NAND(x)    ((x >= 0x08 && x <= 0x15) || (x >= 0x18 &&
> > x <= 0x25))
> > > +#define BOOT_FROM_SPINAND(x) (x == 0x26 || x == 0x27)
> > > +#define BOOT_FROM_UART(x)    (x == 0x28 || x == 0x29)
> > > +#define BOOT_FROM_SATA(x)    (x == 0x2A || x == 0x2B)
> > > +#define BOOT_FROM_PEX(x)     (x == 0x2C || x == 0x2D)
> > >  #define BOOT_FROM_MMC(x)     (x == 0x30 || x == 0x31)
> > > +#define BOOT_FROM_SPI(x)     (x >= 0x32 && x <= 0x39)
> > >
> > >  #define CONFIG_SYS_TCLK              ((readl(CONFIG_SAR_REG) & BIT(15))
> > ? \
> > >                                200000000 : 250000000)
> > > --
> > > 2.20.1
> > >
> >
diff mbox series

Patch

diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index aa42db36a1ee..698b70339436 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -160,11 +160,14 @@ 
 #define BOOT_DEV_SEL_OFFS	4
 #define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
 
-#define BOOT_FROM_NAND(x)	(x == 0x0A)
-#define BOOT_FROM_SATA(x)	(x == 0x2A)
-#define BOOT_FROM_UART(x)	(x == 0x28)
-#define BOOT_FROM_SPI(x)	(x == 0x32)
+#define BOOT_FROM_NOR(x)	((x >= 0x00 && x <= 0x07) || x == 0x16 || x == 0x17 || x == 0x2E || x == 0x2F || (x >= 0x3A && x <= 0x3C))
+#define BOOT_FROM_NAND(x)	((x >= 0x08 && x <= 0x15) || (x >= 0x18 && x <= 0x25))
+#define BOOT_FROM_SPINAND(x)	(x == 0x26 || x == 0x27)
+#define BOOT_FROM_UART(x)	(x == 0x28 || x == 0x29)
+#define BOOT_FROM_SATA(x)	(x == 0x2A || x == 0x2B)
+#define BOOT_FROM_PEX(x)	(x == 0x2C || x == 0x2D)
 #define BOOT_FROM_MMC(x)	(x == 0x30 || x == 0x31)
+#define BOOT_FROM_SPI(x)	(x >= 0x32 && x <= 0x39)
 
 #define CONFIG_SYS_TCLK		((readl(CONFIG_SAR_REG) & BIT(15)) ? \
 				 200000000 : 250000000)