Skip to content

Commit

Permalink
usb: musb: factor out hcd initalization
Browse files Browse the repository at this point in the history
The musb struct is currently allocated along with the hcd, which makes
it difficult to build a driver that only acts as gadget device.

Fix this by allocating musb directly, and keep the hcd around as
a pointer in the musb struct.

struct hc_driver musb_hc_driver can now also be static to musb_host.c,
and the macro musb_to_hcd() is just a pointer dereferencer for now, and
will be eliminated later.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Daniel Mack authored and Felipe Balbi committed May 28, 2013
1 parent 69ae2a7 commit 74c2e93
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 39 deletions.
40 changes: 19 additions & 21 deletions drivers/usb/musb/musb_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,8 @@ void musb_hnp_stop(struct musb *musb)
break;
case OTG_STATE_B_HOST:
dev_dbg(musb->controller, "HNP: Disabling HR\n");
hcd->self.is_b_host = 0;
if (hcd)
hcd->self.is_b_host = 0;
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb);
reg = musb_readb(mbase, MUSB_POWER);
Expand Down Expand Up @@ -725,7 +726,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n");
b_host:
musb->xceiv->state = OTG_STATE_B_HOST;
hcd->self.is_b_host = 1;
if (musb->hcd)
musb->hcd->self.is_b_host = 1;
del_timer(&musb->otg_timer);
break;
default:
Expand Down Expand Up @@ -766,7 +768,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
* in hnp_stop() is currently not used...
*/
musb_root_disconnect(musb);
musb_to_hcd(musb)->self.is_b_host = 0;
if (musb->hcd)
musb->hcd->self.is_b_host = 0;
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb);
musb_g_disconnect(musb);
Expand Down Expand Up @@ -1706,24 +1709,18 @@ static struct musb *allocate_instance(struct device *dev,
struct musb *musb;
struct musb_hw_ep *ep;
int epnum;
struct usb_hcd *hcd;
int ret;

hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));
if (!hcd)
musb = devm_kzalloc(dev, sizeof(*musb), GFP_KERNEL);
if (!musb)
return NULL;
/* usbcore sets dev->driver_data to hcd, and sometimes uses that... */

musb = hcd_to_musb(hcd);
INIT_LIST_HEAD(&musb->control);
INIT_LIST_HEAD(&musb->in_bulk);
INIT_LIST_HEAD(&musb->out_bulk);

hcd->uses_new_polling = 1;
hcd->has_tt = 1;

musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
dev_set_drvdata(dev, musb);
musb->mregs = mbase;
musb->ctrl_base = mbase;
musb->nIrq = -ENODEV;
Expand All @@ -1738,7 +1735,16 @@ static struct musb *allocate_instance(struct device *dev,

musb->controller = dev;

ret = musb_host_alloc(musb);
if (ret < 0)
goto err_free;

dev_set_drvdata(dev, musb);

return musb;

err_free:
return NULL;
}

static void musb_free(struct musb *musb)
Expand All @@ -1764,7 +1770,7 @@ static void musb_free(struct musb *musb)
dma_controller_destroy(c);
}

usb_put_hcd(musb_to_hcd(musb));
musb_host_free(musb);
}

/*
Expand All @@ -1781,7 +1787,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
int status;
struct musb *musb;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct usb_hcd *hcd;

/* The driver might handle more features than the board; OK.
* Fail when the board needs a feature that's not enabled.
Expand Down Expand Up @@ -1882,13 +1887,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->irq_wake = 0;
}

/* host side needs more setup */
hcd = musb_to_hcd(musb);
otg_set_host(musb->xceiv->otg, &hcd->self);
hcd->self.otg_port = 1;
musb->xceiv->otg->host = &hcd->self;
hcd->power_budget = 2 * (plat->power ? : 250);

/* program PHY to use external vBus if required */
if (plat->extvbus) {
u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/musb/musb_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ struct musb {
enum musb_g_ep0_state ep0_state;
struct usb_gadget g; /* the gadget */
struct usb_gadget_driver *gadget_driver; /* its driver */
struct usb_hcd *hcd; /* the usb hcd */

/*
* FIXME: Remove this flag.
Expand Down
46 changes: 39 additions & 7 deletions drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@
* of transfers between endpoints, or anything clever.
*/

struct musb *hcd_to_musb(struct usb_hcd *hcd)
{
return *(struct musb **) hcd->hcd_priv;
}


static void musb_ep_program(struct musb *musb, u8 epnum,
struct urb *urb, int is_out,
Expand Down Expand Up @@ -2464,7 +2469,6 @@ static int musb_bus_resume(struct usb_hcd *hcd)
return 0;
}


#ifndef CONFIG_MUSB_PIO_ONLY

#define MUSB_USB_DMA_ALIGN 4
Expand Down Expand Up @@ -2576,10 +2580,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
}
#endif /* !CONFIG_MUSB_PIO_ONLY */

const struct hc_driver musb_hc_driver = {
static const struct hc_driver musb_hc_driver = {
.description = "musb-hcd",
.product_desc = "MUSB HDRC host driver",
.hcd_priv_size = sizeof(struct musb),
.hcd_priv_size = sizeof(struct musb *),
.flags = HCD_USB2 | HCD_MEMORY,

/* not using irq handler or reset hooks from usbcore, since
Expand Down Expand Up @@ -2608,16 +2612,44 @@ const struct hc_driver musb_hc_driver = {
/* .hub_irq_enable = NULL, */
};

int musb_host_alloc(struct musb *musb)
{
struct device *dev = musb->controller;

/* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
musb->hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));
if (!musb->hcd)
return -EINVAL;

*musb->hcd->hcd_priv = (unsigned long) musb;
musb->hcd->self.uses_pio_for_control = 1;
musb->hcd->uses_new_polling = 1;
musb->hcd->has_tt = 1;

return 0;
}

void musb_host_cleanup(struct musb *musb)
{
usb_remove_hcd(musb->hcd);
musb->hcd = NULL;
}

void musb_host_free(struct musb *musb)
{
usb_put_hcd(musb->hcd);
}

void musb_host_resume_root_hub(struct musb *musb)
{
usb_hcd_resume_root_hub(musb_to_hcd(musb));
usb_hcd_resume_root_hub(musb->hcd);
}

void musb_host_poke_root_hub(struct musb *musb)
{
MUSB_HST_MODE(musb);
if (musb_to_hcd(musb)->status_urb)
usb_hcd_poll_rh_status(musb_to_hcd(musb));
if (musb->hcd->status_urb)
usb_hcd_poll_rh_status(musb->hcd);
else
usb_hcd_resume_root_hub(musb_to_hcd(musb));
usb_hcd_resume_root_hub(musb->hcd);
}
19 changes: 8 additions & 11 deletions drivers/usb/musb/musb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,9 @@

#include <linux/scatterlist.h>

static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
{
return container_of((void *) musb, struct usb_hcd, hcd_priv);
}
#define musb_to_hcd(MUSB) ((MUSB)->hcd)

static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
{
return (struct musb *) (hcd->hcd_priv);
}
extern struct musb *hcd_to_musb(struct usb_hcd *);

/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */
struct musb_qh {
Expand Down Expand Up @@ -85,10 +79,15 @@ static inline struct musb_qh *first_qh(struct list_head *q)
}

extern irqreturn_t musb_h_ep0_irq(struct musb *);
extern int musb_host_alloc(struct musb *);
extern void musb_host_tx(struct musb *, u8);
extern void musb_host_rx(struct musb *, u8);
extern void musb_root_disconnect(struct musb *musb);
extern void musb_host_free(struct musb *);
extern void musb_host_cleanup(struct musb *);
extern void musb_host_tx(struct musb *, u8);
extern void musb_host_rx(struct musb *, u8);
extern void musb_root_disconnect(struct musb *musb);

extern void musb_host_resume_root_hub(struct musb *musb);
extern void musb_host_poke_root_hub(struct musb *musb);

Expand All @@ -99,8 +98,6 @@ extern int musb_hub_control(struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);

extern const struct hc_driver musb_hc_driver;

static inline struct urb *next_urb(struct musb_qh *qh)
{
struct list_head *queue;
Expand Down

0 comments on commit 74c2e93

Please sign in to comment.