usb: musb: factor out hcd initalization
authorDaniel Mack <zonque@gmail.com>
Wed, 10 Apr 2013 19:55:45 +0000 (21:55 +0200)
committerFelipe Balbi <balbi@ti.com>
Tue, 28 May 2013 16:22:23 +0000 (19:22 +0300)
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>
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_host.h

index 8b50cd9..727a687 100644 (file)
@@ -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);
@@ -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:
@@ -766,7 +768,8 @@ b_host:
                         * 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);
@@ -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;
@@ -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)
@@ -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);
 }
 
 /*
@@ -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.
@@ -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);
index e981b9b..e633fce 100644 (file)
@@ -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.
index 8b977d2..e6ece8a 100644 (file)
  * 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,
@@ -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
@@ -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
@@ -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);
 }
index c63e585..e47035e 100644 (file)
 
 #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 {
@@ -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);
 
@@ -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;