f78c902cfd
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 36215
311 lines
8.4 KiB
Diff
311 lines
8.4 KiB
Diff
From d7e679017ec92824145b275572f6ef83d461f076 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <blogic@openwrt.org>
|
|
Date: Tue, 19 Mar 2013 09:26:22 +0100
|
|
Subject: [PATCH 204/208] owrt: MIPS: ralink: add usb platform support
|
|
|
|
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@openwrt.org>
|
|
---
|
|
arch/mips/ralink/Makefile | 4 +-
|
|
arch/mips/ralink/common.h | 1 +
|
|
arch/mips/ralink/mt7620.c | 5 ++
|
|
arch/mips/ralink/of.c | 1 +
|
|
arch/mips/ralink/rt305x-usb.c | 120 +++++++++++++++++++++++++++++++++++++++++
|
|
arch/mips/ralink/rt3883-usb.c | 118 ++++++++++++++++++++++++++++++++++++++++
|
|
6 files changed, 247 insertions(+), 2 deletions(-)
|
|
create mode 100644 arch/mips/ralink/rt305x-usb.c
|
|
create mode 100644 arch/mips/ralink/rt3883-usb.c
|
|
|
|
--- a/arch/mips/ralink/Makefile
|
|
+++ b/arch/mips/ralink/Makefile
|
|
@@ -9,8 +9,8 @@
|
|
obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o
|
|
|
|
obj-$(CONFIG_SOC_RT288X) += rt288x.o
|
|
-obj-$(CONFIG_SOC_RT305X) += rt305x.o
|
|
-obj-$(CONFIG_SOC_RT3883) += rt3883.o
|
|
+obj-$(CONFIG_SOC_RT305X) += rt305x.o rt305x-usb.o
|
|
+obj-$(CONFIG_SOC_RT3883) += rt3883.o rt3883-usb.o
|
|
obj-$(CONFIG_SOC_MT7620) += mt7620.o
|
|
|
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
|
--- a/arch/mips/ralink/common.h
|
|
+++ b/arch/mips/ralink/common.h
|
|
@@ -43,5 +43,6 @@ extern void prom_soc_init(struct ralink_
|
|
__iomem void *plat_of_remap_node(const char *node);
|
|
|
|
void ralink_pinmux(void);
|
|
+void ralink_usb_platform(void);
|
|
|
|
#endif /* _RALINK_COMMON_H__ */
|
|
--- a/arch/mips/ralink/mt7620.c
|
|
+++ b/arch/mips/ralink/mt7620.c
|
|
@@ -146,6 +146,11 @@ struct ralink_pinmux rt_pinmux = {
|
|
// .wdt_reset = rt305x_wdt_reset,
|
|
};
|
|
|
|
+void ralink_usb_platform(void)
|
|
+{
|
|
+
|
|
+}
|
|
+
|
|
void __init ralink_clk_init(void)
|
|
{
|
|
unsigned long cpu_rate, sys_rate;
|
|
--- a/arch/mips/ralink/of.c
|
|
+++ b/arch/mips/ralink/of.c
|
|
@@ -102,6 +102,7 @@ static int __init plat_of_setup(void)
|
|
panic("failed to populate DT\n");
|
|
|
|
ralink_pinmux();
|
|
+ ralink_usb_platform();
|
|
|
|
return 0;
|
|
}
|
|
--- /dev/null
|
|
+++ b/arch/mips/ralink/rt305x-usb.c
|
|
@@ -0,0 +1,120 @@
|
|
+/*
|
|
+ * 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@openwrt.org>
|
|
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
|
|
+ */
|
|
+
|
|
+#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/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;
|
|
+ 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 rt3352_ohci_dmamask = DMA_BIT_MASK(32);
|
|
+static u64 rt3352_ehci_dmamask = DMA_BIT_MASK(32);
|
|
+
|
|
+void ralink_usb_platform(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);
|
|
+ }
|
|
+}
|
|
--- /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@openwrt.org>
|
|
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
|
|
+ */
|
|
+
|
|
+#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_platform(void)
|
|
+{
|
|
+ ralink_add_usb("ohci-platform",
|
|
+ &rt3883_ohci_data, &rt3883_ohci_dmamask);
|
|
+ ralink_add_usb("ehci-platform",
|
|
+ &rt3883_ehci_data, &rt3883_ehci_dmamask);
|
|
+}
|