reset驅(qū)動(dòng)實(shí)例
類似于clock驅(qū)動(dòng),reset驅(qū)動(dòng)也是編進(jìn)內(nèi)核的,在Linux啟動(dòng)時(shí),完成reset驅(qū)動(dòng)的加載。
設(shè)備樹(shù)
reset:reset-controller{
compatible = "xx,xx-reset";
reg = < 0x0 0xc0000000 0x0 0x1000 >;
#reset-cells = < 1 >;
};
上述是一個(gè)reset控制器的節(jié)點(diǎn),0xc0000000
是寄存器基址,0x1000
是映射大小。#reset-cells
代表引用該reset時(shí)需要的cells個(gè)數(shù)。
例如,#reset-cells = <1>;
則正確引用為:
mmc:mmc@0x12345678{
......
resets = < &reset 0 >;//0代表reset設(shè)備id,id是自定義的,但是不能超過(guò)reset驅(qū)動(dòng)中指定的設(shè)備個(gè)數(shù)
......
};
驅(qū)動(dòng)編寫
reset驅(qū)動(dòng)編寫的基本步驟:
1、實(shí)現(xiàn)struct reset_control_ops
結(jié)構(gòu)體中的.reset
、.assert
、.deassert
、.status
函數(shù)
2、分配struct reset_controller_dev
結(jié)構(gòu)體,填充ops
、owner
、nr_resets
等成員內(nèi)容
3、調(diào)用reset_controller_register
函數(shù)注冊(cè)reset設(shè)備
以下是從實(shí)際項(xiàng)目中分離出來(lái)的reset驅(qū)動(dòng)代碼:
#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 >
// 自定義芯片廠的結(jié)構(gòu)體,保存寄存器基址等信息
struct xx_reset{
struct reset_controller_dev rcdev;
void __iomem *base;
//......
};
static int xx_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:先復(fù)位,延遲一會(huì),然后解復(fù)位
return 0;
}
static int xx_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:復(fù)位
return 0;
}
static int xx_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:解復(fù)位
return 0;
}
static int xx_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
{
//操作寄存器:獲取復(fù)位狀態(tài)
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操作函數(shù)集合
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設(shè)備個(gè)數(shù)
return reset_controller_register(&xx_reset- >rcdev);//注冊(cè)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");
-
內(nèi)核
+關(guān)注
關(guān)注
3文章
1408瀏覽量
41084 -
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1898瀏覽量
86511 -
Linux
+關(guān)注
關(guān)注
87文章
11456瀏覽量
212750
發(fā)布評(píng)論請(qǐng)先 登錄
Linux clock子系統(tǒng)及驅(qū)動(dòng)實(shí)例

Linux reset子系統(tǒng)及驅(qū)動(dòng)實(shí)例

Linux內(nèi)核空間設(shè)備驅(qū)動(dòng)程序的開(kāi)發(fā)
Android的Linux內(nèi)核與驅(qū)動(dòng)程序開(kāi)發(fā)教程

基于Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究
linux內(nèi)核驅(qū)動(dòng)第三版
《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第4章、Linux內(nèi)核模塊

Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究

基于Linux與Busybox的Reboot命令流程分析

如何使用Linux內(nèi)核實(shí)現(xiàn)USB驅(qū)動(dòng)程序框架

Linux內(nèi)核代碼60%都是驅(qū)動(dòng)?

Linux reset子系統(tǒng)有什么功能

評(píng)論