cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zynqmp-fpga.c (2810B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2019 Xilinx, Inc.
      4 */
      5
      6#include <linux/dma-mapping.h>
      7#include <linux/fpga/fpga-mgr.h>
      8#include <linux/io.h>
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/of_address.h>
     12#include <linux/string.h>
     13#include <linux/firmware/xlnx-zynqmp.h>
     14
     15/* Constant Definitions */
     16#define IXR_FPGA_DONE_MASK	BIT(3)
     17
     18/**
     19 * struct zynqmp_fpga_priv - Private data structure
     20 * @dev:	Device data structure
     21 * @flags:	flags which is used to identify the bitfile type
     22 */
     23struct zynqmp_fpga_priv {
     24	struct device *dev;
     25	u32 flags;
     26};
     27
     28static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
     29				      struct fpga_image_info *info,
     30				      const char *buf, size_t size)
     31{
     32	struct zynqmp_fpga_priv *priv;
     33
     34	priv = mgr->priv;
     35	priv->flags = info->flags;
     36
     37	return 0;
     38}
     39
     40static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
     41				 const char *buf, size_t size)
     42{
     43	struct zynqmp_fpga_priv *priv;
     44	dma_addr_t dma_addr;
     45	u32 eemi_flags = 0;
     46	char *kbuf;
     47	int ret;
     48
     49	priv = mgr->priv;
     50
     51	kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
     52	if (!kbuf)
     53		return -ENOMEM;
     54
     55	memcpy(kbuf, buf, size);
     56
     57	wmb(); /* ensure all writes are done before initiate FW call */
     58
     59	if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
     60		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
     61
     62	ret = zynqmp_pm_fpga_load(dma_addr, size, eemi_flags);
     63
     64	dma_free_coherent(priv->dev, size, kbuf, dma_addr);
     65
     66	return ret;
     67}
     68
     69static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
     70{
     71	u32 status = 0;
     72
     73	zynqmp_pm_fpga_get_status(&status);
     74	if (status & IXR_FPGA_DONE_MASK)
     75		return FPGA_MGR_STATE_OPERATING;
     76
     77	return FPGA_MGR_STATE_UNKNOWN;
     78}
     79
     80static const struct fpga_manager_ops zynqmp_fpga_ops = {
     81	.state = zynqmp_fpga_ops_state,
     82	.write_init = zynqmp_fpga_ops_write_init,
     83	.write = zynqmp_fpga_ops_write,
     84};
     85
     86static int zynqmp_fpga_probe(struct platform_device *pdev)
     87{
     88	struct device *dev = &pdev->dev;
     89	struct zynqmp_fpga_priv *priv;
     90	struct fpga_manager *mgr;
     91
     92	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
     93	if (!priv)
     94		return -ENOMEM;
     95
     96	priv->dev = dev;
     97
     98	mgr = devm_fpga_mgr_register(dev, "Xilinx ZynqMP FPGA Manager",
     99				     &zynqmp_fpga_ops, priv);
    100	return PTR_ERR_OR_ZERO(mgr);
    101}
    102
    103#ifdef CONFIG_OF
    104static const struct of_device_id zynqmp_fpga_of_match[] = {
    105	{ .compatible = "xlnx,zynqmp-pcap-fpga", },
    106	{},
    107};
    108MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
    109#endif
    110
    111static struct platform_driver zynqmp_fpga_driver = {
    112	.probe = zynqmp_fpga_probe,
    113	.driver = {
    114		.name = "zynqmp_fpga_manager",
    115		.of_match_table = of_match_ptr(zynqmp_fpga_of_match),
    116	},
    117};
    118
    119module_platform_driver(zynqmp_fpga_driver);
    120
    121MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
    122MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
    123MODULE_LICENSE("GPL");