|  | AVR32 Port multiplexer configuration | 
|  | ==================================== | 
|  |  | 
|  | On AVR32 chips, most external I/O pins are routed through a port | 
|  | multiplexer. There are currently two kinds of port multiplexer | 
|  | hardware around with different register interfaces: | 
|  |  | 
|  | * PIO (AT32AP700x; this is also used on ARM AT91 chips) | 
|  | * GPIO (all other AVR32 chips) | 
|  |  | 
|  | The "PIO" variant supports multiplexing up to two peripherals per pin | 
|  | in addition to GPIO (software control). Each pin has configurable | 
|  | pull-up, glitch filter, interrupt and multi-drive capabilities. | 
|  |  | 
|  | The "GPIO" variant supports multiplexing up to four peripherals per | 
|  | pin in addition to GPIO. Each pin has configurable | 
|  | pull-up/pull-down/buskeeper, glitch filter, interrupt, open-drain and | 
|  | schmitt-trigger capabilities, as well as configurable drive strength | 
|  | and slew rate control. | 
|  |  | 
|  | Both controllers are configured using the same API, but the functions | 
|  | may accept different values for some parameters depending on the | 
|  | actual portmux implementation, and some parameters may be ignored by | 
|  | one of the implementation (e.g. the "PIO" implementation will ignore | 
|  | the drive strength flags since the hardware doesn't support | 
|  | configurable drive strength.) | 
|  |  | 
|  | Selecting the portmux implementation | 
|  | ------------------------------------ | 
|  | Since u-boot is lacking a Kconfig-style configuration engine, the | 
|  | portmux implementation must be selected manually by defining one of | 
|  | the following symbols: | 
|  |  | 
|  | CONFIG_PORTMUX_PIO | 
|  | CONFIG_PORTMUX_GPIO | 
|  |  | 
|  | depending on which implementation the chip in question uses. | 
|  |  | 
|  | Identifying pins | 
|  | ---------------- | 
|  | The portmux configuration functions described below identify the pins | 
|  | to act on based on two parameters: A "port" (i.e. a block of pins | 
|  | that somehow belong together) and a pin mask. Both are defined in an | 
|  | implementation-specific manner. | 
|  |  | 
|  | The available ports are defined on the form | 
|  |  | 
|  | #define PORTMUX_PORT_A	(something) | 
|  |  | 
|  | where "A" matches the identifier given in the chip's data sheet, and | 
|  | "something" is whatever the portmux implementation needs to identify | 
|  | the port (usually a memory address). | 
|  |  | 
|  | The pin mask is a bitmask where each '1' bit indicates a pin to apply | 
|  | the current operation to. The width of the bitmask may vary from port | 
|  | to port, but it is never wider than 32 bits (which is the width of | 
|  | 'unsigned long' on avr32). | 
|  |  | 
|  | Selecting functions | 
|  | ------------------- | 
|  | Each pin can either be assigned to one of a predefined set of on-chip | 
|  | peripherals, or it can be set up to be controlled by software. For the | 
|  | former case, the portmux implementation defines an enum containing all | 
|  | the possible peripheral functions that can be selected. For example, | 
|  | the PIO implementation, which allows multiplexing two peripherals per | 
|  | pin, defines it like this: | 
|  |  | 
|  | enum portmux_function { | 
|  | PORTMUX_FUNC_A, | 
|  | PORTMUX_FUNC_B, | 
|  | }; | 
|  |  | 
|  | To configure a set of pins to be connected to a given peripheral | 
|  | function, the following function is used. | 
|  |  | 
|  | void portmux_select_peripheral(void *port, unsigned long pin_mask, | 
|  | enum portmux_function func, unsigned long flags); | 
|  |  | 
|  | To configure a set of pins to be controlled by software (GPIO), the | 
|  | following function is used. In this case, no "function" argument is | 
|  | required since "GPIO" is a function in its own right. | 
|  |  | 
|  | void portmux_select_gpio(void *port, unsigned int pin_mask, | 
|  | unsigned long flags); | 
|  |  | 
|  | Both of these functions take a "flags" parameter which may be used to | 
|  | alter the default configuration of the pin. This is a bitmask of | 
|  | various flags defined in an implementation-specific way, but the names | 
|  | of the flags are the same on all implementations. | 
|  |  | 
|  | PORTMUX_DIR_OUTPUT | 
|  | PORTMUX_DIR_INPUT | 
|  |  | 
|  | These mutually-exlusive flags configure the initial direction of the | 
|  | pins. PORTMUX_DIR_OUTPUT means that the pins are driven by the CPU, | 
|  | while PORTMUX_DIR_INPUT means that the pins are tristated by the CPU. | 
|  | These flags are ignored by portmux_select_peripheral(). | 
|  |  | 
|  | PORTMUX_INIT_HIGH | 
|  | PORTMUX_INIT_LOW | 
|  |  | 
|  | These mutually-exclusive flags configure the initial state of the | 
|  | pins: High (Vdd) or low (Vss). They are only effective when | 
|  | portmux_select_gpio() is called with the PORTMUX_DIR_OUTPUT flag set. | 
|  |  | 
|  | PORTMUX_PULL_UP | 
|  | PORTMUX_PULL_DOWN | 
|  | PORTMUX_BUSKEEPER | 
|  |  | 
|  | These mutually-exclusive flags are used to enable any on-chip CMOS | 
|  | resistors connected to the pins. PORTMUX_PULL_UP causes the pins to be | 
|  | pulled up to Vdd, PORTMUX_PULL_DOWN causes the pins to be pulled down | 
|  | to Vss, and PORTMUX_BUSKEEPER will keep the pins in whatever state | 
|  | they were left in by whatever was driving them last. If none of the | 
|  | flags are specified, the pins are left floating if no one are driving | 
|  | them; this is only recommended for always-output pins (e.g. extern | 
|  | address and control lines driven by the CPU.) | 
|  |  | 
|  | Note that the "PIO" implementation will silently ignore the | 
|  | PORTMUX_PULL_DOWN flag and interpret PORTMUX_BUSKEEPER as | 
|  | PORTMUX_PULL_UP. | 
|  |  | 
|  | PORTMUX_DRIVE_MIN | 
|  | PORTMUX_DRIVE_LOW | 
|  | PORTMUX_DRIVE_HIGH | 
|  | PORTMUX_DRIVE_MAX | 
|  |  | 
|  | These mutually-exlusive flags determine the drive strength of the | 
|  | pins. PORTMUX_DRIVE_MIN will give low power-consumption, but may cause | 
|  | corruption of high-speed signals. PORTMUX_DRIVE_MAX will give high | 
|  | power-consumption, but may be necessary on pins toggling at very high | 
|  | speeds. PORTMUX_DRIVE_LOW and PORTMUX_DRIVE_HIGH specify something in | 
|  | between the other two. | 
|  |  | 
|  | Note that setting the drive strength too high may cause excessive | 
|  | overshoot and EMI problems, which may in turn cause signal corruption. | 
|  | Also note that the "PIO" implementation will silently ignore these | 
|  | flags. | 
|  |  | 
|  | PORTMUX_OPEN_DRAIN | 
|  |  | 
|  | This flag will configure the pins as "open drain", i.e. setting the | 
|  | pin state to 0 will drive it low, while setting it to 1 will leave it | 
|  | floating (or, in most cases, let it be pulled high by an internal or | 
|  | external pull-up resistor.) In the data sheet for chips using the | 
|  | "PIO" variant, this mode is called "multi-driver". | 
|  |  | 
|  | Enabling specific peripherals | 
|  | ----------------------------- | 
|  | In addition to the above functions, each chip provides a set of | 
|  | functions for setting up the port multiplexer to use a given | 
|  | peripheral. The following are some of the functions available. | 
|  |  | 
|  | All the functions below take a "drive_strength" parameter, which must | 
|  | be one of the PORTMUX_DRIVE_x flags specified above.  Any other | 
|  | portmux flags will be silently filtered out. | 
|  |  | 
|  | To set up the External Bus Interface (EBI), call | 
|  |  | 
|  | void portmux_enable_ebi(unsigned int bus_width, | 
|  | unsigned long flags, unsigned long drive_strength) | 
|  |  | 
|  | where "bus_width" must be either 16 or 32. "flags" can be any | 
|  | combination of the following flags. | 
|  |  | 
|  | PORTMUX_EBI_CS(x)	/* Enable chip select x */ | 
|  | PORTMUX_EBI_NAND	/* Enable NAND flash interface */ | 
|  | PORTMUX_EBI_CF(x)	/* Enable CompactFlash interface x */ | 
|  | PORTMUX_EBI_NWAIT	/* Enable NWAIT signal */ | 
|  |  | 
|  | To set up a USART, call | 
|  |  | 
|  | void portmux_enable_usartX(unsigned long drive_strength); | 
|  |  | 
|  | where X is replaced by the USART instance to be configured. | 
|  |  | 
|  | To set up an ethernet MAC: | 
|  |  | 
|  | void portmux_enable_macbX(unsigned long flags, | 
|  | unsigned long drive_strength); | 
|  |  | 
|  | where X is replaced by the MACB instance to be configured. "flags" can | 
|  | be any combination of the following flags. | 
|  |  | 
|  | PORTMUX_MACB_RMII	/* Just set up the RMII interface */ | 
|  | PORTMUX_MACB_MII	/* Set up full MII interface */ | 
|  | PORTMUX_MACB_SPEED	/* Enable the SPEED pin */ | 
|  |  | 
|  | To set up the MMC controller: | 
|  |  | 
|  | void portmux_enable_mmci(unsigned long slot, unsigned long flags | 
|  | unsigned long drive_strength); | 
|  |  | 
|  | where "slot" identifies which of the alternative SD card slots to | 
|  | enable. "flags" can be any combination of the following flags: | 
|  |  | 
|  | PORTMUX_MMCI_4BIT	/* Enable 4-bit SD card interface */ | 
|  | PORTMUX_MMCI_8BIT	/* Enable 8-bit MMC+ interface */ | 
|  | PORTMUX_MMCI_EXT_PULLUP	/* Board has external pull-ups */ | 
|  |  | 
|  | To set up a SPI controller: | 
|  |  | 
|  | void portmux_enable_spiX(unsigned long cs_mask, | 
|  | unsigned long drive_strength); | 
|  |  | 
|  | where X is replaced by the SPI instance to be configured. "cs_mask" is | 
|  | a 4-bit bitmask specifying which of the four standard chip select | 
|  | lines to set up as GPIOs. |