usb: dwc3: allocate gadget structure dynamically

The current code uses commit fac323471d ("usb: udc: allow adding
and removing the same gadget device") as the workaround to let
the gadget device is re-used, but it is not allowed from driver
core point. In this commit, we allocate gadget structure dynamically,
and free it at its release function. Since the gadget device's
driver_data has already occupied by usb_composite_dev structure, we have
to use gadget device's platform data to store dwc3 structure.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
This commit is contained in:
Peter Chen 2020-08-21 10:55:48 +08:00 committed by Felipe Balbi
parent 6b7778924c
commit e81a7018d9
4 changed files with 79 additions and 61 deletions

View file

@ -1080,7 +1080,7 @@ struct dwc3 {
struct dwc3_event_buffer *ev_buf; struct dwc3_event_buffer *ev_buf;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
struct usb_gadget gadget; struct usb_gadget *gadget;
struct usb_gadget_driver *gadget_driver; struct usb_gadget_driver *gadget_driver;
struct clk_bulk_data *clks; struct clk_bulk_data *clks;

View file

@ -131,7 +131,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
direction = !dwc->ep0_expect_in; direction = !dwc->ep0_expect_in;
dwc->delayed_status = false; dwc->delayed_status = false;
usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); usb_gadget_set_state(dwc->gadget, USB_STATE_CONFIGURED);
if (dwc->ep0state == EP0_STATUS_PHASE) if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@ -325,7 +325,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
/* /*
* LTM will be set once we know how to set this in HW. * LTM will be set once we know how to set this in HW.
*/ */
usb_status |= dwc->gadget.is_selfpowered; usb_status |= dwc->gadget->is_selfpowered;
if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
(dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
@ -450,7 +450,7 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
wValue = le16_to_cpu(ctrl->wValue); wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex); wIndex = le16_to_cpu(ctrl->wIndex);
state = dwc->gadget.state; state = dwc->gadget->state;
switch (wValue) { switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP: case USB_DEVICE_REMOTE_WAKEUP:
@ -564,7 +564,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
enum usb_device_state state = dwc->gadget.state; enum usb_device_state state = dwc->gadget->state;
u32 addr; u32 addr;
u32 reg; u32 reg;
@ -585,9 +585,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr) if (addr)
usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS);
else else
usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); usb_gadget_set_state(dwc->gadget, USB_STATE_DEFAULT);
return 0; return 0;
} }
@ -597,14 +597,14 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
int ret; int ret;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
return ret; return ret;
} }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
enum usb_device_state state = dwc->gadget.state; enum usb_device_state state = dwc->gadget->state;
u32 cfg; u32 cfg;
int ret; int ret;
u32 reg; u32 reg;
@ -627,7 +627,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
* to change the state on the next usb_ep_queue() * to change the state on the next usb_ep_queue()
*/ */
if (ret == 0) if (ret == 0)
usb_gadget_set_state(&dwc->gadget, usb_gadget_set_state(dwc->gadget,
USB_STATE_CONFIGURED); USB_STATE_CONFIGURED);
/* /*
@ -646,7 +646,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
case USB_STATE_CONFIGURED: case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl); ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg && !ret) if (!cfg && !ret)
usb_gadget_set_state(&dwc->gadget, usb_gadget_set_state(dwc->gadget,
USB_STATE_ADDRESS); USB_STATE_ADDRESS);
break; break;
default: default:
@ -702,7 +702,7 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
struct dwc3_ep *dep; struct dwc3_ep *dep;
enum usb_device_state state = dwc->gadget.state; enum usb_device_state state = dwc->gadget->state;
u16 wLength; u16 wLength;
if (state == USB_STATE_DEFAULT) if (state == USB_STATE_DEFAULT)
@ -746,7 +746,7 @@ static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ct
if (wIndex || wLength) if (wIndex || wLength)
return -EINVAL; return -EINVAL;
dwc->gadget.isoch_delay = wValue; dwc->gadget->isoch_delay = wValue;
return 0; return 0;
} }
@ -1118,7 +1118,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
*/ */
if (!list_empty(&dep->pending_list)) { if (!list_empty(&dep->pending_list)) {
dwc->delayed_status = false; dwc->delayed_status = false;
usb_gadget_set_state(&dwc->gadget, usb_gadget_set_state(dwc->gadget,
USB_STATE_CONFIGURED); USB_STATE_CONFIGURED);
dwc3_ep0_do_control_status(dwc, event); dwc3_ep0_do_control_status(dwc, event);
} }

View file

@ -291,7 +291,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
* *
* DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2 * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2
*/ */
if (dwc->gadget.speed <= USB_SPEED_HIGH) { if (dwc->gadget->speed <= USB_SPEED_HIGH) {
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) {
saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
@ -423,7 +423,7 @@ static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep)
*/ */
if (dep->direction && if (dep->direction &&
!DWC3_VER_IS_PRIOR(DWC3, 260A) && !DWC3_VER_IS_PRIOR(DWC3, 260A) &&
(dwc->gadget.speed >= USB_SPEED_SUPER)) (dwc->gadget->speed >= USB_SPEED_SUPER))
cmd |= DWC3_DEPCMD_CLEARPENDIN; cmd |= DWC3_DEPCMD_CLEARPENDIN;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
@ -563,7 +563,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action)
| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
/* Burst size is only needed in SuperSpeed mode */ /* Burst size is only needed in SuperSpeed mode */
if (dwc->gadget.speed >= USB_SPEED_SUPER) { if (dwc->gadget->speed >= USB_SPEED_SUPER) {
u32 burst = dep->endpoint.maxburst; u32 burst = dep->endpoint.maxburst;
params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1);
@ -950,7 +950,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
unsigned int is_last) unsigned int is_last)
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
struct usb_gadget *gadget = &dwc->gadget; struct usb_gadget *gadget = dwc->gadget;
enum usb_device_speed speed = gadget->speed; enum usb_device_speed speed = gadget->speed;
trb->size = DWC3_TRB_SIZE_LENGTH(length); trb->size = DWC3_TRB_SIZE_LENGTH(length);
@ -1542,12 +1542,12 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
if (!dwc->dis_start_transfer_quirk && if (!dwc->dis_start_transfer_quirk &&
(DWC3_VER_IS_PRIOR(DWC31, 170A) || (DWC3_VER_IS_PRIOR(DWC31, 170A) ||
DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) { DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) {
if (dwc->gadget.speed <= USB_SPEED_HIGH && dep->direction) if (dwc->gadget->speed <= USB_SPEED_HIGH && dep->direction)
return dwc3_gadget_start_isoc_quirk(dep); return dwc3_gadget_start_isoc_quirk(dep);
} }
if (desc->bInterval <= 14 && if (desc->bInterval <= 14 &&
dwc->gadget.speed >= USB_SPEED_HIGH) { dwc->gadget->speed >= USB_SPEED_HIGH) {
u32 frame = __dwc3_gadget_get_frame(dwc); u32 frame = __dwc3_gadget_get_frame(dwc);
bool rollover = frame < bool rollover = frame <
(dep->frame_number & DWC3_FRNUMBER_MASK); (dep->frame_number & DWC3_FRNUMBER_MASK);
@ -2256,7 +2256,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
if (dwc->gadget_driver) { if (dwc->gadget_driver) {
dev_err(dwc->dev, "%s is already bound to %s\n", dev_err(dwc->dev, "%s is already bound to %s\n",
dwc->gadget.name, dwc->gadget->name,
dwc->gadget_driver->driver.name); dwc->gadget_driver->driver.name);
ret = -EBUSY; ret = -EBUSY;
goto err1; goto err1;
@ -2428,7 +2428,7 @@ static int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep)
dep->endpoint.maxburst = 1; dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops; dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!dep->direction) if (!dep->direction)
dwc->gadget.ep0 = &dep->endpoint; dwc->gadget->ep0 = &dep->endpoint;
dep->endpoint.caps.type_control = true; dep->endpoint.caps.type_control = true;
@ -2474,7 +2474,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
dep->endpoint.max_streams = 15; dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops; dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list, list_add_tail(&dep->endpoint.ep_list,
&dwc->gadget.ep_list); &dwc->gadget->ep_list);
dep->endpoint.caps.type_iso = true; dep->endpoint.caps.type_iso = true;
dep->endpoint.caps.type_bulk = true; dep->endpoint.caps.type_bulk = true;
dep->endpoint.caps.type_int = true; dep->endpoint.caps.type_int = true;
@ -2523,7 +2523,7 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
dep->endpoint.max_streams = 15; dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops; dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list, list_add_tail(&dep->endpoint.ep_list,
&dwc->gadget.ep_list); &dwc->gadget->ep_list);
dep->endpoint.caps.type_iso = true; dep->endpoint.caps.type_iso = true;
dep->endpoint.caps.type_bulk = true; dep->endpoint.caps.type_bulk = true;
dep->endpoint.caps.type_int = true; dep->endpoint.caps.type_int = true;
@ -2584,7 +2584,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total)
{ {
u8 epnum; u8 epnum;
INIT_LIST_HEAD(&dwc->gadget.ep_list); INIT_LIST_HEAD(&dwc->gadget->ep_list);
for (epnum = 0; epnum < total; epnum++) { for (epnum = 0; epnum < total; epnum++) {
int ret; int ret;
@ -3051,7 +3051,7 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)
{ {
if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dwc->gadget_driver->disconnect(&dwc->gadget); dwc->gadget_driver->disconnect(dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
@ -3060,7 +3060,7 @@ static void dwc3_suspend_gadget(struct dwc3 *dwc)
{ {
if (dwc->gadget_driver && dwc->gadget_driver->suspend) { if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dwc->gadget_driver->suspend(&dwc->gadget); dwc->gadget_driver->suspend(dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
@ -3069,7 +3069,7 @@ static void dwc3_resume_gadget(struct dwc3 *dwc)
{ {
if (dwc->gadget_driver && dwc->gadget_driver->resume) { if (dwc->gadget_driver && dwc->gadget_driver->resume) {
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dwc->gadget_driver->resume(&dwc->gadget); dwc->gadget_driver->resume(dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
@ -3079,9 +3079,9 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
if (!dwc->gadget_driver) if (!dwc->gadget_driver)
return; return;
if (dwc->gadget.speed != USB_SPEED_UNKNOWN) { if (dwc->gadget->speed != USB_SPEED_UNKNOWN) {
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver); usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
@ -3182,9 +3182,9 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
dwc3_disconnect_gadget(dwc); dwc3_disconnect_gadget(dwc);
dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget->speed = USB_SPEED_UNKNOWN;
dwc->setup_packet_pending = false; dwc->setup_packet_pending = false;
usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED); usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED);
dwc->connected = false; dwc->connected = false;
} }
@ -3263,8 +3263,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
switch (speed) { switch (speed) {
case DWC3_DSTS_SUPERSPEED_PLUS: case DWC3_DSTS_SUPERSPEED_PLUS:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
dwc->gadget.ep0->maxpacket = 512; dwc->gadget->ep0->maxpacket = 512;
dwc->gadget.speed = USB_SPEED_SUPER_PLUS; dwc->gadget->speed = USB_SPEED_SUPER_PLUS;
break; break;
case DWC3_DSTS_SUPERSPEED: case DWC3_DSTS_SUPERSPEED:
/* /*
@ -3284,27 +3284,27 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
dwc3_gadget_reset_interrupt(dwc); dwc3_gadget_reset_interrupt(dwc);
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
dwc->gadget.ep0->maxpacket = 512; dwc->gadget->ep0->maxpacket = 512;
dwc->gadget.speed = USB_SPEED_SUPER; dwc->gadget->speed = USB_SPEED_SUPER;
break; break;
case DWC3_DSTS_HIGHSPEED: case DWC3_DSTS_HIGHSPEED:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
dwc->gadget.ep0->maxpacket = 64; dwc->gadget->ep0->maxpacket = 64;
dwc->gadget.speed = USB_SPEED_HIGH; dwc->gadget->speed = USB_SPEED_HIGH;
break; break;
case DWC3_DSTS_FULLSPEED: case DWC3_DSTS_FULLSPEED:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
dwc->gadget.ep0->maxpacket = 64; dwc->gadget->ep0->maxpacket = 64;
dwc->gadget.speed = USB_SPEED_FULL; dwc->gadget->speed = USB_SPEED_FULL;
break; break;
case DWC3_DSTS_LOWSPEED: case DWC3_DSTS_LOWSPEED:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8);
dwc->gadget.ep0->maxpacket = 8; dwc->gadget->ep0->maxpacket = 8;
dwc->gadget.speed = USB_SPEED_LOW; dwc->gadget->speed = USB_SPEED_LOW;
break; break;
} }
dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket; dwc->eps[1]->endpoint.maxpacket = dwc->gadget->ep0->maxpacket;
/* Enable USB2 LPM Capability */ /* Enable USB2 LPM Capability */
@ -3372,7 +3372,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
if (dwc->gadget_driver && dwc->gadget_driver->resume) { if (dwc->gadget_driver && dwc->gadget_driver->resume) {
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dwc->gadget_driver->resume(&dwc->gadget); dwc->gadget_driver->resume(dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
@ -3543,7 +3543,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
* Ignore suspend event until the gadget enters into * Ignore suspend event until the gadget enters into
* USB_STATE_CONFIGURED state. * USB_STATE_CONFIGURED state.
*/ */
if (dwc->gadget.state >= USB_STATE_CONFIGURED) if (dwc->gadget->state >= USB_STATE_CONFIGURED)
dwc3_gadget_suspend_interrupt(dwc, dwc3_gadget_suspend_interrupt(dwc,
event->event_info); event->event_info);
} }
@ -3718,6 +3718,13 @@ static int dwc3_gadget_get_irq(struct dwc3 *dwc)
return irq; return irq;
} }
static void dwc_gadget_release(struct device *dev)
{
struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
kfree(gadget);
}
/** /**
* dwc3_gadget_init - initializes gadget related registers * dwc3_gadget_init - initializes gadget related registers
* @dwc: pointer to our controller context structure * @dwc: pointer to our controller context structure
@ -3728,6 +3735,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
{ {
int ret; int ret;
int irq; int irq;
struct device *dev;
irq = dwc3_gadget_get_irq(dwc); irq = dwc3_gadget_get_irq(dwc);
if (irq < 0) { if (irq < 0) {
@ -3760,12 +3768,21 @@ int dwc3_gadget_init(struct dwc3 *dwc)
} }
init_completion(&dwc->ep0_in_setup); init_completion(&dwc->ep0_in_setup);
dwc->gadget = kzalloc(sizeof(struct usb_gadget), GFP_KERNEL);
if (!dwc->gadget) {
ret = -ENOMEM;
goto err3;
}
dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.speed = USB_SPEED_UNKNOWN; usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release);
dwc->gadget.sg_supported = true; dev = &dwc->gadget->dev;
dwc->gadget.name = "dwc3-gadget"; dev->platform_data = dwc;
dwc->gadget.lpm_capable = true; dwc->gadget->ops = &dwc3_gadget_ops;
dwc->gadget->speed = USB_SPEED_UNKNOWN;
dwc->gadget->sg_supported = true;
dwc->gadget->name = "dwc3-gadget";
dwc->gadget->lpm_capable = true;
/* /*
* FIXME We might be setting max_speed to <SUPER, however versions * FIXME We might be setting max_speed to <SUPER, however versions
@ -3788,7 +3805,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dev_info(dwc->dev, "changing max_speed on rev %08x\n", dev_info(dwc->dev, "changing max_speed on rev %08x\n",
dwc->revision); dwc->revision);
dwc->gadget.max_speed = dwc->maximum_speed; dwc->gadget->max_speed = dwc->maximum_speed;
/* /*
* REVISIT: Here we should clear all pending IRQs to be * REVISIT: Here we should clear all pending IRQs to be
@ -3797,21 +3814,22 @@ int dwc3_gadget_init(struct dwc3 *dwc)
ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps);
if (ret) if (ret)
goto err3;
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
goto err4; goto err4;
ret = usb_add_gadget(dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to add gadget\n");
goto err5;
} }
dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed); dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
return 0; return 0;
err4: err5:
dwc3_gadget_free_endpoints(dwc); dwc3_gadget_free_endpoints(dwc);
err4:
usb_put_gadget(dwc->gadget);
err3: err3:
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
dwc->bounce_addr); dwc->bounce_addr);
@ -3831,7 +3849,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
void dwc3_gadget_exit(struct dwc3 *dwc) void dwc3_gadget_exit(struct dwc3 *dwc)
{ {
usb_del_gadget_udc(&dwc->gadget); usb_del_gadget_udc(dwc->gadget);
dwc3_gadget_free_endpoints(dwc); dwc3_gadget_free_endpoints(dwc);
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
dwc->bounce_addr); dwc->bounce_addr);

View file

@ -17,7 +17,7 @@
struct dwc3; struct dwc3;
#define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint)) #define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint))
#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) #define gadget_to_dwc(g) (dev_get_platdata(&g->dev))
/* DEPCFG parameter 1 */ /* DEPCFG parameter 1 */
#define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0)