]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/usb/otg/ulpi.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / usb / otg / ulpi.c
index ccc81950822b25e9550b3947863630516f4b2d54..059d9ac0ab5b14f4bb80895d1d69fbeb921970d9 100644 (file)
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
+
+struct ulpi_info {
+       unsigned int    id;
+       char            *name;
+};
+
 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
+#define ULPI_INFO(_id, _name)          \
+       {                               \
+               .id     = (_id),        \
+               .name   = (_name),      \
+       }
 
 /* ULPI hardcoded IDs, used for probing */
-static unsigned int ulpi_ids[] = {
-       ULPI_ID(0x04cc, 0x1504),        /* NXP ISP1504 */
-       ULPI_ID(0x0424, 0x0006),        /* SMSC USB3319 */
+static struct ulpi_info ulpi_ids[] = {
+       ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
+       ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"),
 };
 
 static int ulpi_set_otg_flags(struct otg_transceiver *otg)
@@ -137,6 +148,32 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
        return ulpi_set_fc_flags(otg);
 }
 
+static int ulpi_check_integrity(struct otg_transceiver *otg)
+{
+       int ret, i;
+       unsigned int val = 0x55;
+
+       for (i = 0; i < 2; i++) {
+               ret = otg_io_write(otg, val, ULPI_SCRATCH);
+               if (ret < 0)
+                       return ret;
+
+               ret = otg_io_read(otg, ULPI_SCRATCH);
+               if (ret < 0)
+                       return ret;
+
+               if (ret != val) {
+                       pr_err("ULPI integrity check: failed!");
+                       return -ENODEV;
+               }
+               val = val << 1;
+       }
+
+       pr_info("ULPI integrity check: passed.\n");
+
+       return 0;
+}
+
 static int ulpi_init(struct otg_transceiver *otg)
 {
        int i, vid, pid, ret;
@@ -153,12 +190,19 @@ static int ulpi_init(struct otg_transceiver *otg)
 
        pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 
-       for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
-               if (ulpi_ids[i] == ULPI_ID(vid, pid))
-                       return ulpi_set_flags(otg);
+       for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
+               if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
+                       pr_info("Found %s ULPI transceiver.\n",
+                               ulpi_ids[i].name);
+                       break;
+               }
+       }
+
+       ret = ulpi_check_integrity(otg);
+       if (ret)
+               return ret;
 
-       pr_err("ULPI ID does not match any known transceiver.\n");
-       return -ENODEV;
+       return ulpi_set_flags(otg);
 }
 
 static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)