回答

收藏

[评测分享] 【百度大脑AI计算盒FZ5C】firmware power 驱动代码分析

#板卡评测 #板卡评测 1941 人阅读 | 0 人回复 | 2021-04-15

【百度大脑AI计算盒FZ5C】firmware power 驱动代码分析

# 设备树
  1. zynqmp_power: zynqmp-power {
  2.     u-boot,dm-pre-reloc;
  3.     compatible = "xlnx,zynqmp-power";
  4.     interrupt-parent = <&gic>;
  5.     interrupts = <0 35 4>;
  6.     mboxes = <&ipi_mailbox_pmu1 0>,
  7.          <&ipi_mailbox_pmu1 1>;
  8.     mbox-names = "tx", "rx";
  9. };
复制代码
# match table
  1. static const struct of_device_id pm_of_match[] = {
  2.     { .compatible = "xlnx,zynqmp-power", },
  3.     { /* end of table */ },
  4. };
  5. MODULE_DEVICE_TABLE(of, pm_of_match);
复制代码
# driver
  1. static struct platform_driver zynqmp_pm_platform_driver = {
  2.     .probe = zynqmp_pm_probe,
  3.     .remove = zynqmp_pm_remove,
  4.     .driver = {
  5.         .name = "zynqmp_power",
  6.         .of_match_table = pm_of_match,
  7.     },
  8. };
  9. module_platform_driver(zynqmp_pm_platform_driver);
复制代码
# probe:调用了 eemi_ops 的两个方法,创建工作堆列,用到了 mailbox,收到 mailbox 消息添加工作队列,回复消息
  1. static int zynqmp_pm_probe(struct platform_device *pdev)
  2. {
  3.     int ret, irq;
  4.     u32 pm_api_version;
  5.     struct mbox_client *client;

  6.     eemi_ops = zynqmp_pm_get_eemi_ops();
  7.     if (IS_ERR(eemi_ops))
  8.         return PTR_ERR(eemi_ops);

  9.     if (!eemi_ops->get_api_version || !eemi_ops->init_finalize)
  10.         return -ENXIO;

  11.     eemi_ops->init_finalize();
  12.     eemi_ops->get_api_version(&pm_api_version);

  13.     /* Check PM API version number */
  14.     if (pm_api_version < ZYNQMP_PM_VERSION)
  15.         return -ENODEV;

  16.     if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) {
  17.         zynqmp_pm_init_suspend_work =
  18.             devm_kzalloc(&pdev->dev,
  19.                      sizeof(struct zynqmp_pm_work_struct),
  20.                      GFP_KERNEL);
  21.         if (!zynqmp_pm_init_suspend_work)
  22.             return -ENOMEM;

  23.         INIT_WORK(&zynqmp_pm_init_suspend_work->callback_work,
  24.               zynqmp_pm_init_suspend_work_fn);
  25.         client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
  26.         if (!client)
  27.             return -ENOMEM;

  28.         client->dev = &pdev->dev;
  29.         client->rx_callback = ipi_receive_callback;

  30.         rx_chan = mbox_request_channel_byname(client, "rx");
  31.         if (IS_ERR(rx_chan)) {
  32.             dev_err(&pdev->dev, "Failed to request rx channel\n");
  33.             return IS_ERR(rx_chan);
  34.         }
  35.     } else if (of_find_property(pdev->dev.of_node, "interrupts", NULL)) {
  36.         irq = platform_get_irq(pdev, 0);
  37.         if (irq <= 0)
  38.             return -ENXIO;

  39.         ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
  40.                         zynqmp_pm_isr,
  41.                         IRQF_NO_SUSPEND | IRQF_ONESHOT,
  42.                         dev_name(&pdev->dev),
  43.                         &pdev->dev);
  44.         if (ret) {
  45.             dev_err(&pdev->dev, "devm_request_threaded_irq '%d' "
  46.                         "failed with %d\n", irq, ret);
  47.             return ret;
  48.         }
  49.     } else {
  50.         dev_err(&pdev->dev, "Required property not found in DT node\n");
  51.         return -ENOENT;
  52.     }

  53.     ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
  54.     if (ret) {
  55.         dev_err(&pdev->dev, "unable to create sysfs interface\n");
  56.         return ret;
  57.     }

  58.     return 0;
  59. }
复制代码
# 总结:仅初始化,确认版本,调用了 firmware 驱动
# power 是自己实现的功能,通过 mailbox 传递消息,通过工作队列调整电源状态。更深层面是不是继续调用 firmware 方法,暂时未知






分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条