Latest hcm's patchset, non-working hcm-patch
authorHagen Meyer <hagen@hcmeyer.de>
Mon, 30 Aug 2010 18:58:34 +0000 (22:58 +0400)
committerPaul Fertser <fercerpav@gmail.com>
Mon, 30 Aug 2010 18:58:34 +0000 (22:58 +0400)
I've been trying to cleanly implement hostmode, based on Datasheets and
proposals in the forum.

It doesn't work, yet, but maybe some of you can merge my ideas with
their own to make some progress.

I'll try to explain the different chunks of the patch, and after that
some remarks:

-#################################
1. isp1704.h
-#################################
Just changed some definitions, e.g. the XCVRSELECT_SHIFT was wrong in my
opinion (was 1 instead of 0). HIGH_SPEED and LOW_SPEED were missing, I
added them for convenience.

-#################################
2. musb_core.c
-#################################
functions to configure ISP1704/1707 in host/otg mode. Refer to datasheet
The ??? is because of DP/DM Pullup, the Datasheet somewhat contradicts
the code used in omap2430.c:musb_restore_ctx_and_resume (ISP1704 ds, p29)

In some of my tests, the ulpi_read/write requests timeouted. So maybe
the chip is somehow misconfigured somewhere.

NOTE: CTRL_RESET causes an USB Reset, this should not affect the chip
itself and its registers

-#################################
3. musb_core.h
-#################################
only an enum and the prototypes of above functions

-#################################
4. musb_procfs.c
-#################################
- Output TESTMODE with cat /proc/driver/musb_hdrc
- 'M' enters hostmode (hypothetically)
 - configure ISP1707 as host (lowspeed for testing)
 - deactivate MUSB suspendmodes (needed?)
 - FORCE_HOST mode
 - set SESSION (should actually start host session)
- 'm' leaves hostmode (hypothetically)
 - reset SESSION
 - reset FORCE_HOST
 - configure ISP1707 as otg

Also, I deactivated musb_platform_try_idle after access to
/proc/driver/musb_hdrc. Not sure if this is needed.
Somewhat redundant to the next chunk: do not idle if FORCE_HOST is set.

-#################################
5. twl4030-usb.c
-#################################
This chunk seems to be rather IMPORTANT!
Disables suspending the PHY, it seems that without this chunk, the MUSB
registers (POWER, DEVCTL, TESTMODE) are reset from time to time.
Probably because the musb_save_ctx_and_suspend and
musb_restore_ctx_and_resume routines are not host-aware.
It seems that these routines can also be deactivated by applying VBUS at
the right moment.

-#################################
-#################################
My Remarks
-#################################
-#################################

- I did NOT change the Software-Statemachine at all.
 - Maybe it is needed to force the SW-Statemachine into another state
 - It should not be needed to change the IRQ-Routine which controls the
Statmachine, as this is exactly as proposed in the docs, also for
hostmode (SPRUF98D, p3232).

My Tests:
1. stop bme
2. echo M > /proc/driver/musb_hdrc
3. start vbus
with or without device attached, sometimes I changed 2+3.

Most of the time, the BDEVICE bit in DEVCTL was set, strangely, also the
LSDEV (LS dev recognized) was set sometimes.

drivers/usb/musb/isp1704.h
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_procfs.c
drivers/usb/musb/omap2430.c
drivers/usb/otg/twl4030-usb.c

index c52406e..a20e96a 100644 (file)
 #define ISP1704_PWR_CTRL               0x3d
 
 /* Function control */
-#define ISP1704_FUNC_CTRL_FULL_SPEED   (1 << 0)
-#define ISP1704_FUNC_CTRL_XCVRSELECT   0x3
-#define ISP1704_FUNC_CTRL_XCVRSELECT_SHIFT     (1 << 0)
-#define ISP1704_FUNC_CTRL_TERMSELECT   (1 << 2)
-#define ISP1704_FUNC_CTRL_OPMODE       (1 << 3)
-#define ISP1704_FUNC_CTRL_OPMODE_SHIFT 3
-#define ISP1704_FUNC_CTRL_RESET                (1 << 5)
-#define ISP1704_FUNC_CTRL_SUSPENDM     (1 << 6)
+#define ISP1704_FUNC_CTRL_XCVRSELECT_SHIFT     0
+#define ISP1704_FUNC_CTRL_XCVRSELECT_MASK      (3 << 0)
+#define ISP1704_FUNC_CTRL_HIGH_SPEED           (0 << 0)
+#define ISP1704_FUNC_CTRL_FULL_SPEED           (1 << 0)
+#define ISP1704_FUNC_CTRL_LOW_SPEED            (2 << 0)
+#define ISP1704_FUNC_CTRL_TERMSELECT           (1 << 2)
+#define ISP1704_FUNC_CTRL_OPMODE               (1 << 3)
+#define ISP1704_FUNC_CTRL_OPMODE_SHIFT         3
+#define ISP1704_FUNC_CTRL_RESET                        (1 << 5)
+#define ISP1704_FUNC_CTRL_SUSPENDM             (1 << 6)
 
 /* OTG Control */
 #define ISP1704_OTG_CTRL_IDPULLUP      (1 << 0)
index 6adab83..6dabefb 100644 (file)
@@ -142,6 +142,64 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
 
+void musb_isp1704_host(void __iomem *addr, enum musb_term term)
+{
+       u8 r;
+
+       /* activate pulldown resistors on datalines */
+       r = musb_ulpi_readb(addr, ISP1704_OTG_CTRL);
+       r |= ISP1704_OTG_CTRL_DP_PULLDOWN | ISP1704_OTG_CTRL_DM_PULLDOWN;
+       musb_ulpi_writeb(addr, ISP1704_OTG_CTRL, r);
+
+       r = ISP1704_FUNC_CTRL_SUSPENDM | ISP1704_FUNC_CTRL_RESET;
+       /* set new speed-selection bits */
+       switch(term) {
+
+       case MUSB_TERM_HOST_HIGHSPEED:
+               r |= ISP1704_FUNC_CTRL_HIGH_SPEED;
+               r &= ~ISP1704_FUNC_CTRL_TERMSELECT;
+               r &= ~ISP1704_FUNC_CTRL_OPMODE;
+               DBG(1,"musb_force_term, highspeed\n");
+               break;
+
+       case MUSB_TERM_HOST_FULLSPEED:
+               r |= ISP1704_FUNC_CTRL_FULL_SPEED;
+               r |= ISP1704_FUNC_CTRL_TERMSELECT;
+               r &= ~ISP1704_FUNC_CTRL_OPMODE;
+               DBG(1,"musb_force_term, fullspeed\n");
+               break;
+
+       case MUSB_TERM_HOST_LOWSPEED:
+               r |= ISP1704_FUNC_CTRL_LOW_SPEED;
+               r |= ISP1704_FUNC_CTRL_TERMSELECT;
+               r &= ~ISP1704_FUNC_CTRL_OPMODE;
+               DBG(1,"musb_force_term, lowspeed\n");
+               break;
+
+       default:
+               ERR("Unknown musb termination\n");
+               return;
+       }
+
+       musb_ulpi_writeb(addr, ISP1704_FUNC_CTRL, r);
+}
+
+void musb_isp1704_otg(void __iomem *addr)
+{
+       u8 r;
+       
+       /* Recover OTG control */
+       r = musb_ulpi_readb(addr, ISP1704_OTG_CTRL);
+       r &= ~ISP1704_OTG_CTRL_DM_PULLDOWN;
+       r |= ISP1704_OTG_CTRL_IDPULLUP | ISP1704_OTG_CTRL_DP_PULLDOWN; //???
+       musb_ulpi_writeb(addr, ISP1704_OTG_CTRL, r);
+
+       /* Recover FUNC control */
+       r = ISP1704_FUNC_CTRL_FULL_SPEED;
+       r |= ISP1704_FUNC_CTRL_SUSPENDM | ISP1704_FUNC_CTRL_RESET;
+       musb_ulpi_writeb(addr, ISP1704_FUNC_CTRL, r);
+}
+
 static inline int musb_verify_charger(void __iomem *addr)
 {
        u8 r, ret = 0;
index dd9de46..a3a02b6 100644 (file)
@@ -621,6 +621,15 @@ static inline void musb_restore_ctx_and_resume(struct usb_gadget *) {}
 extern int __init musb_platform_init(struct musb *musb);
 extern int musb_platform_exit(struct musb *musb);
 
+enum musb_term {
+       MUSB_TERM_HOST_HIGHSPEED,
+       MUSB_TERM_HOST_FULLSPEED,
+       MUSB_TERM_HOST_LOWSPEED,
+};
+
+extern void musb_isp1704_host(void __iomem *addr, enum musb_term term);
+extern void musb_isp1704_otg(void __iomem *addr);
+
 /*-------------------------- ProcFS definitions ---------------------*/
 
 struct proc_dir_entry;
index 8915b62..7d7e1b3 100644 (file)
@@ -442,10 +442,11 @@ static int dump_header_stats(struct musb *musb, char *buffer)
 
        *buffer = 0;
        count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
-                               "(Power=%02x, DevCtl=%02x)\n",
+                               "(Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
                        (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
                        musb_readb(mbase, MUSB_POWER),
-                       musb_readb(mbase, MUSB_DEVCTL));
+                       musb_readb(mbase, MUSB_DEVCTL),
+                       musb_readb(mbase, MUSB_TESTMODE));
        if (count <= 0)
                return 0;
        buffer += count;
@@ -678,6 +679,62 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                                        MUSB_TEST_PACKET);
                }
                break;
+       case 'M':
+               if (mbase) {
+                       musb_isp1704_host(mbase, MUSB_TERM_HOST_LOWSPEED);
+                       DBG(1, "STARTING HOSTMODE (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       reg = musb_readb(mbase, MUSB_POWER);
+                       reg &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_ENSUSPEND);
+                       musb_writeb(mbase, MUSB_POWER, reg);
+                       DBG(1, "(1) disabled suspendmodes (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       
+                       reg = musb_readb(mbase, MUSB_TESTMODE);
+                       reg |= MUSB_TEST_FORCE_HOST;
+                       musb_writeb(mbase, MUSB_TESTMODE, reg);
+                       DBG(1, "(2) set FORCE_HOST (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       
+                       reg = musb_readb(mbase, MUSB_DEVCTL);
+                       reg |= MUSB_DEVCTL_SESSION;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+                       DBG(1, "(3) set SESSION (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+               }
+               break;
+       case 'm':
+               if (mbase) {
+                       DBG(1, "LEAVING HOSTMODE (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       reg = musb_readb(mbase, MUSB_DEVCTL);
+                       reg &= ~MUSB_DEVCTL_SESSION;
+                       musb_writeb(mbase, MUSB_DEVCTL, reg);
+                       DBG(1, "(1) reset SESSION (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       
+                       reg = musb_readb(mbase, MUSB_TESTMODE);
+                       reg &= ~MUSB_TEST_FORCE_HOST;
+                       musb_writeb(mbase, MUSB_TESTMODE, reg);
+                       DBG(1, "(2) reset FORCE_HOST (Power=%02x, DevCtl=%02x, Testmode=%02x)\n",
+                               musb_readb(mbase, MUSB_POWER),
+                               musb_readb(mbase, MUSB_DEVCTL),
+                               musb_readb(mbase, MUSB_TESTMODE));
+                       musb_isp1704_otg(mbase);
+               }
+               break;
 
        case '?':
                INFO("?: you are seeing it\n");
@@ -693,7 +750,7 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                break;
        }
 
-       musb_platform_try_idle(musb, 0);
+       //musb_platform_try_idle(musb, 0);
 
        return count;
 }
@@ -731,7 +788,7 @@ static int musb_proc_read(char *page, char **start,
                }
        }
 
-       musb_platform_try_idle(musb, 0);
+       //musb_platform_try_idle(musb, 0);
 
        spin_unlock_irqrestore(&musb->lock, flags);
        *eof = 1;
index a712bc9..6d56751 100644 (file)
@@ -131,8 +131,8 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
                timeout = default_timeout;
 
        /* Never idle if active, or when VBUS timeout is not set as host */
-       if (musb->is_active || ((musb->a_wait_bcon == 0)
-                       && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+       if (musb->is_active || (musb_readb(musb->mregs, MUSB_TESTMODE) & MUSB_TEST_FORCE_HOST)
+               ||((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
                DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
                del_timer(&musb_idle_timer);
                last_timer = jiffies;
index ecffb2a..1577e7a 100644 (file)
@@ -480,7 +480,7 @@ extern void musb_restore_ctx_and_resume(struct usb_gadget *gadget);
 
 static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
 {
-       if (twl->asleep)
+       if (!twl->asleep)
                return;
 
        twl4030_phy_power(twl, 0);