概述
本章主要是翻译《spi-howto.txt》,文档路径u-boot/doc/driver-model/spi-howto.txt。
主要是介绍如何porting spi driver到driver model中。
这篇文章以exynos spi driver移植到driver model(DM)为例子一步步介绍如何将一个spi驱动移植到驱动模型中,文章比较长,因为涉及实际的代码例子,例子代码基于U-Boot v2014.10-rc2(commit be9f643)。
在DM之前,SPI驱动将struct spi_slave放到它们自己的私有数据结构中。在DM中,struct spi_slave仍然存在,但是它是以spi bus的per-child data存在。每个child就是spi bus的一个spi slave。意味着可以将struct spi_slave从驱动指定的slave结构中移植到spi bus的私有数据中。
例如如下的struct tegra_spi_slave结构,slave应该是per-child data,而ctrl可以作为SPI的总线私有数据。
struct tegra_spi_slave {
struct spi_slave slave;
struct tegra_spi_ctrl *ctrl;
};
0. 需要花多长时间?
您应该能够在2小时内完成此操作,包括测试,但不包括准备补丁。API与以前基本相同,只有细微的变化:
- 设置速度和模式的方法是分开的
- cs_info用于获取芯片选择信息
1. 打开驱动模型以及spi flash
在板子配置文件中添加这些宏:
CONFIG_DM_SPI
CONFIG_DM_SPI_FLASH
2. 添加框架
将此代码放在现有驱动程序文件的底部:
struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
return NULL;
}
struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
int spi_node)
{
return NULL;
}
static int exynos_spi_ofdata_to_platdata(struct udevice *dev)
{
return -ENODEV;
}
static int exynos_spi_probe(struct udevice *dev)
{
return -ENODEV;
}
static int exynos_spi_remove(struct udevice *dev)
{
return -ENODEV;
}
static int exynos_spi_claim_bus(struct udevice *dev)
{
return -ENODEV;
}
static int exynos_spi_release_bus(struct udevice *dev)
{
return -ENODEV;
}
static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
return -ENODEV;
}
static int exynos_spi_set_speed(struct udevice *dev, uint speed)
{
return -ENODEV;
}
static int exynos_spi_set_mode(struct udevice *dev, uint mode)
{
return -ENODEV;
}
static int exynos_cs_info(struct udevice *bus, uint cs,
struct spi_cs_info *info)
{
return -ENODEV;
}
static const struct dm_spi_ops exynos_spi_ops = {
.claim_bus = exynos_spi_claim_bus,
.release_bus = exynos_spi_release_bus,
.xfer = exynos_spi_xfer,
.set_speed = exynos_spi_set_speed,
.set_mode = exynos_spi_set_mode,
.cs_info = exynos_cs_info,
};
static const struct udevice_id exynos_spi_ids[] = {
{ .compatible = "samsung,exynos-spi" },
{ }
};
U_BOOT_DRIVER(exynos_spi) = {
.name = "exynos_spi",
.id = UCLASS_SPI,
.of_match = exynos_spi_ids,
.ops = &exynos_spi_ops,
.ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
.probe = exynos_spi_probe,
.remove = exynos_spi_remove,
};
3. 修改框架名称
把上面代码中的exynos替换为你的驱动名字
4. 隔开旧代码
用#ifdef把驱动文件中非上述的代码隔开,这就允许编译它,这意味着您可以逐步工作。由于所有方法最初都会返回错误,你不小心把东西留在里面的可能性较小。
此外,尽管基本上对你来说是在重写,但是保留之前的函数在文件相同的地方对review的人来说是由帮助的,特别是对于大型的驱动来说。
5. 添加一些头文件
在你的驱动中添加这些头文件:
<

最低0.47元/天 解锁文章
1213

被折叠的 条评论
为什么被折叠?



