二,在内核代码增加一个spi的设备 1,根据硬件我们的mcp2515是挂在在spi0的接口中,不同的板子对应的内核实现都不一样 N32926 增加一个spi的是设备是在linux-2.6.35.4/arch/arm/mach-w55fa92/dev.c中 可以其他板子是在 mach-xxx.c中注册一个spi的设备具体可以搜索 spi_register_board_info(structspi_board_info const *info, unsigned n) 函数说明 structspi_board_info 结构体 structspi_board_info { char modalias[SPI_NAME_SIZE];//定义的spi设备名字 const void *platform_data; //平台数据 void *controller_data; int irq; //中断号 u32 max_speed_hz;
u16 bus_num;//spi u16 chip_select; u8 mode;// 模式选择 }; 在 dev.c中定义了 staticstruct spi_board_info w55fa92_spi_board_info[] __initdata{ ………. };
因此我们把mcp2515所需的数据定义到这个数组中 staticstruct mcp251x_platform_data mcp251x_info = { .oscillator_frequency = 8000000, }; staticstruct spi_board_info w55fa92_spi_board_info[] __initdata = { { .modalias ="mcp2515", .bus_num = 0, .chip_select = 0, .platform_data =&mcp251x_info, .irq = W55FA92_IRQ(2), .max_speed_hz = 2*1000*1000, .mode = SPI_MODE_0, },
}; 最终spi注册 void__init w55fa92_dev_init() { platform_add_devices(w55fa92_public_dev,ARRAY_SIZE(w55fa92_public_dev));//注册平台设备 spi_register_board_info(w55fa92_spi_board_info,ARRAY_SIZE(w55fa92_spi_board_info));//注册spi设备 } 貌似驱动方面搞定了?看上去好像很简单。那我们编译一下吧! 编译成功后。 重新启动板子 发现can驱动报错: mcp251xspi0.0: MCP251x didn't enter in conf mode after reset mcp251xspi0.0: Probe failed mcp251xspi0.0: probe failed 这是什么情况?于是我跟了一下代码 /* Here is OK to not lock the MCP, no oneknows about it yet */ if(!mcp251x_hw_probe(spi)) { dev_info(&spi->dev,"Probe failed\n"); gotoerror_probe; } static int mcp251x_hw_probe(structspi_device *spi) { intst1, st2;
mcp251x_hw_reset(spi);
st1= mcp251x_read_reg(spi, CANSTAT) & 0xEE; st2= mcp251x_read_reg(spi, CANCTRL) & 0x17;
dev_dbg(&spi->dev,"CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2);
/*Check for power up default values */ return(st1 == 0x80 && st2 == 0x07) ? 1 : 0; } static int mcp251x_hw_reset(structspi_device *spi) { structmcp251x_priv *priv = dev_get_drvdata(&spi->dev); intret; unsignedlong timeout;
priv->spi_tx_buf[0]= INSTRUCTION_RESET;//¸´Î»Ö¸Áî ret= spi_write(spi, priv->spi_tx_buf, 1); if(ret) { dev_err(&spi->dev,"reset failed: ret = %d\n", ret); return-EIO; }
/*Wait for reset to finish */ timeout= jiffies + HZ; mdelay(10); while((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) { schedule(); if(time_after(jiffies, timeout)) { dev_err(&spi->dev,"MCP251x didn't" "enter in conf mode after reset\n"); return-EBUSY; } } return0; }
|