Commit 073b8546 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge branch 'for-next' of git://gitorious.org/usb/usb into usb-next

* 'for-next' of git://gitorious.org/usb/usb: (47 commits)
  usb: musb: Enable DMA mode1 RX for transfers without short packets
  usb: musb: fix build breakage
  usb: gadget: audio: queue wLength-sized requests
  usb: gadget: audio: actually support both speeds
  usb: gadget: storage: make FSG_NUM_BUFFERS variable size
  USB: gadget: storage: remove alignment assumption
  usb: gadget: storage: adapt logic block size to bound block devices
  usb: dwc3: gadget: improve debug on link state change
  usb: dwc3: omap: set idle and standby modes
  usb: dwc3: ep0: introduce ep0_expect_in flag
  usb: dwc3: ep0: giveback requests on stall_and_restart
  usb: dwc3: gadget: drop the useless dma_sync_single* calls
  usb: dwc3: gadget: fix GCTL programming
  usb: dwc3: define ScaleDown macro helper
  usb: dwc3: Fix definition of DWC3_GCTL_U2RSTECN
  usb: dwc3: gadget: do not map/unmap ZLP transfers
  usb: dwc3: omap: fix IRQ handling
  usb: dwc3: omap: change IRQ name to dwc3-omap
  usb: dwc3: add module.h to dwc3-omap.c and core.c
  usb: dwc3: omap: distinguish between SW and HW modes
  ...
parents b5dd18d8 0ae52d54
......@@ -242,14 +242,11 @@ obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \
obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \
hsmmc.o \
omap_phy_internal.o
hsmmc.o
obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
hsmmc.o \
omap_phy_internal.o
hsmmc.o
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
omap_phy_internal.o \
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o
obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o
......@@ -260,6 +257,8 @@ obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o
usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o
obj-y += $(usbfs-m) $(usbfs-y)
obj-y += usb-musb.o
obj-y += omap_phy_internal.o
obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o
obj-y += usb-host.o
......
......@@ -37,6 +37,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
......@@ -241,6 +242,15 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
u32 reg;
int ret;
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
/* This should read as U3 followed by revision number */
if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
ret = -ENODEV;
goto err0;
}
dwc->revision = reg & DWC3_GSNPSREV_MASK;
dwc3_core_soft_reset(dwc);
/* issue device SoftReset too */
......@@ -260,16 +270,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
cpu_relax();
} while (true);
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
/* This should read as U3 followed by revision number */
if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
ret = -ENODEV;
goto err0;
}
dwc->revision = reg & DWC3_GSNPSREV_MASK;
ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_NUM,
DWC3_EVENT_BUFFERS_SIZE);
if (ret) {
......
......@@ -147,7 +147,7 @@
/* Global Configuration Register */
#define DWC3_GCTL_PWRDNSCALE(n) (n << 19)
#define DWC3_GCTL_U2RSTECN 16
#define DWC3_GCTL_U2RSTECN (1 << 16)
#define DWC3_GCTL_RAMCLKSEL(x) ((x & DWC3_GCTL_CLK_MASK) << 6)
#define DWC3_GCTL_CLK_BUS (0)
#define DWC3_GCTL_CLK_PIPE (1)
......@@ -160,6 +160,7 @@
#define DWC3_GCTL_PRTCAP_OTG 3
#define DWC3_GCTL_CORESOFTRESET (1 << 11)
#define DWC3_GCTL_SCALEDOWN(n) (n << 4)
#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
/* Global USB2 PHY Configuration Register */
......@@ -348,7 +349,9 @@ struct dwc3_ep {
#define DWC3_EP_WEDGE (1 << 2)
#define DWC3_EP_BUSY (1 << 4)
#define DWC3_EP_PENDING_REQUEST (1 << 5)
#define DWC3_EP_WILL_SHUTDOWN (1 << 6)
/* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN (1 << 31)
unsigned current_trb;
......@@ -368,18 +371,19 @@ enum dwc3_phy {
DWC3_PHY_USB2,
};
enum dwc3_ep0_next {
DWC3_EP0_UNKNOWN = 0,
DWC3_EP0_COMPLETE,
DWC3_EP0_NRDY_SETUP,
DWC3_EP0_NRDY_DATA,
DWC3_EP0_NRDY_STATUS,
};
enum dwc3_ep0_state {
EP0_UNCONNECTED = 0,
EP0_IDLE,
EP0_IN_DATA_PHASE,
EP0_OUT_DATA_PHASE,
EP0_IN_WAIT_GADGET,
EP0_OUT_WAIT_GADGET,
EP0_IN_WAIT_NRDY,
EP0_OUT_WAIT_NRDY,
EP0_IN_STATUS_PHASE,
EP0_OUT_STATUS_PHASE,
EP0_STALL,
EP0_SETUP_PHASE,
EP0_DATA_PHASE,
EP0_STATUS_PHASE,
};
enum dwc3_link_state {
......@@ -503,13 +507,15 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
/**
* struct dwc3 - representation of our controller
* ctrl_req: usb control request which is used for ep0
* ep0_trb: trb which is used for the ctrl_req
* setup_buf: used while precessing STD USB requests
* ctrl_req_addr: dma address of ctrl_req
* ep0_trb: dma address of ep0_trb
* ep0_usb_req: dummy req used while handling STD USB requests
* setup_buf_addr: dma address of setup_buf
* @ctrl_req: usb control request which is used for ep0
* @ep0_trb: trb which is used for the ctrl_req
* @ep0_bounce: bounce buffer for ep0
* @setup_buf: used while precessing STD USB requests
* @ctrl_req_addr: dma address of ctrl_req
* @ep0_trb: dma address of ep0_trb
* @ep0_usb_req: dummy req used while handling STD USB requests
* @setup_buf_addr: dma address of setup_buf
* @ep0_bounce_addr: dma address of ep0_bounce
* @lock: for synchronizing
* @dev: pointer to our struct device
* @event_buffer_list: a list of event buffers
......@@ -522,6 +528,9 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
* @is_selfpowered: true when we are selfpowered
* @three_stage_setup: set if we perform a three phase setup
* @ep0_status_pending: ep0 status response without a req is pending
* @ep0_bounced: true when we used bounce buffer
* @ep0_expect_in: true when we expect a DATA IN transfer
* @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero
* @link_state: link state
* @speed: device speed (super, high, full, low)
......@@ -531,10 +540,12 @@ static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
struct dwc3_trb_hw *ep0_trb;
void *ep0_bounce;
u8 *setup_buf;
dma_addr_t ctrl_req_addr;
dma_addr_t ep0_trb_addr;
dma_addr_t setup_buf_addr;
dma_addr_t ep0_bounce_addr;
struct usb_request ep0_usb_req;
/* device lock */
spinlock_t lock;
......@@ -564,7 +575,10 @@ struct dwc3 {
unsigned is_selfpowered:1;
unsigned three_stage_setup:1;
unsigned ep0_status_pending:1;
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
enum dwc3_device_state dev_state;
......@@ -634,6 +648,12 @@ struct dwc3_event_depevt {
#define DEPEVT_STATUS_SHORT (1 << 1)
#define DEPEVT_STATUS_IOC (1 << 2)
#define DEPEVT_STATUS_LST (1 << 3)
/* Control-only Status */
#define DEPEVT_STATUS_CONTROL_SETUP 0
#define DEPEVT_STATUS_CONTROL_DATA 1
#define DEPEVT_STATUS_CONTROL_STATUS 2
u32 parameters:16;
} __packed;
......
......@@ -406,91 +406,6 @@ static const struct file_operations dwc3_regdump_fops = {
.release = single_release,
};
static int dwc3_send_testmode_cmd(struct dwc3 *dwc, int mode)
{
u32 timeout = 250;
dwc3_writel(dwc->regs, DWC3_DGCMDPAR, mode);
dwc3_writel(dwc->regs, DWC3_DGCMD, DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK |
DWC3_DEPCMD_CMDACT);
do {
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_DGCMD);
if (!(reg & DWC3_DEPCMD_CMDACT))
return 0;
timeout--;
if (!timeout)
return -ETIMEDOUT;
mdelay(1);
} while (1);
}
static struct dwc3_trb_hw trb_0 __aligned(16);
static struct dwc3_trb_hw trb_1 __aligned(16);
#define BUF_SIZE 4096
static int dwc3_testmode_open(struct inode *inode, struct file *file)
{
struct dwc3 *dwc = inode->i_private;
struct dwc3_gadget_ep_cmd_params par0;
struct dwc3_gadget_ep_cmd_params par1;
struct dwc3_trb trb;
int ret;
u8 *buf0;
u8 *buf1;
buf0 = kmalloc(BUF_SIZE, GFP_KERNEL);
if (!buf0)
return -ENOMEM;
buf1 = kmalloc(BUF_SIZE, GFP_KERNEL);
if (!buf1)
return -ENOMEM;
memset(buf0, 0xaa, BUF_SIZE);
memset(buf1, 0x33, BUF_SIZE);
memset(&trb, 0, sizeof(trb));
memset(&par0, 0, sizeof(par0));
memset(&par1, 0, sizeof(par1));
trb.lst = 1;
trb.trbctl = DWC3_TRBCTL_NORMAL;
trb.length = BUF_SIZE;
trb.hwo = 1;
trb.bplh = virt_to_phys(buf0);
dwc3_trb_to_hw(&trb, &trb_0);
trb.bplh = virt_to_phys(buf1);
dwc3_trb_to_hw(&trb, &trb_1);
par0.param0.depstrtxfer.transfer_desc_addr_high =
upper_32_bits(virt_to_phys(&trb_0));
par0.param1.depstrtxfer.transfer_desc_addr_low =
lower_32_bits(virt_to_phys(&trb_0));
par1.param0.depstrtxfer.transfer_desc_addr_high =
upper_32_bits(virt_to_phys(&trb_1));
par1.param1.depstrtxfer.transfer_desc_addr_low =
lower_32_bits(virt_to_phys(&trb_1));
dwc3_send_testmode_cmd(dwc, 1);
ret = dwc3_send_gadget_ep_cmd(dwc, 0, DWC3_DEPCMD_STARTTRANSFER, &par0);
ret = dwc3_send_gadget_ep_cmd(dwc, 1, DWC3_DEPCMD_STARTTRANSFER, &par1);
dwc3_send_testmode_cmd(dwc, 0);
return -EBUSY;
}
static const struct file_operations dwc3_testmode_fops = {
.open = dwc3_testmode_open,
.read = seq_read,
.release = single_release,
};
int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
{
struct dentry *root;
......@@ -511,13 +426,6 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
ret = PTR_ERR(file);
goto err1;
}
file = debugfs_create_file("testmode", S_IRUGO, root, dwc,
&dwc3_testmode_fops);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
goto err1;
}
return 0;
err1:
......
......@@ -37,11 +37,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dwc3-omap.h>
#include <linux/dma-mapping.h>
#include <linux/ioport.h>
#include <linux/io.h>
......@@ -74,8 +76,23 @@
/* SYSCONFIG REGISTER */
#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16)
#define USBOTGSS_SYSCONFIG_STANDBYMODE(x) ((x) << 4)
#define USBOTGSS_STANDBYMODE_FORCE_STANDBY 0
#define USBOTGSS_STANDBYMODE_NO_STANDBY 1
#define USBOTGSS_STANDBYMODE_SMART_STANDBY 2
#define USBOTGSS_STANDBYMODE_SMART_WAKEUP 3
#define USBOTGSS_STANDBYMODE_MASK (0x03 << 4)
#define USBOTGSS_SYSCONFIG_IDLEMODE(x) ((x) << 2)
#define USBOTGSS_IDLEMODE_FORCE_IDLE 0
#define USBOTGSS_IDLEMODE_NO_IDLE 1
#define USBOTGSS_IDLEMODE_SMART_IDLE 2
#define USBOTGSS_IDLEMODE_SMART_WAKEUP 3
#define USBOTGSS_IDLEMODE_MASK (0x03 << 2)
/* IRQ_EOI REGISTER */
#define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0)
......@@ -125,106 +142,51 @@ struct dwc3_omap {
u32 dma_status:1;
};
#ifdef CONFIG_PM
static int dwc3_omap_suspend(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
memcpy_fromio(omap->context, omap->base, omap->resource_size);
return 0;
}
static int dwc3_omap_resume(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
memcpy_toio(omap->base, omap->context, omap->resource_size);
return 0;
}
static int dwc3_omap_idle(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
u32 reg;
/* stop DMA Engine */
reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG);
reg &= ~(USBOTGSS_SYSCONFIG_DMADISABLE);
dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
return 0;
}
static UNIVERSAL_DEV_PM_OPS(dwc3_omap_pm_ops, dwc3_omap_suspend,
dwc3_omap_resume, dwc3_omap_idle);
#define DEV_PM_OPS (&dwc3_omap_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
struct dwc3_omap *omap = _omap;
u32 reg;
u32 ctrl;
spin_lock(&omap->lock);
reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_1);
ctrl = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_CTRL);
if (reg & USBOTGSS_IRQ1_DMADISABLECLR) {
dev_dbg(omap->base, "DMA Disable was Cleared\n");
dev_dbg(omap->dev, "DMA Disable was Cleared\n");
omap->dma_status = false;
}
if (reg & USBOTGSS_IRQ1_OEVT)
dev_dbg(omap->base, "OTG Event\n");
dev_dbg(omap->dev, "OTG Event\n");
if (reg & USBOTGSS_IRQ1_DRVVBUS_RISE) {
dev_dbg(omap->base, "DRVVBUS Rise\n");
ctrl |= USBOTGSS_UTMI_OTG_CTRL_DRVVBUS;
}
if (reg & USBOTGSS_IRQ1_DRVVBUS_RISE)
dev_dbg(omap->dev, "DRVVBUS Rise\n");
if (reg & USBOTGSS_IRQ1_CHRGVBUS_RISE) {
dev_dbg(omap->base, "CHRGVBUS Rise\n");
ctrl |= USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS;
}
if (reg & USBOTGSS_IRQ1_CHRGVBUS_RISE)
dev_dbg(omap->dev, "CHRGVBUS Rise\n");
if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_RISE) {
dev_dbg(omap->base, "DISCHRGVBUS Rise\n");
ctrl |= USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS;
}
if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_RISE)
dev_dbg(omap->dev, "DISCHRGVBUS Rise\n");
if (reg & USBOTGSS_IRQ1_IDPULLUP_RISE) {
dev_dbg(omap->base, "IDPULLUP Rise\n");
ctrl |= USBOTGSS_UTMI_OTG_CTRL_IDPULLUP;
}
if (reg & USBOTGSS_IRQ1_IDPULLUP_RISE)
dev_dbg(omap->dev, "IDPULLUP Rise\n");
if (reg & USBOTGSS_IRQ1_DRVVBUS_FALL) {
dev_dbg(omap->base, "DRVVBUS Fall\n");
ctrl &= ~USBOTGSS_UTMI_OTG_CTRL_DRVVBUS;
}
if (reg & USBOTGSS_IRQ1_DRVVBUS_FALL)
dev_dbg(omap->dev, "DRVVBUS Fall\n");
if (reg & USBOTGSS_IRQ1_CHRGVBUS_FALL) {
dev_dbg(omap->base, "CHRGVBUS Fall\n");
ctrl &= ~USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS;
}
if (reg & USBOTGSS_IRQ1_CHRGVBUS_FALL)
dev_dbg(omap->dev, "CHRGVBUS Fall\n");
if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_FALL) {
dev_dbg(omap->base, "DISCHRGVBUS Fall\n");
ctrl &= ~USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS;
}
if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_FALL)
dev_dbg(omap->dev, "DISCHRGVBUS Fall\n");
if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL) {
dev_dbg(omap->base, "IDPULLUP Fall\n");
ctrl &= ~USBOTGSS_UTMI_OTG_CTRL_IDPULLUP;
}
if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL)
dev_dbg(omap->dev, "IDPULLUP Fall\n");
dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_CTRL, ctrl);
dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg);
reg = dwc3_readl(omap->base, USBOTGSS_IRQSTATUS_0);
dwc3_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg);
spin_unlock(&omap->lock);
......@@ -233,6 +195,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
static int __devinit dwc3_omap_probe(struct platform_device *pdev)
{
struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct platform_device *dwc3;
struct dwc3_omap *omap;
struct resource *res;
......@@ -298,12 +261,41 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
omap->base = base;
omap->dwc3 = dwc3;
reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
if (!pdata) {
dev_dbg(&pdev->dev, "missing platform data\n");
} else {
switch (pdata->utmi_mode) {
case DWC3_OMAP_UTMI_MODE_SW:
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
case DWC3_OMAP_UTMI_MODE_HW:
reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
default:
dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n",
pdata->utmi_mode);
}
}
dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
/* check the DMA Status */
reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG);
omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
/* Set No-Idle and No-Standby */
reg &= ~(USBOTGSS_STANDBYMODE_MASK
| USBOTGSS_IDLEMODE_MASK);
reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));
dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
ret = request_irq(omap->irq, dwc3_omap_interrupt, 0,
"dwc3-wrapper", omap);
"dwc3-omap", omap);
if (ret) {
dev_err(&pdev->dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret);
......@@ -311,10 +303,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
}
/* enable all IRQs */
dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x01);
reg = USBOTGSS_IRQO_COREIRQ_ST;
dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
reg = (USBOTGSS_IRQ1_DMADISABLECLR |
USBOTGSS_IRQ1_OEVT |
reg = (USBOTGSS_IRQ1_OEVT |
USBOTGSS_IRQ1_DRVVBUS_RISE |
USBOTGSS_IRQ1_CHRGVBUS_RISE |
USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
......@@ -388,7 +380,6 @@ static struct platform_driver dwc3_omap_driver = {
.remove = __devexit_p(dwc3_omap_remove),
.driver = {
.name = "omap-dwc3",
.pm = DEV_PM_OPS,
.of_match_table = of_dwc3_matach,
},
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -96,6 +96,22 @@ config USB_GADGET_VBUS_DRAW
This value will be used except for system-specific gadget
drivers that have more specific information.
config USB_GADGET_STORAGE_NUM_BUFFERS
int "Number of storage pipeline buffers"
range 2 4
default 2
help
Usually 2 buffers are enough to establish a good buffering
pipeline. The number may be increased in order to compensate
for a bursty VFS behaviour. For instance there may be CPU wake up
latencies that makes the VFS to appear bursty in a system with
an CPU on-demand governor. Especially if DMA is doing IO to
offload the CPU. In this case the CPU will go into power
save often and spin up occasionally to move data within VFS.
If selecting USB_GADGET_DEBUG_FILES this value may be set by
a module parameter as well.
If unsure, say 2.
#
# USB Peripheral Controller Support
#
......
......@@ -460,7 +460,7 @@ static int audio_set_endpoint_req(struct usb_function *f,
switch (ctrl->bRequest) {
case UAC_SET_CUR:
value = 0;
value = len;
break;
case UAC_SET_MIN:
......@@ -499,7 +499,7 @@ static int audio_get_endpoint_req(struct usb_function *f,
case UAC_GET_MIN:
case UAC_GET_MAX:
case UAC_GET_RES:
value = 3;
value = len;
break;
case UAC_GET_MEM:
break;
......@@ -681,17 +681,18 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
/* supcard all relevant hardware speeds... we expect that when
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(f_audio_desc);
/*
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
/* copy descriptors, and track endpoint copies */
if (gadget_is_dualspeed(c->cdev->gadget)) {
c->highspeed = true;
f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
} else
f->descriptors = usb_copy_descriptors(f_audio_desc);
}
return 0;
......
This diff is collapsed.
This diff is collapsed.
......@@ -43,6 +43,12 @@
* characters rather then a pointer to void.
*/
/*
* When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
* sets the number of pipeline buffers (length of the fsg_buffhd array).
* The valid range of num_buffers is: num >= 2 && num <= 4.
*/
#include <linux/usb/storage.h>
#include <scsi/scsi.h>
......@@ -238,6 +244,8 @@ struct fsg_lun {
u32 sense_data_info;
u32 unit_attention_data;
unsigned int blkbits; /* Bits of logical block size of bound block device */
unsigned int blksize; /* logical block size of bound block device */
struct device dev;
};
......@@ -253,8 +261,31 @@ static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
#define EP0_BUFSIZE 256
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
/* Number of buffers we will use. 2 is enough for double-buffering */
#define FSG_NUM_BUFFERS 2
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);
MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers");
#else
/*
* Number of buffers we will use.
* 2 is usually enough for good buffering pipeline
*/
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
#endif /* CONFIG_USB_DEBUG */
/* check if fsg_num_buffers is within a valid range */
static inline int fsg_num_buffers_validate(void)
{
if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
return 0;
pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
fsg_num_buffers, 2 ,4);
return -EINVAL;
}
/* Default size of buffer length. */
#define FSG_BUFLEN ((u32)16384)
......@@ -571,13 +602,24 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
rc = (int) size;
goto out;
}
num_sectors = size >> 9; /* File size in 512-byte blocks */
if (curlun->cdrom) {
curlun->blksize = 2048;
curlun->blkbits = 11;
} else if (inode->i_bdev) {
curlun->blksize = bdev_logical_block_size(inode->i_bdev);
curlun->blkbits = blksize_bits(curlun->blksize);
} else {
curlun->blksize = 512;
curlun->blkbits = 9;
}
num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */
min_sectors = 1;
if (curlun->cdrom) {
num_sectors &= ~3; /* Reduce to a multiple of 2048 */
min_sectors = 300*4; /* Smallest track is 300 frames */
if (num_sectors >= 256*60*75*4) {
num_sectors = (256*60*75 - 1) * 4;
min_sectors = 300; /* Smallest track is 300 frames */
if (num_sectors >= 256*60*75) {
num_sectors = 256*60*75 - 1;
LINFO(curlun, "file too big: %s\n", filename);
LINFO(curlun, "using only first %d blocks\n",
(int) num_sectors);
......
......@@ -634,6 +634,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
u16 len;
u16 csr = musb_readw(epio, MUSB_RXCSR);
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
u8 use_mode_1;
if (hw_ep->is_shared_fifo)
musb_ep = &hw_ep->ep_in;
......@@ -683,6 +684,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (csr & MUSB_RXCSR_RXPKTRDY) {
len = musb_readw(epio, MUSB_RXCOUNT);
/*
* Enable Mode 1 on RX transfers only when short_not_ok flag
* is set. Currently short_not_ok flag is set only from
* file_storage and f_mass_storage drivers
*/
if (request->short_not_ok && len == musb_ep->packet_sz)
use_mode_1 = 1;
else
use_mode_1 = 0;
if (request->actual < request->length) {
#ifdef CONFIG_USB_INVENTRA_DMA
if (is_buffer_mapped(req)) {
......@@ -714,37 +727,41 @@ static void rxstate(struct musb *musb, struct musb_request *req)
* then becomes usable as a runtime "use mode 1" hint...
*/
csr |= MUSB_RXCSR_DMAENAB;
#ifdef USE_MODE1
csr |= MUSB_RXCSR_AUTOCLEAR;
/* csr |= MUSB_RXCSR_DMAMODE; */
/* this special sequence (enabling and then
* disabling MUSB_RXCSR_DMAMODE) is required
* to get DMAReq to activate
*/
musb_writew(epio, MUSB_RXCSR,
csr | MUSB_RXCSR_DMAMODE);
#else
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
/* Experimental: Mode1 works with mass storage use cases */
if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR;
#endif
musb_writew(epio, MUSB_RXCSR, csr);
musb_writew(epio, MUSB_RXCSR, csr);
csr |= MUSB_RXCSR_DMAENAB;
musb_writew(epio, MUSB_RXCSR, csr);
/*
* this special sequence (enabling and then
* disabling MUSB_RXCSR_DMAMODE) is required
* to get DMAReq to activate
*/
musb_writew(epio, MUSB_RXCSR,
csr | MUSB_RXCSR_DMAMODE);
musb_writew(epio, MUSB_RXCSR, csr);
} else {
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
csr |= MUSB_RXCSR_AUTOCLEAR;
csr |= MUSB_RXCSR_DMAENAB;
musb_writew(epio, MUSB_RXCSR, csr);
}
if (request->actual < request->length) {
int transfer_size = 0;
#ifdef USE_MODE1
transfer_size = min(request->length - request->actual,
channel->max_len);
#else
transfer_size = min(request->length - request->actual,
(unsigned)len);
#endif
if (transfer_size <= musb_ep->packet_sz)
musb_ep->dma->desired_mode = 0;
else
if (use_mode_1) {
transfer_size = min(request->length - request->actual,
channel->max_len);
musb_ep->dma->desired_mode = 1;
} else {
transfer_size = min(request->length - request->actual,
(unsigned)len);
musb_ep->dma->desired_mode = 0;
}
use_dma = c->channel_program(
channel,
......
/**
* dwc3-omap.h - OMAP Specific Glue layer, header.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
* All rights reserved.
*
* Author: Felipe Balbi <balbi@ti.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
enum dwc3_omap_utmi_mode {
DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
DWC3_OMAP_UTMI_MODE_HW,
DWC3_OMAP_UTMI_MODE_SW,
};
struct dwc3_omap_data {
enum dwc3_omap_utmi_mode utmi_mode;
};
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