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 (Application Programming Interface) was developed to make resource management trivial. Blackfin Interface Please consult the HRM ((Blackfin) Hardware Reference Manual) 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 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 (General Purpose Input/Output) 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 (Application Programming Interface) is based on that. This hides the exact pins that are bound to a peripheral on that processor variant. 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 (Serial Peripheral Interface) peripheral directly with a specific SPI (Serial Peripheral Interface) CS, then it would do something like: ... #include ... 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.