diff mbox

[v8,2/3] ARM: shmobile: r8a7778: add USB support

Message ID 201306020210.37520.sergei.shtylyov@cogentembedded.com (mailing list archive)
State Superseded
Headers show

Commit Message

Sergei Shtylyov June 1, 2013, 10:10 p.m. UTC
Add USB clock and EHCI, OHCI, and USB PHY platform devices for R8A7778 SoC;  add
a function to register PHY device with board-specific platform data and register
EHCI and OHCI platfrom devices from the init_late() board method.

Also,  don't forget to enable CONFIG_ARCH_HAS_[EO]HCI options for R8A7778 SoC in
Kconfig...

The patch has been tested on the BOCK-W board.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

---
Changes since version 7:
- changed PHY checks to IS_ERR(phy) and returning PTR_ERR(phy) where applicable;
- resolved reject.

Changes since version 5:
- renamed the R-Car PHY driver header file in #include.

Changes since version 4:
- annotated USB resources and '[eo]hci_info' as '__initdata' since they're
  kmemdup()'ed while registering the platform devices anyway;
- refreshed the patch.

Changes since version 3:
- resolved reject in the 'clock-r8a7778.c' file, refreshed the patch.

Changes since version 2:
- refreshed the patch.

Changes since the original posting:
- resolved rejects in the 'clock-r8a7778.c' file;
- lowercased the SoC name in the subject.

 arch/arm/mach-shmobile/Kconfig                |    2 
 arch/arm/mach-shmobile/clock-r8a7778.c        |    4 
 arch/arm/mach-shmobile/include/mach/r8a7778.h |    3 
 arch/arm/mach-shmobile/setup-r8a7778.c        |  108 ++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)


--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Kuninori Morimoto June 3, 2013, 12:24 a.m. UTC | #1
Hi


> Add USB clock and EHCI, OHCI, and USB PHY platform devices for R8A7778 SoC;  add
> a function to register PHY device with board-specific platform data and register
> EHCI and OHCI platfrom devices from the init_late() board method.
> 
> Also,  don't forget to enable CONFIG_ARCH_HAS_[EO]HCI options for R8A7778 SoC in
> Kconfig...
> 
> The patch has been tested on the BOCK-W board.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> ---
(snip)
> +void __init r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
> +{
> +	platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
> +					  usb_phy_resources,
> +					  ARRAY_SIZE(usb_phy_resources),
> +					  pdata, sizeof(*pdata));
> +}
(snip)
> +void __init r8a7778_init_late(void)
> +{
> +	phy = usb_get_phy(USB_PHY_TYPE_USB2);
> +
> +	platform_device_register_full(&ehci_info);
> +	platform_device_register_full(&ohci_info);
> +}

This means ehci/ohci device registration happened compulsorily if Soc/platform calls r8a7778_init_late().
but, usb phy isn't registered without r8a7778_add_usb_phy_device().

The ohci/ehci resource will be  used vainly if platform doesn't have USB

ohci/ehci and phy should be registered in same time/function.

Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sergei Shtylyov June 3, 2013, 10:14 a.m. UTC | #2
Hello.

On 03-06-2013 4:24, Kuninori Morimoto wrote:

>> Add USB clock and EHCI, OHCI, and USB PHY platform devices for R8A7778 SoC;  add
>> a function to register PHY device with board-specific platform data and register
>> EHCI and OHCI platfrom devices from the init_late() board method.

>> Also,  don't forget to enable CONFIG_ARCH_HAS_[EO]HCI options for R8A7778 SoC in
>> Kconfig...

>> The patch has been tested on the BOCK-W board.

>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>> ---
> (snip)
>> +void __init r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
>> +{
>> +	platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
>> +					  usb_phy_resources,
>> +					  ARRAY_SIZE(usb_phy_resources),
>> +					  pdata, sizeof(*pdata));
>> +}
> (snip)
>> +void __init r8a7778_init_late(void)
>> +{
>> +	phy = usb_get_phy(USB_PHY_TYPE_USB2);
>> +
>> +	platform_device_register_full(&ehci_info);
>> +	platform_device_register_full(&ohci_info);
>> +}

> This means ehci/ohci device registration happened compulsorily if Soc/platform calls r8a7778_init_late().
> but, usb phy isn't registered without r8a7778_add_usb_phy_device().

> The ohci/ehci resource will be  used vainly if platform doesn't have USB

    The platform device resources are never used vainly. And remember 
that if PHY doesn't get registered, OHCI/EHCI won't get probed 
successfully either -- mind the usb_power_on() platform method.

> ohci/ehci and phy should be registered in same time/function.

    I just copied your approach from the R8A7779 code.

> Best regards
> ---
> Kuninori Morimoto

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kuninori Morimoto June 4, 2013, 5:45 a.m. UTC | #3
Hi

> > The ohci/ehci resource will be  used vainly if platform doesn't have USB
> 
>     The platform device resources are never used vainly. And remember 
> that if PHY doesn't get registered, OHCI/EHCI won't get probed 
> successfully either -- mind the usb_power_on() platform method.

?
Could you please teach me who/how/when free resource memory
which was kmemdup'ed by platform_device_add_xxx()
(and kmalloc'ed dma_mask) on platform_device_register_full() ??

>> ohci/ehci and phy should be registered in same time/function.
>
>    I just copied your approach from the R8A7779 code.

Ahh, yes, indeed


Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sergei Shtylyov June 4, 2013, 10:22 a.m. UTC | #4
Hello.

On 04-06-2013 9:45, Kuninori Morimoto wrote:

>>> The ohci/ehci resource will be  used vainly if platform doesn't have USB

>>      The platform device resources are never used vainly. And remember
>> that if PHY doesn't get registered, OHCI/EHCI won't get probed
>> successfully either -- mind the usb_power_on() platform method.

> ?
> Could you please teach me who/how/when free resource memory
> which was kmemdup'ed by platform_device_add_xxx()
> (and kmalloc'ed dma_mask) on platform_device_register_full() ??

    I don't think there's a need to free them. The EHCI/OHCI devices
are always there after all.

>>> ohci/ehci and phy should be registered in same time/function.

>>     I just copied your approach from the R8A7779 code.

> Ahh, yes, indeed

     Moreover, from our prior testing, I'm afraid registering USB PHY 
and EHCI/OHCI in one function wouldn't work. Unless maybe if it's done 
from the init_late() machine's method...

> Best regards
> ---
> Kuninori Morimoto

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kuninori Morimoto June 5, 2013, 12:17 a.m. UTC | #5
Hi

> > Could you please teach me who/how/when free resource memory
> > which was kmemdup'ed by platform_device_add_xxx()
> > (and kmalloc'ed dma_mask) on platform_device_register_full() ??
> 
>     I don't think there's a need to free them. The EHCI/OHCI devices
> are always there after all.

Yes, you are correct.
Many devices are existing in Renesas chip, not only EHCI/OHCI.

But in r8a7778 case, these ehci/ohci doesn't work if usb-phy wasn't enabled,
and without PFC settings from platform.


> >>     I just copied your approach from the R8A7779 code.
> 
> > Ahh, yes, indeed
> 
>      Moreover, from our prior testing, I'm afraid registering USB PHY 
> and EHCI/OHCI in one function wouldn't work. Unless maybe if it's done 
> from the init_late() machine's method...

I'm sorry.
This mention (= phy and ohci/ehci registration in one function) was my fault.
Your style is correct I think.

Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

Index: renesas/arch/arm/mach-shmobile/Kconfig
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/Kconfig
+++ renesas/arch/arm/mach-shmobile/Kconfig
@@ -41,6 +41,8 @@  config ARCH_R8A7778
 	select CPU_V7
 	select SH_CLK_CPG
 	select ARM_GIC
+	select USB_ARCH_HAS_EHCI
+	select USB_ARCH_HAS_OHCI
 
 config ARCH_R8A7779
 	bool "R-Car H1 (R8A77790)"
Index: renesas/arch/arm/mach-shmobile/clock-r8a7778.c
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/clock-r8a7778.c
+++ renesas/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -105,6 +105,7 @@  static struct clk *main_clks[] = {
 enum {
 	MSTP323, MSTP322, MSTP321,
 	MSTP114,
+	MSTP100,
 	MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015,
 	MSTP_NR };
@@ -114,6 +115,7 @@  static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
 	[MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
 	[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
+	[MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1,  0, 0), /* USB0/1 */
 	[MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
 	[MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
 	[MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
@@ -130,6 +132,8 @@  static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh-eth",	&mstp_clks[MSTP114]), /* Ether */
+	CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
+	CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
Index: renesas/arch/arm/mach-shmobile/include/mach/r8a7778.h
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ renesas/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -20,10 +20,13 @@ 
 
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
+#include <linux/platform_data/usb-rcar-phy.h>
 
 extern void r8a7778_add_standard_devices(void);
 extern void r8a7778_add_standard_devices_dt(void);
 extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata);
+extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
+extern void r8a7778_init_late(void);
 extern void r8a7778_init_delay(void);
 extern void r8a7778_init_irq(void);
 extern void r8a7778_init_irq_dt(void);
Index: renesas/arch/arm/mach-shmobile/setup-r8a7778.c
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/setup-r8a7778.c
+++ renesas/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -30,6 +30,12 @@ 
 #include <linux/irqchip.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/dma-mapping.h>
 #include <mach/irqs.h>
 #include <mach/r8a7778.h>
 #include <mach/common.h>
@@ -89,6 +95,99 @@  static struct sh_timer_config sh_tmu1_pl
 		&sh_tmu##idx##_platform_data,		\
 		sizeof(sh_tmu##idx##_platform_data))
 
+/* USB PHY */
+static struct resource usb_phy_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe70800, 0x100),
+	DEFINE_RES_MEM(0xffe76000, 0x100),
+};
+
+void __init r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
+{
+	platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1,
+					  usb_phy_resources,
+					  ARRAY_SIZE(usb_phy_resources),
+					  pdata, sizeof(*pdata));
+}
+
+/* USB */
+static struct usb_phy *phy;
+
+static int usb_power_on(struct platform_device *pdev)
+{
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	usb_phy_init(phy);
+
+	return 0;
+}
+
+static void usb_power_off(struct platform_device *pdev)
+{
+	if (IS_ERR(phy))
+		return;
+
+	usb_phy_shutdown(phy);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+}
+
+static int ehci_init_internal_buffer(struct usb_hcd *hcd)
+{
+	/*
+	 * Below are recommended values from the datasheet;
+	 * see [USB :: Setting of EHCI Internal Buffer].
+	 */
+	/* EHCI IP internal buffer setting */
+	iowrite32(0x00ff0040, hcd->regs + 0x0094);
+	/* EHCI IP internal buffer enable */
+	iowrite32(0x00000001, hcd->regs + 0x009C);
+
+	return 0;
+}
+
+static struct usb_ehci_pdata ehci_pdata __initdata = {
+	.power_on	= usb_power_on,
+	.power_off	= usb_power_off,
+	.power_suspend	= usb_power_off,
+	.pre_setup	= ehci_init_internal_buffer,
+};
+
+static struct resource ehci_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe70000, 0x400),
+	DEFINE_RES_IRQ(gic_iid(0x4c)),
+};
+
+static struct usb_ohci_pdata ohci_pdata __initdata = {
+	.power_on	= usb_power_on,
+	.power_off	= usb_power_off,
+	.power_suspend	= usb_power_off,
+};
+
+static struct resource ohci_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe70400, 0x400),
+	DEFINE_RES_IRQ(gic_iid(0x4c)),
+};
+
+#define USB_PLATFORM_INFO(hci)					\
+static struct platform_device_info hci##_info __initdata = {	\
+	.parent		= &platform_bus,			\
+	.name		= #hci "-platform",			\
+	.id		= -1,					\
+	.res		= hci##_resources,			\
+	.num_res	= ARRAY_SIZE(hci##_resources),		\
+	.data		= &hci##_pdata,				\
+	.size_data	= sizeof(hci##_pdata),			\
+	.dma_mask	= DMA_BIT_MASK(32),			\
+}
+
+USB_PLATFORM_INFO(ehci);
+USB_PLATFORM_INFO(ohci);
+
 /* Ether */
 static struct resource ether_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfde00000, 0x400),
@@ -197,6 +296,14 @@  void __init r8a7778_add_standard_devices
 	r8a7778_register_tmu(1);
 }
 
+void __init r8a7778_init_late(void)
+{
+	phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+	platform_device_register_full(&ehci_info);
+	platform_device_register_full(&ohci_info);
+}
+
 static struct renesas_intc_irqpin_config irqpin_platform_data __initdata = {
 	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
 	.sense_bitfield_width = 2,
@@ -310,6 +417,7 @@  DT_MACHINE_START(R8A7778_DT, "Generic R8
 	.init_machine	= r8a7778_add_standard_devices_dt,
 	.init_time	= shmobile_timer_init,
 	.dt_compat	= r8a7778_compat_dt,
+	.init_late      = r8a7778_init_late,
 MACHINE_END
 
 #endif /* CONFIG_USE_OF */