Commit 5027070b authored by Anoop P A's avatar Anoop P A Committed by Ralf Baechle

MIPS: MSP71xx: Platform support for MSP on-chip USB controller.

Signed-off-by: default avatarAnoop P A <anoop.pa@gmail.com>
To: linux-mips@linux-mips.org
To: linux-kernel@vger.kernel.org
Cc: Anoop P A <anoop.pa@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/2043/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 088f3876
...@@ -91,12 +91,10 @@ ...@@ -91,12 +91,10 @@
/* MAC C device registers */ /* MAC C device registers */
#define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000) #define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000)
/* ADSL2 device registers */ /* ADSL2 device registers */
#define MSP_USB_BASE (MSP_MSB_BASE + 0xB40000) #define MSP_USB0_BASE (MSP_MSB_BASE + 0xB00000)
/* USB device registers */ /* USB0 device registers */
#define MSP_USB_BASE_START (MSP_MSB_BASE + 0xB40100) #define MSP_USB1_BASE (MSP_MSB_BASE + 0x300000)
/* USB device registers */ /* USB1 device registers */
#define MSP_USB_BASE_END (MSP_MSB_BASE + 0xB401FF)
/* USB device registers */
#define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000) #define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000)
/* CPU interface registers */ /* CPU interface registers */
...@@ -319,8 +317,11 @@ ...@@ -319,8 +317,11 @@
#define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184) #define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184)
/* CPU/SLP Error status 1 */ /* CPU/SLP Error status 1 */
#define EXTENDED_GPIO_REG regptr(MSP_SLP_BASE + 0x188) /* Extended GPIO registers */
/* Extended GPIO register */ #define EXTENDED_GPIO1_REG regptr(MSP_SLP_BASE + 0x188)
#define EXTENDED_GPIO2_REG regptr(MSP_SLP_BASE + 0x18c)
#define EXTENDED_GPIO_REG EXTENDED_GPIO1_REG
/* Backward-compatibility */
/* System Error registers */ /* System Error registers */
#define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190) #define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190)
......
/******************************************************************
* Copyright (c) 2000-2007 PMC-Sierra INC.
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
* 02139, USA.
*
* PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
* SOFTWARE.
*/
#ifndef MSP_USB_H_
#define MSP_USB_H_
#ifdef CONFIG_MSP_HAS_DUAL_USB
#define NUM_USB_DEVS 2
#else
#define NUM_USB_DEVS 1
#endif
/* Register spaces for USB host 0 */
#define MSP_USB0_MAB_START (MSP_USB0_BASE + 0x0)
#define MSP_USB0_MAB_END (MSP_USB0_BASE + 0x17)
#define MSP_USB0_ID_START (MSP_USB0_BASE + 0x40000)
#define MSP_USB0_ID_END (MSP_USB0_BASE + 0x4008f)
#define MSP_USB0_HS_START (MSP_USB0_BASE + 0x40100)
#define MSP_USB0_HS_END (MSP_USB0_BASE + 0x401FF)
/* Register spaces for USB host 1 */
#define MSP_USB1_MAB_START (MSP_USB1_BASE + 0x0)
#define MSP_USB1_MAB_END (MSP_USB1_BASE + 0x17)
#define MSP_USB1_ID_START (MSP_USB1_BASE + 0x40000)
#define MSP_USB1_ID_END (MSP_USB1_BASE + 0x4008f)
#define MSP_USB1_HS_START (MSP_USB1_BASE + 0x40100)
#define MSP_USB1_HS_END (MSP_USB1_BASE + 0x401ff)
/* USB Identification registers */
struct msp_usbid_regs {
u32 id; /* 0x0: Identification register */
u32 hwgen; /* 0x4: General HW params */
u32 hwhost; /* 0x8: Host HW params */
u32 hwdev; /* 0xc: Device HW params */
u32 hwtxbuf; /* 0x10: Tx buffer HW params */
u32 hwrxbuf; /* 0x14: Rx buffer HW params */
u32 reserved[26];
u32 timer0_load; /* 0x80: General-purpose timer 0 load*/
u32 timer0_ctrl; /* 0x84: General-purpose timer 0 control */
u32 timer1_load; /* 0x88: General-purpose timer 1 load*/
u32 timer1_ctrl; /* 0x8c: General-purpose timer 1 control */
};
/* MSBus to AMBA registers */
struct msp_mab_regs {
u32 isr; /* 0x0: Interrupt status */
u32 imr; /* 0x4: Interrupt mask */
u32 thcr0; /* 0x8: Transaction header capture 0 */
u32 thcr1; /* 0xc: Transaction header capture 1 */
u32 int_stat; /* 0x10: Interrupt status summary */
u32 phy_cfg; /* 0x14: USB phy config */
};
/* EHCI registers */
struct msp_usbhs_regs {
u32 hciver; /* 0x0: Version and offset to operational regs */
u32 hcsparams; /* 0x4: Host control structural parameters */
u32 hccparams; /* 0x8: Host control capability parameters */
u32 reserved0[5];
u32 dciver; /* 0x20: Device interface version */
u32 dccparams; /* 0x24: Device control capability parameters */
u32 reserved1[6];
u32 cmd; /* 0x40: USB command */
u32 sts; /* 0x44: USB status */
u32 int_ena; /* 0x48: USB interrupt enable */
u32 frindex; /* 0x4c: Frame index */
u32 reserved3;
union {
struct {
u32 flb_addr; /* 0x54: Frame list base address */
u32 next_async_addr; /* 0x58: next asynchronous addr */
u32 ttctrl; /* 0x5c: embedded transaction translator
async buffer status */
u32 burst_size; /* 0x60: Controller burst size */
u32 tx_fifo_ctrl; /* 0x64: Tx latency FIFO tuning */
u32 reserved0[4];
u32 endpt_nak; /* 0x78: Endpoint NAK */
u32 endpt_nak_ena; /* 0x7c: Endpoint NAK enable */
u32 cfg_flag; /* 0x80: Config flag */
u32 port_sc1; /* 0x84: Port status & control 1 */
u32 reserved1[7];
u32 otgsc; /* 0xa4: OTG status & control */
u32 mode; /* 0xa8: USB controller mode */
} host;
struct {
u32 dev_addr; /* 0x54: Device address */
u32 endpt_list_addr; /* 0x58: Endpoint list address */
u32 reserved0[7];
u32 endpt_nak; /* 0x74 */
u32 endpt_nak_ctrl; /* 0x78 */
u32 cfg_flag; /* 0x80 */
u32 port_sc1; /* 0x84: Port status & control 1 */
u32 reserved[7];
u32 otgsc; /* 0xa4: OTG status & control */
u32 mode; /* 0xa8: USB controller mode */
u32 endpt_setup_stat; /* 0xac */
u32 endpt_prime; /* 0xb0 */
u32 endpt_flush; /* 0xb4 */
u32 endpt_stat; /* 0xb8 */
u32 endpt_complete; /* 0xbc */
u32 endpt_ctrl0; /* 0xc0 */
u32 endpt_ctrl1; /* 0xc4 */
u32 endpt_ctrl2; /* 0xc8 */
u32 endpt_ctrl3; /* 0xcc */
} device;
} u;
};
/*
* Container for the more-generic platform_device.
* This exists mainly as a way to map the non-standard register
* spaces and make them accessible to the USB ISR.
*/
struct mspusb_device {
struct msp_mab_regs __iomem *mab_regs;
struct msp_usbid_regs __iomem *usbid_regs;
struct msp_usbhs_regs __iomem *usbhs_regs;
struct platform_device dev;
};
#define to_mspusb_device(x) container_of((x), struct mspusb_device, dev)
#define TO_HOST_ID(x) ((x) & 0x3)
#endif /*MSP_USB_H_*/
...@@ -23,6 +23,7 @@ config PMC_MSP7120_GW ...@@ -23,6 +23,7 @@ config PMC_MSP7120_GW
select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_MULTITHREADING
select IRQ_MSP_CIC select IRQ_MSP_CIC
select HW_HAS_PCI select HW_HAS_PCI
select MSP_HAS_USB
config PMC_MSP7120_FPGA config PMC_MSP7120_FPGA
bool "PMC-Sierra MSP7120 FPGA" bool "PMC-Sierra MSP7120 FPGA"
...@@ -35,3 +36,7 @@ endchoice ...@@ -35,3 +36,7 @@ endchoice
config HYPERTRANSPORT config HYPERTRANSPORT
bool "Hypertransport Support for PMC-Sierra Yosemite" bool "Hypertransport Support for PMC-Sierra Yosemite"
depends on PMC_YOSEMITE depends on PMC_YOSEMITE
config MSP_HAS_USB
boolean
depends on PMC_MSP
...@@ -9,6 +9,6 @@ obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o ...@@ -9,6 +9,6 @@ obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o msp_irq_per.o obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o msp_irq_per.o
obj-$(CONFIG_PCI) += msp_pci.o obj-$(CONFIG_PCI) += msp_pci.o
obj-$(CONFIG_MSPETH) += msp_eth.o obj-$(CONFIG_MSPETH) += msp_eth.o
obj-$(CONFIG_USB_MSP71XX) += msp_usb.o obj-$(CONFIG_MSP_HAS_USB) += msp_usb.o
obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o
obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o
/* /*
* The setup file for USB related hardware on PMC-Sierra MSP processors. * The setup file for USB related hardware on PMC-Sierra MSP processors.
* *
* Copyright 2006-2007 PMC-Sierra, Inc. * Copyright 2006 PMC-Sierra, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
#include <linux/dma-mapping.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -34,12 +34,14 @@ ...@@ -34,12 +34,14 @@
#include <msp_regs.h> #include <msp_regs.h>
#include <msp_int.h> #include <msp_int.h>
#include <msp_prom.h> #include <msp_prom.h>
#include <msp_usb.h>
#if defined(CONFIG_USB_EHCI_HCD) #if defined(CONFIG_USB_EHCI_HCD)
static struct resource msp_usbhost_resources [] = { static struct resource msp_usbhost0_resources[] = {
[0] = { [0] = { /* EHCI-HS operational and capabilities registers */
.start = MSP_USB_BASE_START, .start = MSP_USB0_HS_START,
.end = MSP_USB_BASE_END, .end = MSP_USB0_HS_END,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
...@@ -47,27 +49,80 @@ static struct resource msp_usbhost_resources [] = { ...@@ -47,27 +49,80 @@ static struct resource msp_usbhost_resources [] = {
.end = MSP_INT_USB, .end = MSP_INT_USB,
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { /* MSBus-to-AMBA bridge register space */
.start = MSP_USB0_MAB_START,
.end = MSP_USB0_MAB_END,
.flags = IORESOURCE_MEM,
},
[3] = { /* Identification and general hardware parameters */
.start = MSP_USB0_ID_START,
.end = MSP_USB0_ID_END,
.flags = IORESOURCE_MEM,
},
}; };
static u64 msp_usbhost_dma_mask = DMA_BIT_MASK(32); static u64 msp_usbhost0_dma_mask = 0xffffffffUL;
static struct platform_device msp_usbhost_device = { static struct mspusb_device msp_usbhost0_device = {
.dev = {
.name = "pmcmsp-ehci", .name = "pmcmsp-ehci",
.id = 0, .id = 0,
.dev = { .dev = {
.dma_mask = &msp_usbhost_dma_mask, .dma_mask = &msp_usbhost0_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32), .coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE(msp_usbhost0_resources),
.resource = msp_usbhost0_resources,
},
};
/* MSP7140/MSP82XX has two USB2 hosts. */
#ifdef CONFIG_MSP_HAS_DUAL_USB
static u64 msp_usbhost1_dma_mask = 0xffffffffUL;
static struct resource msp_usbhost1_resources[] = {
[0] = { /* EHCI-HS operational and capabilities registers */
.start = MSP_USB1_HS_START,
.end = MSP_USB1_HS_END,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = MSP_INT_USB,
.end = MSP_INT_USB,
.flags = IORESOURCE_IRQ,
},
[2] = { /* MSBus-to-AMBA bridge register space */
.start = MSP_USB1_MAB_START,
.end = MSP_USB1_MAB_END,
.flags = IORESOURCE_MEM,
},
[3] = { /* Identification and general hardware parameters */
.start = MSP_USB1_ID_START,
.end = MSP_USB1_ID_END,
.flags = IORESOURCE_MEM,
},
};
static struct mspusb_device msp_usbhost1_device = {
.dev = {
.name = "pmcmsp-ehci",
.id = 1,
.dev = {
.dma_mask = &msp_usbhost1_dma_mask,
.coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE(msp_usbhost1_resources),
.resource = msp_usbhost1_resources,
}, },
.num_resources = ARRAY_SIZE(msp_usbhost_resources),
.resource = msp_usbhost_resources,
}; };
#endif /* CONFIG_MSP_HAS_DUAL_USB */
#endif /* CONFIG_USB_EHCI_HCD */ #endif /* CONFIG_USB_EHCI_HCD */
#if defined(CONFIG_USB_GADGET) #if defined(CONFIG_USB_GADGET)
static struct resource msp_usbdev_resources [] = { static struct resource msp_usbdev0_resources[] = {
[0] = { [0] = { /* EHCI-HS operational and capabilities registers */
.start = MSP_USB_BASE, .start = MSP_USB0_HS_START,
.end = MSP_USB_BASE_END, .end = MSP_USB0_HS_END,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
...@@ -75,76 +130,134 @@ static struct resource msp_usbdev_resources [] = { ...@@ -75,76 +130,134 @@ static struct resource msp_usbdev_resources [] = {
.end = MSP_INT_USB, .end = MSP_INT_USB,
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { /* MSBus-to-AMBA bridge register space */
.start = MSP_USB0_MAB_START,
.end = MSP_USB0_MAB_END,
.flags = IORESOURCE_MEM,
},
[3] = { /* Identification and general hardware parameters */
.start = MSP_USB0_ID_START,
.end = MSP_USB0_ID_END,
.flags = IORESOURCE_MEM,
},
}; };
static u64 msp_usbdev_dma_mask = DMA_BIT_MASK(32); static u64 msp_usbdev_dma_mask = 0xffffffffUL;
static struct platform_device msp_usbdev_device = { /* This may need to be converted to a mspusb_device, too. */
static struct mspusb_device msp_usbdev0_device = {
.dev = {
.name = "msp71xx_udc", .name = "msp71xx_udc",
.id = 0, .id = 0,
.dev = { .dev = {
.dma_mask = &msp_usbdev_dma_mask, .dma_mask = &msp_usbdev_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32), .coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE(msp_usbdev0_resources),
.resource = msp_usbdev0_resources,
}, },
.num_resources = ARRAY_SIZE(msp_usbdev_resources),
.resource = msp_usbdev_resources,
}; };
#endif /* CONFIG_USB_GADGET */
#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET) #ifdef CONFIG_MSP_HAS_DUAL_USB
static struct platform_device *msp_devs[1]; static struct resource msp_usbdev1_resources[] = {
#endif [0] = { /* EHCI-HS operational and capabilities registers */
.start = MSP_USB1_HS_START,
.end = MSP_USB1_HS_END,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = MSP_INT_USB,
.end = MSP_INT_USB,
.flags = IORESOURCE_IRQ,
},
[2] = { /* MSBus-to-AMBA bridge register space */
.start = MSP_USB1_MAB_START,
.end = MSP_USB1_MAB_END,
.flags = IORESOURCE_MEM,
},
[3] = { /* Identification and general hardware parameters */
.start = MSP_USB1_ID_START,
.end = MSP_USB1_ID_END,
.flags = IORESOURCE_MEM,
},
};
/* This may need to be converted to a mspusb_device, too. */
static struct mspusb_device msp_usbdev1_device = {
.dev = {
.name = "msp71xx_udc",
.id = 0,
.dev = {
.dma_mask = &msp_usbdev_dma_mask,
.coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE(msp_usbdev1_resources),
.resource = msp_usbdev1_resources,
},
};
#endif /* CONFIG_MSP_HAS_DUAL_USB */
#endif /* CONFIG_USB_GADGET */
static int __init msp_usb_setup(void) static int __init msp_usb_setup(void)
{ {
#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
char *strp; char *strp;
char envstr[32]; char envstr[32];
unsigned int val = 0; struct platform_device *msp_devs[NUM_USB_DEVS];
int result = 0; unsigned int val;
/* construct environment name usbmode */
/* set usbmode <host/device> as pmon environment var */
/* /*
* construct environment name usbmode * Could this perhaps be integrated into the "features" env var?
* set usbmode <host/device> as pmon environment var * Use the features key "U", and follow with "H" for host-mode,
* "D" for device-mode. If it works for Ethernet, why not USB...
* -- hammtrev, 2007/03/22
*/ */
snprintf((char *)&envstr[0], sizeof(envstr), "usbmode"); snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
#if defined(CONFIG_USB_EHCI_HCD) /* set default host mode */
/* default to host mode */
val = 1; val = 1;
#endif
/* get environment string */ /* get environment string */
strp = prom_getenv((char *)&envstr[0]); strp = prom_getenv((char *)&envstr[0]);
if (strp) { if (strp) {
/* compare string */
if (!strcmp(strp, "device")) if (!strcmp(strp, "device"))
val = 0; val = 0;
} }
if (val) { if (val) {
#if defined(CONFIG_USB_EHCI_HCD) #if defined(CONFIG_USB_EHCI_HCD)
/* get host mode device */ msp_devs[0] = &msp_usbhost0_device.dev;
msp_devs[0] = &msp_usbhost_device; ppfinit("platform add USB HOST done %s.\n", msp_devs[0]->name);
ppfinit("platform add USB HOST done %s.\n", #ifdef CONFIG_MSP_HAS_DUAL_USB
msp_devs[0]->name); msp_devs[1] = &msp_usbhost1_device.dev;
ppfinit("platform add USB HOST done %s.\n", msp_devs[1]->name);
result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs)); #endif
#else
ppfinit("%s: echi_hcd not supported\n", __FILE__);
#endif /* CONFIG_USB_EHCI_HCD */ #endif /* CONFIG_USB_EHCI_HCD */
} } else {
#if defined(CONFIG_USB_GADGET) #if defined(CONFIG_USB_GADGET)
else {
/* get device mode structure */ /* get device mode structure */
msp_devs[0] = &msp_usbdev_device; msp_devs[0] = &msp_usbdev0_device.dev;
ppfinit("platform add USB DEVICE done %s.\n", ppfinit("platform add USB DEVICE done %s.\n"
msp_devs[0]->name); , msp_devs[0]->name);
#ifdef CONFIG_MSP_HAS_DUAL_USB
result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs)); msp_devs[1] = &msp_usbdev1_device.dev;
} ppfinit("platform add USB DEVICE done %s.\n"
, msp_devs[1]->name);
#endif
#else
ppfinit("%s: usb_gadget not supported\n", __FILE__);
#endif /* CONFIG_USB_GADGET */ #endif /* CONFIG_USB_GADGET */
#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */ }
/* add device */
platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs));
return result; return 0;
} }
subsys_initcall(msp_usb_setup); subsys_initcall(msp_usb_setup);
#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment