dfl-fme-br.c (2520B)
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 = fpga_bridge_register(dev, "DFL FPGA FME Bridge", 72 &fme_bridge_ops, priv); 73 if (IS_ERR(br)) 74 return PTR_ERR(br); 75 76 platform_set_drvdata(pdev, br); 77 78 return 0; 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");