One more item: the Ingenic SoCs have the somewhat unusual feature that many registers are implemented as set/reset flip-flops, and to change a bit you have to write a 1 to the corresponding set or clear register.
For example, to set pin PD09 to "1", you would write the value 1 << 9 to PDDATS. To set it back to "0", you would write 1 << 9 to PDDATC instead. To set pins PD08 and PD09, you would write 1 << 8 | 1 << 9 to PDDATS, etc. USB uses differential signaling. This means that if D+ is 0, D- must be 1, and vice versa. The exception to this rule are some special conditions, like the end-of-packet indication, where both are set to 0. This is called a "single-ended 0", abbreviated as "SE0". All this is summarized in table 7-2 on page 145 of the USB 2.0 specification. Changing a pair of pins where one goes 0 -> 1 and the other goes 1 -> 0 requires two writes - one to PxDATS to set the pin that should become "1", and another one to PxDATC to clear the pin that should become "0". This has two undesirable properties: 1) port register accesses are slow and this therefore burns quite a few CPU cycles, 2) there will be a small delay between the pin changes. For USB, this means that during this short delay, the bus will be in an invalid configuration. I don't know if this will cause trouble for low-speed USB, but I wouldn't be surprised if it did. Here's an idea for how one could perhaps avoid this problem: - configure the GPIO to output D+ = 1, D- = 0 (or the opposite) - configure the MMC controller to output, on the same pins, D+ = 0, D- = 1. - to send a differential "1" (D+ = 1, D- = 0), let the GPIOs have the pins - to send a differential "0" (D+ = 0, D- = 1), let the MMC controller have the pins A pin is switched between GPIO and a funcion, e.g., MMC, through the "function" register. Again, this register is not set directly, but its bits are set or cleared through a set and a clear register, respectively. With the above approach, the bits in the function register both change in the same direction with switching between differential 0 and differential 1, so only a single write is needed. To send a single-ended "0" (SE0) (D+ = 0, D- = 0), one would clear the GPIO data bit for D+ and switch to GPIOs. To return from SE0 to differential "1", one would simply set the D+ data bit again. I've illustrated this here: http://downloads.qi-hardware.com/people/werner/ubb/usb/pin-change.pdf The two flip-flops on top are for the GPIO data. In the middle is the MMC controller. The two flip-flops at the bottom are for selecting whether a pin is used as GPIO or for a function. The pair of multiplexers right of the MMC controller switch to GPIO if the corresponding PDFUN bit is 0 and to MMC if the bit is 1. A few detail remarks and clarifications: - the naming convention for the port registers is P<port><purpose><access> where <port> is A, B, ... <purpose> is DAT for the value output on the GPIO, FUN is the GPIO/function selection, and so on (see the section on "General-Purpose I/O Ports" in the JZ4720 or JZ4740 Programming Manual) <access> is S for set, C for clean, or nothing for reading the register's current value. - all the MMC pins are on port D. The register names and bit numbers shown in the drawing are the ones that actually correspond to CLK and CMD. - in the Ingenic CPU, whether a function block has access to a given pin is controlled on that pin. Enabling or disabling the function block per se is independent from its access to pins. This is different from the way some microcontrollers handle this, where enabling a function block automatically assigns a set of I/O pins to it. - it should be relatively easy to make the MMC controller output a constant bit pattern by setting it to a low clock frequency and making it begin sending an MMC command. Then, when CMD and CLK have the desired value, stop the clock. All the necessary ingredients for selecting the clock and, erm, controlling the controller can be found in ubb-vga.c Note that the MMC bus clock is the 336 MHZ main clock divided first by 1...32 according to register MSCCDR and then by 2^0...2^7 according to register MSC_CLKRT. - I haven't thought this through enough to be sure whether it's more convenient to configure the GPIOs for a differential "1" and MMC for a differential "0", or the other way around. I think the best choice - if it makes a difference at all - will automatically emerge during development. - I don't know whether switching a pin between function and GPIO is "smooth" or whether there can be glitches. And I also don't know if such a switch is, as I assume here, as fast as setting/clearing the port's data bit would be. All this would have to be verified by measurement. - Werner _______________________________________________ Qi Hardware Discussion List Mail to list (members only): [email protected] Subscribe or Unsubscribe: http://lists.en.qi-hardware.com/mailman/listinfo/discussion

