aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMian Yousaf Kaukab <yousaf.kaukab@intel.com>2015-05-16 16:33:36 -0400
committerFelipe Balbi <balbi@ti.com>2015-05-26 11:40:16 -0400
commitc65c4f052bc3b67989bf54914798513685c54988 (patch)
treecaa96a137633bb213c7c5a30d51181557a9ae25d
parenta09e23f53e2c14a65a3b14a00060fea163081e1f (diff)
usb: gadget: net2280: fix use of GPEP in both directions
USB3380 enhanced mode allows GPEP to be used in both IN and OUT directions. However, IN and OUT endpoints must use same USB endpoint address (bEndpointAddress). Fix this by setting the ep_cfg.ep_number during initialization and keep it in net2280_enable() Tested-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/gadget/udc/net2280.c41
-rw-r--r--include/linux/usb/usb338x.h4
2 files changed, 36 insertions, 9 deletions
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index a78a9c048b87..779e6fe0005f 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -144,7 +144,9 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
144{ 144{
145 struct net2280 *dev; 145 struct net2280 *dev;
146 struct net2280_ep *ep; 146 struct net2280_ep *ep;
147 u32 max, tmp; 147 u32 max;
148 u32 tmp = 0;
149 u32 type;
148 unsigned long flags; 150 unsigned long flags;
149 static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 }; 151 static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
150 int ret = 0; 152 int ret = 0;
@@ -200,15 +202,29 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
200 202
201 /* set type, direction, address; reset fifo counters */ 203 /* set type, direction, address; reset fifo counters */
202 writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat); 204 writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
203 tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); 205
204 if (tmp == USB_ENDPOINT_XFER_INT) { 206 if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
207 tmp = readl(&ep->cfg->ep_cfg);
208 /* If USB ep number doesn't match hardware ep number */
209 if ((tmp & 0xf) != usb_endpoint_num(desc)) {
210 ret = -EINVAL;
211 spin_unlock_irqrestore(&dev->lock, flags);
212 goto print_err;
213 }
214 if (ep->is_in)
215 tmp &= ~USB3380_EP_CFG_MASK_IN;
216 else
217 tmp &= ~USB3380_EP_CFG_MASK_OUT;
218 }
219 type = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
220 if (type == USB_ENDPOINT_XFER_INT) {
205 /* erratum 0105 workaround prevents hs NYET */ 221 /* erratum 0105 workaround prevents hs NYET */
206 if (dev->chiprev == 0100 && 222 if (dev->chiprev == 0100 &&
207 dev->gadget.speed == USB_SPEED_HIGH && 223 dev->gadget.speed == USB_SPEED_HIGH &&
208 !(desc->bEndpointAddress & USB_DIR_IN)) 224 !(desc->bEndpointAddress & USB_DIR_IN))
209 writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE), 225 writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
210 &ep->regs->ep_rsp); 226 &ep->regs->ep_rsp);
211 } else if (tmp == USB_ENDPOINT_XFER_BULK) { 227 } else if (type == USB_ENDPOINT_XFER_BULK) {
212 /* catch some particularly blatant driver bugs */ 228 /* catch some particularly blatant driver bugs */
213 if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) || 229 if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
214 (dev->gadget.speed == USB_SPEED_HIGH && max != 512) || 230 (dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
@@ -218,10 +234,10 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
218 goto print_err; 234 goto print_err;
219 } 235 }
220 } 236 }
221 ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC); 237 ep->is_iso = (type == USB_ENDPOINT_XFER_ISOC);
222 /* Enable this endpoint */ 238 /* Enable this endpoint */
223 if (dev->quirks & PLX_LEGACY) { 239 if (dev->quirks & PLX_LEGACY) {
224 tmp <<= ENDPOINT_TYPE; 240 tmp |= type << ENDPOINT_TYPE;
225 tmp |= desc->bEndpointAddress; 241 tmp |= desc->bEndpointAddress;
226 /* default full fifo lines */ 242 /* default full fifo lines */
227 tmp |= (4 << ENDPOINT_BYTE_COUNT); 243 tmp |= (4 << ENDPOINT_BYTE_COUNT);
@@ -230,16 +246,17 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
230 } else { 246 } else {
231 /* In Legacy mode, only OUT endpoints are used */ 247 /* In Legacy mode, only OUT endpoints are used */
232 if (dev->enhanced_mode && ep->is_in) { 248 if (dev->enhanced_mode && ep->is_in) {
233 tmp <<= IN_ENDPOINT_TYPE; 249 tmp |= type << IN_ENDPOINT_TYPE;
234 tmp |= BIT(IN_ENDPOINT_ENABLE); 250 tmp |= BIT(IN_ENDPOINT_ENABLE);
235 } else { 251 } else {
236 tmp <<= OUT_ENDPOINT_TYPE; 252 tmp |= type << OUT_ENDPOINT_TYPE;
237 tmp |= BIT(OUT_ENDPOINT_ENABLE); 253 tmp |= BIT(OUT_ENDPOINT_ENABLE);
238 tmp |= (ep->is_in << ENDPOINT_DIRECTION); 254 tmp |= (ep->is_in << ENDPOINT_DIRECTION);
239 } 255 }
240 256
241 tmp |= (4 << ENDPOINT_BYTE_COUNT); 257 tmp |= (4 << ENDPOINT_BYTE_COUNT);
242 tmp |= usb_endpoint_num(desc); 258 if (!dev->enhanced_mode)
259 tmp |= usb_endpoint_num(desc);
243 tmp |= (ep->ep.maxburst << MAX_BURST_SIZE); 260 tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
244 } 261 }
245 262
@@ -2074,6 +2091,12 @@ static void usb_reinit_338x(struct net2280 *dev)
2074 2091
2075 if (dev->enhanced_mode) { 2092 if (dev->enhanced_mode) {
2076 ep->cfg = &dev->epregs[ne[i]]; 2093 ep->cfg = &dev->epregs[ne[i]];
2094 /*
2095 * Set USB endpoint number, hardware allows same number
2096 * in both directions.
2097 */
2098 if (i > 0 && i < 5)
2099 writel(ne[i], &ep->cfg->ep_cfg);
2077 ep->regs = (struct net2280_ep_regs __iomem *) 2100 ep->regs = (struct net2280_ep_regs __iomem *)
2078 (((void __iomem *)&dev->epregs[ne[i]]) + 2101 (((void __iomem *)&dev->epregs[ne[i]]) +
2079 ep_reg_addr[i]); 2102 ep_reg_addr[i]);
diff --git a/include/linux/usb/usb338x.h b/include/linux/usb/usb338x.h
index f92eb635b9d3..11525d8d89a7 100644
--- a/include/linux/usb/usb338x.h
+++ b/include/linux/usb/usb338x.h
@@ -43,6 +43,10 @@
43#define IN_ENDPOINT_TYPE 12 43#define IN_ENDPOINT_TYPE 12
44#define OUT_ENDPOINT_ENABLE 10 44#define OUT_ENDPOINT_ENABLE 10
45#define OUT_ENDPOINT_TYPE 8 45#define OUT_ENDPOINT_TYPE 8
46#define USB3380_EP_CFG_MASK_IN ((0x3 << IN_ENDPOINT_TYPE) | \
47 BIT(IN_ENDPOINT_ENABLE))
48#define USB3380_EP_CFG_MASK_OUT ((0x3 << OUT_ENDPOINT_TYPE) | \
49 BIT(OUT_ENDPOINT_ENABLE))
46 50
47struct usb338x_usb_ext_regs { 51struct usb338x_usb_ext_regs {
48 u32 usbclass; 52 u32 usbclass;