]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/musb/musb_core.c
usb: musb: allow board to pass down fifo mode
[~andy/linux] / drivers / usb / musb / musb_core.c
index 8b68f21d3f8220a05920fc7ca99e1464d919b92c..3f4c158a9f5e984af037ed0bd04a21710241a57f 100644 (file)
@@ -353,8 +353,7 @@ void musb_hnp_stop(struct musb *musb)
         * which cause occasional OPT A "Did not receive reset after connect"
         * errors.
         */
-       musb->port1_status &=
-               ~(1 << USB_PORT_FEAT_C_CONNECTION);
+       musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
 }
 
 #endif
@@ -530,8 +529,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                musb_writeb(mbase, MUSB_DEVCTL, devctl);
                        } else {
                                musb->port1_status |=
-                                         (1 << USB_PORT_FEAT_OVER_CURRENT)
-                                       | (1 << USB_PORT_FEAT_C_OVER_CURRENT);
+                                         USB_PORT_STAT_OVERCURRENT
+                                       | (USB_PORT_STAT_C_OVERCURRENT << 16);
                        }
                        break;
                default:
@@ -996,24 +995,13 @@ static ushort __initdata fifo_mode = 2;
 module_param(fifo_mode, ushort, 0);
 MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
 
-
-enum fifo_style { FIFO_RXTX, FIFO_TX, FIFO_RX } __attribute__ ((packed));
-enum buf_mode { BUF_SINGLE, BUF_DOUBLE } __attribute__ ((packed));
-
-struct fifo_cfg {
-       u8              hw_ep_num;
-       enum fifo_style style;
-       enum buf_mode   mode;
-       u16             maxpacket;
-};
-
 /*
  * tables defining fifo_mode values.  define more if you like.
  * for host side, make sure both halves of ep1 are set up.
  */
 
 /* mode 0 - fits in 2KB */
-static struct fifo_cfg __initdata mode_0_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_0_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
@@ -1022,7 +1010,7 @@ static struct fifo_cfg __initdata mode_0_cfg[] = {
 };
 
 /* mode 1 - fits in 4KB */
-static struct fifo_cfg __initdata mode_1_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_1_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
@@ -1031,7 +1019,7 @@ static struct fifo_cfg __initdata mode_1_cfg[] = {
 };
 
 /* mode 2 - fits in 4KB */
-static struct fifo_cfg __initdata mode_2_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_2_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1041,7 +1029,7 @@ static struct fifo_cfg __initdata mode_2_cfg[] = {
 };
 
 /* mode 3 - fits in 4KB */
-static struct fifo_cfg __initdata mode_3_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_3_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1051,7 +1039,7 @@ static struct fifo_cfg __initdata mode_3_cfg[] = {
 };
 
 /* mode 4 - fits in 16KB */
-static struct fifo_cfg __initdata mode_4_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_4_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1082,7 +1070,7 @@ static struct fifo_cfg __initdata mode_4_cfg[] = {
 };
 
 /* mode 5 - fits in 8KB */
-static struct fifo_cfg __initdata mode_5_cfg[] = {
+static struct musb_fifo_cfg __initdata mode_5_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1120,7 +1108,7 @@ static struct fifo_cfg __initdata mode_5_cfg[] = {
  */
 static int __init
 fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
-               const struct fifo_cfg *cfg, u16 offset)
+               const struct musb_fifo_cfg *cfg, u16 offset)
 {
        void __iomem    *mbase = musb->mregs;
        int     size = 0;
@@ -1191,17 +1179,23 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
        return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
 }
 
-static struct fifo_cfg __initdata ep0_cfg = {
+static struct musb_fifo_cfg __initdata ep0_cfg = {
        .style = FIFO_RXTX, .maxpacket = 64,
 };
 
 static int __init ep_config_from_table(struct musb *musb)
 {
-       const struct fifo_cfg   *cfg;
+       const struct musb_fifo_cfg      *cfg;
        unsigned                i, n;
        int                     offset;
        struct musb_hw_ep       *hw_ep = musb->endpoints;
 
+       if (musb->config->fifo_cfg) {
+               cfg = musb->config->fifo_cfg;
+               n = musb->config->fifo_cfg_size;
+               goto done;
+       }
+
        switch (fifo_mode) {
        default:
                fifo_mode = 0;
@@ -1236,6 +1230,7 @@ static int __init ep_config_from_table(struct musb *musb)
                        musb_driver_name, fifo_mode);
 
 
+done:
        offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
        /* assert(offset > 0) */
 
@@ -1851,10 +1846,6 @@ static void musb_free(struct musb *musb)
        put_device(musb->xceiv->dev);
 #endif
 
-       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
-       musb_platform_exit(musb);
-       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
-
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
        usb_put_hcd(musb_to_hcd(musb));
 #else
@@ -1882,8 +1873,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
         */
        if (!plat) {
                dev_dbg(dev, "no platform_data?\n");
-               return -ENODEV;
+               status = -ENODEV;
+               goto fail0;
        }
+
        switch (plat->mode) {
        case MUSB_HOST:
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
@@ -1905,13 +1898,16 @@ bad_config:
 #endif
        default:
                dev_err(dev, "incompatible Kconfig role setting\n");
-               return -EINVAL;
+               status = -EINVAL;
+               goto fail0;
        }
 
        /* allocate */
        musb = allocate_instance(dev, plat->config, ctrl);
-       if (!musb)
-               return -ENOMEM;
+       if (!musb) {
+               status = -ENOMEM;
+               goto fail0;
+       }
 
        spin_lock_init(&musb->lock);
        musb->board_mode = plat->mode;
@@ -1929,7 +1925,7 @@ bad_config:
                if (IS_ERR(musb->clock)) {
                        status = PTR_ERR(musb->clock);
                        musb->clock = NULL;
-                       goto fail;
+                       goto fail1;
                }
        }
 
@@ -1948,12 +1944,12 @@ bad_config:
         */
        musb->isr = generic_interrupt;
        status = musb_platform_init(musb);
-
        if (status < 0)
-               goto fail;
+               goto fail2;
+
        if (!musb->isr) {
                status = -ENODEV;
-               goto fail2;
+               goto fail3;
        }
 
 #ifndef CONFIG_MUSB_PIO_ONLY
@@ -1979,7 +1975,7 @@ bad_config:
                        ? MUSB_CONTROLLER_MHDRC
                        : MUSB_CONTROLLER_HDRC, musb);
        if (status < 0)
-               goto fail2;
+               goto fail3;
 
 #ifdef CONFIG_USB_MUSB_OTG
        setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
@@ -1992,7 +1988,7 @@ bad_config:
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
                status = -ENODEV;
-               goto fail2;
+               goto fail3;
        }
        musb->nIrq = nIrq;
 /* FIXME this handles wakeup irqs wrong */
@@ -2032,8 +2028,6 @@ bad_config:
                musb->xceiv->state = OTG_STATE_A_IDLE;
 
                status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
-               if (status)
-                       goto fail;
 
                DBG(1, "%s mode, status %d, devctl %02x %c\n",
                        "HOST", status,
@@ -2048,8 +2042,6 @@ bad_config:
                musb->xceiv->state = OTG_STATE_B_IDLE;
 
                status = musb_gadget_setup(musb);
-               if (status)
-                       goto fail;
 
                DBG(1, "%s mode, status %d, dev%02x\n",
                        is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
@@ -2057,12 +2049,14 @@ bad_config:
                        musb_readb(musb->mregs, MUSB_DEVCTL));
 
        }
+       if (status < 0)
+               goto fail3;
 
 #ifdef CONFIG_SYSFS
        status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
-#endif
        if (status)
-               goto fail2;
+               goto fail4;
+#endif
 
        dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
                        ({char *s;
@@ -2078,17 +2072,29 @@ bad_config:
 
        return 0;
 
-fail2:
+fail4:
+       if (!is_otg_enabled(musb) && is_host_enabled(musb))
+               usb_remove_hcd(musb_to_hcd(musb));
+       else
+               musb_gadget_cleanup(musb);
+
+fail3:
+       if (musb->irq_wake)
+               device_init_wakeup(dev, 0);
        musb_platform_exit(musb);
-fail:
-       dev_err(musb->controller,
-               "musb_init_controller failed with status %d\n", status);
 
+fail2:
        if (musb->clock)
                clk_put(musb->clock);
-       device_init_wakeup(dev, 0);
+
+fail1:
+       dev_err(musb->controller,
+               "musb_init_controller failed with status %d\n", status);
+
        musb_free(musb);
 
+fail0:
+
        return status;
 
 }
@@ -2125,7 +2131,6 @@ static int __init musb_probe(struct platform_device *pdev)
        /* clobbered by use_dma=n */
        orig_dma_mask = dev->dma_mask;
 #endif
-
        status = musb_init_controller(dev, irq, base);
        if (status < 0)
                iounmap(base);
@@ -2148,6 +2153,10 @@ static int __exit musb_remove(struct platform_device *pdev)
        if (musb->board_mode == MUSB_HOST)
                usb_remove_hcd(musb_to_hcd(musb));
 #endif
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+       musb_platform_exit(musb);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+
        musb_free(musb);
        iounmap(ctrl_base);
        device_init_wakeup(&pdev->dev, 0);