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>
19 #include <linux/uaccess.h>
20 #include <linux/fpga-dfl.h>
25 static ssize_t ports_num_show(struct device *dev,
26 struct device_attribute *attr, char *buf)
31 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
33 v = readq(base + FME_HDR_CAP);
35 return scnprintf(buf, PAGE_SIZE, "%u\n",
36 (unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
38 static DEVICE_ATTR_RO(ports_num);
41 * Bitstream (static FPGA region) identifier number. It contains the
42 * detailed version and other information of this static FPGA region.
44 static ssize_t bitstream_id_show(struct device *dev,
45 struct device_attribute *attr, char *buf)
50 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
52 v = readq(base + FME_HDR_BITSTREAM_ID);
54 return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
56 static DEVICE_ATTR_RO(bitstream_id);
59 * Bitstream (static FPGA region) meta data. It contains the synthesis
60 * date, seed and other information of this static FPGA region.
62 static ssize_t bitstream_metadata_show(struct device *dev,
63 struct device_attribute *attr, char *buf)
68 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
70 v = readq(base + FME_HDR_BITSTREAM_MD);
72 return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
74 static DEVICE_ATTR_RO(bitstream_metadata);
76 static ssize_t cache_size_show(struct device *dev,
77 struct device_attribute *attr, char *buf)
82 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
84 v = readq(base + FME_HDR_CAP);
86 return sprintf(buf, "%u\n",
87 (unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v));
89 static DEVICE_ATTR_RO(cache_size);
91 static ssize_t fabric_version_show(struct device *dev,
92 struct device_attribute *attr, char *buf)
97 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
99 v = readq(base + FME_HDR_CAP);
101 return sprintf(buf, "%u\n",
102 (unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v));
104 static DEVICE_ATTR_RO(fabric_version);
106 static ssize_t socket_id_show(struct device *dev,
107 struct device_attribute *attr, char *buf)
112 base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
114 v = readq(base + FME_HDR_CAP);
116 return sprintf(buf, "%u\n",
117 (unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v));
119 static DEVICE_ATTR_RO(socket_id);
121 static struct attribute *fme_hdr_attrs[] = {
122 &dev_attr_ports_num.attr,
123 &dev_attr_bitstream_id.attr,
124 &dev_attr_bitstream_metadata.attr,
125 &dev_attr_cache_size.attr,
126 &dev_attr_fabric_version.attr,
127 &dev_attr_socket_id.attr,
130 ATTRIBUTE_GROUPS(fme_hdr);
132 static int fme_hdr_init(struct platform_device *pdev,
133 struct dfl_feature *feature)
135 void __iomem *base = feature->ioaddr;
138 dev_dbg(&pdev->dev, "FME HDR Init.\n");
139 dev_dbg(&pdev->dev, "FME cap %llx.\n",
140 (unsigned long long)readq(base + FME_HDR_CAP));
142 ret = device_add_groups(&pdev->dev, fme_hdr_groups);
149 static void fme_hdr_uinit(struct platform_device *pdev,
150 struct dfl_feature *feature)
152 dev_dbg(&pdev->dev, "FME HDR UInit.\n");
153 device_remove_groups(&pdev->dev, fme_hdr_groups);
156 static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
159 struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
162 if (get_user(port_id, (int __user *)arg))
165 return dfl_fpga_cdev_release_port(cdev, port_id);
168 static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
171 struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
174 if (get_user(port_id, (int __user *)arg))
177 return dfl_fpga_cdev_assign_port(cdev, port_id);
180 static long fme_hdr_ioctl(struct platform_device *pdev,
181 struct dfl_feature *feature,
182 unsigned int cmd, unsigned long arg)
184 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
187 case DFL_FPGA_FME_PORT_RELEASE:
188 return fme_hdr_ioctl_release_port(pdata, arg);
189 case DFL_FPGA_FME_PORT_ASSIGN:
190 return fme_hdr_ioctl_assign_port(pdata, arg);
196 static const struct dfl_feature_id fme_hdr_id_table[] = {
197 {.id = FME_FEATURE_ID_HEADER,},
201 static const struct dfl_feature_ops fme_hdr_ops = {
202 .init = fme_hdr_init,
203 .uinit = fme_hdr_uinit,
204 .ioctl = fme_hdr_ioctl,
207 static struct dfl_feature_driver fme_feature_drvs[] = {
209 .id_table = fme_hdr_id_table,
213 .id_table = fme_pr_mgmt_id_table,
214 .ops = &fme_pr_mgmt_ops,
221 static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
224 /* No extension support for now */
228 static int fme_open(struct inode *inode, struct file *filp)
230 struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
231 struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
237 ret = dfl_feature_dev_use_begin(pdata);
241 dev_dbg(&fdev->dev, "Device File Open\n");
242 filp->private_data = pdata;
247 static int fme_release(struct inode *inode, struct file *filp)
249 struct dfl_feature_platform_data *pdata = filp->private_data;
250 struct platform_device *pdev = pdata->dev;
252 dev_dbg(&pdev->dev, "Device File Release\n");
253 dfl_feature_dev_use_end(pdata);
258 static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
260 struct dfl_feature_platform_data *pdata = filp->private_data;
261 struct platform_device *pdev = pdata->dev;
262 struct dfl_feature *f;
265 dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
268 case DFL_FPGA_GET_API_VERSION:
269 return DFL_FPGA_API_VERSION;
270 case DFL_FPGA_CHECK_EXTENSION:
271 return fme_ioctl_check_extension(pdata, arg);
274 * Let sub-feature's ioctl function to handle the cmd.
275 * Sub-feature's ioctl returns -ENODEV when cmd is not
276 * handled in this sub feature, and returns 0 or other
277 * error code if cmd is handled.
279 dfl_fpga_dev_for_each_feature(pdata, f) {
280 if (f->ops && f->ops->ioctl) {
281 ret = f->ops->ioctl(pdev, f, cmd, arg);
291 static int fme_dev_init(struct platform_device *pdev)
293 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
296 fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
302 mutex_lock(&pdata->lock);
303 dfl_fpga_pdata_set_private(pdata, fme);
304 mutex_unlock(&pdata->lock);
309 static void fme_dev_destroy(struct platform_device *pdev)
311 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
314 mutex_lock(&pdata->lock);
315 fme = dfl_fpga_pdata_get_private(pdata);
316 dfl_fpga_pdata_set_private(pdata, NULL);
317 mutex_unlock(&pdata->lock);
320 static const struct file_operations fme_fops = {
321 .owner = THIS_MODULE,
323 .release = fme_release,
324 .unlocked_ioctl = fme_ioctl,
327 static int fme_probe(struct platform_device *pdev)
331 ret = fme_dev_init(pdev);
335 ret = dfl_fpga_dev_feature_init(pdev, fme_feature_drvs);
339 ret = dfl_fpga_dev_ops_register(pdev, &fme_fops, THIS_MODULE);
346 dfl_fpga_dev_feature_uinit(pdev);
348 fme_dev_destroy(pdev);
353 static int fme_remove(struct platform_device *pdev)
355 dfl_fpga_dev_ops_unregister(pdev);
356 dfl_fpga_dev_feature_uinit(pdev);
357 fme_dev_destroy(pdev);
362 static struct platform_driver fme_driver = {
364 .name = DFL_FPGA_FEATURE_DEV_FME,
367 .remove = fme_remove,
370 module_platform_driver(fme_driver);
372 MODULE_DESCRIPTION("FPGA Management Engine driver");
373 MODULE_AUTHOR("Intel Corporation");
374 MODULE_LICENSE("GPL v2");
375 MODULE_ALIAS("platform:dfl-fme");