Renesas USB updates for v3.11
These updates are by Sergei Shtylyov to clean-up USB support present for R8A7779/Marzen and then extend USB support coverage to R8A7778/BOCK-W. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRuWA6AAoJENfPZGlqN0++YFAP/ArB3kdvcKNQNjXM0BmX/Pim TFIOIN4NRpRFcS467PSSSObm/YJsbR+5TViISZdpo7O6hmZzUPeK2MrKNq5wmUIf OpX0eI8dCWCRZIAZjQcOiro1BR05UEzqyc8GjnmiVnV6TShO8x9IaFKGl+RRI4WD KoG3wNo1OvOuEToXhsyB6kMnpD8Ab/Xrj5xAAzLkml8gx6K/kAvdCnn+0Zhv8Nvu Vp0hEnCC/z6peBrFFWqXPpt0aV4iILVtxG36funGIuMB1YE0Ih5TnoJDlAPZSIO7 RnUz6vfjczobR7Pt8wBf5wFsMuWMUt5trLgruSeeskRw+728Vc7MzFwLV8IdtlAY LJpnrA7bd4W6R6d9u+eiCEekA4/+6SZySsLGflwfB3yzhaDr5LIMK8YZZFlXb2Bm p2Gkh556bT7lrYdqiyjqjSk71qFokynSFUp61GMWbQTNbSY2azlpDfxG1Epo6kFu XxpAr/XjGm4mMOp8ObxjvTlb9encP1snAHBnB3CoFh/LyjcG0nLwdWySAbTGlTy2 iabAegy7pQ+wD3Qri7WR7VYyiLogb5cF+rvVSDzS0HhtYH9OMFdb8z3NrHY+mk3Q OCZf9bbIk5pGhQyryDXg8G6nT9qLMsjy1SB2kj6S+Tyaox4WiLJZJiZiiwI+tGrn 7bst42iHBVMJaWQKRcAq =5+Te -----END PGP SIGNATURE----- Merge tag 'renesas-phy-rcar-usb-for-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/soc From Simon Horman: Renesas USB updates for v3.11 These updates are by Sergei Shtylyov to clean-up USB support present for R8A7779/Marzen and then extend USB support coverage to R8A7778/BOCK-W. * tag 'renesas-phy-rcar-usb-for-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas: ARM: shmobile: BOCK-W: add USB support ARM: shmobile: r8a7778: add USB support phy-rcar-usb: add R8A7778 support phy-rcar-usb: handle platform data ARM: shmobile: Marzen: pass platform data to USB PHY device phy-rcar-usb: add platform data phy-rcar-usb: correct base address ARM: shmobile: r8a7779: remove USB PHY 2nd memory resource phy-rcar-usb: remove EHCI internal buffer setup ARM: shmobile: r8a7779: setup EHCI internal buffer ehci-platform: add pre_setup() method to platform data ARM: shmobile: Marzen: move USB EHCI, OHCI, and PHY devices to R8A7779 code Conflicts: arch/arm/mach-shmobile/board-marzen.c arch/arm/mach-shmobile/setup-r8a7778.c Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Коммит
a114926964
|
@ -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)"
|
||||
|
|
|
@ -38,12 +38,18 @@ static struct resource smsc911x_resources[] = {
|
|||
DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
|
||||
};
|
||||
|
||||
static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
|
||||
|
||||
static const struct pinctrl_map bockw_pinctrl_map[] = {
|
||||
/* SCIF0 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
|
||||
"scif0_data_a", "scif0"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
|
||||
"scif0_ctrl", "scif0"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
|
||||
"usb0", "usb0"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
|
||||
"usb1", "usb1"),
|
||||
};
|
||||
|
||||
#define IRQ0MR 0x30
|
||||
|
@ -54,6 +60,7 @@ static void __init bockw_init(void)
|
|||
r8a7778_clock_init();
|
||||
r8a7778_init_irq_extpin(1);
|
||||
r8a7778_add_standard_devices();
|
||||
r8a7778_add_usb_phy_device(&usb_phy_platform_data);
|
||||
|
||||
pinctrl_register_mappings(bockw_pinctrl_map,
|
||||
ARRAY_SIZE(bockw_pinctrl_map));
|
||||
|
@ -91,4 +98,5 @@ DT_MACHINE_START(BOCKW_DT, "bockw")
|
|||
.init_machine = bockw_init,
|
||||
.init_time = shmobile_timer_init,
|
||||
.dt_compat = bockw_boards_compat_dt,
|
||||
.init_late = r8a7778_init_late,
|
||||
MACHINE_END
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sh_mobile_sdhi.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/ehci_pdriver.h>
|
||||
#include <linux/usb/ohci_pdriver.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/r8a7779.h>
|
||||
#include <mach/common.h>
|
||||
|
@ -61,6 +57,8 @@ static struct regulator_consumer_supply dummy_supplies[] = {
|
|||
REGULATOR_SUPPLY("vdd33a", "smsc911x"),
|
||||
};
|
||||
|
||||
static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
|
||||
|
||||
/* SMSC LAN89218 */
|
||||
static struct resource smsc911x_resources[] = {
|
||||
[0] = {
|
||||
|
@ -150,26 +148,6 @@ static struct platform_device hspi_device = {
|
|||
.num_resources = ARRAY_SIZE(hspi_resources),
|
||||
};
|
||||
|
||||
/* USB PHY */
|
||||
static struct resource usb_phy_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffe70000,
|
||||
.end = 0xffe70900 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0xfff70000,
|
||||
.end = 0xfff70900 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device usb_phy_device = {
|
||||
.name = "rcar_usb_phy",
|
||||
.resource = usb_phy_resources,
|
||||
.num_resources = ARRAY_SIZE(usb_phy_resources),
|
||||
};
|
||||
|
||||
/* LEDS */
|
||||
static struct gpio_led marzen_leds[] = {
|
||||
{
|
||||
|
@ -205,161 +183,9 @@ static struct platform_device *marzen_devices[] __initdata = {
|
|||
&sdhi0_device,
|
||||
&thermal_device,
|
||||
&hspi_device,
|
||||
&usb_phy_device,
|
||||
&leds_device,
|
||||
};
|
||||
|
||||
/* 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 struct usb_ehci_pdata ehcix_pdata = {
|
||||
.power_on = usb_power_on,
|
||||
.power_off = usb_power_off,
|
||||
.power_suspend = usb_power_off,
|
||||
};
|
||||
|
||||
static struct resource ehci0_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffe70000,
|
||||
.end = 0xffe70400 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4c),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ehci0_device = {
|
||||
.name = "ehci-platform",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ehci0_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ehcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ehci0_resources),
|
||||
.resource = ehci0_resources,
|
||||
};
|
||||
|
||||
static struct resource ehci1_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfff70000,
|
||||
.end = 0xfff70400 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4d),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ehci1_device = {
|
||||
.name = "ehci-platform",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ehci1_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ehcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ehci1_resources),
|
||||
.resource = ehci1_resources,
|
||||
};
|
||||
|
||||
static struct usb_ohci_pdata ohcix_pdata = {
|
||||
.power_on = usb_power_on,
|
||||
.power_off = usb_power_off,
|
||||
.power_suspend = usb_power_off,
|
||||
};
|
||||
|
||||
static struct resource ohci0_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffe70400,
|
||||
.end = 0xffe70800 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4c),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ohci0_device = {
|
||||
.name = "ohci-platform",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci0_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ohcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ohci0_resources),
|
||||
.resource = ohci0_resources,
|
||||
};
|
||||
|
||||
static struct resource ohci1_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfff70400,
|
||||
.end = 0xfff70800 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4d),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ohci1_device = {
|
||||
.name = "ohci-platform",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ohci1_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ohcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ohci1_resources),
|
||||
.resource = ohci1_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *marzen_late_devices[] __initdata = {
|
||||
&ehci0_device,
|
||||
&ehci1_device,
|
||||
&ohci0_device,
|
||||
&ohci1_device,
|
||||
};
|
||||
|
||||
void __init marzen_init_late(void)
|
||||
{
|
||||
/* get usb phy */
|
||||
phy = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
|
||||
shmobile_init_late();
|
||||
platform_add_devices(marzen_late_devices,
|
||||
ARRAY_SIZE(marzen_late_devices));
|
||||
}
|
||||
|
||||
static const struct pinctrl_map marzen_pinctrl_map[] = {
|
||||
/* HSPI0 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779",
|
||||
|
@ -407,6 +233,7 @@ static void __init marzen_init(void)
|
|||
r8a7779_pinmux_init();
|
||||
|
||||
r8a7779_add_standard_devices();
|
||||
r8a7779_add_usb_phy_device(&usb_phy_platform_data);
|
||||
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
|
||||
}
|
||||
|
||||
|
@ -417,6 +244,6 @@ MACHINE_START(MARZEN, "marzen")
|
|||
.nr_irqs = NR_IRQS_LEGACY,
|
||||
.init_irq = r8a7779_init_irq,
|
||||
.init_machine = marzen_init,
|
||||
.init_late = marzen_init_late,
|
||||
.init_late = r8a7779_init_late,
|
||||
.init_time = r8a7779_earlytimer_init,
|
||||
MACHINE_END
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/sh_clk.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/sh_eth.h>
|
||||
#include <linux/platform_data/usb-rcar-phy.h>
|
||||
|
||||
struct platform_device;
|
||||
|
||||
|
@ -33,6 +34,8 @@ extern void r8a7779_add_early_devices(void);
|
|||
extern void r8a7779_add_standard_devices(void);
|
||||
extern void r8a7779_add_standard_devices_dt(void);
|
||||
extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata);
|
||||
extern void r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
|
||||
extern void r8a7779_init_late(void);
|
||||
extern void r8a7779_clock_init(void);
|
||||
extern void r8a7779_pinmux_init(void);
|
||||
extern void r8a7779_pm_init(void);
|
||||
|
|
|
@ -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_platform_data = {
|
|||
&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[] = {
|
||||
DEFINE_RES_MEM(0xfde00000, 0x400),
|
||||
|
@ -197,6 +296,14 @@ void __init r8a7778_add_standard_devices(void)
|
|||
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 = {
|
||||
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
|
||||
.sense_bitfield_width = 2,
|
||||
|
@ -310,6 +417,7 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
|
|||
.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 */
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
#include <linux/sh_intc.h>
|
||||
#include <linux/sh_timer.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/usb/ehci_pdriver.h>
|
||||
#include <linux/usb/ohci_pdriver.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/r8a7779.h>
|
||||
|
@ -383,6 +388,165 @@ static struct platform_device sata_device = {
|
|||
},
|
||||
};
|
||||
|
||||
/* USB PHY */
|
||||
static struct resource usb_phy_resources[] __initdata = {
|
||||
[0] = {
|
||||
.start = 0xffe70800,
|
||||
.end = 0xffe70900 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
/* 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 ehcix_pdata = {
|
||||
.power_on = usb_power_on,
|
||||
.power_off = usb_power_off,
|
||||
.power_suspend = usb_power_off,
|
||||
.pre_setup = ehci_init_internal_buffer,
|
||||
};
|
||||
|
||||
static struct resource ehci0_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffe70000,
|
||||
.end = 0xffe70400 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4c),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ehci0_device = {
|
||||
.name = "ehci-platform",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ehci0_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ehcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ehci0_resources),
|
||||
.resource = ehci0_resources,
|
||||
};
|
||||
|
||||
static struct resource ehci1_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfff70000,
|
||||
.end = 0xfff70400 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4d),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ehci1_device = {
|
||||
.name = "ehci-platform",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ehci1_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ehcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ehci1_resources),
|
||||
.resource = ehci1_resources,
|
||||
};
|
||||
|
||||
static struct usb_ohci_pdata ohcix_pdata = {
|
||||
.power_on = usb_power_on,
|
||||
.power_off = usb_power_off,
|
||||
.power_suspend = usb_power_off,
|
||||
};
|
||||
|
||||
static struct resource ohci0_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffe70400,
|
||||
.end = 0xffe70800 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4c),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ohci0_device = {
|
||||
.name = "ohci-platform",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci0_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ohcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ohci0_resources),
|
||||
.resource = ohci0_resources,
|
||||
};
|
||||
|
||||
static struct resource ohci1_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfff70400,
|
||||
.end = 0xfff70800 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = gic_iid(0x4d),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ohci1_device = {
|
||||
.name = "ohci-platform",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ohci1_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ohcix_pdata,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ohci1_resources),
|
||||
.resource = ohci1_resources,
|
||||
};
|
||||
|
||||
/* Ether */
|
||||
static struct resource ether_resources[] = {
|
||||
{
|
||||
|
@ -406,7 +570,7 @@ static struct platform_device *r8a7779_devices_dt[] __initdata = {
|
|||
&tmu01_device,
|
||||
};
|
||||
|
||||
static struct platform_device *r8a7779_late_devices[] __initdata = {
|
||||
static struct platform_device *r8a7779_standard_devices[] __initdata = {
|
||||
&i2c0_device,
|
||||
&i2c1_device,
|
||||
&i2c2_device,
|
||||
|
@ -426,8 +590,8 @@ void __init r8a7779_add_standard_devices(void)
|
|||
|
||||
platform_add_devices(r8a7779_devices_dt,
|
||||
ARRAY_SIZE(r8a7779_devices_dt));
|
||||
platform_add_devices(r8a7779_late_devices,
|
||||
ARRAY_SIZE(r8a7779_late_devices));
|
||||
platform_add_devices(r8a7779_standard_devices,
|
||||
ARRAY_SIZE(r8a7779_standard_devices));
|
||||
}
|
||||
|
||||
void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
|
||||
|
@ -438,6 +602,14 @@ void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
|
|||
pdata, sizeof(*pdata));
|
||||
}
|
||||
|
||||
void __init r8a7779_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));
|
||||
}
|
||||
|
||||
/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
|
||||
void __init __weak r8a7779_register_twd(void) { }
|
||||
|
||||
|
@ -470,6 +642,23 @@ void __init r8a7779_add_early_devices(void)
|
|||
*/
|
||||
}
|
||||
|
||||
static struct platform_device *r8a7779_late_devices[] __initdata = {
|
||||
&ehci0_device,
|
||||
&ehci1_device,
|
||||
&ohci0_device,
|
||||
&ohci1_device,
|
||||
};
|
||||
|
||||
void __init r8a7779_init_late(void)
|
||||
{
|
||||
/* get USB PHY */
|
||||
phy = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
|
||||
shmobile_init_late();
|
||||
platform_add_devices(r8a7779_late_devices,
|
||||
ARRAY_SIZE(r8a7779_late_devices));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USE_OF
|
||||
void __init r8a7779_init_delay(void)
|
||||
{
|
||||
|
@ -503,6 +692,7 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
|
|||
.init_irq = r8a7779_init_irq_dt,
|
||||
.init_machine = r8a7779_add_standard_devices_dt,
|
||||
.init_time = shmobile_timer_init,
|
||||
.init_late = r8a7779_init_late,
|
||||
.dt_compat = r8a7779_compat_dt,
|
||||
MACHINE_END
|
||||
#endif /* CONFIG_USE_OF */
|
||||
|
|
|
@ -48,6 +48,12 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
|
|||
ehci->big_endian_desc = pdata->big_endian_desc;
|
||||
ehci->big_endian_mmio = pdata->big_endian_mmio;
|
||||
|
||||
if (pdata->pre_setup) {
|
||||
retval = pdata->pre_setup(hcd);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
ehci->caps = hcd->regs + pdata->caps_offset;
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
|
|
|
@ -180,15 +180,15 @@ config USB_MXS_PHY
|
|||
MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
|
||||
|
||||
config USB_RCAR_PHY
|
||||
tristate "Renesas R-Car USB phy support"
|
||||
tristate "Renesas R-Car USB PHY support"
|
||||
depends on USB || USB_GADGET
|
||||
help
|
||||
Say Y here to add support for the Renesas R-Car USB phy driver.
|
||||
This chip is typically used as USB phy for USB host, gadget.
|
||||
This driver supports: R8A7779
|
||||
Say Y here to add support for the Renesas R-Car USB common PHY driver.
|
||||
This chip is typically used as USB PHY for USB host, gadget.
|
||||
This driver supports R8A7778 and R8A7779.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rcar-phy.
|
||||
module will be called phy-rcar-usb.
|
||||
|
||||
config USB_ULPI
|
||||
bool "Generic ULPI Transceiver Driver"
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* Renesas R-Car USB phy driver
|
||||
*
|
||||
* Copyright (C) 2012 Renesas Solutions Corp.
|
||||
* Copyright (C) 2012-2013 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
* Copyright (C) 2013 Cogent Embedded, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -15,17 +16,41 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/usb-rcar-phy.h>
|
||||
|
||||
/* USBH common register */
|
||||
#define USBPCTRL0 0x0800
|
||||
#define USBPCTRL1 0x0804
|
||||
#define USBST 0x0808
|
||||
#define USBEH0 0x080C
|
||||
#define USBOH0 0x081C
|
||||
#define USBCTL0 0x0858
|
||||
#define EIIBC1 0x0094
|
||||
#define EIIBC2 0x009C
|
||||
/* REGS block */
|
||||
#define USBPCTRL0 0x00
|
||||
#define USBPCTRL1 0x04
|
||||
#define USBST 0x08
|
||||
#define USBEH0 0x0C
|
||||
#define USBOH0 0x1C
|
||||
#define USBCTL0 0x58
|
||||
|
||||
/* High-speed signal quality characteristic control registers (R8A7778 only) */
|
||||
#define HSQCTL1 0x24
|
||||
#define HSQCTL2 0x28
|
||||
|
||||
/* USBPCTRL0 */
|
||||
#define OVC2 (1 << 10) /* (R8A7779 only) */
|
||||
/* Switches the OVC input pin for port 2: */
|
||||
/* 1: USB_OVC2, 0: OVC2 */
|
||||
#define OVC1_VBUS1 (1 << 9) /* Switches the OVC input pin for port 1: */
|
||||
/* 1: USB_OVC1, 0: OVC1/VBUS1 */
|
||||
/* Function mode: set to 0 */
|
||||
#define OVC0 (1 << 8) /* Switches the OVC input pin for port 0: */
|
||||
/* 1: USB_OVC0 pin, 0: OVC0 */
|
||||
#define OVC2_ACT (1 << 6) /* (R8A7779 only) */
|
||||
/* Host mode: OVC2 polarity: */
|
||||
/* 1: active-high, 0: active-low */
|
||||
#define PENC (1 << 4) /* Function mode: output level of PENC1 pin: */
|
||||
/* 1: high, 0: low */
|
||||
#define OVC0_ACT (1 << 3) /* Host mode: OVC0 polarity: */
|
||||
/* 1: active-high, 0: active-low */
|
||||
#define OVC1_ACT (1 << 1) /* Host mode: OVC1 polarity: */
|
||||
/* 1: active-high, 0: active-low */
|
||||
/* Function mode: be sure to set to 1 */
|
||||
#define PORT1 (1 << 0) /* Selects port 1 mode: */
|
||||
/* 1: function, 0: host */
|
||||
/* USBPCTRL1 */
|
||||
#define PHY_RST (1 << 2)
|
||||
#define PLL_ENB (1 << 1)
|
||||
|
@ -58,8 +83,10 @@ static int rcar_usb_phy_init(struct usb_phy *phy)
|
|||
{
|
||||
struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
|
||||
struct device *dev = phy->dev;
|
||||
struct rcar_phy_platform_data *pdata = dev->platform_data;
|
||||
void __iomem *reg0 = priv->reg0;
|
||||
void __iomem *reg1 = priv->reg1;
|
||||
static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT };
|
||||
int i;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
@ -77,7 +104,16 @@ static int rcar_usb_phy_init(struct usb_phy *phy)
|
|||
/* (2) start USB-PHY internal PLL */
|
||||
iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
|
||||
|
||||
/* (3) USB module status check */
|
||||
/* (3) set USB-PHY in accord with the conditions of usage */
|
||||
if (reg1) {
|
||||
u32 hsqctl1 = pdata->ferrite_bead ? 0x41 : 0;
|
||||
u32 hsqctl2 = pdata->ferrite_bead ? 0x0d : 7;
|
||||
|
||||
iowrite32(hsqctl1, reg1 + HSQCTL1);
|
||||
iowrite32(hsqctl2, reg1 + HSQCTL2);
|
||||
}
|
||||
|
||||
/* (4) USB module status check */
|
||||
for (i = 0; i < 1024; i++) {
|
||||
udelay(10);
|
||||
val = ioread32(reg0 + USBST);
|
||||
|
@ -90,24 +126,24 @@ static int rcar_usb_phy_init(struct usb_phy *phy)
|
|||
goto phy_init_end;
|
||||
}
|
||||
|
||||
/* (4) USB-PHY reset clear */
|
||||
/* (5) USB-PHY reset clear */
|
||||
iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
|
||||
|
||||
/* set platform specific port settings */
|
||||
iowrite32(0x00000000, (reg0 + USBPCTRL0));
|
||||
|
||||
/*
|
||||
* EHCI IP internal buffer setting
|
||||
* EHCI IP internal buffer enable
|
||||
*
|
||||
* These are recommended value of a datasheet
|
||||
* see [USB :: EHCI internal buffer setting]
|
||||
*/
|
||||
iowrite32(0x00ff0040, (reg0 + EIIBC1));
|
||||
iowrite32(0x00ff0040, (reg1 + EIIBC1));
|
||||
|
||||
iowrite32(0x00000001, (reg0 + EIIBC2));
|
||||
iowrite32(0x00000001, (reg1 + EIIBC2));
|
||||
/* Board specific port settings */
|
||||
val = 0;
|
||||
if (pdata->port1_func)
|
||||
val |= PORT1;
|
||||
if (pdata->penc1)
|
||||
val |= PENC;
|
||||
for (i = 0; i < 3; i++) {
|
||||
/* OVCn bits follow each other in the right order */
|
||||
if (pdata->ovc_pin[i].select_3_3v)
|
||||
val |= OVC0 << i;
|
||||
/* OVCn_ACT bits are spaced by irregular intervals */
|
||||
if (pdata->ovc_pin[i].active_high)
|
||||
val |= ovcn_act[i];
|
||||
}
|
||||
iowrite32(val, (reg0 + USBPCTRL0));
|
||||
|
||||
/*
|
||||
* Bus alignment settings
|
||||
|
@ -134,10 +170,8 @@ static void rcar_usb_phy_shutdown(struct usb_phy *phy)
|
|||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
if (priv->counter-- == 1) { /* last user */
|
||||
iowrite32(0x00000000, (reg0 + USBPCTRL0));
|
||||
if (priv->counter-- == 1) /* last user */
|
||||
iowrite32(0x00000000, (reg0 + USBPCTRL1));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
@ -147,27 +181,29 @@ static int rcar_usb_phy_probe(struct platform_device *pdev)
|
|||
struct rcar_usb_phy_priv *priv;
|
||||
struct resource *res0, *res1;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *reg0, *reg1;
|
||||
void __iomem *reg0, *reg1 = NULL;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!res0 || !res1) {
|
||||
if (!res0) {
|
||||
dev_err(dev, "Not enough platform resources\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* CAUTION
|
||||
*
|
||||
* Because this phy address is also mapped under OHCI/EHCI address area,
|
||||
* this driver can't use devm_request_and_ioremap(dev, res) here
|
||||
*/
|
||||
reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
|
||||
reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
|
||||
if (!reg0 || !reg1) {
|
||||
dev_err(dev, "ioremap error\n");
|
||||
return -ENOMEM;
|
||||
reg0 = devm_ioremap_resource(dev, res0);
|
||||
if (IS_ERR(reg0))
|
||||
return PTR_ERR(reg0);
|
||||
|
||||
res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (res1) {
|
||||
reg1 = devm_ioremap_resource(dev, res1);
|
||||
if (IS_ERR(reg1))
|
||||
return PTR_ERR(reg1);
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||
* Copyright (C) 2013 Cogent Embedded, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __USB_RCAR_PHY_H
|
||||
#define __USB_RCAR_PHY_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct rcar_phy_platform_data {
|
||||
bool ferrite_bead:1; /* (R8A7778 only) */
|
||||
|
||||
bool port1_func:1; /* true: port 1 used by function, false: host */
|
||||
unsigned penc1:1; /* Output of the PENC1 pin in function mode */
|
||||
struct { /* Overcurrent pin control for ports 0..2 */
|
||||
bool select_3_3v:1; /* true: USB_OVCn pin, false: OVCn pin */
|
||||
/* Set to false on port 1 in function mode */
|
||||
bool active_high:1; /* true: active high, false: active low */
|
||||
/* Set to true on port 1 in function mode */
|
||||
} ovc_pin[3]; /* (R8A7778 only has 2 ports) */
|
||||
};
|
||||
|
||||
#endif /* __USB_RCAR_PHY_H */
|
|
@ -19,6 +19,9 @@
|
|||
#ifndef __USB_CORE_EHCI_PDRIVER_H
|
||||
#define __USB_CORE_EHCI_PDRIVER_H
|
||||
|
||||
struct platform_device;
|
||||
struct usb_hcd;
|
||||
|
||||
/**
|
||||
* struct usb_ehci_pdata - platform_data for generic ehci driver
|
||||
*
|
||||
|
@ -50,6 +53,7 @@ struct usb_ehci_pdata {
|
|||
/* Turn on only VBUS suspend power and hotplug detection,
|
||||
* turn off everything else */
|
||||
void (*power_suspend)(struct platform_device *pdev);
|
||||
int (*pre_setup)(struct usb_hcd *hcd);
|
||||
};
|
||||
|
||||
#endif /* __USB_CORE_EHCI_PDRIVER_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче