GPIO Configuration

GPIO setup is done for every board variant, but never for the baseboard, by configuring the file ./board/<board>/gpio.inc. This file configures all the the pins on the EC chipset through the following macros.

  • GPIO(<name>, ...) - Configures simple GPIO input and outputs
  • GPIO_INT(<name>, ...) - Configures GPIO inputs that connect to an interrupt service routine. Historically these entries are defined first, but this no longer required.
  • ALTERNATE(...) - Configures a pin for an alternate function (e.g I2C, ADC, SPI, etc)
  • UNIMPLEMENTED(<name>, ...) - Creates a fake GPIO entry

The GPIO(), GPIO_INT(), and UNIMPLEMENTED() macros create a C enumeration of the form GPIO_<name> that can be used in the code. As noted in GPIO Naming, the <name> parameter should always match the schematic net name.

GPIO() macro

Prototype

GPIO(name, pin, flags)

  • name - Defines the schematic net name, which is expanded to the enumeration GPIO_name by the macro.
  • pin - Use the PIN(group,pin) macro to define the GPIO group and pin number. Note that on a few EC chipsets, the PIN macro is just PIN(pin).
  • flags - Define attributes of the pin (direction, pullup/pulldown, open drain, voltage level, etc). All supported flags are found following the GPIO_FLAG_NONE definition in ./include/gpio.h.

Example

GPIO Example

GPIO(EC_ENTERING_RW, PIN(E, 3), GPIO_OUT_LOW)

The EC common code requires the enum GPIO_ENTERING_RW to be defined, so you should also map the net name to the EC name in the board.h file.

#define GPIO_ENTERING_RW    GPIO_EC_ENTERING_RW

GPIO_INT() macro

Prototype

GPIO_INT(name, pin, flags, signal)

  • name - Defines the schematic net name, which is expanded to the enumeration GPIO_name by the macro.
  • pin - Same definition as GPIO() macro.
  • flags - Same definition as GPIO() macro. Should always have one of the GPIO_INT_* flags set.
  • signal - Interrupt service routine called when the pin asserts according to the flags set.

Example

GPIO_INT Example

GPIO_INT(EC_LID_OPEN, PIN(D, 2), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, lid_interrupt)

The EC common code requires the enum GPIO_LID_OPEN to be defined, so you als need to map the net name to the EC name in the board.h file.

#define GPIO_LID_OPEN       GPIO_EC_LID_OPEN

ALTERNATE() macro

Prototype

ALTERNATE(pinmask, function, module, flags)

  • pinmask - Defines a set of pins in the same GPIO group to assign to a different function.
  • function - A chip-specific function number. Only used if the EC chipset provides multiple alternate functions in addition to GPIO (e.g. pin can be UART, I2C, SPI, or GPIO). The permitted values for this parameter vary based on the EC chipset type.
    • STM32 - 0 to 7
    • Maxim - 1 to 3
    • Microchip - 0 to 3
    • MediaTek - 0 to 7
    • All others (Nuvton, ITE, TI Stellaris, ) only support one alternate function per pin, so this parameter should be set to 0.
  • module - One of the enum module_id values defined in ./include/module_id.h.
  • flags - Same definition as GPIO() macro.

Notes

At runtime there are two mechanisms for switching a pin between GPIO mode and alternate function mode.

  • gpio_config_module(enum module_id id, int enable) - Configures all pins matching the module enumeration id.
  • gpio_config_pin(enum module_id id, enum gpio_signal signal, int enable) - Configures a single pin matching the GPIO enumeration signal.

For both routines, if enable is 1, then the corresponding pins are configured for alternate mode operation. If enable is 0, then the corresponding pins are configure for GPIO mode.

gpio_config_module() is automatically called at runtime for all enabled interfaces (I2C, SPI, UART, etc). You can use gpio_config_pin() to temporarily configure a pin for GPIO operation, and to restore the original alternate function. The I2C bus error recovery employs this mechanism to temporarily driver the I2C SCL and SDA signals to known states, without interference by the I2C controller in the EC chipset.

The general recipe for overriding alternate functions is shown below.

    /* Disconnect I2C1_SDA pin from I2C controller */
    gpio_config_pin(MODULE_I2C, GPIO_I2C1_SDA, 0);

    /* Setup I2C1_SDA as an GPIO open drain output and drive initial state low */
    gpio_set_flags(GPIO_I2C1_SDA, GPIO_ODR_LOW);

    /* Set GPIO high (or low) as required */
    gpio_set_level (GPIO_I2C1_SDA, 1);

    /* Restore I2C1_SDA pin to I2C function */'
    gpio_config_pin(MODULE_I2C, GPIO_I2C1_SDA, 1);

Example

ALTERNATE Example

ALTERNATE(PIN_MASK(B, BIT(4) | BIT(5)), 0, MODULE_I2C, (GPIO_INPUT | GPIO_SEL_1P8V))