设为首页 加入收藏

TOP

在f1c100s芯片上移植spi网卡enc28j60的linux驱动(三)
2023-09-09 10:25:37 】 浏览:169
Tags:f1c100s spi 网卡 enc28j60 linux 驱动
6, 1, 9)), SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x2, "csi"), /* D7 */ SUNXI_FUNCTION(0x3, "uart2"), /* CTS */ SUNXI_FUNCTION(0x4, "spi1"), /* MISO */ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x2, "clk0"), /* OUT */ SUNXI_FUNCTION(0x3, "i2c0"), /* SCK */ SUNXI_FUNCTION(0x4, "ir"), /* RX */ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x2, "i2s"), /* MCLK */ SUNXI_FUNCTION(0x3, "i2c0"), /* SDA */ SUNXI_FUNCTION(0x4, "pwm0"), /* PWM0 */ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)),

所以,我们现在知道了function这个字符串的值域。那么对于外部中断引脚,应该怎么填function呢?像spi的功能,上面的代码告诉我们,直接填spi1,那么SUNXI_FUNCTION_IRQ_BANK又是个啥?继续看它的头文件pinctrl-sunxi.h

#define SUNXI_FUNCTION_IRQ(_val, _irq)    \
{       \
        .name = "irq",     \
        .muxval = _val,     \
        .irqnum = _irq,     \
}

#define SUNXI_FUNCTION_IRQ_BANK(_val, _bank, _irq)  \
{       \
        .name = "irq",     \
        .muxval = _val,     \
        .irqbank = _bank,    \
        .irqnum = _irq,     \
}

所以我猜对于中断引脚,我们应该把function设置为irq,这样他就会自动帮我们初始化这个引脚的复用功能(全志可能没这个说法)。

接下来让我们修改suniv-f1c100s-licheepi-nano.dts

&spi1{
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&spi1_pins>;
        enc28j60: ethernet@0 {
                compatible = "microchip,enc28j60";
                pinctrl-names = "default";
                pinctrl-0 = <&enc28j60_pins>;
                reg = <0>;
                interrupt-parent = <&pio>;
                interrupts = <4 11 IRQ_TYPE_EDGE_FALLING>;
                spi-max-frequency = <12000000>;
        };
};

这里基本就是对着全志设备树,照着它文档抄了。现在我们也可以解答一下我高中时代的疑问。这个interrupt-parent是啥呢?interrupt-parent属性用于指定中断路由到的控制器,并包含引用中断控制器节点的单个 phandle。 该属性是继承的,因此可以在中断客户端节点或其任何父节点中指定。 “中断”属性中列出的中断始终引用节点的中断父级。翻译成人话就是它用的中断要对应在哪个中断控制器,至少在本芯片内是一种些许无用的抽象,因为f1c100s就一个简单的中断控制器INTC,但是对于更复杂的片上中断控制器则是特别好的设计。并且这样做也方便了我们配置外部引脚的中断。

dtsi中的#interrupt-cells = <3>告诉我们,interrupts这个属性应该有3个元素。通过翻其它全志的设备树,我们也知道了应该要如何配置interrupts这个属性。那就是先放引脚Port的编号,那就是A放0,B放1,C放2,D放3,E放4。。。第二个参数是引脚编号,我们用的PE11,直接填。第三个参数,直接抄模块的文档。

现在已经大功告成,让我们拷贝好设备树和内核镜像,准备启动!

第三步:启动内核

启动内核后,我们dmesg,发现并没有任何关于enc28j60的影子,甚至连关于spi的影子也没有,这是怎么回事呢?再折腾了好几天后,我发现这是因为spi根本就没有被加载。我们芯片设备树对spi的配置中是这样配置compatible属性的:"allwinner,suniv-spi", "allwinner,sun8i-h3-spi",事实上,linux内核中根本没有代码去适配allwinner,suniv-spi,所以内核会去找allwinner,sun8i-h3-spi。而在drivers/spi/spi-sun6i.c中:

static const struct of_device_id sun6i_spi_match[] = {
        { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
        { .compatible = "allwinner,sun8i-h3-spi",  .data = &sun8i_h3_spi_cfg },
        {
                .compatible = "allwinner,sun50i-r329-spi",
                .data = &sun50i_r329_spi_cfg

所以我们来到内核配置Device Drivers ---> SPI support,发现allwinner的spi就俩,一个Allwinner A31 SPI controller,一个Allwinner A31 SPI controller。查看Kconfig后发现,后者对应的symbol是SPI_SUN6I。故我们应该将后者设置成Y。而我之前是将前者设置成Y,后者设置成了N。

再次启动内核,一切都顺利

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇使用Yocto进行嵌入式Linux开发3 T.. 下一篇S905L3A(M401A)拆解, 运行EmuELEC..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目