亚洲综合图片区自拍_思思91精品国产综合在线观看_一区二区三区欧美_欧美黑人又粗又大_亚洲人成精品久久久久桥本

世界消息!Linux reset子系統(tǒng)及驅(qū)動實(shí)例

2023-05-31 16:12:27 來源:嵌入式Linux充電站

上篇講了Linuxclock驅(qū)動,今天說說Linux的reset驅(qū)動。

時鐘和復(fù)位是兩個不同的驅(qū)動,但通常都是由負(fù)責(zé)clock驅(qū)動的人,把reset驅(qū)動完成。同樣,reset驅(qū)動也是由芯片廠商去完成的。


【資料圖】

Linux reset子系統(tǒng)

reset子系統(tǒng)非常簡單,與clock子系統(tǒng)非常類似,但在驅(qū)動實(shí)現(xiàn)上,reset驅(qū)動更簡單。

因?yàn)閏lock驅(qū)動主要是時鐘的實(shí)現(xiàn),涉及到固定時鐘、分頻、門控等一些時鐘的分級關(guān)系,需要弄清楚時鐘樹里每個時鐘的關(guān)系。

而reset驅(qū)動有點(diǎn)相當(dāng)于clock驅(qū)動的門控,它只有復(fù)位和解復(fù)位兩個功能。

類似于clock子系統(tǒng),reset子系統(tǒng)也分為了consumerprovider,結(jié)構(gòu)體關(guān)系如下:

consumer

reset API接口的使用者,內(nèi)核提供了統(tǒng)一的reset接口:

devm_reset_control_get(struct device *dev, const char *id)//獲取reset句柄< font >< /font >reset_control_deassert(struct reset_control *rstc)//解復(fù)位< font >< /font >reset_control_assert(struct reset_control *rstc)//復(fù)位< font >< /font >reset_control_reset(struct reset_control *rstc)//先復(fù)位,延遲一會,然后解復(fù)位< font >< /font >

struct reset_control結(jié)構(gòu)體表示一個reset句柄,驅(qū)動中使用reset API,需要先獲取reset句柄

provider

reset提供者,即reset驅(qū)動。struct reset_controller_dev結(jié)構(gòu)體代表一個reset控制器,內(nèi)部包含了reset操作函數(shù)集合struct reset_control_ops,注冊reset驅(qū)動時,需要分配一個struct reset_controller_dev結(jié)構(gòu)體,然后填充成員,最后將該結(jié)構(gòu)體注冊。

struct reset_controller_dev{< font >< /font >    const struct reset_control_ops *ops;//復(fù)位控制操作函數(shù)< font >< /font >    struct list_headlist;//全局鏈表,復(fù)位控制器注冊后掛載到全局鏈表< font >< /font >    struct list_head reset_control_head;//各個模塊復(fù)位的鏈表頭< font >< /font >    struct device *dev;< font >< /font >    int of_reset_n_cells;//dts中引用時,需要幾個參數(shù)< font >< /font >        < font >< /font >    //通過dts引用的參數(shù),解析復(fù)位控制器中相應(yīng)的參數(shù)< font >< /font >    int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec);< font >< /font >    unsigned int nr_resets;//復(fù)位設(shè)備個數(shù)< font >< /font >}< font >< /font >< font >< /font >struct reset_control_ops{< font >< /font >    int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);//復(fù)位+解復(fù)位< font >< /font >    int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);//復(fù)位< font >< /font >    int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);//解復(fù)位< font >< /font >    int (*status)(struct reset_controller_dev *rcdev, unsigned long id);//復(fù)位狀態(tài)查詢< font >< /font >}< font >< /font >

reset復(fù)位API說明

devm_reset_control_get

struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
作用:獲取相應(yīng)的reset句柄參數(shù):dev:指向申請reset資源的設(shè)備句柄id:指向要申請的reset資源名(字符串),可以為NULL返回:成功:返回reset句柄失?。悍祷豊ULL

reset_control_deassert

int reset_control_deassert(struct reset_control *rstc)
作用:對傳入的reset資源進(jìn)行解復(fù)位操作參數(shù):rstc:指向申請reset資源的設(shè)備句柄返回:成功:返回0失敗:返回錯誤碼

reset_control_assert

int reset_control_assert(struct reset_control *rstc)
作用:對傳入的reset資源進(jìn)行復(fù)位操作。

參數(shù)和返回值與reset_control_deassert相同

reset_control_reset

int reset_control_reset(struct reset_control *rstc)
作用:對傳入的reset資源先進(jìn)行復(fù)位操作,然后等待5us,再進(jìn)行解復(fù)位操作。相當(dāng)于執(zhí)行了一遍reset_control_assert后,然后delay一會,再調(diào)用reset_control_deassert

reset API使用示例

基本步驟:

1、調(diào)用devm_reset_control_get()獲取reset句柄

2、調(diào)用reset_control_assert()進(jìn)行復(fù)位操作

3、調(diào)用reset_control_deassert()進(jìn)行解復(fù)位操作

static int xx_probe(struct platform_device *pdev)< font >< /font >{< font >< /font >< font >< /font > struct device_node* np = pdev- >dev.of_node;< font >< /font > ......< font >< /font >< font >< /font >    /* 1、獲取reset句柄 */< font >< /font > host- >rstc = devm_reset_control_get(&pdev- >dev, np- >name);< font >< /font > if (IS_ERR(host- >rstc)) {< font >< /font >  dev_err(&pdev- >dev, "No reset controller specified\\n");< font >< /font >  return PTR_ERR(host- >rstc);< font >< /font > }< font >< /font >< font >< /font > if (host- >rstc) {< font >< /font >        /* 2、復(fù)位 */< font >< /font >  ret = reset_control_assert(host- >rstc);< font >< /font >  if (ret) {< font >< /font >   dev_err(&pdev- >dev, "unable to reset_control_assert\\n");< font >< /font >   return ret;< font >< /font >  }< font >< /font >  udelay(1);< font >< /font > < font >< /font >        /* 3、解復(fù)位 */< font >< /font >  ret = reset_control_deassert(host- >rstc);< font >< /font >  if (ret) {< font >< /font >   dev_err(&pdev- >dev, "unable to reset_control_deassert\\n");< font >< /font >   return ret;< font >< /font >  }< font >< /font > }< font >< /font > ......< font >< /font >}< font >< /font >

reset驅(qū)動實(shí)例

類似于clock驅(qū)動,reset驅(qū)動也是編進(jìn)內(nèi)核的,在Linux啟動時,完成reset驅(qū)動的加載。

設(shè)備樹

reset:reset-controller{< font >< /font > compatible = "xx,xx-reset";< font >< /font > reg = < 0x0 0xc0000000 0x0 0x1000 >;< font >< /font > #reset-cells = < 1 >;< font >< /font >};< font >< /font >

上述是一個reset控制器的節(jié)點(diǎn),0xc0000000是寄存器基址,0x1000是映射大小。 #reset-cells代表引用該reset時需要的cells個數(shù)。

例如,#reset-cells = <1>;則正確引用為:

mmc:mmc@0x12345678{< font >< /font >    ......< font >< /font >    resets = < &reset  0 >;//0代表reset設(shè)備id,id是自定義的,但是不能超過reset驅(qū)動中指定的設(shè)備個數(shù)< font >< /font >    ......< font >< /font >};< font >< /font >

驅(qū)動編寫

reset驅(qū)動編寫的基本步驟:

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、ownernr_resets等成員內(nèi)容

3、調(diào)用reset_controller_register函數(shù)注冊reset設(shè)備

以下是從實(shí)際項(xiàng)目中分離出來的reset驅(qū)動代碼:

#include < linux/of.h >< font >< /font >#include < linux/module.h >< font >< /font >#include < linux/of_device.h >< font >< /font >#include < linux/reset-controller.h >< font >< /font >#include < linux/io.h >< font >< /font >#include < linux/delay.h >< font >< /font >< font >< /font >// 自定義芯片廠的結(jié)構(gòu)體,保存寄存器基址等信息< font >< /font >struct xx_reset{< font >< /font > struct reset_controller_dev rcdev;< font >< /font > void __iomem *base;< font >< /font >    //......< font >< /font >};< font >< /font >< font >< /font >< font >< /font >static int xx_reset(struct reset_controller_dev *rcdev, unsigned long id)< font >< /font >{< font >< /font > //操作寄存器:先復(fù)位,延遲一會,然后解復(fù)位< font >< /font > return 0;< font >< /font >}< font >< /font >< font >< /font >static int xx_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)< font >< /font >{< font >< /font > //操作寄存器:復(fù)位< font >< /font > return 0;< font >< /font >}< font >< /font >< font >< /font >static int xx_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)< font >< /font >{< font >< /font > //操作寄存器:解復(fù)位< font >< /font > return  0;< font >< /font >}< font >< /font >< font >< /font >static int xx_reset_status(struct reset_controller_dev *rcdev, unsigned long id)< font >< /font >{< font >< /font > //操作寄存器:獲取復(fù)位狀態(tài)< font >< /font > return 0; < font >< /font >}< font >< /font >< font >< /font >static struct reset_control_ops xx_reset_ops = {< font >< /font > .rest = xx_rest,< font >< /font > .assert = xx_reset_asser,< font >< /font > .deassert = xx_reset_deassert,< font >< /font > .status = xx_rest_status,< font >< /font >};< font >< /font >< font >< /font >static int xx_reset_probe(struct platform_device *pdev)< font >< /font >{< font >< /font > struct xx_reset *xx_reset;< font >< /font > struct resource *res;< font >< /font > < font >< /font > xx_reset = devm_kzalloc(&pdev- >dev, sizeof(*xx_reset), GFP_KERNEL);< font >< /font > if (!xx_reset)< font >< /font >  return -ENOMEM;< font >< /font >< font >< /font > platform_set_drvdata(pdev, xx_reset);< font >< /font >< font >< /font > res = platform_get_resource(pdev, IORESOURCE_MEM, 0);< font >< /font > xx_reset- >base = devm_ioremap_resource(&pdev- >dev, res);//映射寄存器基址< font >< /font > if (IS_ERR(xx_reset- >base))< font >< /font >  return PTR_ERR(xx_reset- >base);< font >< /font >< font >< /font > xx_reset- >rcdev.ops = &xx_reset_ops;//reset_ops操作函數(shù)集合< font >< /font > xx_reset- >rcdev.owner = THIS_MODULE;< font >< /font > xx_reset- >rcdev.of_node = pdev- >dev.of_node;< font >< /font > xx_reset- >rcdev.of_reset_n_cells = 1;  < font >< /font > xx_reset- >rcdev.nr_resets = BITS_PER_LONG;//reset設(shè)備個數(shù)< font >< /font >< font >< /font > return reset_controller_register(&xx_reset- >rcdev);//注冊reset controller< font >< /font > < font >< /font >}< font >< /font >< font >< /font >< font >< /font >static int xx_reset_remove(struct platform_device *pdev)< font >< /font >{< font >< /font > struct xx_reste *xx_reset = platform_get_drvdata(pdev);< font >< /font > < font >< /font > reset_controller_unregister(&xx_reset- >rcdev);< font >< /font > return 0;< font >< /font >}< font >< /font >< font >< /font >static const struct of_device_id ak_reset_of_match[]={< font >< /font > {.compatible = "xx,xx-reset"},< font >< /font > {},< font >< /font >};< font >< /font >< font >< /font >MODULE_DEVICE_TABLE(of, xx_reset_of_match);< font >< /font >< font >< /font >static struct platform_driver xx_reset_driver = {< font >< /font > .probe = xx_reset_probe,< font >< /font > .remove = xx_reset_remove,< font >< /font > .driver = {< font >< /font >  .name = "xx-reset",< font >< /font >  .of_match_table = ak_reset_of_match,< font >< /font > },< font >< /font >};< font >< /font >< font >< /font >< font >< /font >module_platorm_driver(xx_reset_driver);< font >< /font >< font >< /font >MODULE_LICENSE("GPL");< font >< /font >MODULE_DESCPRIPTION("xx reset controller driver");< font >< /font >MODULE_AUTHOR("xx Microelectronic");< font >< /font >MODULE_VERSION("v1.0.00");< font >< /font >

標(biāo)簽:

上一篇:PCB Layout設(shè)計(jì)要點(diǎn)與技巧-世界即時
下一篇:最后一頁