]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/blob - drivers/fpga/zynqmp-fpga.c
46180d9eda00e39ed963418cbdc128eb10c450b5
[vajnamar/linux-xlnx.git] / drivers / fpga / zynqmp-fpga.c
1 /*
2  * Copyright (C) 2016 Xilinx, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include <asm/cacheflush.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/fpga/fpga-mgr.h>
18 #include <linux/io.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/of_address.h>
22 #include <linux/string.h>
23 #include <linux/soc/xilinx/zynqmp/firmware.h>
24
25 /* Constant Definitions */
26 #define IXR_FPGA_DONE_MASK      0X00000008U
27 #define IXR_FPGA_AUTHENTICATIN  0x00000004U
28 #define IXR_FPGA_ENCRYPTION_EN  0x00000008U
29
30 struct zynqmp_fpga_priv {
31         struct device *dev;
32         u32 flags;
33 };
34
35 static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
36                                       struct fpga_image_info *info,
37                                       const char *buf, size_t size)
38 {
39         struct zynqmp_fpga_priv *priv;
40
41         priv = mgr->priv;
42         priv->flags = info->flags;
43
44         return 0;
45 }
46
47 static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
48                                         const char *buf, size_t size)
49 {
50         struct zynqmp_fpga_priv *priv;
51         char *kbuf;
52         size_t dma_size = size;
53         dma_addr_t dma_addr;
54         u32 transfer_length;
55         int ret;
56
57         priv = mgr->priv;
58
59         if (mgr->flags & IXR_FPGA_AUTHENTICATIN)
60                 dma_size = dma_size + SIGNATURE_LEN + PUBLIC_KEY_LEN;
61         if (mgr->flags & IXR_FPGA_ENCRYPTION_EN)
62                 dma_size = dma_size + ENCRYPTED_KEY_LEN + ENCRYPTED_IV_LEN;
63
64         kbuf = dma_alloc_coherent(priv->dev, dma_size, &dma_addr, GFP_KERNEL);
65         if (!kbuf)
66                 return -ENOMEM;
67
68         memcpy(kbuf, buf, size);
69
70         if (mgr->flags & IXR_FPGA_AUTHENTICATIN) {
71                 memcpy(kbuf + size, mgr->signature, SIGNATURE_LEN);
72                 memcpy(kbuf + size + SIGNATURE_LEN, mgr->pubkey,
73                                                 PUBLIC_KEY_LEN);
74         }
75         if (mgr->flags & IXR_FPGA_ENCRYPTION_EN) {
76                 memcpy(kbuf + size, mgr->key, ENCRYPTED_KEY_LEN);
77                 memcpy(kbuf + size + ENCRYPTED_KEY_LEN, mgr->iv,
78                                                 ENCRYPTED_IV_LEN);
79         }
80
81         __flush_cache_user_range((unsigned long)kbuf,
82                                  (unsigned long)kbuf + dma_size);
83
84         /**
85          * Translate size from bytes to number of 32bit words that
86          * the DMA should write to the PCAP interface
87          */
88         if (size & 3)
89                 transfer_length = (size >> 2) + 1;
90         else
91                 transfer_length = size >> 2;
92
93         ret = zynqmp_pm_fpga_load(dma_addr, transfer_length, mgr->flags);
94
95         dma_free_coherent(priv->dev, dma_size, kbuf, dma_addr);
96
97         return ret;
98 }
99
100 static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
101                                           struct fpga_image_info *info)
102 {
103         return 0;
104 }
105
106 static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
107 {
108         u32 status;
109
110         zynqmp_pm_fpga_get_status(&status);
111         if (status & IXR_FPGA_DONE_MASK)
112                 return FPGA_MGR_STATE_OPERATING;
113
114         return FPGA_MGR_STATE_UNKNOWN;
115 }
116
117 static const struct fpga_manager_ops zynqmp_fpga_ops = {
118         .state = zynqmp_fpga_ops_state,
119         .write_init = zynqmp_fpga_ops_write_init,
120         .write = zynqmp_fpga_ops_write,
121         .write_complete = zynqmp_fpga_ops_write_complete,
122 };
123
124 static int zynqmp_fpga_probe(struct platform_device *pdev)
125 {
126         struct device *dev = &pdev->dev;
127         struct zynqmp_fpga_priv *priv;
128         int err, ret;
129
130         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
131         if (!priv)
132                 return -ENOMEM;
133
134         priv->dev = dev;
135         ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
136         if (ret < 0)
137                 dev_err(dev, "no usable DMA configuration");
138
139         err = fpga_mgr_register(dev, "Xilinx ZynqMP FPGA Manager",
140                                 &zynqmp_fpga_ops, priv);
141         if (err) {
142                 dev_err(dev, "unable to register FPGA manager");
143                 return err;
144         }
145
146         return 0;
147 }
148
149 static int zynqmp_fpga_remove(struct platform_device *pdev)
150 {
151
152         fpga_mgr_unregister(&pdev->dev);
153
154         return 0;
155 }
156
157 static const struct of_device_id zynqmp_fpga_of_match[] = {
158         { .compatible = "xlnx,zynqmp-pcap-fpga", },
159         {},
160 };
161
162 MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
163
164 static struct platform_driver zynqmp_fpga_driver = {
165         .probe = zynqmp_fpga_probe,
166         .remove = zynqmp_fpga_remove,
167         .driver = {
168                 .name = "zynqmp_fpga_manager",
169                 .of_match_table = of_match_ptr(zynqmp_fpga_of_match),
170         },
171 };
172
173 module_platform_driver(zynqmp_fpga_driver);
174
175 MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
176 MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
177 MODULE_LICENSE("GPL");