world leader in high performance signal processing
Trace: » portmux

Peripheral Multiplexers (portmuxing)

Many pins on modern processors are able to act in different modes at any particular time, such as a GPIO or with different peripherals. Often times, related pins are grouped together under the same I/O port. This helps to simplify management a bit at the lowest levels. The exact details of muxing specific pins in specific modes tends to be highly specific down to processor variants. So a Blackfin 548 will be vastly different from a Blackfin 533.

Since management of these pins can quickly explode out of control, a simple API was developed to make resource management trivial.

Blackfin Interface

Please consult the HRM for your processor variant for specific details.

Linux/U-Boot Framework

All of the relevant prototypes and defines for the portmux framework can be found in the asm/portmux.h header file.

#include <asm/portmux.h>

The portmux core takes care of managing resource conflicts and setting the Blackfin peripheral MMRs so that the pin(s) in question are muxed to the desired functionality. It also takes care of detecting conflicts with pins that have already been reserved for GPIO functionality.

Pin Allocation

There are two sets of simple functions to reserve and release pins for specific functionality. Since driver code is geared towards specific peripherals, the API is based on that. This hides the exact pins that are bound to a peripheral on that processor variant.

file: arch/blackfin/include/asm/portmux.h

scm failed with exit code 1:
file does not exist in git

The “list” variants of these functions should be an array of pins that are terminated by the value 0. The request functions are of the “all or nothing” type, so there is no need to worry about partial requests.

Example Allocation

If a driver wants to use the SPI peripheral directly with a specific SPI CS, then it would do something like:

...
#include <asm/portmux.h>
...
 
int some_init_func(...)
{
    ...
    const unsigned short pins[] = { P_SPI0_MOSI, P_SPI0_MISO, P_SPI0_SCK, P_SPI0_SSEL1, 0 };
    ...
    if (peripheral_request_list(pins, "my-driver")) {
        ... do some error handling ...
    }
    ...
}
 
int some_fini_func(...)
{
    ...
    const unsigned short pins[] = { P_SPI0_MOSI, P_SPI0_MISO, P_SPI0_SCK, P_SPI0_SSEL1, 0 };
    ...
    peripheral_free_list(pins);
    ...
}

Pin Defines

Each arch has a portmux.h header which defines all of the pins that are available for requesting. For dedicated pins that do not have portmuxing capabilities, “no-op” defines are provided so that code can be ported across variants without any changes.

Complete Table of Contents/Topics