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