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