linux/drivers/fpga/dfl-fme-br.c
<<
>>
Prefs
   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
  16#include <linux/module.h>
  17#include <linux/fpga/fpga-bridge.h>
  18
  19#include "dfl.h"
  20#include "dfl-fme-pr.h"
  21
  22struct fme_br_priv {
  23        struct dfl_fme_br_pdata *pdata;
  24        struct dfl_fpga_port_ops *port_ops;
  25        struct platform_device *port_pdev;
  26};
  27
  28static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
  29{
  30        struct fme_br_priv *priv = bridge->priv;
  31        struct platform_device *port_pdev;
  32        struct dfl_fpga_port_ops *ops;
  33
  34        if (!priv->port_pdev) {
  35                port_pdev = dfl_fpga_cdev_find_port(priv->pdata->cdev,
  36                                                    &priv->pdata->port_id,
  37                                                    dfl_fpga_check_port_id);
  38                if (!port_pdev)
  39                        return -ENODEV;
  40
  41                priv->port_pdev = port_pdev;
  42        }
  43
  44        if (priv->port_pdev && !priv->port_ops) {
  45                ops = dfl_fpga_port_ops_get(priv->port_pdev);
  46                if (!ops || !ops->enable_set)
  47                        return -ENOENT;
  48
  49                priv->port_ops = ops;
  50        }
  51
  52        return priv->port_ops->enable_set(priv->port_pdev, enable);
  53}
  54
  55static const struct fpga_bridge_ops fme_bridge_ops = {
  56        .enable_set = fme_bridge_enable_set,
  57};
  58
  59static int fme_br_probe(struct platform_device *pdev)
  60{
  61        struct device *dev = &pdev->dev;
  62        struct fme_br_priv *priv;
  63        struct fpga_bridge *br;
  64
  65        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  66        if (!priv)
  67                return -ENOMEM;
  68
  69        priv->pdata = dev_get_platdata(dev);
  70
  71        br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
  72                                     &fme_bridge_ops, priv);
  73        if (!br)
  74                return -ENOMEM;
  75
  76        platform_set_drvdata(pdev, br);
  77
  78        return fpga_bridge_register(br);
  79}
  80
  81static int fme_br_remove(struct platform_device *pdev)
  82{
  83        struct fpga_bridge *br = platform_get_drvdata(pdev);
  84        struct fme_br_priv *priv = br->priv;
  85
  86        fpga_bridge_unregister(br);
  87
  88        if (priv->port_pdev)
  89                put_device(&priv->port_pdev->dev);
  90        if (priv->port_ops)
  91                dfl_fpga_port_ops_put(priv->port_ops);
  92
  93        return 0;
  94}
  95
  96static struct platform_driver fme_br_driver = {
  97        .driver = {
  98                .name    = DFL_FPGA_FME_BRIDGE,
  99        },
 100        .probe   = fme_br_probe,
 101        .remove  = fme_br_remove,
 102};
 103
 104module_platform_driver(fme_br_driver);
 105
 106MODULE_DESCRIPTION("FPGA Bridge for DFL FPGA Management Engine");
 107MODULE_AUTHOR("Intel Corporation");
 108MODULE_LICENSE("GPL v2");
 109MODULE_ALIAS("platform:dfl-fme-bridge");
 110