Hi, On 10/05/10 07:42, Daniel Mack wrote: > On Mon, Oct 04, 2010 at 05:15:35PM +0200, Igor Grinberg wrote: >> On 10/04/10 16:54, Sergei Shtylyov wrote: >>> Hello. >>> >>> Eric Bénard wrote: >>> >>>> without this patch, the initialization of the OTG port in host mode >>>> fails with : >>>> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver >>>> mxc-ehci mxc-ehci.0: initializing i.MX USB Controller >>>> ULPI transceiver vendor/product ID 0x0000/0x0000 >>>> ULPI ID does not match any known transceiver. >>>> mxc-ehci mxc-ehci.0: unable to init transceiver, probably missing >>>> Signed-off-by: Eric Bénard <eric@xxxxxxxxxx> >>>> --- >>>> drivers/usb/otg/ulpi.c | 5 ++++- >>>> 1 files changed, 4 insertions(+), 1 deletions(-) >>> You should have CC'ed linux-usb@xxxxxxxxxxxxxxxx >>> >>>> diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c >>>> index ccc8195..e802e44 100644 >>>> --- a/drivers/usb/otg/ulpi.c >>>> +++ b/drivers/usb/otg/ulpi.c >>>> @@ -34,7 +34,10 @@ >>>> /* ULPI hardcoded IDs, used for probing */ >>>> static unsigned int ulpi_ids[] = { >>>> ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ >>>> - ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ >>>> + ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ >>>> +#if (defined(CONFIG_ARCH_MX25) || defined(CONFIG_ARCH_MX35)) >>>> + ULPI_ID(0x0000, 0x0000), /* i.MX25 & i.MX35 internal PHY */ >>>> +#endif >>> I don't know why this table is at all used in the first place. IMO, checking for the vendor/device ID serves no purpose... >> Well, it was there in first place, when Daniel merged this. >> May be it was taken from Sascha. >> I think its purpose to check if there is a ulpi transceiver out there, >> although, ulpi defines a special scratch register for testing purposes. > Correct, its primary purpose was to see whether the ULPI low-level > communication works at all, and to bail out when it doesn't. > > I wasn't aware of that scratch register. If we don't need that table any > more, feel free to drop it. This driver is still in development stage and is not fully functional, so I'd like to keep the table and ID info printing, but I really don't like trivial IDs, like that of Eric. How about something like the attached patch? Eric, can you test if it works for you? If it's good, I can send a prettier version of it for review and merging. -- Regards, Igor.
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index ccc8195..059d9ac 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)