forked from Minki/linux
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: Daniel Mack <zonque@gmail.com> Acked-by: Peter Korsgaard <jacmet@sunsite.dk> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
69ae2a70bf
commit
74c2e93600
@ -403,6 +403,7 @@ 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");
|
||||||
|
if (hcd)
|
||||||
hcd->self.is_b_host = 0;
|
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);
|
||||||
@ -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 @@ b_host:
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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 @@
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
#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 = {
|
|||||||
/* .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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user