Commit ea934651 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-ci-v4.3-rc2' of...

Merge tag 'usb-ci-v4.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-linus

Peter writes:

USB Chipidea fixes for v4.3-rc2

- Fix the stall implementation
- Fix device mode transfer at zynq platform
- other small fixes
parents 74a09391 8315b77d
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
"lsi,zevio-usb" "lsi,zevio-usb"
"qcom,ci-hdrc" "qcom,ci-hdrc"
"chipidea,usb2" "chipidea,usb2"
"xlnx,zynq-usb-2.20a"
- reg: base address and length of the registers - reg: base address and length of the registers
- interrupts: interrupt for the USB controller - interrupts: interrupt for the USB controller
......
...@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = { ...@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
{ .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
{ .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data}, { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/usb/chipidea.h> #include <linux/usb/chipidea.h>
...@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = { ...@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = {
.flags = CI_HDRC_DISABLE_STREAMING, .flags = CI_HDRC_DISABLE_STREAMING,
}; };
static struct ci_hdrc_platform_data ci_zynq_pdata = {
.capoffset = DEF_CAPOFFSET,
};
static const struct of_device_id ci_hdrc_usb2_of_match[] = {
{ .compatible = "chipidea,usb2"},
{ .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata},
{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
static int ci_hdrc_usb2_probe(struct platform_device *pdev) static int ci_hdrc_usb2_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ci_hdrc_usb2_priv *priv; struct ci_hdrc_usb2_priv *priv;
struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev); struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
int ret; int ret;
const struct of_device_id *match;
if (!ci_pdata) { if (!ci_pdata) {
ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL); ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
*ci_pdata = ci_default_pdata; /* struct copy */ *ci_pdata = ci_default_pdata; /* struct copy */
} }
match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
if (match && match->data) {
/* struct copy */
*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
...@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev) ...@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id ci_hdrc_usb2_of_match[] = {
{ .compatible = "chipidea,usb2" },
{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
static struct platform_driver ci_hdrc_usb2_driver = { static struct platform_driver ci_hdrc_usb2_driver = {
.probe = ci_hdrc_usb2_probe, .probe = ci_hdrc_usb2_probe,
.remove = ci_hdrc_usb2_remove, .remove = ci_hdrc_usb2_remove,
......
...@@ -656,6 +656,44 @@ __acquires(hwep->lock) ...@@ -656,6 +656,44 @@ __acquires(hwep->lock)
return 0; return 0;
} }
static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer)
{
struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
int direction, retval = 0;
unsigned long flags;
if (ep == NULL || hwep->ep.desc == NULL)
return -EINVAL;
if (usb_endpoint_xfer_isoc(hwep->ep.desc))
return -EOPNOTSUPP;
spin_lock_irqsave(hwep->lock, flags);
if (value && hwep->dir == TX && check_transfer &&
!list_empty(&hwep->qh.queue) &&
!usb_endpoint_xfer_control(hwep->ep.desc)) {
spin_unlock_irqrestore(hwep->lock, flags);
return -EAGAIN;
}
direction = hwep->dir;
do {
retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
if (!value)
hwep->wedge = 0;
if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
hwep->dir = (hwep->dir == TX) ? RX : TX;
} while (hwep->dir != direction);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
}
/** /**
* _gadget_stop_activity: stops all USB activity, flushes & disables all endpts * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
* @gadget: gadget * @gadget: gadget
...@@ -1051,7 +1089,7 @@ __acquires(ci->lock) ...@@ -1051,7 +1089,7 @@ __acquires(ci->lock)
num += ci->hw_ep_max / 2; num += ci->hw_ep_max / 2;
spin_unlock(&ci->lock); spin_unlock(&ci->lock);
err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false);
spin_lock(&ci->lock); spin_lock(&ci->lock);
if (!err) if (!err)
isr_setup_status_phase(ci); isr_setup_status_phase(ci);
...@@ -1117,8 +1155,8 @@ __acquires(ci->lock) ...@@ -1117,8 +1155,8 @@ __acquires(ci->lock)
if (err < 0) { if (err < 0) {
spin_unlock(&ci->lock); spin_unlock(&ci->lock);
if (usb_ep_set_halt(&hwep->ep)) if (_ep_set_halt(&hwep->ep, 1, false))
dev_err(ci->dev, "error: ep_set_halt\n"); dev_err(ci->dev, "error: _ep_set_halt\n");
spin_lock(&ci->lock); spin_lock(&ci->lock);
} }
} }
...@@ -1149,9 +1187,9 @@ __acquires(ci->lock) ...@@ -1149,9 +1187,9 @@ __acquires(ci->lock)
err = isr_setup_status_phase(ci); err = isr_setup_status_phase(ci);
if (err < 0) { if (err < 0) {
spin_unlock(&ci->lock); spin_unlock(&ci->lock);
if (usb_ep_set_halt(&hwep->ep)) if (_ep_set_halt(&hwep->ep, 1, false))
dev_err(ci->dev, dev_err(ci->dev,
"error: ep_set_halt\n"); "error: _ep_set_halt\n");
spin_lock(&ci->lock); spin_lock(&ci->lock);
} }
} }
...@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) ...@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
*/ */
static int ep_set_halt(struct usb_ep *ep, int value) static int ep_set_halt(struct usb_ep *ep, int value)
{ {
struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); return _ep_set_halt(ep, value, true);
int direction, retval = 0;
unsigned long flags;
if (ep == NULL || hwep->ep.desc == NULL)
return -EINVAL;
if (usb_endpoint_xfer_isoc(hwep->ep.desc))
return -EOPNOTSUPP;
spin_lock_irqsave(hwep->lock, flags);
#ifndef STALL_IN
/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
!list_empty(&hwep->qh.queue)) {
spin_unlock_irqrestore(hwep->lock, flags);
return -EAGAIN;
}
#endif
direction = hwep->dir;
do {
retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
if (!value)
hwep->wedge = 0;
if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
hwep->dir = (hwep->dir == TX) ? RX : TX;
} while (hwep->dir != direction);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
} }
/** /**
......
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