Patchwork [RFC,v2,08/11] powerpc: gamecube/wii: early debugging using usbgecko

login
register
mail settings
Submitter Albert Herranz
Date Nov. 28, 2009, 8:43 p.m.
Message ID <1259441037-15725-9-git-send-email-albert_herranz@yahoo.es>
Download mbox | patch
Permalink /patch/39708/
State Superseded
Headers show

Comments

Albert Herranz - Nov. 28, 2009, 8:43 p.m.
Add support for using the USB Gecko adapter as an early debugging
console on the Nintendo GameCube and Wii video game consoles.
The USB Gecko is a 3rd party memory card interface adapter that provides
a EXI (External Interface) to USB serial converter.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
v1 -> v2
- Do not enclose declaration within #ifdef's. Suggestion by Arnd Bergmann.
- Document apparent double setting of BATs.
- Isolate hardcoded settings into functions.
- Prevent compilation if not targeted for the GameCube or Wii.

 arch/powerpc/Kconfig.debug                         |    8 +++
 arch/powerpc/include/asm/udbg.h                    |    1 +
 arch/powerpc/kernel/head_32.S                      |   21 ++++++++
 arch/powerpc/kernel/udbg.c                         |    2 +
 arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c |   53 ++++++++++++++++++++
 arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h |    2 +
 6 files changed, 87 insertions(+), 0 deletions(-)
Benjamin Herrenschmidt - Nov. 29, 2009, 11:18 p.m.
On Sat, 2009-11-28 at 21:43 +0100, Albert Herranz wrote:
> +        * Prepare again the same BAT for MMU_init.
> +        * This allows udbg I/O to continue working after the MMU is
> +        * turned on for real.
> +        *
> +        * We are assuming here that exi_io_base is identity mapped.
> +        */
> +       addr = ((unsigned long)exi_io_base) & 0xffff0000;
> +       setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG); 

How do you prevent that from overlapping otherwise valid kernel
mappings ?

You need to allocate the virtual space. For a debug thing like that, you
could use the fixmap. In fact, I think we should create a fixmap entry
or two always available for use by early debug.

Cheers,
Ben.
Albert Herranz - Nov. 30, 2009, 5:50 a.m.
Benjamin Herrenschmidt wrote:
> On Sat, 2009-11-28 at 21:43 +0100, Albert Herranz wrote:
>> +        * Prepare again the same BAT for MMU_init.
>> +        * This allows udbg I/O to continue working after the MMU is
>> +        * turned on for real.
>> +        *
>> +        * We are assuming here that exi_io_base is identity mapped.
>> +        */
>> +       addr = ((unsigned long)exi_io_base) & 0xffff0000;
>> +       setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG); 
> 
> How do you prevent that from overlapping otherwise valid kernel
> mappings ?
> 

ug_udbg_init() is called from ppc_md.init_early.
It doesn't overlap any valid kernel mappings because exi_io_base is hardcoded to an i/o region not used yet by the kernel.
See udbg_early_grab_exi_io_base().

The setbat just prepares again, exactly in the same way, the same BAT that we got setup by setup_usbgecko_bat in head_32.S.

_start
__start
> early_init
> mmu_off
# mmu off
> clear_bats
> flush_tlbs
> initial_bats
> setup_usbgecko_bat <--- BAT1 setup here
> call_setup_cpu
> init_idle_6xx
! relocate_kernel
! turn_on_mmu
# mmu on
! start_here
> machine_init
>> udbg_early_init
>>> udbg_init_usbgecko <--- BAT1 prepared again here for after MMU_init
>> early_init_devtree
> __save_cpu_setup
> MMU_init
# mmu off
> load_up_mmu
# mmu on
! start_kernel

> You need to allocate the virtual space. For a debug thing like that, you
> could use the fixmap. In fact, I think we should create a fixmap entry
> or two always available for use by early debug.
> 

Or give us back ppc_md.setup_io_mappings :)

> Cheers,
> Ben.
> 

Thanks,
Albert
Benjamin Herrenschmidt - Nov. 30, 2009, 6:14 a.m.
On Mon, 2009-11-30 at 06:50 +0100, Albert Herranz wrote:
> Benjamin Herrenschmidt wrote:
> > On Sat, 2009-11-28 at 21:43 +0100, Albert Herranz wrote:
> >> +        * Prepare again the same BAT for MMU_init.
> >> +        * This allows udbg I/O to continue working after the MMU is
> >> +        * turned on for real.
> >> +        *
> >> +        * We are assuming here that exi_io_base is identity mapped.
> >> +        */
> >> +       addr = ((unsigned long)exi_io_base) & 0xffff0000;
> >> +       setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG); 
> > 
> > How do you prevent that from overlapping otherwise valid kernel
> > mappings ?
> > 
> 
> ug_udbg_init() is called from ppc_md.init_early.
> It doesn't overlap any valid kernel mappings because exi_io_base is
> hardcoded to an i/o region not used yet by the kernel.

But that doesn't allocate virtual space does it ?

> See udbg_early_grab_exi_io_base().

Yeah, I see that:

+#if defined(CONFIG_GAMECUBE)
+       return (void __iomem *)0x0c006800;
+#elif defined(CONFIG_WII)
+       return (void __iomem *)0x0d006800;
+#else

So you'll have BATs floating over user addresses ? That sounds fishy :-)

It should be trivial to just create a fixmap entry instead. That will
give you a virtual address that is known at compile time (so you can
use it from head_32.S as well for setting up your BAT).

Actually you probably need more than one entry in there since it needs
to be big enough to cover a BAT min size and be aligned, but it's not
-that- hard to do (I think x86 does similar tricks in their fixmap
iirc) 

> The setbat just prepares again, exactly in the same way, the same BAT that we got
> setup by setup_usbgecko_bat in head_32.S.

 .../...

> > You need to allocate the virtual space. For a debug thing like that, you
> > could use the fixmap. In fact, I think we should create a fixmap entry
> > or two always available for use by early debug.
> > 
> 
> Or give us back ppc_md.setup_io_mappings :)

Not happening :-) Or if you get one, it will allocate virtual addresses
and so you cannot rely on an identity mapping.
Albert Herranz - Nov. 30, 2009, 6:15 a.m.
Albert Herranz wrote:
> Benjamin Herrenschmidt wrote:
>> On Sat, 2009-11-28 at 21:43 +0100, Albert Herranz wrote:
>>> +        * Prepare again the same BAT for MMU_init.
>>> +        * This allows udbg I/O to continue working after the MMU is
>>> +        * turned on for real.
>>> +        *
>>> +        * We are assuming here that exi_io_base is identity mapped.
>>> +        */
>>> +       addr = ((unsigned long)exi_io_base) & 0xffff0000;
>>> +       setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG); 
>> How do you prevent that from overlapping otherwise valid kernel
>> mappings ?
>>
> 
> ug_udbg_init() is called from ppc_md.init_early.

  ^^^
This got here, but although it's true it doesn't apply here :)

> It doesn't overlap any valid kernel mappings because exi_io_base is hardcoded to an i/o region not used yet by the kernel.
> See udbg_early_grab_exi_io_base().
> The setbat just prepares again, exactly in the same way, the same BAT that we got setup by setup_usbgecko_bat in head_32.S.
> 

Thanks,
Albert
Albert Herranz - Nov. 30, 2009, 6:28 a.m.
Benjamin Herrenschmidt wrote:
> On Mon, 2009-11-30 at 06:50 +0100, Albert Herranz wrote:
>> Benjamin Herrenschmidt wrote:
>>> On Sat, 2009-11-28 at 21:43 +0100, Albert Herranz wrote:
>>>> +        * Prepare again the same BAT for MMU_init.
>>>> +        * This allows udbg I/O to continue working after the MMU is
>>>> +        * turned on for real.
>>>> +        *
>>>> +        * We are assuming here that exi_io_base is identity mapped.
>>>> +        */
>>>> +       addr = ((unsigned long)exi_io_base) & 0xffff0000;
>>>> +       setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG); 
>>> How do you prevent that from overlapping otherwise valid kernel
>>> mappings ?
>>>
>> ug_udbg_init() is called from ppc_md.init_early.
>> It doesn't overlap any valid kernel mappings because exi_io_base is
>> hardcoded to an i/o region not used yet by the kernel.
> 
> But that doesn't allocate virtual space does it ?
> 

No.

>> See udbg_early_grab_exi_io_base().
> 
> Yeah, I see that:
> 
> +#if defined(CONFIG_GAMECUBE)
> +       return (void __iomem *)0x0c006800;
> +#elif defined(CONFIG_WII)
> +       return (void __iomem *)0x0d006800;
> +#else
> 
> So you'll have BATs floating over user addresses ? That sounds fishy :-)
> 

Heh, I was told to identity map it :)
Originally it used kernel address space (0xc{c,d}006800).

> It should be trivial to just create a fixmap entry instead. That will
> give you a virtual address that is known at compile time (so you can
> use it from head_32.S as well for setting up your BAT).
> 
> Actually you probably need more than one entry in there since it needs
> to be big enough to cover a BAT min size and be aligned, but it's not
> -that- hard to do (I think x86 does similar tricks in their fixmap
> iirc) 
> 

I've never worked with fixmap entries. I'll look into it. Thanks.

>> The setbat just prepares again, exactly in the same way, the same BAT that we got
>> setup by setup_usbgecko_bat in head_32.S.
> 
>  .../...
> 
>>> You need to allocate the virtual space. For a debug thing like that, you
>>> could use the fixmap. In fact, I think we should create a fixmap entry
>>> or two always available for use by early debug.
>>>
>> Or give us back ppc_md.setup_io_mappings :)
> 
> Not happening :-) Or if you get one, it will allocate virtual addresses
> and so you cannot rely on an identity mapping.
> 

But we can use then a known mapping scheme, and have all the i/o region covered by bats there.
We can do that already, yes, but setup_io_mappings purpose was originally that, no?

Thanks,
Albert
Benjamin Herrenschmidt - Nov. 30, 2009, 6:42 a.m.
On Mon, 2009-11-30 at 07:28 +0100, Albert Herranz wrote:
> 
> 
> Heh, I was told to identity map it :)

Hah ? By whome ? :-)

> Originally it used kernel address space (
> 0xc{c,d}006800).

In any case, kernel space also needs to be reserved. There is no magic
free spot in the kernel virtual space unless you reserve some either by
lowering ioremap_bot early at boot or by using the fixmap (well, there
is if you don't enable HIGHMEM but that's going away soon :-)

> I've never worked with fixmap entries. I'll look into it. Thanks.

Look at fixmap.h, basically it's an emum of reserved pages starting near
the top of the address space and walking down from there. The kernel
ensure that space stays reserved and it gives you things calculated at
compile time (so via asm-offsets.h you can feed them into your asm).

I'm half tempted to say we should just bluntly reserve the top 128K (or
whatever is the min size of a BAT) for that sort of debug crap though
and be done with it :-) Always handy to have some space we know we can
mess around with.

> But we can use then a known mapping scheme, and have all the i/o
> region covered by bats there.

We could yes. I was hoping Grant would produce something there but he
hadn't had time yet.,

> We can do that already, yes, but setup_io_mappings purpose was
> originally that, no?

Sort-of. I don't like hard coding virtual addresses, it causes all sort
of problems (other than in the fixmap). It wouldn't be very hard to
bring back some variant of io_block_mapping() though that works by
moving ioremap_bot down early during boot, and allows you to setup some
IO BATs for perfs reasons. Subsequent ioremaps would automatically pick
up that space and benefit from it.

Cheers,
Ben.

Patch

diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 3b10051..11e385b 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -254,6 +254,14 @@  config PPC_EARLY_DEBUG_CPM
 	  using a CPM-based serial port.  This assumes that the bootwrapper
 	  has run, and set up the CPM in a particular way.
 
+config PPC_EARLY_DEBUG_USBGECKO
+	bool "Early debugging through the USB Gecko adapter"
+	depends on GAMECUBE_COMMON
+	select USBGECKO_UDBG
+	help
+	  Select this to enable early debugging for Nintendo GameCube/Wii
+	  consoles via an external USB Gecko adapter.
+
 endchoice
 
 config PPC_EARLY_DEBUG_44x_PHYSLOW
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index cd21e5e..11ae699 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -51,6 +51,7 @@  extern void __init udbg_init_btext(void);
 extern void __init udbg_init_44x_as1(void);
 extern void __init udbg_init_40x_realmode(void);
 extern void __init udbg_init_cpm(void);
+extern void __init udbg_init_usbgecko(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 829c3fe..c3f3737 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -164,6 +164,9 @@  __after_mmu_off:
 #ifdef CONFIG_PPC_EARLY_DEBUG_CPM
 	bl	setup_cpm_bat
 #endif
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+	bl	setup_usbgecko_bat
+#endif
 
 /*
  * Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -1203,6 +1206,24 @@  setup_cpm_bat:
 	blr
 #endif
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+setup_usbgecko_bat:
+	/* prepare a BAT for early io */
+#if defined(CONFIG_GAMECUBE)
+	lis	r8, 0x0c00
+#elif defined(CONFIG_WII)
+	lis	r8, 0x0d00
+#else
+#error Invalid platform for USB Gecko based early debugging.
+#endif
+	mr	r11, r8
+	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
+	ori	r11, r11, 0x3	/* 128K */
+	mtspr	SPRN_DBAT1L, r8
+	mtspr	SPRN_DBAT1U, r11
+	blr
+#endif
+
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
  * We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index fc9af47..e39cad8 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -60,6 +60,8 @@  void __init udbg_early_init(void)
 	udbg_init_40x_realmode();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
 	udbg_init_cpm();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO)
+	udbg_init_usbgecko();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
index 581ce61..f9d7991 100644
--- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
@@ -270,3 +270,56 @@  done:
 		of_node_put(np);
 	return;
 }
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+
+static void __iomem * __init udbg_early_grab_exi_io_base(void)
+{
+#if defined(CONFIG_GAMECUBE)
+	return (void __iomem *)0x0c006800;
+#elif defined(CONFIG_WII)
+	return (void __iomem *)0x0d006800;
+#else
+#error Invalid platform for USB Gecko based early debugging.
+#endif
+}
+
+/*
+ * USB Gecko early debug support initialization for udbg.
+ */
+void __init udbg_init_usbgecko(void)
+{
+	void __iomem *exi_io_base;
+	unsigned long addr;
+
+	/*
+	 * At this point we have a BAT already setup that enables I/O
+	 * to the EXI hardware.
+	 */
+
+	exi_io_base = udbg_early_grab_exi_io_base();
+	if (!exi_io_base)
+		return;
+
+	/* try to detect a USB Gecko */
+	if (!ug_udbg_probe(exi_io_base))
+		return;
+
+	/* we found a USB Gecko, load udbg hooks */
+	udbg_putc = ug_udbg_putc;
+	udbg_getc = ug_udbg_getc;
+	udbg_getc_poll = ug_udbg_getc_poll;
+
+	/*
+	 * Prepare again the same BAT for MMU_init.
+	 * This allows udbg I/O to continue working after the MMU is
+	 * turned on for real.
+	 *
+	 * We are assuming here that exi_io_base is identity mapped.
+	 */
+	addr = ((unsigned long)exi_io_base) & 0xffff0000;
+	setbat(1, addr, addr, 128*1024, PAGE_KERNEL_NCG);
+}
+
+#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
+
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
index 3929de3..bb6cde4 100644
--- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
@@ -27,4 +27,6 @@  static inline void __init ug_udbg_init(void)
 
 #endif /* CONFIG_USBGECKO_UDBG */
 
+void __init udbg_init_usbgecko(void);
+
 #endif /* __USBGECKO_UDBG_H */