As always, thanks for the responses Hannu and Pasi! Your help has been instrumental in helping move this project forward.
Hannu wrote: ↑Mon 2022-06-27 13:50
I am also on uncharted waters and I'll try to get you a better answer, but USB_UTMIW register is the one register to poke.
Ok. I wasn't sure if there were additional registers that weren't documented due to not normally needing to be accessed directly. I haven't tried, but I don't think the UTMIW registers would be helpful. I will investigate further
I took a look at the spec and then I remembered again that this is USB. Too many TLAs and ETLAs for my taste to give quick answer.

I understand! No need for too much investigation
So you want USBP 1.5k pull-up and USBN 15k pull-down. Is there need for some signaling ? Or just to keep the system passive and resistors on?
The USB DCP spec is simple. A DCP is something like the power adapter you plug into a mains outlet and has a USB port that you plug devices in to charge, such as phones etc. The spec says that such a charger should have D+ & D- on its port shorted together with no more than 200 Ohms. Since such a charger is "dumb" because it provides no capability for enumeration, the device being charged needs to be able to detect the short on D+/D-. The way the spec recommends it is to drive the D+ line to 3.3V, and have a resistor on D-. Then, you read the state of D-, and if it is high, then it is shorted to D+, meaning it is a DCP device. Of course, you might want to toggle the 3.3V on D+ and check the results on D- just to make sure.
So there is no signaling. Just need a way to check for a short.
I found this from kernel sources (scsi.c) and optimized it for you
Code: Select all
u_int16 MyUSBReadLines(void) {
return PERIP(USB_UTMIR)>>14;
}
/* Actually fastest implementation: #define MyUSBReadLines() (PERIP(USB_UTMIR)>>14) */
Thanks for this! It was right in front of my eyes, and I didn't see it. Time for some glasses
This gets me most of the way there.
What else is needed, I don't currently know. Some hints could be found from UsbHost porgram code and umsc code from kernel If you want to have an interesting journey around USB hardware.
I spent much of last week digging through the usbmsc and related code trying to figure out how to implement multiple configuration descriptors. Pretty sure I got it figured out and have all the relevant code for enumeration in place, but I haven't tested it yet. I am not an expert programmer, so a lot of the VLSI code looks like magic that I'll never understand
pasi wrote: ↑Mon 2022-06-27 16:53
A few starting points:
- To control the resistors, the USB needs to be set to NOHIGHSPEED and enabled in USB_CF, and naturally all respective analog powers and bias generators enabled in the ANA_CF registers.
- For the host pull-downs the USB needs to be in host (master) mode, possibly. For the 1.5k pull-up it needs to be slave mode, possibly.
This is the impression that the UTM bit tables gives me as well as another comment in the datasheet. It was the graphic in figure 23 that gave me some doubt.
- USB_UTMIW is the register to try. You can control what gets put in the USB pins by setting the UTMIW_ORIDE, set OPMODE to 2, and set either J or K. But if I understood, you don't want the pins to drive, just the host pull-downs. There are also RCVSEL and TERMSEL. I would try setting ORIDE and then seeing what those SEL signals do.
To my understanding, all chirps are differential, so it wouldn't work. Thanks for the tips on ORIDE and the OPMODEs. The function of these were a bit of a mystery to me.
Unfortunately I don't have time right at the moment to measure what happens.
No problem! You have helped me plenty!
I think the UTMIR_LSTATE bits and the D+ pull-up resistor gets me almost there. I will also need to do something about the 1M pull-up resistors on D+/D- which I now understand are used for the MyUSBIsDetached() function. Maybe the remainder of my solution lays in switching these resistors in and out of circuit, high and low, as necessary, directly from GPIO? That way I can still use the technique for connection detection and switching them out so as to not interfere with DCP detection, or maybe even help with it.
Any thoughts driving those resistors from GPIO instead of directly from AVDD? As in, is it a bad idea for some reason?