[U-Boot] [PATCH] x86: minnowmax: add GPIO mapping support

Gabriel Huau contact at huau-gabriel.fr
Wed Feb 25 17:12:56 CET 2015


Hi Simon,

With a little bit of delay here are the responses ... :)

On 02/17/2015 08:04 PM, Simon Glass wrote:
> Hi Gabriel,
>
> On 15 February 2015 at 14:55, Gabriel Huau <contact at huau-gabriel.fr> wrote:
>> Configure the pinctrl as it required to make some IO controllers
>> working (USB/UART/I2C/...).
>> The idea would be in the next version to modify the pch GPIO driver and
>> configure these pins through the device tree.
>>
>> These modifications are ported from the coreboot project.
>>
>> Signed-off-by: Gabriel Huau <contact at huau-gabriel.fr>
> Thanks for the patch!
>
> I have mostly nits except for one comment about register access which
> is different in U-Boot...
I read all the comments and I agree on almost all of them but I have 
some questions.

>> +
>> +               /* Add correct func to GPIO pad config */
>> +               pad_conf0 = config->pad_conf0;
>> +               if (config->is_gpio) {
>> +                       if (gpio >= bank->gpio_f1_range_start &&
>> +                           gpio <= bank->gpio_f1_range_end)
>> +                               pad_conf0 |= PAD_FUNC1;
>> +                       else
>> +                               pad_conf0 |= PAD_FUNC0;
>> +               }
>> +
>> +               writel(reg + PAD_CONF0_REG, pad_conf0);
>> +               writel(reg + PAD_CONF1_REG, config->pad_conf1);
>> +               writel(reg + PAD_VAL_REG, config->pad_val);
>> +       }
>> +
>> +       if (bank->legacy_base != GP_LEGACY_BASE_NONE)
>> +               for (set = 0; set <= (bank->gpio_count - 1) / 32; ++set) {
>> +                       reg = bank->legacy_base + 0x20 * set;
>> +
>> +                       outl(use_sel[set], reg + LEGACY_USE_SEL_REG);
>> +                       outl(io_sel[set], reg + LEGACY_IO_SEL_REG);
>> +                       outl(gp_lvl[set], reg + LEGACY_GP_LVL_REG);
>> +                       outl(tpe[set], reg + LEGACY_TPE_REG);
>> +                       outl(tne[set], reg + LEGACY_TNE_REG);
>> +
>> +                       /* TS registers are WOC  */
> If you know what this comment means, please spell it out without abbreviations.

Actually, I don't know the meaning of WOC and I couldn't find a 
definition in the datasheet.

>
>> +                       outl(0, reg + LEGACY_TS_REG);
>> +
>> +                       if (bank->has_wake_en)
>> +                               outl(wake_en[set], reg + LEGACY_WAKE_EN_REG);
>> +               }
>> +}
>> +
>> +static void setup_gpio_route(const struct byt_gpio_map *sus,
>> +               const struct byt_gpio_map *core)
>> +{
>> +       uint32_t route_reg = 0;
>> +       int i;
>> +
>> +       for (i = 0; i < 8; i++) {
>> +               /* SMI takes precedence and wake_en implies SCI. */
>> +               if (sus[i].smi)
>> +                       route_reg |= ROUTE_SMI << (2 * i);
>> +               else if (sus[i].sci)
>> +                       route_reg |= ROUTE_SCI << (2 * i);
>> +
>> +               if (core[i].smi)
>> +                       route_reg |= ROUTE_SMI << (2 * (i + 8));
>> +               else if (core[i].sci)
>> +                       route_reg |= ROUTE_SCI << (2 * (i + 8));
>> +       }
> What happens to route_reg after this? I don't see it get returned.
>

I will remove the code, actually it was used when the SMI was enabled.

>> +
>> +#define GPIO_LEVEL_LOW         0
>> +#define GPIO_LEVEL_HIGH                1
>> +
>> +#define GPIO_PEDGE_DISABLE     0
>> +#define GPIO_PEDGE_ENABLE      1
>> +
>> +#define GPIO_NEDGE_DISABLE     0
>> +#define GPIO_NEDGE_ENABLE      1
>> +
>> +/* config0[29] - Disable second mask */
>> +#define PAD_MASK2_DISABLE      (1 << 29)
>> +
>> +/* config0[27] - Direct Irq En */
>> +#define PAD_IRQ_EN             (1 << 27)
>> +
>> +/* config0[26] - gd_tne */
>> +#define PAD_TNE_IRQ            (1 << 26)
>> +
>> +/* config0[25] - gd_tpe */
>> +#define PAD_TPE_IRQ            (1 << 25)
>> +
>> +/* config0[24] - Gd Level */
>> +#define PAD_LEVEL_IRQ          (1 << 24)
>> +#define PAD_EDGE_IRQ           (0 << 24)
>> +
>> +/* config0[17] - Slow clkgate / glitch filter */
>> +#define PAD_SLOWGF_ENABLE      (1 << 17)
>> +
>> +/* config0[16] - Fast clkgate / glitch filter */
>> +#define PAD_FASTGF_ENABLE      (1 << 16)
>> +
>> +/* config0[15] - Hysteresis enable (inverted) */
>> +#define PAD_HYST_DISABLE       (1 << 15)
>> +#define PAD_HYST_ENABLE                (0 << 15)
>> +
>> +/* config0[14:13] - Hysteresis control */
>> +#define PAD_HYST_CTRL_DEFAULT  (2 << 13)
>> +
>> +/* config0[11] - Bypass Flop */
>> +#define PAD_FLOP_BYPASS                (1 << 11)
>> +#define PAD_FLOP_ENABLE                (0 << 11)
>> +
>> +/* config0[10:9] - Pull str */
>> +#define PAD_PU_2K              (0 << 9)
>> +#define PAD_PU_10K             (1 << 9)
>> +#define PAD_PU_20K             (2 << 9)
>> +#define PAD_PU_40K             (3 << 9)
>> +
>> +/* config0[8:7] - Pull assign */
>> +#define PAD_PULL_DISABLE       (0 << 7)
>> +#define PAD_PULL_UP            (1 << 7)
>> +#define PAD_PULL_DOWN          (2 << 7)
>> +
>> +/* config0[2:0] - Func. pin mux */
>> +#define PAD_FUNC0              0x0
>> +#define PAD_FUNC1              0x1
>> +#define PAD_FUNC2              0x2
>> +#define PAD_FUNC3              0x3
>> +#define PAD_FUNC4              0x4
>> +#define PAD_FUNC5              0x5
>> +#define PAD_FUNC6              0x6
> These could be an anonymous enum (optional)
For me, only the PAD_FUNCX could be part of an enum.
>> +
>> +/* pad config0 power-on values - We will not often want to change these */
>> +#define PAD_CONFIG0_DEFAULT    (PAD_MASK2_DISABLE     | PAD_SLOWGF_ENABLE | \
>> +                                PAD_FASTGF_ENABLE     | PAD_HYST_DISABLE | \
>> +                                PAD_HYST_CTRL_DEFAULT | PAD_FLOP_BYPASS)
> Then this could be part of the same enum, and you avoid the line continuations.

Actually, I don't really see how the enum will avoid this? Do you have 
an example somewhere of what you are thinking about?

>
>> +
>> +/* pad config1 reg power-on values - Shouldn't need to change this */
>> +#define PAD_CONFIG1_DEFAULT    0x8000
>> +
>> +/* pad_val[2] - Iinenb - active low */
>> +#define PAD_VAL_INPUT_DISABLE  (1 << 2)
>> +#define PAD_VAL_INPUT_ENABLE   (0 << 2)
>> +
>> +/* pad_val[1] - Ioutenb - active low */
>> +#define PAD_VAL_OUTPUT_DISABLE (1 << 1)
>> +#define PAD_VAL_OUTPUT_ENABLE  (0 << 1)
>> +
>> +/* Input / Output state should usually be mutually exclusive */
>> +#define PAD_VAL_INPUT          (PAD_VAL_INPUT_ENABLE | PAD_VAL_OUTPUT_DISABLE)
>> +#define PAD_VAL_OUTPUT         (PAD_VAL_OUTPUT_ENABLE | PAD_VAL_INPUT_DISABLE)
>> +
>> +/* pad_val[0] - Value */
>> +#define PAD_VAL_HIGH           (1 << 0)
>> +#define PAD_VAL_LOW            (0 << 0)
>> +
>> +/* pad_val reg power-on default varies by pad, and apparently can cause issues
>> + * if not set correctly, even if the pin isn't configured as GPIO. */
>> +#define PAD_VAL_DEFAULT                PAD_VAL_INPUT
>> +
>> +/* Configure GPIOs as MMIO by default */
>> +#define GPIO_INPUT_PU_10K(_func) \
>> +       { .pad_conf0 = PAD_FUNC##_func | PAD_PU_10K | \
>> +               PAD_PULL_UP | \
>> +               PAD_CONFIG0_DEFAULT, \
>> +         .pad_conf1 = PAD_CONFIG1_DEFAULT, \
>> +         .pad_val   = PAD_VAL_INPUT, \
>> +         .use_sel   = GPIO_USE_MMIO, \
>> +         .is_gpio   = 1 }
> I'm not a big fan of this sort of thing- #defines for structures in
> header files. It feels pretty ugly?
>
> I wonder if there is another way of doing it?
>
I agree, it's ugly, but I don't see any other 'clean' way to that. I 
believe with the device tree support we should be able to configure 
everything outside of this file.

>> +#define PIRQA                          0
>> +#define PIRQB                          1
>> +#define PIRQC                          2
>> +#define PIRQD                          3
>> +#define PIRQE                          4
>> +#define PIRQF                          5
>> +#define PIRQG                          6
>> +#define PIRQH                          7
>> +
>> +/* These registers live behind the ILB_BASE_ADDRESS */
> What what are they?
It was used for the PCI IRQ routing, but I think I can drop these 
modifications, we don't really need this in this patch.
>
>> +#define ACTL                           0x00
>> +# define SCIS_MASK                             0x07
>> +# define SCIS_IRQ9                             0x00
>> +# define SCIS_IRQ10                            0x01
>> +# define SCIS_IRQ11                            0x02
>> +# define SCIS_IRQ20                            0x04
>> +# define SCIS_IRQ21                            0x05
>> +# define SCIS_IRQ22                            0x06
>> +# define SCIS_IRQ23                            0x07
>> +
>> +#endif /* _BAYTRAIL_IRQ_H_ */
>> diff --git a/arch/x86/include/asm/arch-baytrail/irqroute.h b/arch/x86/include/asm/arch-baytrail/irqroute.h
>> new file mode 100644
>> index 0000000..f129880
>> --- /dev/null
>> +++ b/arch/x86/include/asm/arch-baytrail/irqroute.h
>> @@ -0,0 +1,67 @@
>> +/*
>> + * From Coreboot file of same name
>> + *
>> + * Copyright (C) 2014 Google, Inc
>> + * Copyright (C) 2014 Sage Electronic Engineering, LLC.
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0
>> + */
>> +
>> +#ifndef IRQROUTE_H
>> +#define IRQROUTE_H
>> +
>> +#include <asm/arch/irq.h>
>> +#include <asm/arch/pci_devs.h>
>> +
>> +/*
>> + *IR02h GFX      INT(A)                - PIRQ A
>> + *IR10h EMMC    INT(ABCD)      - PIRQ DEFG
>> + *IR11h SDIO     INT(A)                - PIRQ B
>> + *IR12h SD       INT(A)                - PIRQ C
>> + *IR13h SATA     INT(A)                - PIRQ D
>> + *IR14h XHCI     INT(A)                - PIRQ E
>> + *IR15h LP Audio INT(A)                - PIRQ F
>> + *IR17h MMC      INT(A)                - PIRQ F
>> + *IR18h SIO      INT(ABCD)     - PIRQ BADC
>> + *IR1Ah TXE      INT(A)                - PIRQ F
>> + *IR1Bh HD Audio INT(A)                - PIRQ G
>> + *IR1Ch PCIe     INT(ABCD)     - PIRQ EFGH
>> + *IR1Dh EHCI     INT(A)                - PIRQ D
>> + *IR1Eh SIO      INT(ABCD)     - PIRQ BDEF
>> + *IR1Fh LPC      INT(ABCD)     - PIRQ HGBC
>> + */
>> +#define PCI_DEV_PIRQ_ROUTES \
>> +       PCI_DEV_PIRQ_ROUTE(GFX_DEV,    A, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(EMMC_DEV,   D, E, F, G), \
>> +       PCI_DEV_PIRQ_ROUTE(SDIO_DEV,   B, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(SD_DEV,     C, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(SATA_DEV,   D, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(XHCI_DEV,   E, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(LPE_DEV,    F, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(MMC45_DEV,  F, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(SIO1_DEV,   B, A, D, C), \
>> +       PCI_DEV_PIRQ_ROUTE(TXE_DEV,    F, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(HDA_DEV,    G, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(PCIE_DEV,   E, F, G, H), \
>> +       PCI_DEV_PIRQ_ROUTE(EHCI_DEV,   D, A, A, A), \
>> +       PCI_DEV_PIRQ_ROUTE(SIO2_DEV,   B, D, E, F), \
>> +       PCI_DEV_PIRQ_ROUTE(PCU_DEV,    H, G, B, C)
>> +
> Is this actually used? In general I think this sort of monstrosity is
> better off in a C file.

It was when I was doing the IRQ routing, but I dropped the function as 
this is not necessary at the moment, I will remove it.

Thanks,
Regards,
Gabriel


More information about the U-Boot mailing list