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 @@
29#include <linux/usb/otg.h> 29#include <linux/usb/otg.h>
30#include <linux/usb/ulpi.h> 30#include <linux/usb/ulpi.h>
31 31
32
33struct ulpi_info {
34 unsigned int id;
35 char *name;
36};
37
32#define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) 38#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
39#define ULPI_INFO(_id, _name) \
40 { \
41 .id = (_id), \
42 .name = (_name), \
43 }
33 44
34/* ULPI hardcoded IDs, used for probing */ 45/* ULPI hardcoded IDs, used for probing */
35static unsigned int ulpi_ids[] = { 46static struct ulpi_info ulpi_ids[] = {
36 ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ 47 ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
37 ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ 48 ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"),
38}; 49};
39 50
40static int ulpi_set_otg_flags(struct otg_transceiver *otg) 51static int ulpi_set_otg_flags(struct otg_transceiver *otg)
@@ -137,6 +148,32 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
137 return ulpi_set_fc_flags(otg); 148 return ulpi_set_fc_flags(otg);
138} 149}
139 150
151static int ulpi_check_integrity(struct otg_transceiver *otg)
152{
153 int ret, i;
154 unsigned int val = 0x55;
155
156 for (i = 0; i < 2; i++) {
157 ret = otg_io_write(otg, val, ULPI_SCRATCH);
158 if (ret < 0)
159 return ret;
160
161 ret = otg_io_read(otg, ULPI_SCRATCH);
162 if (ret < 0)
163 return ret;
164
165 if (ret != val) {
166 pr_err("ULPI integrity check: failed!");
167 return -ENODEV;
168 }
169 val = val << 1;
170 }
171
172 pr_info("ULPI integrity check: passed.\n");
173
174 return 0;
175}
176
140static int ulpi_init(struct otg_transceiver *otg) 177static int ulpi_init(struct otg_transceiver *otg)
141{ 178{
142 int i, vid, pid, ret; 179 int i, vid, pid, ret;
@@ -153,12 +190,19 @@ static int ulpi_init(struct otg_transceiver *otg)
153 190
154 pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); 191 pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
155 192
156 for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) 193 for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
157 if (ulpi_ids[i] == ULPI_ID(vid, pid)) 194 if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
158 return ulpi_set_flags(otg); 195 pr_info("Found %s ULPI transceiver.\n",
196 ulpi_ids[i].name);
197 break;
198 }
199 }
200
201 ret = ulpi_check_integrity(otg);
202 if (ret)
203 return ret;
159 204
160 pr_err("ULPI ID does not match any known transceiver.\n"); 205 return ulpi_set_flags(otg);
161 return -ENODEV;
162} 206}
163 207
164static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) 208static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)