From: John Crispin <blogic@xxxxxxxxxxx> Add code to load the platform ehci/ohci driver on Ralink SoC. For the usb core to work we need to populate the platform_data during boot, prior to the usb driver being loaded. Signed-off-by: John Crispin <blogic@xxxxxxxxxxx> [matthijs@xxxxxxxx: Extracted non-ohci/ehci 3052 code into separate patch] Signed-off-by: Matthijs Kooijman <matthijs@xxxxxxxx> --- arch/mips/ralink/Makefile | 2 +- arch/mips/ralink/rt305x-usb.c | 74 ++++++++++++++++++++++++++ arch/mips/ralink/rt3883-usb.c | 118 ++++++++++++++++++++++++++++++++++++++++++ arch/mips/ralink/rt3883.c | 5 -- 4 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 arch/mips/ralink/rt3883-usb.c v2: Rebased on top of mips-next-3.10 Switched order with previous patch This patch isn't intended for mips-next-3.10 yet. diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index c5572a3..ef7d6c8 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -10,7 +10,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o obj-$(CONFIG_SOC_RT288X) += rt288x.o obj-$(CONFIG_SOC_RT305X) += rt305x.o rt305x-usb.o -obj-$(CONFIG_SOC_RT3883) += rt3883.o +obj-$(CONFIG_SOC_RT3883) += rt3883.o rt3883-usb.o obj-$(CONFIG_SOC_MT7620) += mt7620.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o diff --git a/arch/mips/ralink/rt305x-usb.c b/arch/mips/ralink/rt305x-usb.c index af6f062..d18f739 100644 --- a/arch/mips/ralink/rt305x-usb.c +++ b/arch/mips/ralink/rt305x-usb.c @@ -11,11 +11,77 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/delay.h> #include <linux/of_platform.h> #include <linux/dma-mapping.h> +#include <linux/usb/ehci_pdriver.h> +#include <linux/usb/ohci_pdriver.h> +#include <asm/mach-ralink/ralink_regs.h> #include <asm/mach-ralink/rt305x.h> +static atomic_t rt3352_usb_pwr_ref = ATOMIC_INIT(0); + +static int rt3352_usb_power_on(struct platform_device *pdev) +{ + + if (atomic_inc_return(&rt3352_usb_pwr_ref) == 1) { + u32 t; + + t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS); + + /* enable clock for port0's and port1's phys */ + t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1); + t |= RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN; + rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1); + mdelay(500); + + /* pull USBHOST and USBDEV out from reset */ + t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL); + t &= ~(RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV); + rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL); + mdelay(500); + + /* enable host mode */ + t = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG1); + t |= RT3352_SYSCFG1_USB0_HOST_MODE; + rt_sysc_w32(t, RT3352_SYSC_REG_SYSCFG1); + + t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS); + } + + return 0; +} + +static void rt3352_usb_power_off(struct platform_device *pdev) +{ + if (atomic_dec_return(&rt3352_usb_pwr_ref) == 0) { + u32 t; + + /* put USBHOST and USBDEV into reset */ + t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL); + t |= RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV; + rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL); + udelay(10000); + + /* disable clock for port0's and port1's phys*/ + t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1); + t &= ~(RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN); + rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1); + udelay(10000); + } +} + +static struct usb_ehci_pdata rt3352_ehci_data = { + .power_on = rt3352_usb_power_on, + .power_off = rt3352_usb_power_off, +}; + +static struct usb_ohci_pdata rt3352_ohci_data = { + .power_on = rt3352_usb_power_on, + .power_off = rt3352_usb_power_off, +}; + static void ralink_add_usb(char *name, void *pdata, u64 *mask) { struct device_node *node; @@ -40,10 +106,18 @@ error_out: of_node_put(node); } +static u64 rt3352_ohci_dmamask = DMA_BIT_MASK(32); +static u64 rt3352_ehci_dmamask = DMA_BIT_MASK(32); static u64 rt3050_dwc2_dmamask = DMA_BIT_MASK(32); void ralink_usb_init(void) { + if (soc_is_rt3352() || soc_is_rt5350()) { + ralink_add_usb("ohci-platform", + &rt3352_ohci_data, &rt3352_ohci_dmamask); + ralink_add_usb("ehci-platform", + &rt3352_ehci_data, &rt3352_ehci_dmamask); + } if (soc_is_rt305x() || soc_is_rt3350()) { ralink_add_usb("ralink,rt3050-usb", NULL, &rt3050_dwc2_dmamask); diff --git a/arch/mips/ralink/rt3883-usb.c b/arch/mips/ralink/rt3883-usb.c new file mode 100644 index 0000000..8cf778e --- /dev/null +++ b/arch/mips/ralink/rt3883-usb.c @@ -0,0 +1,118 @@ +/* + * 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. + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@xxxxxxxxxxx> + * Copyright (C) 2013 John Crispin <blogic@xxxxxxxxxxx> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <linux/delay.h> +#include <linux/of_platform.h> +#include <linux/dma-mapping.h> +#include <linux/usb/ehci_pdriver.h> +#include <linux/usb/ohci_pdriver.h> + +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/rt3883.h> + +static atomic_t rt3883_usb_pwr_ref = ATOMIC_INIT(0); + +static int rt3883_usb_power_on(struct platform_device *pdev) +{ + if (atomic_inc_return(&rt3883_usb_pwr_ref) == 1) { + u32 t; + + t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS); + + /* enable clock for port0's and port1's phys */ + t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + t |= RT3883_CLKCFG1_UPHY0_CLK_EN | RT3883_CLKCFG1_UPHY1_CLK_EN; + rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); + mdelay(500); + + /* pull USBHOST and USBDEV out from reset */ + t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + t &= ~(RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV); + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + mdelay(500); + + /* enable host mode */ + t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); + t |= RT3883_SYSCFG1_USB0_HOST_MODE; + rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS); + } + + return 0; +} + +static void rt3883_usb_power_off(struct platform_device *pdev) +{ + if (atomic_dec_return(&rt3883_usb_pwr_ref) == 0) { + u32 t; + + /* put USBHOST and USBDEV into reset */ + t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + udelay(10000); + + /* disable clock for port0's and port1's phys*/ + t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + t &= ~(RT3883_CLKCFG1_UPHY0_CLK_EN | + RT3883_CLKCFG1_UPHY1_CLK_EN); + rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); + udelay(10000); + } +} + +static struct usb_ohci_pdata rt3883_ohci_data = { + .power_on = rt3883_usb_power_on, + .power_off = rt3883_usb_power_off, +}; + +static struct usb_ehci_pdata rt3883_ehci_data = { + .power_on = rt3883_usb_power_on, + .power_off = rt3883_usb_power_off, +}; + +static void ralink_add_usb(char *name, void *pdata, u64 *mask) +{ + struct device_node *node; + struct platform_device *pdev; + + node = of_find_compatible_node(NULL, NULL, name); + if (!node) + return; + + pdev = of_find_device_by_node(node); + if (!pdev) + goto error_out; + + if (pdata) + pdev->dev.platform_data = pdata; + if (mask) { + pdev->dev.dma_mask = mask; + pdev->dev.coherent_dma_mask = *mask; + } + +error_out: + of_node_put(node); +} + +static u64 rt3883_ohci_dmamask = DMA_BIT_MASK(32); +static u64 rt3883_ehci_dmamask = DMA_BIT_MASK(32); + +void ralink_usb_init(void) +{ + ralink_add_usb("ohci-platform", + &rt3883_ohci_data, &rt3883_ohci_dmamask); + ralink_add_usb("ehci-platform", + &rt3883_ehci_data, &rt3883_ehci_dmamask); +} diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index c403696..afbf2ce 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -166,11 +166,6 @@ struct ralink_pinmux rt_gpio_pinmux = { .pci_mask = RT3883_GPIO_MODE_PCI_MASK, }; -void ralink_usb_init(void) -{ -} - - void __init ralink_clk_init(void) { unsigned long cpu_rate, sys_rate; -- 1.8.0