1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for FPGA Management Engine (FME)
5 * Copyright (C) 2017-2018 Intel Corporation, Inc.
8 * Kang Luwei <luwei.kang@intel.com>
9 * Xiao Guangrong <guangrong.xiao@linux.intel.com>
10 * Joseph Grecco <joe.grecco@intel.com>
11 * Enno Luebbers <enno.luebbers@intel.com>
12 * Tim Whisonant <tim.whisonant@intel.com>
13 * Ananda Ravuri <ananda.ravuri@intel.com>
14 * Henry Mitchel <henry.mitchel@intel.com>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
22 static ssize_t ports_num_show(struct device *dev,
23 struct device_attribute *attr, char *buf)
28 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
30 v = readq(base + FME_HDR_CAP);
32 return scnprintf(buf, PAGE_SIZE, "%u\n",
33 (unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
35 static DEVICE_ATTR_RO(ports_num);
38 * Bitstream (static FPGA region) identifier number. It contains the
39 * detailed version and other information of this static FPGA region.
41 static ssize_t bitstream_id_show(struct device *dev,
42 struct device_attribute *attr, char *buf)
47 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
49 v = readq(base + FME_HDR_BITSTREAM_ID);
51 return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
53 static DEVICE_ATTR_RO(bitstream_id);
56 * Bitstream (static FPGA region) meta data. It contains the synthesis
57 * date, seed and other information of this static FPGA region.
59 static ssize_t bitstream_metadata_show(struct device *dev,
60 struct device_attribute *attr, char *buf)
65 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
67 v = readq(base + FME_HDR_BITSTREAM_MD);
69 return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
71 static DEVICE_ATTR_RO(bitstream_metadata);
73 static const struct attribute *fme_hdr_attrs[] = {
74 &dev_attr_ports_num.attr,
75 &dev_attr_bitstream_id.attr,
76 &dev_attr_bitstream_metadata.attr,
80 static int fme_hdr_init(struct platform_device *pdev,
81 struct dfl_feature *feature)
83 void __iomem *base = feature->ioaddr;
86 dev_dbg(&pdev->dev, "FME HDR Init.\n");
87 dev_dbg(&pdev->dev, "FME cap %llx.\n",
88 (unsigned long long)readq(base + FME_HDR_CAP));
90 ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs);
97 static void fme_hdr_uinit(struct platform_device *pdev,
98 struct dfl_feature *feature)
100 dev_dbg(&pdev->dev, "FME HDR UInit.\n");
101 sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs);
104 static const struct dfl_feature_ops fme_hdr_ops = {
105 .init = fme_hdr_init,
106 .uinit = fme_hdr_uinit,
109 static struct dfl_feature_driver fme_feature_drvs[] = {
111 .id = FME_FEATURE_ID_HEADER,
119 static int fme_open(struct inode *inode, struct file *filp)
121 struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
122 struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
128 ret = dfl_feature_dev_use_begin(pdata);
132 dev_dbg(&fdev->dev, "Device File Open\n");
133 filp->private_data = pdata;
138 static int fme_release(struct inode *inode, struct file *filp)
140 struct dfl_feature_platform_data *pdata = filp->private_data;
141 struct platform_device *pdev = pdata->dev;
143 dev_dbg(&pdev->dev, "Device File Release\n");
144 dfl_feature_dev_use_end(pdata);
149 static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
151 struct dfl_feature_platform_data *pdata = filp->private_data;
152 struct platform_device *pdev = pdata->dev;
153 struct dfl_feature *f;
156 dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
161 * Let sub-feature's ioctl function to handle the cmd.
162 * Sub-feature's ioctl returns -ENODEV when cmd is not
163 * handled in this sub feature, and returns 0 or other
164 * error code if cmd is handled.
166 dfl_fpga_dev_for_each_feature(pdata, f) {
167 if (f->ops && f->ops->ioctl) {
168 ret = f->ops->ioctl(pdev, f, cmd, arg);
178 static const struct file_operations fme_fops = {
179 .owner = THIS_MODULE,
181 .release = fme_release,
182 .unlocked_ioctl = fme_ioctl,
185 static int fme_probe(struct platform_device *pdev)
189 ret = dfl_fpga_dev_feature_init(pdev, fme_feature_drvs);
193 ret = dfl_fpga_dev_ops_register(pdev, &fme_fops, THIS_MODULE);
200 dfl_fpga_dev_feature_uinit(pdev);
205 static int fme_remove(struct platform_device *pdev)
207 dfl_fpga_dev_ops_unregister(pdev);
208 dfl_fpga_dev_feature_uinit(pdev);
213 static struct platform_driver fme_driver = {
215 .name = DFL_FPGA_FEATURE_DEV_FME,
218 .remove = fme_remove,
221 module_platform_driver(fme_driver);
223 MODULE_DESCRIPTION("FPGA Management Engine driver");
224 MODULE_AUTHOR("Intel Corporation");
225 MODULE_LICENSE("GPL v2");
226 MODULE_ALIAS("platform:dfl-fme");