dfl-fme-br.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * FPGA Bridge Driver for FPGA Management Engine (FME)
  4. *
  5. * Copyright (C) 2017-2018 Intel Corporation, Inc.
  6. *
  7. * Authors:
  8. * Wu Hao <hao.wu@intel.com>
  9. * Joseph Grecco <joe.grecco@intel.com>
  10. * Enno Luebbers <enno.luebbers@intel.com>
  11. * Tim Whisonant <tim.whisonant@intel.com>
  12. * Ananda Ravuri <ananda.ravuri@intel.com>
  13. * Henry Mitchel <henry.mitchel@intel.com>
  14. */
  15. #include <linux/module.h>
  16. #include <linux/fpga/fpga-bridge.h>
  17. #include "dfl.h"
  18. #include "dfl-fme-pr.h"
  19. struct fme_br_priv {
  20. struct dfl_fme_br_pdata *pdata;
  21. struct dfl_fpga_port_ops *port_ops;
  22. struct platform_device *port_pdev;
  23. };
  24. static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
  25. {
  26. struct fme_br_priv *priv = bridge->priv;
  27. struct platform_device *port_pdev;
  28. struct dfl_fpga_port_ops *ops;
  29. if (!priv->port_pdev) {
  30. port_pdev = dfl_fpga_cdev_find_port(priv->pdata->cdev,
  31. &priv->pdata->port_id,
  32. dfl_fpga_check_port_id);
  33. if (!port_pdev)
  34. return -ENODEV;
  35. priv->port_pdev = port_pdev;
  36. }
  37. if (priv->port_pdev && !priv->port_ops) {
  38. ops = dfl_fpga_port_ops_get(priv->port_pdev);
  39. if (!ops || !ops->enable_set)
  40. return -ENOENT;
  41. priv->port_ops = ops;
  42. }
  43. return priv->port_ops->enable_set(priv->port_pdev, enable);
  44. }
  45. static const struct fpga_bridge_ops fme_bridge_ops = {
  46. .enable_set = fme_bridge_enable_set,
  47. };
  48. static int fme_br_probe(struct platform_device *pdev)
  49. {
  50. struct device *dev = &pdev->dev;
  51. struct fme_br_priv *priv;
  52. struct fpga_bridge *br;
  53. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  54. if (!priv)
  55. return -ENOMEM;
  56. priv->pdata = dev_get_platdata(dev);
  57. br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
  58. &fme_bridge_ops, priv);
  59. if (!br)
  60. return -ENOMEM;
  61. platform_set_drvdata(pdev, br);
  62. return fpga_bridge_register(br);
  63. }
  64. static int fme_br_remove(struct platform_device *pdev)
  65. {
  66. struct fpga_bridge *br = platform_get_drvdata(pdev);
  67. struct fme_br_priv *priv = br->priv;
  68. fpga_bridge_unregister(br);
  69. if (priv->port_pdev)
  70. put_device(&priv->port_pdev->dev);
  71. if (priv->port_ops)
  72. dfl_fpga_port_ops_put(priv->port_ops);
  73. return 0;
  74. }
  75. static struct platform_driver fme_br_driver = {
  76. .driver = {
  77. .name = DFL_FPGA_FME_BRIDGE,
  78. },
  79. .probe = fme_br_probe,
  80. .remove = fme_br_remove,
  81. };
  82. module_platform_driver(fme_br_driver);
  83. MODULE_DESCRIPTION("FPGA Bridge for DFL FPGA Management Engine");
  84. MODULE_AUTHOR("Intel Corporation");
  85. MODULE_LICENSE("GPL v2");
  86. MODULE_ALIAS("platform:dfl-fme-bridge");