mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 07:34:31 +00:00
209 lines
7.7 KiB
Text
209 lines
7.7 KiB
Text
|
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.
|