[Qemu-devel] [PATCH v7 57/80] mips_malta: Setup GT64120 BARs in nanoMIPS bootloader

Aleksandar Markovic posted 80 patches 7 years, 3 months ago
There is a newer version of this series
[Qemu-devel] [PATCH v7 57/80] mips_malta: Setup GT64120 BARs in nanoMIPS bootloader
Posted by Aleksandar Markovic 7 years, 3 months ago
From: Paul Burton <pburton@wavecomp.com>

Setup the GT64120 BARs in the nanoMIPS bootloader, in the same way that
they are setup in the MIPS32 bootloader. This is necessary for Linux to
be able to access peripherals, including the UART.

Signed-off-by: Paul Burton <pburton@wavecomp.com>
Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
---
 hw/mips/mips_malta.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 4bc9036..d1a7c1f 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -664,6 +664,79 @@ static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr,
                                 /* lui a3,%hi(loaderparams.ram_low_size) */
     stw_p(p++, 0x80e7); stw_p(p++, NM_LO(loaderparams.ram_low_size));
                                 /* ori a3,a3,%lo(loaderparams.ram_low_size) */
+
+    /* Load BAR registers as done by YAMON */
+    stw_p(p++, 0xe040); stw_p(p++, 0x0681);
+                                /* lui t1, %hi(0xb4000000) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0be1);
+                                /* lui t0, %hi(0xdf000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x00df);
+                                /* addiu[32] t0, $0, 0xdf */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9068);
+                                /* sw t0, 0x68(t1) */
+
+    stw_p(p++, 0xe040); stw_p(p++, 0x077d);
+                                /* lui t1, %hi(0xbbe00000) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0801);
+                                /* lui t0, %hi(0xc0000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x00c0);
+                                /* addiu[32] t0, $0, 0xc0 */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9048);
+                                /* sw t0, 0x48(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0800);
+                                /* lui t0, %hi(0x40000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x0040);
+                                /* addiu[32] t0, $0, 0x40 */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9050);
+                                /* sw t0, 0x50(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0001);
+                                /* lui t0, %hi(0x80000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x0080);
+                                /* addiu[32] t0, $0, 0x80 */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9058);
+                                /* sw t0, 0x58(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x07e0);
+                                /* lui t0, %hi(0x3f000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x003f);
+                                /* addiu[32] t0, $0, 0x3f */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9060);
+                                /* sw t0, 0x60(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0821);
+                                /* lui t0, %hi(0xc1000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x00c1);
+                                /* addiu[32] t0, $0, 0xc1 */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9080);
+                                /* sw t0, 0x80(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stw_p(p++, 0xe020); stw_p(p++, 0x0bc0);
+                                /* lui t0, %hi(0x5e000000) */
+#else
+    stw_p(p++, 0x0020); stw_p(p++, 0x005e);
+                                /* addiu[32] t0, $0, 0x5e */
+#endif
+    stw_p(p++, 0x8422); stw_p(p++, 0x9088);
+                                /* sw t0, 0x88(t1) */
+
     stw_p(p++, 0xe320 | NM_HI1(kernel_entry));
     stw_p(p++, NM_HI2(kernel_entry));
                                 /* lui t9,%hi(kernel_entry) */
-- 
2.7.4


Re: [Qemu-devel] [PATCH v7 57/80] mips_malta: Setup GT64120 BARs in nanoMIPS bootloader
Posted by Philippe Mathieu-Daudé 7 years, 2 months ago
Hi Aleksandar,

On 08/06/2018 02:00 PM, Aleksandar Markovic wrote:
> From: Paul Burton <pburton@wavecomp.com>
> 
> Setup the GT64120 BARs in the nanoMIPS bootloader, in the same way that
> they are setup in the MIPS32 bootloader. This is necessary for Linux to
> be able to access peripherals, including the UART.
> 
> Signed-off-by: Paul Burton <pburton@wavecomp.com>
> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
> Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> ---
>  hw/mips/mips_malta.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 73 insertions(+)
> 
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 4bc9036..d1a7c1f 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -664,6 +664,79 @@ static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr,
>                                  /* lui a3,%hi(loaderparams.ram_low_size) */
>      stw_p(p++, 0x80e7); stw_p(p++, NM_LO(loaderparams.ram_low_size));
>                                  /* ori a3,a3,%lo(loaderparams.ram_low_size) */
> +
> +    /* Load BAR registers as done by YAMON */
> +    stw_p(p++, 0xe040); stw_p(p++, 0x0681);
> +                                /* lui t1, %hi(0xb4000000) */

you access the GT64120 via kseg2 having default ISD = 0x14000000.

> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0be1);
> +                                /* lui t0, %hi(0xdf000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x00df);
> +                                /* addiu[32] t0, $0, 0xdf */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9068);
> +                                /* sw t0, 0x68(t1) */

looking at hw/mips/gt64xxx_pci.c, 0x68 is GT_ISD, that will remap the
registers to 0xdf << 21 = 0x1be00000.

--

> +
> +    stw_p(p++, 0xe040); stw_p(p++, 0x077d);
> +                                /* lui t1, %hi(0xbbe00000) */

you now use kseg2 remapped address 0x1be00000.

> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0801);
> +                                /* lui t0, %hi(0xc0000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x00c0);
> +                                /* addiu[32] t0, $0, 0xc0 */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9048);
> +                                /* sw t0, 0x48(t1) */

0x48 is GT_PCI0IOLD, so the new I/O low address is 0xc0 << 21 = 0x18000000,

> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0800);
> +                                /* lui t0, %hi(0x40000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x0040);
> +                                /* addiu[32] t0, $0, 0x40 */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9050);
> +                                /* sw t0, 0x50(t1) */

0x50 is GT_PCI0IOHD, new I/O high address is (0x40 + 1) << 21 =
0x08200000, so the region size is 0x00200000 = 2 MiB.

So this setup PCI0 I/O bar from 0x18000000 to 0x181fffff.

--

> +
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0001);
> +                                /* lui t0, %hi(0x80000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x0080);
> +                                /* addiu[32] t0, $0, 0x80 */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9058);
> +                                /* sw t0, 0x58(t1) */
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x07e0);
> +                                /* lui t0, %hi(0x3f000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x003f);
> +                                /* addiu[32] t0, $0, 0x3f */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9060);
> +                                /* sw t0, 0x60(t1) */

0x58 is GT_PCI0M0LD,
0x60 is GT_PCI0M0HD,
0x80 << 21 = 0x10000000,
(0x3f + 1) << 21 = 0x8000000,

so you setup PCI0 MEM0 at 0x10000000, size 0x8000000

> +
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0821);
> +                                /* lui t0, %hi(0xc1000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x00c1);
> +                                /* addiu[32] t0, $0, 0xc1 */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9080);
> +                                /* sw t0, 0x80(t1) */
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    stw_p(p++, 0xe020); stw_p(p++, 0x0bc0);
> +                                /* lui t0, %hi(0x5e000000) */
> +#else
> +    stw_p(p++, 0x0020); stw_p(p++, 0x005e);
> +                                /* addiu[32] t0, $0, 0x5e */
> +#endif
> +    stw_p(p++, 0x8422); stw_p(p++, 0x9088);
> +                                /* sw t0, 0x88(t1) */

similarly GT_PCI0M1LD & GT_PCI0M1HD,
0xc1 << 21 = 0x18200000
(0x5e + 1) << 21 = 0xbe00000,

so you setup PCI0 MEM1 at 0x18200000, size 0xbe00000.

--

Can you add comments about all this? That would ease to understand what
this code is doing, and avoid the next person to redo what I just did.

Now that we have cross-tools Docker images available, we could add the
.S in the repository and commit the hexblob.

--

A bigger ifdef would be easier to read, such:

#ifdef TARGET_WORDS_BIGENDIAN
    a
    b
    c
    d
#else
    e
    f
    g
    h
#endif

> +
>      stw_p(p++, 0xe320 | NM_HI1(kernel_entry));
>      stw_p(p++, NM_HI2(kernel_entry));
>                                  /* lui t9,%hi(kernel_entry) */
> 

With review addressed:
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Regards,

Phil.