Commit 74c2e936 authored by Daniel Mack's avatar Daniel Mack Committed by Felipe Balbi

usb: musb: factor out hcd initalization

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: default avatarDaniel Mack <zonque@gmail.com>
Acked-by: default avatarPeter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 69ae2a70
...@@ -403,7 +403,8 @@ void musb_hnp_stop(struct musb *musb) ...@@ -403,7 +403,8 @@ void musb_hnp_stop(struct musb *musb)
break; break;
case OTG_STATE_B_HOST: case OTG_STATE_B_HOST:
dev_dbg(musb->controller, "HNP: Disabling HR\n"); 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->xceiv->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
reg = musb_readb(mbase, MUSB_POWER); reg = musb_readb(mbase, MUSB_POWER);
...@@ -725,7 +726,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -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"); dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n");
b_host: b_host:
musb->xceiv->state = OTG_STATE_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); del_timer(&musb->otg_timer);
break; break;
default: default:
...@@ -766,7 +768,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -766,7 +768,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
* in hnp_stop() is currently not used... * in hnp_stop() is currently not used...
*/ */
musb_root_disconnect(musb); 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->xceiv->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb); MUSB_DEV_MODE(musb);
musb_g_disconnect(musb); musb_g_disconnect(musb);
...@@ -1706,24 +1709,18 @@ static struct musb *allocate_instance(struct device *dev, ...@@ -1706,24 +1709,18 @@ static struct musb *allocate_instance(struct device *dev,
struct musb *musb; struct musb *musb;
struct musb_hw_ep *ep; struct musb_hw_ep *ep;
int epnum; int epnum;
struct usb_hcd *hcd; int ret;
hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); musb = devm_kzalloc(dev, sizeof(*musb), GFP_KERNEL);
if (!hcd) if (!musb)
return NULL; 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->control);
INIT_LIST_HEAD(&musb->in_bulk); INIT_LIST_HEAD(&musb->in_bulk);
INIT_LIST_HEAD(&musb->out_bulk); INIT_LIST_HEAD(&musb->out_bulk);
hcd->uses_new_polling = 1;
hcd->has_tt = 1;
musb->vbuserr_retry = VBUSERR_RETRY_COUNT; musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
dev_set_drvdata(dev, musb);
musb->mregs = mbase; musb->mregs = mbase;
musb->ctrl_base = mbase; musb->ctrl_base = mbase;
musb->nIrq = -ENODEV; musb->nIrq = -ENODEV;
...@@ -1738,7 +1735,16 @@ static struct musb *allocate_instance(struct device *dev, ...@@ -1738,7 +1735,16 @@ static struct musb *allocate_instance(struct device *dev,
musb->controller = dev; musb->controller = dev;
ret = musb_host_alloc(musb);
if (ret < 0)
goto err_free;
dev_set_drvdata(dev, musb);
return musb; return musb;
err_free:
return NULL;
} }
static void musb_free(struct musb *musb) static void musb_free(struct musb *musb)
...@@ -1764,7 +1770,7 @@ static void musb_free(struct musb *musb) ...@@ -1764,7 +1770,7 @@ static void musb_free(struct musb *musb)
dma_controller_destroy(c); 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) ...@@ -1781,7 +1787,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
int status; int status;
struct musb *musb; struct musb *musb;
struct musb_hdrc_platform_data *plat = dev->platform_data; struct musb_hdrc_platform_data *plat = dev->platform_data;
struct usb_hcd *hcd;
/* The driver might handle more features than the board; OK. /* The driver might handle more features than the board; OK.
* Fail when the board needs a feature that's not enabled. * 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) ...@@ -1882,13 +1887,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->irq_wake = 0; 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 */ /* program PHY to use external vBus if required */
if (plat->extvbus) { if (plat->extvbus) {
u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
......
...@@ -401,6 +401,7 @@ struct musb { ...@@ -401,6 +401,7 @@ struct musb {
enum musb_g_ep0_state ep0_state; enum musb_g_ep0_state ep0_state;
struct usb_gadget g; /* the gadget */ struct usb_gadget g; /* the gadget */
struct usb_gadget_driver *gadget_driver; /* its driver */ struct usb_gadget_driver *gadget_driver; /* its driver */
struct usb_hcd *hcd; /* the usb hcd */
/* /*
* FIXME: Remove this flag. * FIXME: Remove this flag.
......
...@@ -95,6 +95,11 @@ ...@@ -95,6 +95,11 @@
* of transfers between endpoints, or anything clever. * 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, static void musb_ep_program(struct musb *musb, u8 epnum,
struct urb *urb, int is_out, struct urb *urb, int is_out,
...@@ -2464,7 +2469,6 @@ static int musb_bus_resume(struct usb_hcd *hcd) ...@@ -2464,7 +2469,6 @@ static int musb_bus_resume(struct usb_hcd *hcd)
return 0; return 0;
} }
#ifndef CONFIG_MUSB_PIO_ONLY #ifndef CONFIG_MUSB_PIO_ONLY
#define MUSB_USB_DMA_ALIGN 4 #define MUSB_USB_DMA_ALIGN 4
...@@ -2576,10 +2580,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) ...@@ -2576,10 +2580,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
} }
#endif /* !CONFIG_MUSB_PIO_ONLY */ #endif /* !CONFIG_MUSB_PIO_ONLY */
const struct hc_driver musb_hc_driver = { static const struct hc_driver musb_hc_driver = {
.description = "musb-hcd", .description = "musb-hcd",
.product_desc = "MUSB HDRC host driver", .product_desc = "MUSB HDRC host driver",
.hcd_priv_size = sizeof(struct musb), .hcd_priv_size = sizeof(struct musb *),
.flags = HCD_USB2 | HCD_MEMORY, .flags = HCD_USB2 | HCD_MEMORY,
/* not using irq handler or reset hooks from usbcore, since /* not using irq handler or reset hooks from usbcore, since
...@@ -2608,16 +2612,44 @@ const struct hc_driver musb_hc_driver = { ...@@ -2608,16 +2612,44 @@ const struct hc_driver musb_hc_driver = {
/* .hub_irq_enable = NULL, */ /* .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) 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) void musb_host_poke_root_hub(struct musb *musb)
{ {
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
if (musb_to_hcd(musb)->status_urb) if (musb->hcd->status_urb)
usb_hcd_poll_rh_status(musb_to_hcd(musb)); usb_hcd_poll_rh_status(musb->hcd);
else else
usb_hcd_resume_root_hub(musb_to_hcd(musb)); usb_hcd_resume_root_hub(musb->hcd);
} }
...@@ -37,15 +37,9 @@ ...@@ -37,15 +37,9 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
static inline struct usb_hcd *musb_to_hcd(struct musb *musb) #define musb_to_hcd(MUSB) ((MUSB)->hcd)
{
return container_of((void *) musb, struct usb_hcd, hcd_priv);
}
static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) extern struct musb *hcd_to_musb(struct usb_hcd *);
{
return (struct musb *) (hcd->hcd_priv);
}
/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ /* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */
struct musb_qh { struct musb_qh {
...@@ -85,10 +79,15 @@ static inline struct musb_qh *first_qh(struct list_head *q) ...@@ -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 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_tx(struct musb *, u8);
extern void musb_host_rx(struct musb *, u8); extern void musb_host_rx(struct musb *, u8);
extern void musb_root_disconnect(struct musb *musb); extern void musb_root_disconnect(struct musb *musb);
extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb);
extern void musb_host_poke_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, ...@@ -99,8 +98,6 @@ extern int musb_hub_control(struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex, u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength); char *buf, u16 wLength);
extern const struct hc_driver musb_hc_driver;
static inline struct urb *next_urb(struct musb_qh *qh) static inline struct urb *next_urb(struct musb_qh *qh)
{ {
struct list_head *queue; struct list_head *queue;
......
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