aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h34
-rw-r--r--target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c132
2 files changed, 161 insertions, 5 deletions
diff --git a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h
index e121582055..db037a583a 100644
--- a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h
+++ b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h
@@ -46,6 +46,11 @@
#define RT305X_FLASH1_SIZE (16 * 1024 * 1024)
#define RT305X_FLASH0_SIZE (8 * 1024 * 1024)
+#define RT3352_EHCI_BASE 0x101c0000
+#define RT3352_EHCI_SIZE 0x1000
+#define RT3352_OHCI_BASE 0x101c1000
+#define RT3352_OHCI_SIZE 0x1000
+
/* SYSC registers */
#define SYSC_REG_CHIP_NAME0 0x000 /* Chip Name 0 */
#define SYSC_REG_CHIP_NAME1 0x004 /* Chip Name 1 */
@@ -57,6 +62,11 @@
#define SYSC_REG_IA_ADDRESS 0x310 /* Illegal Access Address */
#define SYSC_REG_IA_TYPE 0x314 /* Illegal Access Type */
+#define RT3352_SYSC_REG_SYSCFG1 0x014
+#define RT3352_SYSC_REG_CLKCFG1 0x030
+#define RT3352_SYSC_REG_RSTCTRL 0x034
+#define RT3352_SYSC_REG_USB_PS 0x05c
+
#define RT3052_CHIP_NAME0 0x30335452
#define RT3052_CHIP_NAME1 0x20203235
@@ -85,6 +95,11 @@
#define RT3352_SYSCFG0_CPUCLK_LOW 0x0
#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1
+#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10)
+
+#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18)
+#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20)
+
#define RT305X_GPIO_MODE_I2C BIT(0)
#define RT305X_GPIO_MODE_SPI BIT(1)
#define RT305X_GPIO_MODE_UART0_SHIFT 2
@@ -121,6 +136,25 @@
#define RT305X_RESET_OTG BIT(22)
#define RT305X_RESET_ESW BIT(23)
+#define RT3352_RSTCTRL_SYS BIT(0)
+#define RT3352_RSTCTRL_TIMER BIT(8)
+#define RT3352_RSTCTRL_INTC BIT(9)
+#define RT3352_RSTCTRL_MEMC BIT(10)
+#define RT3352_RSTCTRL_PCM BIT(11)
+#define RT3352_RSTCTRL_UART0 BIT(12)
+#define RT3352_RSTCTRL_PIO BIT(13)
+#define RT3352_RSTCTRL_DMA BIT(14)
+#define RT3352_RSTCTRL_I2C BIT(16)
+#define RT3352_RSTCTRL_I2S BIT(17)
+#define RT3352_RSTCTRL_SPI BIT(18)
+#define RT3352_RSTCTRL_UART1 BIT(19)
+#define RT3352_RSTCTRL_WNIC BIT(20)
+#define RT3352_RSTCTRL_FE BIT(21)
+#define RT3352_RSTCTRL_UHST BIT(22)
+#define RT3352_RSTCTRL_ESW BIT(23)
+#define RT3352_RSTCTRL_EPHY BIT(24)
+#define RT3352_RSTCTRL_UDEV BIT(25)
+
#define RT305X_INTC_INT_SYSCTL BIT(0)
#define RT305X_INTC_INT_TIMER0 BIT(1)
#define RT305X_INTC_INT_TIMER1 BIT(2)
diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c
index 60e5711797..bebab8171a 100644
--- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c
+++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c
@@ -16,6 +16,8 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/spi.h>
#include <linux/rt2x00_platform.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <asm/addrspace.h>
@@ -25,6 +27,8 @@
#include <ramips_eth_platform.h>
#include <rt305x_esw_platform.h>
+#include <rt3883_ehci_platform.h>
+#include <rt3883_ohci_platform.h>
static struct resource rt305x_flash0_resources[] = {
{
@@ -257,7 +261,7 @@ void __init rt305x_register_spi(struct spi_board_info *info, int n)
platform_device_register(&rt305x_spi_device);
}
-static struct resource rt305x_usb_resources[] = {
+static struct resource rt305x_dwc_otg_resources[] = {
{
.start = RT305X_OTG_BASE,
.end = RT305X_OTG_BASE + 0x3FFFF,
@@ -269,16 +273,134 @@ static struct resource rt305x_usb_resources[] = {
},
};
-static struct platform_device rt305x_usb_device = {
+static struct platform_device rt305x_dwc_otg_device = {
.name = "dwc_otg",
- .resource = rt305x_usb_resources,
- .num_resources = ARRAY_SIZE(rt305x_usb_resources),
+ .resource = rt305x_dwc_otg_resources,
+ .num_resources = ARRAY_SIZE(rt305x_dwc_otg_resources),
.dev = {
.platform_data = NULL,
}
};
+static atomic_t rt3352_usb_use_count = ATOMIC_INIT(0);
+
+static void rt3352_usb_host_start(void)
+{
+ u32 t;
+
+ if (atomic_inc_return(&rt3352_usb_use_count) != 1)
+ return;
+
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_USB_PS);
+
+ /* enable clock for port0's and port1's phys */
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_CLKCFG1);
+ t = t | RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN;
+ rt305x_sysc_wr(t, RT3352_SYSC_REG_CLKCFG1);
+ mdelay(500);
+
+ /* pull USBHOST and USBDEV out from reset */
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_RSTCTRL);
+ t &= ~(RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV);
+ rt305x_sysc_wr(t, RT3352_SYSC_REG_RSTCTRL);
+ mdelay(500);
+
+ /* enable host mode */
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_SYSCFG1);
+ t |= RT3352_SYSCFG1_USB0_HOST_MODE;
+ rt305x_sysc_wr(t, RT3352_SYSC_REG_SYSCFG1);
+
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_USB_PS);
+}
+
+static void rt3352_usb_host_stop(void)
+{
+ u32 t;
+
+ if (atomic_dec_return(&rt3352_usb_use_count) != 0)
+ return;
+
+ /* put USBHOST and USBDEV into reset */
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_RSTCTRL);
+ t |= RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV;
+ rt305x_sysc_wr(t, RT3352_SYSC_REG_RSTCTRL);
+ udelay(10000);
+
+ /* disable clock for port0's and port1's phys*/
+ t = rt305x_sysc_rr(RT3352_SYSC_REG_CLKCFG1);
+ t &= ~(RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN);
+ rt305x_sysc_wr(t, RT3352_SYSC_REG_CLKCFG1);
+ udelay(10000);
+}
+
+static struct rt3883_ehci_platform_data rt3352_ehci_data = {
+ .start_hw = rt3352_usb_host_start,
+ .stop_hw = rt3352_usb_host_stop,
+};
+
+static struct resource rt3352_ehci_resources[] = {
+ {
+ .start = RT3352_EHCI_BASE,
+ .end = RT3352_EHCI_BASE + RT3352_EHCI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = RT305X_INTC_IRQ_OTG,
+ .end = RT305X_INTC_IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 rt3352_ehci_dmamask = DMA_BIT_MASK(32);
+static struct platform_device rt3352_ehci_device = {
+ .name = "rt3352-ehci",
+ .id = -1,
+ .resource = rt3352_ehci_resources,
+ .num_resources = ARRAY_SIZE(rt3352_ehci_resources),
+ .dev = {
+ .dma_mask = &rt3352_ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &rt3352_ehci_data,
+ },
+};
+
+static struct resource rt3352_ohci_resources[] = {
+ {
+ .start = RT3352_OHCI_BASE,
+ .end = RT3352_OHCI_BASE + RT3352_OHCI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = RT305X_INTC_IRQ_OTG,
+ .end = RT305X_INTC_IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct rt3883_ohci_platform_data rt3352_ohci_data = {
+ .start_hw = rt3352_usb_host_start,
+ .stop_hw = rt3352_usb_host_stop,
+};
+
+static u64 rt3352_ohci_dmamask = DMA_BIT_MASK(32);
+static struct platform_device rt3352_ohci_device = {
+ .name = "rt3352-ohci",
+ .id = -1,
+ .resource = rt3352_ohci_resources,
+ .num_resources = ARRAY_SIZE(rt3352_ohci_resources),
+ .dev = {
+ .dma_mask = &rt3352_ohci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &rt3352_ohci_data,
+ },
+};
+
void __init rt305x_register_usb(void)
{
- platform_device_register(&rt305x_usb_device);
+ if (soc_is_rt305x() || soc_is_rt3350()) {
+ platform_device_register(&rt305x_dwc_otg_device);
+ } else if (soc_is_rt3352()) {
+ platform_device_register(&rt3352_ehci_device);
+ platform_device_register(&rt3352_ohci_device);
+ } else {
+ BUG();
+ }
}