GPIO和SPI之间的关系是什么?

时间:2015-07-26 09:44:25

标签: linux-kernel raspberry-pi driver gpio spi

我发现内核中的GPIO驱动程序离开/sys/class/gpio来控制gpio,但我发现GPIO也可以由/dev/mem控制,我发现这个映射可以在spi-bcm2708中完成(其中将__ioremap称为平台驱动程序,但我不了解spi和GPIO之间的关系,它们如何在linux中协同工作?

1 个答案:

答案 0 :(得分:3)

据我所知,您正在谈论this驱动程序(例如,在Raspberry Pi中使用)。首先,看看BCM2835 datasheet。查看下一节:

  • 1.1概述
  • 6.0通用I / O(GPIO)
  • 6.2替代功能分配(见表6-31)

从驱动程序代码(参见bcm2708_init_pinmode()函数)和数据表(表6-31),我们可以看到SPI引脚实际上是GPIO7..11引脚。这些引脚实际上可以连接到不同的hardware modules(在这种情况下为SPI或SD)。

Alternative Functions Assignment

使用pin muxing完成此类选择。所以基本上你需要将GPIO7..GPIO11引脚连接到SPI模块。为此,您需要为每个GPIO7..GPIO11引脚选择 ALT0 功能。这可以通过将相应的值写入 GPFSEL0 GPFSEL1 寄存器来完成(参见数据表中的表6-1..6-3):

GPFSEL0 address

GPFSELn register description

这就是司机实际上是这样做的:

/*
 * This function sets the ALT mode on the SPI pins so that we can use them with
 * the SPI hardware.
 *
 * FIXME: This is a hack. Use pinmux / pinctrl.
 */
static void bcm2708_init_pinmode(void)
{
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define SET_GPIO_ALT(g, a) *(gpio+(((g)/10))) |= (((a) <= 3 ? (a)+4 : (a) == 4 ? 3 : 2)<<(((g)%10)*3))

    int pin;
    u32 *gpio = ioremap(GPIO_BASE, SZ_16K);

    /* SPI is on GPIO 7..11 */
    for (pin = 7; pin <= 11; pin++) {
        INP_GPIO(pin);      /* set mode to GPIO input first */
        SET_GPIO_ALT(pin, 0);   /* set mode to ALT 0 */
    }

    iounmap(gpio);

#undef INP_GPIO
#undef SET_GPIO_ALT
}

对我来说看起来很快,他们实际上提到了它:正确的方法是使用名为pinctrl的内核机制。

结论:BCM2708驱动器实际上并不触发任何GPIO引脚,它只是执行引脚复用以便将GPIO7..GPIO11引脚连接到SPI模块。为此,该驱动程序写入GPFSELn寄存器,这恰好是GPIO寄存器。这几乎是该驱动程序中SPI和GPIO之间的所有关系。

P.S。:如果您对SPI和GPIO之间可能的关系感到好奇,请阅读bit banging。请参阅Linux内核中的spi-bitbang.c驱动程序。