reset驅動實例
類似于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");
-
內核
+關注
關注
3文章
1372瀏覽量
40278 -
驅動
+關注
關注
12文章
1838瀏覽量
85262 -
Linux
+關注
關注
87文章
11292瀏覽量
209329
發布評論請先 登錄
相關推薦
評論