1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Xilinx Spartan6 and 7 Series SelectMAP interface driver 4 * 5 * (C) 2024 Charles Perry <charles.perry@savoirfairelinux.com> 6 * 7 * Manage Xilinx FPGA firmware loaded over the SelectMAP configuration 8 * interface. 9 */ 10 11 #include "xilinx-core.h" 12 13 #include <linux/gpio/consumer.h> 14 #include <linux/io.h> 15 #include <linux/module.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/of.h> 18 #include <linux/platform_device.h> 19 20 struct xilinx_selectmap_conf { 21 struct xilinx_fpga_core core; 22 void __iomem *base; 23 }; 24 25 #define to_xilinx_selectmap_conf(obj) \ 26 container_of(obj, struct xilinx_selectmap_conf, core) 27 28 static int xilinx_selectmap_write(struct xilinx_fpga_core *core, 29 const char *buf, size_t count) 30 { 31 struct xilinx_selectmap_conf *conf = to_xilinx_selectmap_conf(core); 32 size_t i; 33 34 for (i = 0; i < count; ++i) 35 writeb(buf[i], conf->base); 36 37 return 0; 38 } 39 40 static int xilinx_selectmap_probe(struct platform_device *pdev) 41 { 42 struct xilinx_selectmap_conf *conf; 43 struct gpio_desc *gpio; 44 void __iomem *base; 45 46 conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL); 47 if (!conf) 48 return -ENOMEM; 49 50 conf->core.dev = &pdev->dev; 51 conf->core.write = xilinx_selectmap_write; 52 53 base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 54 if (IS_ERR(base)) 55 return dev_err_probe(&pdev->dev, PTR_ERR(base), 56 "ioremap error\n"); 57 conf->base = base; 58 59 /* CSI_B is active low */ 60 gpio = devm_gpiod_get_optional(&pdev->dev, "csi", GPIOD_OUT_HIGH); 61 if (IS_ERR(gpio)) 62 return dev_err_probe(&pdev->dev, PTR_ERR(gpio), 63 "Failed to get CSI_B gpio\n"); 64 65 /* RDWR_B is active low */ 66 gpio = devm_gpiod_get_optional(&pdev->dev, "rdwr", GPIOD_OUT_HIGH); 67 if (IS_ERR(gpio)) 68 return dev_err_probe(&pdev->dev, PTR_ERR(gpio), 69 "Failed to get RDWR_B gpio\n"); 70 71 return xilinx_core_probe(&conf->core); 72 } 73 74 static const struct of_device_id xlnx_selectmap_of_match[] = { 75 { .compatible = "xlnx,fpga-xc7s-selectmap", }, // Spartan-7 76 { .compatible = "xlnx,fpga-xc7a-selectmap", }, // Artix-7 77 { .compatible = "xlnx,fpga-xc7k-selectmap", }, // Kintex-7 78 { .compatible = "xlnx,fpga-xc7v-selectmap", }, // Virtex-7 79 {}, 80 }; 81 MODULE_DEVICE_TABLE(of, xlnx_selectmap_of_match); 82 83 static struct platform_driver xilinx_selectmap_driver = { 84 .driver = { 85 .name = "xilinx-selectmap", 86 .of_match_table = xlnx_selectmap_of_match, 87 }, 88 .probe = xilinx_selectmap_probe, 89 }; 90 91 module_platform_driver(xilinx_selectmap_driver); 92 93 MODULE_LICENSE("GPL"); 94 MODULE_AUTHOR("Charles Perry <charles.perry@savoirfairelinux.com>"); 95 MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SelectMap"); 96