usb: fixes for v3.13-rc2
First set of fixes for this -rc cycle. A few important fixes which should be backported to stable kernels and the usual set of sparse warning fixes. There's also a regression fix on phy-generic.c which would prevent am335x-based platforms from having their PHY drivers probed. Signed-of-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) iQIcBAABAgAGBQJSk5HFAAoJEIaOsuA1yqRE7xoP/Rz2ZMt1BlRH3rHorQL+0mqs 2KDN7Vz+vLlt4BldLYiMpKTe7zTmV28yR+MaTHzX1RVJEXJl0/hJVPvOmOdAPAkX Y5KnjWrUNhrG6ChxUwaJslWLA8ACnV5PwdQDsSJYGKAi0jWuXE0qSJoGqX8PgJX/ gU9TK5iWHFflmkpg8M8UPx2XyMFHYfonJ6Nh2A8bYTkHqHFZp/CoCZKQqmAathKg 9Kyze3elKyA5Ch1JXf++WIViCXMkNRgWp4YNYUDj9t32mw2iLyg0czMvTNK0OqeR ICqzz4EgiSQjFq4p70kJSDXqRUGIre/JcZk7Gq3zAAUw0ScuJRQOZBmDiyu5K2vk UG+H05YZCFXqr4e+80WoIzLyaZzokOA/RI9sDPKeF3NvaxCCtf9BsEu4ugOwoBrz 9MQhHJBcvJAYbBeUy/L80btL7SoSc76mQ08+HImeDoolZMFgVcS0bUTPE0VSwW9U oDnOAe/kSCRSZPEkDp6nbKqp3OX1tvWA+1bsYslsEbPotnulYWawd4OCPhPWKc2J Uu6HBC6aDZ6DS3YH/GKkJONV3oRjaqjDwHMoTlZa3bDftPACzGgXc+r8s4iiLzya VHK5R8JK32hD/GI/5oWhJVgDQmFbp2Kk6MeSTT1AgiJ75x7Z1dWncePohdaPrMt/ Wn19N0Ype+72HhTZ3oP2 =ZzE5 -----END PGP SIGNATURE----- Merge tag 'fixes-for-v3.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: usb: fixes for v3.13-rc2 First set of fixes for this -rc cycle. A few important fixes which should be backported to stable kernels and the usual set of sparse warning fixes. There's also a regression fix on phy-generic.c which would prevent am335x-based platforms from having their PHY drivers probed. Signed-of-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
commit
c24cb6c8b5
|
@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
|
|||
dep = dwc3_wIndex_to_dep(dwc, wIndex);
|
||||
if (!dep)
|
||||
return -EINVAL;
|
||||
if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
|
||||
break;
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, set);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
|
|||
else
|
||||
dep->flags |= DWC3_EP_STALL;
|
||||
} else {
|
||||
if (dep->flags & DWC3_EP_WEDGE)
|
||||
return 0;
|
||||
|
||||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
|
||||
DWC3_DEPCMD_CLEARSTALL, ¶ms);
|
||||
if (ret)
|
||||
|
@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
|
|||
value ? "set" : "clear",
|
||||
dep->name);
|
||||
else
|
||||
dep->flags &= ~DWC3_EP_STALL;
|
||||
dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET
|
|||
config USB_CONFIGFS_MASS_STORAGE
|
||||
boolean "Mass storage"
|
||||
depends on USB_CONFIGFS
|
||||
depends on BLOCK
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
The Mass Storage Gadget acts as a USB Mass Storage disk drive.
|
||||
|
|
|
@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev)
|
|||
bitmap_zero(f->endpoints, 32);
|
||||
}
|
||||
cdev->config = NULL;
|
||||
cdev->delayed_status = 0;
|
||||
}
|
||||
|
||||
static int set_config(struct usb_composite_dev *cdev,
|
||||
|
|
|
@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void)
|
|||
{
|
||||
struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
|
||||
if (unlikely(!ffs))
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
ENTER();
|
||||
|
||||
|
|
|
@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f,
|
|||
*/
|
||||
DBG(fsg, "bulk reset request\n");
|
||||
raise_exception(fsg->common, FSG_STATE_RESET);
|
||||
return DELAYED_STATUS;
|
||||
return USB_GADGET_DELAYED_STATUS;
|
||||
|
||||
case US_BULK_GET_MAX_LUN:
|
||||
if (ctrl->bRequestType !=
|
||||
|
@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int sleep_thread(struct fsg_common *common)
|
||||
static int sleep_thread(struct fsg_common *common, bool can_freeze)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Wait until a signal arrives or we are woken up */
|
||||
for (;;) {
|
||||
try_to_freeze();
|
||||
if (can_freeze)
|
||||
try_to_freeze();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (signal_pending(current)) {
|
||||
rc = -EINTR;
|
||||
|
@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common)
|
|||
/* Wait for the next buffer to become available */
|
||||
bh = common->next_buffhd_to_fill;
|
||||
while (bh->state != BUF_STATE_EMPTY) {
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common)
|
|||
}
|
||||
|
||||
/* Wait for something to happen */
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common)
|
|||
}
|
||||
|
||||
/* Otherwise wait for something to happen */
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common)
|
|||
/* Wait for the next buffer to become available */
|
||||
bh = common->next_buffhd_to_fill;
|
||||
while (bh->state != BUF_STATE_EMPTY) {
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common)
|
|||
bh = common->next_buffhd_to_fill;
|
||||
common->next_buffhd_to_drain = bh;
|
||||
while (bh->state != BUF_STATE_EMPTY) {
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common)
|
|||
/* Wait for the next buffer to become available */
|
||||
bh = common->next_buffhd_to_fill;
|
||||
while (bh->state != BUF_STATE_EMPTY) {
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common)
|
|||
|
||||
/* Wait for the CBW to arrive */
|
||||
while (bh->state != BUF_STATE_FULL) {
|
||||
rc = sleep_thread(common);
|
||||
rc = sleep_thread(common, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common)
|
|||
}
|
||||
if (num_active == 0)
|
||||
break;
|
||||
if (sleep_thread(common))
|
||||
if (sleep_thread(common, true))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_)
|
|||
}
|
||||
|
||||
if (!common->running) {
|
||||
sleep_thread(common);
|
||||
sleep_thread(common, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
fsg->common->can_stall);
|
||||
if (ret)
|
||||
return ret;
|
||||
fsg_common_set_inquiry_string(fsg->common, 0, 0);
|
||||
fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
|
||||
ret = fsg_common_run_thread(fsg->common);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
*/
|
||||
#ifdef CONFIG_ARCH_PXA
|
||||
#include <mach/pxa25x-udc.h>
|
||||
#include <mach/hardware.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_LUBBOCK
|
||||
|
|
|
@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
|
|||
}
|
||||
|
||||
static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
|
||||
static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
|
||||
|
||||
/**
|
||||
* s3c_hsotg_process_control - process a control request
|
||||
|
@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
|
|||
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
|
||||
switch (ctrl->bRequest) {
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
s3c_hsotg_disconnect(hsotg);
|
||||
dcfg = readl(hsotg->regs + DCFG);
|
||||
dcfg &= ~DCFG_DevAddr_MASK;
|
||||
dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
|
||||
|
@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
|
|||
/* as a fallback, try delivering it to the driver to deal with */
|
||||
|
||||
if (ret == 0 && hsotg->driver) {
|
||||
spin_unlock(&hsotg->lock);
|
||||
ret = hsotg->driver->setup(&hsotg->gadget, ctrl);
|
||||
spin_lock(&hsotg->lock);
|
||||
if (ret < 0)
|
||||
dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
|
||||
}
|
||||
|
@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock(&hsotg->lock);
|
||||
if (req->actual == 0)
|
||||
s3c_hsotg_enqueue_setup(hsotg);
|
||||
else
|
||||
s3c_hsotg_process_control(hsotg, req->buf);
|
||||
spin_unlock(&hsotg->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2533,7 +2539,6 @@ irq_retry:
|
|||
writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
|
||||
|
||||
call_gadget(hsotg, suspend);
|
||||
s3c_hsotg_disconnect(hsotg);
|
||||
}
|
||||
|
||||
if (gintsts & GINTSTS_WkUpInt) {
|
||||
|
|
|
@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
|
|||
return curlun->filp != NULL;
|
||||
}
|
||||
|
||||
/* Big enough to hold our biggest descriptor */
|
||||
#define EP0_BUFSIZE 256
|
||||
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
|
||||
|
||||
/* Default size of buffer length. */
|
||||
#define FSG_BUFLEN ((u32)16384)
|
||||
|
||||
|
|
|
@ -370,7 +370,7 @@ err:
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void bot_cleanup_old_alt(struct f_uas *fu)
|
||||
static void bot_cleanup_old_alt(struct f_uas *fu)
|
||||
{
|
||||
if (!(fu->flags & USBG_ENABLED))
|
||||
return;
|
||||
|
|
|
@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = {
|
|||
* functional coverage for the "USBCV" test harness from USB-IF.
|
||||
* It's always set if OTG mode is enabled.
|
||||
*/
|
||||
unsigned autoresume = DEFAULT_AUTORESUME;
|
||||
static unsigned autoresume = DEFAULT_AUTORESUME;
|
||||
module_param(autoresume, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
|
||||
|
||||
/* Maximum Autoresume time */
|
||||
unsigned max_autoresume;
|
||||
static unsigned max_autoresume;
|
||||
module_param(max_autoresume, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup");
|
||||
|
||||
/* Interval between two remote wakeups */
|
||||
unsigned autoresume_interval_ms;
|
||||
static unsigned autoresume_interval_ms;
|
||||
module_param(autoresume_interval_ms, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(autoresume_interval_ms,
|
||||
"milliseconds to increase successive wakeup delays");
|
||||
|
|
|
@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb)
|
|||
disable_irq_wake(musb->nIrq);
|
||||
free_irq(musb->nIrq, musb);
|
||||
}
|
||||
cancel_work_sync(&musb->irq_work);
|
||||
|
||||
musb_host_free(musb);
|
||||
}
|
||||
|
@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||
musb_platform_disable(musb);
|
||||
musb_generic_disable(musb);
|
||||
|
||||
/* Init IRQ workqueue before request_irq */
|
||||
INIT_WORK(&musb->irq_work, musb_irq_work);
|
||||
|
||||
/* setup musb parts of the core (especially endpoints) */
|
||||
status = musb_core_init(plat->config->multipoint
|
||||
? MUSB_CONTROLLER_MHDRC
|
||||
|
@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||
|
||||
setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
|
||||
|
||||
/* Init IRQ workqueue before request_irq */
|
||||
INIT_WORK(&musb->irq_work, musb_irq_work);
|
||||
|
||||
/* attach to the IRQ */
|
||||
if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
|
||||
dev_err(dev, "request_irq %d failed!\n", nIrq);
|
||||
|
@ -1981,6 +1980,7 @@ fail4:
|
|||
musb_host_cleanup(musb);
|
||||
|
||||
fail3:
|
||||
cancel_work_sync(&musb->irq_work);
|
||||
if (musb->dma_controller)
|
||||
dma_controller_destroy(musb->dma_controller);
|
||||
fail2_5:
|
||||
|
@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev)
|
|||
if (musb->dma_controller)
|
||||
dma_controller_destroy(musb->dma_controller);
|
||||
|
||||
cancel_work_sync(&musb->irq_work);
|
||||
musb_free(musb);
|
||||
device_init_wakeup(dev, 0);
|
||||
return 0;
|
||||
|
|
|
@ -38,6 +38,7 @@ struct cppi41_dma_channel {
|
|||
u32 prog_len;
|
||||
u32 transferred;
|
||||
u32 packet_sz;
|
||||
struct list_head tx_check;
|
||||
};
|
||||
|
||||
#define MUSB_DMA_NUM_CHANNELS 15
|
||||
|
@ -47,6 +48,8 @@ struct cppi41_dma_controller {
|
|||
struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
|
||||
struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
|
||||
struct musb *musb;
|
||||
struct hrtimer early_tx;
|
||||
struct list_head early_tx_list;
|
||||
u32 rx_mode;
|
||||
u32 tx_mode;
|
||||
u32 auto_req;
|
||||
|
@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
|
|||
cppi41_channel->usb_toggle = toggle;
|
||||
}
|
||||
|
||||
static void cppi41_dma_callback(void *private_data)
|
||||
static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
|
||||
{
|
||||
u8 epnum = hw_ep->epnum;
|
||||
struct musb *musb = hw_ep->musb;
|
||||
void __iomem *epio = musb->endpoints[epnum].regs;
|
||||
u16 csr;
|
||||
|
||||
csr = musb_readw(epio, MUSB_TXCSR);
|
||||
if (csr & MUSB_TXCSR_TXPKTRDY)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cppi41_dma_callback(void *private_data);
|
||||
|
||||
static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
|
||||
{
|
||||
struct dma_channel *channel = private_data;
|
||||
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
|
||||
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
|
||||
struct musb *musb = hw_ep->musb;
|
||||
unsigned long flags;
|
||||
struct dma_tx_state txstate;
|
||||
u32 transferred;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
|
||||
&txstate);
|
||||
transferred = cppi41_channel->prog_len - txstate.residue;
|
||||
cppi41_channel->transferred += transferred;
|
||||
|
||||
dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
|
||||
hw_ep->epnum, cppi41_channel->transferred,
|
||||
cppi41_channel->total_len);
|
||||
|
||||
update_rx_toggle(cppi41_channel);
|
||||
|
||||
if (cppi41_channel->transferred == cppi41_channel->total_len ||
|
||||
transferred < cppi41_channel->packet_sz) {
|
||||
if (!cppi41_channel->prog_len) {
|
||||
|
||||
/* done, complete */
|
||||
cppi41_channel->channel.actual_len =
|
||||
|
@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data)
|
|||
remain_bytes,
|
||||
direction,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (WARN_ON(!dma_desc)) {
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
if (WARN_ON(!dma_desc))
|
||||
return;
|
||||
}
|
||||
|
||||
dma_desc->callback = cppi41_dma_callback;
|
||||
dma_desc->callback_param = channel;
|
||||
dma_desc->callback_param = &cppi41_channel->channel;
|
||||
cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
|
||||
dma_async_issue_pending(dc);
|
||||
|
||||
|
@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data)
|
|||
musb_writew(epio, MUSB_RXCSR, csr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
|
||||
{
|
||||
struct cppi41_dma_controller *controller;
|
||||
struct cppi41_dma_channel *cppi41_channel, *n;
|
||||
struct musb *musb;
|
||||
unsigned long flags;
|
||||
enum hrtimer_restart ret = HRTIMER_NORESTART;
|
||||
|
||||
controller = container_of(timer, struct cppi41_dma_controller,
|
||||
early_tx);
|
||||
musb = controller->musb;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list,
|
||||
tx_check) {
|
||||
bool empty;
|
||||
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
|
||||
|
||||
empty = musb_is_tx_fifo_empty(hw_ep);
|
||||
if (empty) {
|
||||
list_del_init(&cppi41_channel->tx_check);
|
||||
cppi41_trans_done(cppi41_channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&controller->early_tx_list)) {
|
||||
ret = HRTIMER_RESTART;
|
||||
hrtimer_forward_now(&controller->early_tx,
|
||||
ktime_set(0, 150 * NSEC_PER_USEC));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cppi41_dma_callback(void *private_data)
|
||||
{
|
||||
struct dma_channel *channel = private_data;
|
||||
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
|
||||
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
|
||||
struct musb *musb = hw_ep->musb;
|
||||
unsigned long flags;
|
||||
struct dma_tx_state txstate;
|
||||
u32 transferred;
|
||||
bool empty;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
|
||||
&txstate);
|
||||
transferred = cppi41_channel->prog_len - txstate.residue;
|
||||
cppi41_channel->transferred += transferred;
|
||||
|
||||
dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
|
||||
hw_ep->epnum, cppi41_channel->transferred,
|
||||
cppi41_channel->total_len);
|
||||
|
||||
update_rx_toggle(cppi41_channel);
|
||||
|
||||
if (cppi41_channel->transferred == cppi41_channel->total_len ||
|
||||
transferred < cppi41_channel->packet_sz)
|
||||
cppi41_channel->prog_len = 0;
|
||||
|
||||
empty = musb_is_tx_fifo_empty(hw_ep);
|
||||
if (empty) {
|
||||
cppi41_trans_done(cppi41_channel);
|
||||
} else {
|
||||
struct cppi41_dma_controller *controller;
|
||||
/*
|
||||
* On AM335x it has been observed that the TX interrupt fires
|
||||
* too early that means the TXFIFO is not yet empty but the DMA
|
||||
* engine says that it is done with the transfer. We don't
|
||||
* receive a FIFO empty interrupt so the only thing we can do is
|
||||
* to poll for the bit. On HS it usually takes 2us, on FS around
|
||||
* 110us - 150us depending on the transfer size.
|
||||
* We spin on HS (no longer than than 25us and setup a timer on
|
||||
* FS to check for the bit and complete the transfer.
|
||||
*/
|
||||
controller = cppi41_channel->controller;
|
||||
|
||||
if (musb->g.speed == USB_SPEED_HIGH) {
|
||||
unsigned wait = 25;
|
||||
|
||||
do {
|
||||
empty = musb_is_tx_fifo_empty(hw_ep);
|
||||
if (empty)
|
||||
break;
|
||||
wait--;
|
||||
if (!wait)
|
||||
break;
|
||||
udelay(1);
|
||||
} while (1);
|
||||
|
||||
empty = musb_is_tx_fifo_empty(hw_ep);
|
||||
if (empty) {
|
||||
cppi41_trans_done(cppi41_channel);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
list_add_tail(&cppi41_channel->tx_check,
|
||||
&controller->early_tx_list);
|
||||
if (!hrtimer_active(&controller->early_tx)) {
|
||||
hrtimer_start_range_ns(&controller->early_tx,
|
||||
ktime_set(0, 140 * NSEC_PER_USEC),
|
||||
40 * NSEC_PER_USEC,
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
out:
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
|
|||
WARN_ON(1);
|
||||
return 1;
|
||||
}
|
||||
if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK)
|
||||
return 0;
|
||||
if (cppi41_channel->is_tx)
|
||||
return 1;
|
||||
/* AM335x Advisory 1.0.13. No workaround for device RX mode */
|
||||
|
@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
|
|||
if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
|
||||
return 0;
|
||||
|
||||
list_del_init(&cppi41_channel->tx_check);
|
||||
if (is_tx) {
|
||||
csr = musb_readw(epio, MUSB_TXCSR);
|
||||
csr &= ~MUSB_TXCSR_DMAENAB;
|
||||
|
@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
|
|||
cppi41_channel->controller = controller;
|
||||
cppi41_channel->port_num = port;
|
||||
cppi41_channel->is_tx = is_tx;
|
||||
INIT_LIST_HEAD(&cppi41_channel->tx_check);
|
||||
|
||||
musb_dma = &cppi41_channel->channel;
|
||||
musb_dma->private_data = cppi41_channel;
|
||||
|
@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c)
|
|||
struct cppi41_dma_controller *controller = container_of(c,
|
||||
struct cppi41_dma_controller, controller);
|
||||
|
||||
hrtimer_cancel(&controller->early_tx);
|
||||
cppi41_dma_controller_stop(controller);
|
||||
kfree(controller);
|
||||
}
|
||||
|
@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb,
|
|||
if (!controller)
|
||||
goto kzalloc_fail;
|
||||
|
||||
hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
controller->early_tx.function = cppi41_recheck_tx_req;
|
||||
INIT_LIST_HEAD(&controller->early_tx_list);
|
||||
controller->musb = musb;
|
||||
|
||||
controller->controller.channel_alloc = cppi41_dma_channel_allocate;
|
||||
|
|
|
@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb)
|
|||
|
||||
/* this "gadget" abstracts/virtualizes the controller */
|
||||
musb->g.name = musb_driver_name;
|
||||
#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE)
|
||||
musb->g.is_otg = 1;
|
||||
#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET)
|
||||
musb->g.is_otg = 0;
|
||||
#endif
|
||||
|
||||
musb_g_init_endpoints(musb);
|
||||
|
||||
|
|
|
@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
|
|||
return am_phy->id;
|
||||
}
|
||||
|
||||
ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
|
||||
USB_PHY_TYPE_USB2, 0, false);
|
||||
ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, am_phy);
|
||||
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int am335x_phy_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void)
|
|||
if (pd)
|
||||
return;
|
||||
pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
|
||||
if (!pd) {
|
||||
if (IS_ERR(pd)) {
|
||||
pr_err("Unable to register generic usb transceiver\n");
|
||||
pd = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
|
|||
}
|
||||
|
||||
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
|
||||
enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
|
||||
struct usb_phy_gen_xceiv_platform_data *pdata)
|
||||
{
|
||||
enum usb_phy_type type = USB_PHY_TYPE_USB2;
|
||||
int err;
|
||||
|
||||
u32 clk_rate = 0;
|
||||
bool needs_vcc = false;
|
||||
|
||||
nop->reset_active_low = true; /* default behaviour */
|
||||
|
||||
if (dev->of_node) {
|
||||
struct device_node *node = dev->of_node;
|
||||
enum of_gpio_flags flags = 0;
|
||||
|
||||
if (of_property_read_u32(node, "clock-frequency", &clk_rate))
|
||||
clk_rate = 0;
|
||||
|
||||
needs_vcc = of_property_read_bool(node, "vcc-supply");
|
||||
nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
|
||||
0, &flags);
|
||||
if (nop->gpio_reset == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
|
||||
|
||||
} else if (pdata) {
|
||||
type = pdata->type;
|
||||
clk_rate = pdata->clk_rate;
|
||||
needs_vcc = pdata->needs_vcc;
|
||||
nop->gpio_reset = pdata->gpio_reset;
|
||||
} else {
|
||||
nop->gpio_reset = -1;
|
||||
}
|
||||
|
||||
nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
|
||||
GFP_KERNEL);
|
||||
if (!nop->phy.otg)
|
||||
|
@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
|
|||
static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct usb_phy_gen_xceiv_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct usb_phy_gen_xceiv *nop;
|
||||
enum usb_phy_type type = USB_PHY_TYPE_USB2;
|
||||
int err;
|
||||
u32 clk_rate = 0;
|
||||
bool needs_vcc = false;
|
||||
|
||||
nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
|
||||
if (!nop)
|
||||
return -ENOMEM;
|
||||
|
||||
nop->reset_active_low = true; /* default behaviour */
|
||||
|
||||
if (dev->of_node) {
|
||||
struct device_node *node = dev->of_node;
|
||||
enum of_gpio_flags flags;
|
||||
|
||||
if (of_property_read_u32(node, "clock-frequency", &clk_rate))
|
||||
clk_rate = 0;
|
||||
|
||||
needs_vcc = of_property_read_bool(node, "vcc-supply");
|
||||
nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
|
||||
0, &flags);
|
||||
if (nop->gpio_reset == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
|
||||
|
||||
} else if (pdata) {
|
||||
type = pdata->type;
|
||||
clk_rate = pdata->clk_rate;
|
||||
needs_vcc = pdata->needs_vcc;
|
||||
nop->gpio_reset = pdata->gpio_reset;
|
||||
}
|
||||
|
||||
err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
|
||||
err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, nop);
|
||||
|
||||
return 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _PHY_GENERIC_H_
|
||||
#define _PHY_GENERIC_H_
|
||||
|
||||
#include <linux/usb/usb_phy_gen_xceiv.h>
|
||||
|
||||
struct usb_phy_gen_xceiv {
|
||||
struct usb_phy phy;
|
||||
struct device *dev;
|
||||
|
@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy);
|
|||
void usb_gen_phy_shutdown(struct usb_phy *phy);
|
||||
|
||||
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
|
||||
enum usb_phy_type type, u32 clk_rate, bool needs_vcc);
|
||||
struct usb_phy_gen_xceiv_platform_data *pdata);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
|
|||
|
||||
mxs_phy->clk = clk;
|
||||
|
||||
platform_set_drvdata(pdev, &mxs_phy->phy);
|
||||
platform_set_drvdata(pdev, mxs_phy);
|
||||
|
||||
ret = usb_add_phy_dev(&mxs_phy->phy);
|
||||
if (ret)
|
||||
|
|
|
@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv)
|
|||
clk_prepare_enable(priv->clk);
|
||||
|
||||
/* Set USB channels in the USBHS UGCTRL2 register */
|
||||
val = ioread32(priv->base);
|
||||
val = ioread32(priv->base + USBHS_UGCTRL2_REG);
|
||||
val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS);
|
||||
val |= priv->ugctrl2;
|
||||
iowrite32(val, priv->base);
|
||||
iowrite32(val, priv->base + USBHS_UGCTRL2_REG);
|
||||
}
|
||||
|
||||
/* Shutdown USB channels */
|
||||
|
|
Loading…
Reference in New Issue