# Intel Pad to Macro (intelp2m) converter

The utility generates `output/gpio.h` with the GPIO configuration for SoC or PCH from intel. Use it to create coreboot port for your motherboard in the `src/mainboard/your-motherboard` directory. Depending on the settings, you can create several configuration formats:

- coreboot macros;

- Intel FSP macros.

Installing the latest version:

    go install review.coreboot.org/coreboot.git/util/intelp2m@master

Including in the project as an external library:

    go get review.coreboot.org/coreboot.git/util/intelp2m@master

## Build

Since the utility is written in Go, you need to install the official go-compiler and go-tools to build the executive image.

    cd util/intelp2m
    make

Set automatic argument completion:

    complete -C `pwd`/intelp2m ./intelp2m

## Demo

    ./intelp2m -platform snr -file parser/testlog/inteltool_test.log

## Input data

The chipset register dump obtained using inteltool is used as input data.

    cd util/inteltool
    make
    sudo ./inteltool -G > inteltool.log

After this step, you can generate `gpio.h`:

    ./intelp2m -file ../inteltool/inteltool.log

More details in the help:

    ./intelp2m -h

## Platforms

The utility supports the following chipsets from Intel:

- `adl` - Alder Lake PCH

- `apl` - Apollo Lake SoC

- `cnl` - CannonLake-LP or Whiskeylake/Coffeelake/Cometlake-U SoC

- `ebg` - Emmitsburg PCH with Xeon SP

- `ehl` - Elkhart Lake SoC

- `jsl` - Jasper Lake SoC

- `lbg` - Lewisburg PCH with Xeon SP

- `mtl` - MeteorLake SoC

- `snr` - Sunrise PCH or Skylake/Kaby Lake SoC

- `tgl` - TigerLake-H SoC

The `-platform` option allows you to identify one of the above platforms:

    ./intelp2m -platform <platform> -file path/to/inteltool.log

Show more details:

    ./intelp2m -platform ?

## Auto-check macro

The utility automatically checks the bit fields of the GPIO registers before generating the macro. If the bit is set to 1 in a register but isn’t used in the “short” macro, the “long” macro is generated. This avoids data loss in the configuration.

    // the "short" macro:
    PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_39, UP_20K, DEEP, NF1, TxLASTRxE, DISPUPD),

    // the "long" macro:
    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

    // [*] PAD_TRIG(OFF) isn't used in the "short" macro.

The option `-u`, `-unchecked` is used to disable automatic verification. In this case, all macros in `gpio.h` are generated in the “short” format:

    ...
    PAD_NC(GPP_F18, NONE),
    PAD_CFG_NF(GPP_F19, NONE, PLTRST, NF1),
    ...

    ./intelp2m -unchecked -platform apl -file path/to/inteltool.log

## Excluding fields from the macro

The utility can generate “long” macros without fields that aren’t used in “short” ones. The `-e`, `-exclude` option is used to exclude these fields from the generated macros in `gpio.h`:

    ./intelp2m -exclude -platform apl -file path/to/inteltool.log

    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

    // [*] PAD_TRIG(OFF) field was excluded from the "long" macro.

## Packages

    +-------------------------------------------------------------------+
    |                              main                                 |
    +-------------------------------------------------------------------+
                             |                 |                 |
                             V                 V                 V
    +------------+   +--------------+   +-------------+   +-------------+
    |  template  |<--|    parser    |   |  generator  |   |   printer   |
    +------------+   +--------------+   +-------------+   +-------------+
                             |
                             V
    +-------------------------------------------------------------------+
    |                           platforms                               |
    +-------------------------------------------------------------------+
        |          |          |          |          |               |
        V          V          V          V          V               V
    +-------+  +-------+  +-------+  +-------+  +-------+       +-------+
    |  adl  |  |  apl  |  |  cnl  |  |  lbg  |  |  snr  | * * * | other |
    +-------+  +-------+  +-------+  +-------+  +-------+       +-------+
        |          |          |          |          |               |
        V          V          V          V          V               V
    +-------------------------------------------------------------------+
    |                             common                                |
    +-------------------------------------------------------------------+
                      |                           |              |
                      V                           |              |
    +------------------------------------+        |              |
    |               fields               |        |              |
    +------------------------------------+        |              |
         |            |             |             |              |
         V            V             V             V              V
    +--------+   +---------+   +---------+  +-----------+  +------------+
    |   cb   |   |   raw   |   |   fsp   |  |   macro   |  |  register  |
    +--------+   +---------+   +---------+  +-----------+  +------------+

## Format

Depending on the options -i, -ii, -iii, -iiiii (information level), the utility can generate the configuration in different formats:

    ./intelp2m [-i | -ii | -iii | -iiii] -platform apl -file path/to/inteltool.log

- i adding a function name:

    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)), /* LPSS_UART0_TXD */

- ii adds configuration register values:

    /* GPIO_39 - LPSS_UART0_TXD */
    /* DW0: 0x44000400, DW1: 0x00003100 */
    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

- iii adds information about ignored fields:

    /* GPIO_39 - LPSS_UART0_TXD */
    /* DW0: 0x44000400, DW1: 0x00003100 */
    /* DW0 : PAD_TRIG(OFF) - IGNORED */
    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

- iiii adds the “short” macro corresponding to the current one (possibly after excluding unused fields):

    /* GPIO_39 - LPSS_UART0_TXD */
    /* DW0: 0x44000400, DW1: 0x00003100 */
    /* DW0: PAD_TRIG(OFF) - IGNORED */
    /* PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_39, UP_20K, DEEP, NF1, TxLASTRxE, DISPUPD), */
    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

The same without automatic check:

    /* GPIO_39 - LPSS_UART0_TXD */
    /* DW0: 0x44000400, DW1: 0x00003100 */
    /* DW0: PAD_TRIG(OFF) - IGNORED */
    /* _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)), */
    PAD_CFG_NF_IOSSTATE_IOSTERM(GPIO_39, UP_20K, DEEP, NF1, TxLASTRxE, DISPUPD),

iiii generates an original macro in the comments.

## Long macros with fields collection

Depending on the value of the option -fields, the utility can generate long macros with different styles of the field collection:

    ./intelp2m -fields [fsp | cb | raw] -platform apl -file ../apollo-inteltool.log

- fsp

    { GPIO_SKL_H_GPP_A12, { GpioPadModeGpio, GpioHostOwnAcpi, GpioDirInInvOut, GpioOutLow, GpioIntSci | GpioIntLvlEdgDis, GpioResetNormal GpioTermNone, GpioPadConfigLock },

- cb

    _PAD_CFG_STRUCT(GPIO_39, PAD_FUNC(NF1) | PAD_RESET(DEEP) | PAD_TRIG(OFF), PAD_PULL(UP_20K) | PAD_IOSTERM(DISPUPD)),

- raw

    _PAD_CFG_STRUCT(GPP_A10, 0x44000500, 0x00000000),

Show more details:

    ./intelp2m -fields ?

## For developers

### Version

    ./intelp2m -version

The version string includes several parts:

    {major}.{minor}-{last commit in the intelp2m directory}-{?dirty}

`major` - incompatible API changes (e.g. remove or update a command line option); `minor` - new platform, new feature or adding a new command line option.

The version is added to the generated `gpio.h` file and it is necessary to support the project.

    /* Pad configuration was generated automatically using intelp2m 2.5-870c694 */
    static const struct pad_config gpio_table[] = {
    ...

Please do not remove this information, as it makes support easier!

### Adding support for new platforms

The platform-dependent code is located in `./platforms/`. Each PCH and SoC is in a separate package with a name corresponding to this platform (adl, apl, snr, …). The macro generation code for all platforms is in the `common` directory.

The package file must contain the structure `BasePlatform struct{}` with methods for the `PlatformIf interface{}` from the `common` package:

    type PlatformIf interface {
    	RemapResetSource(*Macro)
    	Pull(*Macro)
    	AddGpiMacro(*Macro)
    	AddGpoMacro(*Macro)
    	AddNativeFunctionMacro(*Macro)
    	AddNoConnMacro(*Macro)
    	GetRegisterDW0() *register.DW0
    	GetRegisterDW1() *register.DW1
    }

Some methods (for example, register access methods: `GetRegisterDW0()` and `GetRegisterDW1()`) are already defined in the base platform from `common`. Therefore, embedding should be used in the basic platform structure to avoid code duplication:

    type BasePlatform struct {
    	common.BasePlatform
    }

Since GPIO controllers are similar across intel platforms, the macro generation code can also be reused. You can use any platform instead of `common.BasePlatform` from the catalog to reuse its methods and redefine those that differ in logic.

The platform file should also contain the slice `GPPGroups[]` with templates for pad names from `inteltool.log`, register masks `DW0` and `DW1` (the analysis will be only for the bits in these masks), the base platform constructor - `InitBasePlatform()`, and `GetPlatform()` that provides the platform interface.

    const (
    	DW0Mask = (0b1 << 27) | (0b1 << 18) | (0b00111111 << 11) | (0b00111111 << 2) | (0b1 << 1)
    	DW1Mask = 0b11111101111111111100001111111111
    )

    // "GPP_A", "GPP_B", "GPP_C", "GPP_D", "GPP_E", "GPP_F", "GPP_G", "GPP_H", "GPP_R", "GPP_S",
    // "GPP_T", "GPD", "HVMOS", "VGPIO5"
    var GPPGroups = []string{"GPP_", "GPD", "VGPIO"}

    type BasePlatform struct {
    	// based on the Cannon Lake platform
    	cnl.BasePlatform
    }

    func InitBasePlatform(dw0, dw0mask uint32, dw1, dw1mask uint32) BasePlatform {
    	return BasePlatform{cnl.InitBasePlatform(dw0, dw0mask, dw1, dw1mask)}
    }

    func GetPlatform(dw0, dw1 uint32) common.PlatformIf {
    	p := InitBasePlatform(dw0, DW0Mask, dw1, DW1Mask)
    	return &p
    }

    // Override BasePlatform.RemapResetSource()
    func (p *BasePlatform) RemapResetSource(m *common.Macro) {
        // Some code is here
    }

- Use `GetPlatform()` and `GPPGroups[]` in the file `./platform/platform.go` to define the resources for the parser.

- Add the platform argument for the options `-p` (`-platform`) to `cli/options.go`.

- Update the documentation in `Documentation/util/intelp2m/index.md`.

- Add unit tests.

Here is an example of porting the Intel Jasper lake platform.

### Unit testing

Please run the tests before creating a new commit:

    make test

If successful, all tests contain the PASS prefix.