aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/ulpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/otg/ulpi.c')
-rw-r--r--drivers/usb/otg/ulpi.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index ccc81950822b..059d9ac0ab5b 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -29,12 +29,23 @@
#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)