diff mbox

[RFC,10/19] powerpc: gamecube/wii: early debugging using usbgecko

Message ID 1258927311-4340-11-git-send-email-albert_herranz@yahoo.es (mailing list archive)
State Changes Requested
Headers show

Commit Message

Albert Herranz Nov. 22, 2009, 10:01 p.m. UTC
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>
---
 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 |   33 ++++++++++++++++++++
 arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h |    6 +++
 6 files changed, 71 insertions(+), 0 deletions(-)

Comments

Arnd Bergmann Nov. 22, 2009, 10:27 p.m. UTC | #1
On Sunday 22 November 2009, Albert Herranz wrote:
> +#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
> +setup_usbgecko_bat:
> +	/* prepare a BAT for early io */
> +	lis	r8, 0x0c00
> +	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
> +	lis	r11, 0xcc00
> +	ori	r11, r11, 0x3	/* 128K */
> +#ifdef CONFIG_WII
> +	oris	r8, r8, 0x0100
> +	oris	r11, r11, 0x0100
> +#endif
> +	mtspr	SPRN_DBAT1L, r8
> +	mtspr	SPRN_DBAT1U, r11
> +	sync
> +	isync
> +	blr
> +#endif

This will probably break other platforms if CONFIG_PPC_EARLY_DEBUG_USBGECKO
is set. In general, we try hard to make it possible to build generic
kernels for multiple systems, so it would be better to also add a runtime
check here.

> --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
> +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
> @@ -27,4 +27,10 @@ static inline void __init ug_udbg_init(void)
>  
>  #endif /* CONFIG_USBGECKO_UDBG */
>  
> +#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
> +
> +void __init udbg_init_usbgecko(void);
> +
> +#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
> +

No need to enclose a declaration in #ifdef, better leave it there
unconditionally, unless you have an alternative version, like

#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
void __init udbg_init_usbgecko(void);
#else /* !CONFIG_PPC_EARLY_DEBUG_USBGECKO */
static inline void udbg_init_usbgecko(void)
{
}
#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */

That style is now more common than having additional #ifdefs
in the code using the function.

	Arnd <><
Albert Herranz Nov. 23, 2009, 7:10 p.m. UTC | #2
Arnd Bergmann wrote:
> On Sunday 22 November 2009, Albert Herranz wrote:
>> +#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
>> +setup_usbgecko_bat:
>> +	/* prepare a BAT for early io */
>> +	lis	r8, 0x0c00
>> +	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
>> +	lis	r11, 0xcc00
>> +	ori	r11, r11, 0x3	/* 128K */
>> +#ifdef CONFIG_WII
>> +	oris	r8, r8, 0x0100
>> +	oris	r11, r11, 0x0100
>> +#endif
>> +	mtspr	SPRN_DBAT1L, r8
>> +	mtspr	SPRN_DBAT1U, r11
>> +	sync
>> +	isync
>> +	blr
>> +#endif
> 
> This will probably break other platforms if CONFIG_PPC_EARLY_DEBUG_USBGECKO
> is set. In general, we try hard to make it possible to build generic
> kernels for multiple systems, so it would be better to also add a runtime
> check here.
> 

Ok, I see the point.
But, what makes CONFIG_PPC_EARLY_DEBUG_USBGECKO case different from CONFIG_PPC_EARLY_DEBUG_CPM case here?

>> --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
>> +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
>> @@ -27,4 +27,10 @@ static inline void __init ug_udbg_init(void)
>>  
>>  #endif /* CONFIG_USBGECKO_UDBG */
>>  
>> +#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
>> +
>> +void __init udbg_init_usbgecko(void);
>> +
>> +#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
>> +
> 
> No need to enclose a declaration in #ifdef, better leave it there
> unconditionally, unless you have an alternative version, like
> 
> #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
> void __init udbg_init_usbgecko(void);
> #else /* !CONFIG_PPC_EARLY_DEBUG_USBGECKO */
> static inline void udbg_init_usbgecko(void)
> {
> }
> #endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
> 
> That style is now more common than having additional #ifdefs
> in the code using the function.

I'll fix that too. Thanks.

Cheers,
Albert
Arnd Bergmann Nov. 23, 2009, 10:13 p.m. UTC | #3
On Monday 23 November 2009 19:10:55 Albert Herranz wrote:
> 
> Arnd Bergmann wrote:
> > On Sunday 22 November 2009, Albert Herranz wrote:
> >> +#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
> >> +setup_usbgecko_bat:
> >> +    /* prepare a BAT for early io */
> >> +    lis     r8, 0x0c00
> >> +    ori     r8, r8, 0x002a  /* uncached, guarded ,rw */
> >> +    lis     r11, 0xcc00
> >> +    ori     r11, r11, 0x3   /* 128K */
> >> +#ifdef CONFIG_WII
> >> +    oris    r8, r8, 0x0100
> >> +    oris    r11, r11, 0x0100
> >> +#endif
> >> +    mtspr   SPRN_DBAT1L, r8
> >> +    mtspr   SPRN_DBAT1U, r11
> >> +    sync
> >> +    isync
> >> +    blr
> >> +#endif
> > 
> > This will probably break other platforms if CONFIG_PPC_EARLY_DEBUG_USBGECKO
> > is set. In general, we try hard to make it possible to build generic
> > kernels for multiple systems, so it would be better to also add a runtime
> > check here.
> > 
> 
> Ok, I see the point.
> But, what makes CONFIG_PPC_EARLY_DEBUG_USBGECKO case different from CONFIG_PPC_EARLY_DEBUG_CPM case here?
> 

I looked again, and the help text for PPC_EARLY_DEBUG makes it very clear that
are never usable on a production kernel. Just leave your code the way it is here,
but if there are other places that prevent portable kernels, those should be fixed.
I'm not aware of any of those right now.

	Arnd <><
Segher Boessenkool Nov. 24, 2009, 12:54 a.m. UTC | #4
You set up DBAT1 here...

> +setup_usbgecko_bat:
> +	/* prepare a BAT for early io */
> +	lis	r8, 0x0c00
> +	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
> +	lis	r11, 0xcc00
> +	ori	r11, r11, 0x3	/* 128K */
> +#ifdef CONFIG_WII
> +	oris	r8, r8, 0x0100
> +	oris	r11, r11, 0x0100
> +#endif
> +	mtspr	SPRN_DBAT1L, r8
> +	mtspr	SPRN_DBAT1U, r11
> +	sync
> +	isync
> +	blr

... and again here:

> +void __init udbg_init_usbgecko(void)
> +{
> +	unsigned long vaddr, paddr;
> +
> +#if defined(CONFIG_GAMECUBE)
> +	paddr = 0x0c000000;
> +#elif defined(CONFIG_WII)
> +	paddr = 0x0d000000;
> +#else
> +#error Invalid platform for USB Gecko based early debugging.
> +#endif
> +
> +	vaddr = 0xc0000000 | paddr;
> +	setbat(1, vaddr, paddr, 128*1024, PAGE_KERNEL_NCG);

Do you need to do it twice?

> +	ug_io_base = (void __iomem *)(vaddr | 0x6814);

Oh, hardcoded slot2, now i'm confused which one should be it :-)


Segher
Albert Herranz Nov. 24, 2009, 6:19 p.m. UTC | #5
Segher Boessenkool wrote:
> You set up DBAT1 here...
> 
>> +setup_usbgecko_bat:
>> +    /* prepare a BAT for early io */
>> +    lis    r8, 0x0c00
>> +    ori    r8, r8, 0x002a    /* uncached, guarded ,rw */
>> +    lis    r11, 0xcc00
>> +    ori    r11, r11, 0x3    /* 128K */
>> +#ifdef CONFIG_WII
>> +    oris    r8, r8, 0x0100
>> +    oris    r11, r11, 0x0100
>> +#endif
>> +    mtspr    SPRN_DBAT1L, r8
>> +    mtspr    SPRN_DBAT1U, r11
>> +    sync
>> +    isync
>> +    blr
> 
> ... and again here:
> 
>> +void __init udbg_init_usbgecko(void)
>> +{
>> +    unsigned long vaddr, paddr;
>> +
>> +#if defined(CONFIG_GAMECUBE)
>> +    paddr = 0x0c000000;
>> +#elif defined(CONFIG_WII)
>> +    paddr = 0x0d000000;
>> +#else
>> +#error Invalid platform for USB Gecko based early debugging.
>> +#endif
>> +
>> +    vaddr = 0xc0000000 | paddr;
>> +    setbat(1, vaddr, paddr, 128*1024, PAGE_KERNEL_NCG);
> 
> Do you need to do it twice?
> 

Uhmm... I need to re-check it.
IIRC the BATs were re-initialized in between. But I'm not sure now :)

>> +    ug_io_base = (void __iomem *)(vaddr | 0x6814);
> 
> Oh, hardcoded slot2, now i'm confused which one should be it :-)
> 

early udbg  : hardcoded to mem2 slot
normal udbg : as specified in device tree

Clearer now ? ;)

Thanks for the review!
Albert
Benjamin Herrenschmidt Nov. 26, 2009, 5:14 a.m. UTC | #6
On Sun, 2009-11-22 at 23:27 +0100, Arnd Bergmann wrote:
> 
> This will probably break other platforms if
> CONFIG_PPC_EARLY_DEBUG_USBGECKO
> is set. In general, we try hard to make it possible to build generic
> kernels for multiple systems, so it would be better to also add a
> runtime check here.

No Arnd. The whole point of EARLY_DEBUG is that it is -known- to break
other platforms :-) So that we can use it before we even get to probe
anything.

I am still tempted, one day, to change the kernel early init to setup a
stack in .bss and go straight to C to do that sort of stuff by parsing
the flat DT, this could be done using pretty much completely generic
code :-) But not right now.

Cheers,
Ben.
Segher Boessenkool Nov. 26, 2009, 10:54 p.m. UTC | #7
>> This will probably break other platforms if
>> CONFIG_PPC_EARLY_DEBUG_USBGECKO
>> is set. In general, we try hard to make it possible to build generic
>> kernels for multiple systems, so it would be better to also add a
>> runtime check here.
>
> No Arnd. The whole point of EARLY_DEBUG is that it is -known- to break
> other platforms :-) So that we can use it before we even get to probe
> anything.
>
> I am still tempted, one day, to change the kernel early init to  
> setup a
> stack in .bss and go straight to C to do that sort of stuff by parsing
> the flat DT, this could be done using pretty much completely generic
> code :-) But not right now.

No Ben.  The whole point of EARLY_DEBUG is that it _always works_,  
because
it is such trivial code.  Don't break that please, or we'll be forced to
add a "REALLY_EARLY_DEBUG" instead :-)


Segher
Benjamin Herrenschmidt Nov. 26, 2009, 11:27 p.m. UTC | #8
On Thu, 2009-11-26 at 23:54 +0100, Segher Boessenkool wrote:
> No Ben.  The whole point of EARLY_DEBUG is that it _always works_,  
> because
> it is such trivial code.  Don't break that please, or we'll be forced to
> add a "REALLY_EARLY_DEBUG" instead :-) 

I do tend to agree but heh... temptation to do more cute hacks ... :-)

Cheers,
Ben.
diff mbox

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..83a0b79 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 */
+	lis	r8, 0x0c00
+	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
+	lis	r11, 0xcc00
+	ori	r11, r11, 0x3	/* 128K */
+#ifdef CONFIG_WII
+	oris	r8, r8, 0x0100
+	oris	r11, r11, 0x0100
+#endif
+	mtspr	SPRN_DBAT1L, r8
+	mtspr	SPRN_DBAT1U, r11
+	sync
+	isync
+	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 49f86e8..9f5e7ed 100644
--- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
@@ -234,6 +234,9 @@  void __init ug_udbg_init(void)
 	struct device_node *stdout;
 	const char *path;
 
+	if (ug_io_base)
+		udbg_printf("%s: early -> final\n", __func__);
+
 	if (!of_chosen) {
 		udbg_printf("%s: missing of_chosen\n", __func__);
 		goto done;
@@ -283,3 +286,33 @@  done:
 		of_node_put(np);
 	return;
 }
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+
+/*
+ * USB Gecko early debug support initialization for udbg.
+ *
+ */
+void __init udbg_init_usbgecko(void)
+{
+	unsigned long vaddr, paddr;
+
+#if defined(CONFIG_GAMECUBE)
+	paddr = 0x0c000000;
+#elif defined(CONFIG_WII)
+	paddr = 0x0d000000;
+#else
+#error Invalid platform for USB Gecko based early debugging.
+#endif
+
+	vaddr = 0xc0000000 | paddr;
+	setbat(1, vaddr, paddr, 128*1024, PAGE_KERNEL_NCG);
+
+	ug_io_base = (void __iomem *)(vaddr | 0x6814);
+
+	udbg_putc = ug_udbg_putc;
+	udbg_getc = ug_udbg_getc;
+	udbg_getc_poll = ug_udbg_getc_poll;
+}
+
+#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..98034ee 100644
--- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
@@ -27,4 +27,10 @@  static inline void __init ug_udbg_init(void)
 
 #endif /* CONFIG_USBGECKO_UDBG */
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+
+void __init udbg_init_usbgecko(void);
+
+#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
+
 #endif /* __USBGECKO_UDBG_H */