类似于clock驱动,reset驱动也是编进内核的,在Linux启动时,完成reset驱动的加载。
reset:reset-controller{
compatible = "xx,xx-reset";
reg = < 0x0 0xc0000000 0x0 0x1000 >;
#reset-cells = < 1 >;
};
上述是一个reset控制器的节点,0xc0000000
是寄存器基址,0x1000
是映射大小。#reset-cells
代表引用该reset时需要的cells个数。
例如,#reset-cells = <1>;
则正确引用为:
mmc:mmc@0x12345678{
......
resets = < &reset 0 >;//0代表reset设备id,id是自定义的,但是不能超过reset驱动中指定的设备个数
......
};
reset驱动编写的基本步骤:
1、实现struct reset_control_ops
结构体中的.reset
、.assert
、.deassert
、.status
函数
2、分配struct reset_controller_dev
结构体,填充ops
、owner
、nr_resets
等成员内容
3、调用reset_controller_register
函数注册reset设备
以下是从实际项目中分离出来的reset驱动代码:
#include < linux/of.h >
#include < linux/module.h >
#include < linux/of_device.h >
#include < linux/reset-controller.h >
#include < linux/io.h >
#include < linux/delay.h >
// 自定义芯片厂的结构体,保存寄存器基址等信息
struct xx_reset{
struct reset_controller_dev rcdev;
void __iomem *base;
//......
};
static int xx_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:先复位,延迟一会,然后解复位
return 0;
}
static int xx_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:复位
return 0;
}
static int xx_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:解复位
return 0;
}
static int xx_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:获取复位状态
return 0;
}
static struct reset_control_ops xx_reset_ops = {
.rest = xx_rest,
.assert = xx_reset_asser,
.deassert = xx_reset_deassert,
.status = xx_rest_status,
};
static int xx_reset_probe(struct platform_device *pdev)
{
struct xx_reset *xx_reset;
struct resource *res;
xx_reset = devm_kzalloc(&pdev- >dev, sizeof(*xx_reset), GFP_KERNEL);
if (!xx_reset)
return -ENOMEM;
platform_set_drvdata(pdev, xx_reset);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xx_reset- >base = devm_ioremap_resource(&pdev- >dev, res);//映射寄存器基址
if (IS_ERR(xx_reset- >base))
return PTR_ERR(xx_reset- >base);
xx_reset- >rcdev.ops = &xx_reset_ops;//reset_ops操作函数集合
xx_reset- >rcdev.owner = THIS_MODULE;
xx_reset- >rcdev.of_node = pdev- >dev.of_node;
xx_reset- >rcdev.of_reset_n_cells = 1;
xx_reset- >rcdev.nr_resets = BITS_PER_LONG;//reset设备个数
return reset_controller_register(&xx_reset- >rcdev);//注册reset controller
}
static int xx_reset_remove(struct platform_device *pdev)
{
struct xx_reste *xx_reset = platform_get_drvdata(pdev);
reset_controller_unregister(&xx_reset- >rcdev);
return 0;
}
static const struct of_device_id ak_reset_of_match[]={
{.compatible = "xx,xx-reset"},
{},
};
MODULE_DEVICE_TABLE(of, xx_reset_of_match);
static struct platform_driver xx_reset_driver = {
.probe = xx_reset_probe,
.remove = xx_reset_remove,
.driver = {
.name = "xx-reset",
.of_match_table = ak_reset_of_match,
},
};
module_platorm_driver(xx_reset_driver);
MODULE_LICENSE("GPL");
MODULE_DESCPRIPTION("xx reset controller driver");
MODULE_AUTHOR("xx Microelectronic");
MODULE_VERSION("v1.0.00");
全部0条评论
快来发表一下你的评论吧 !