83 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Xilinx Spartan6 and 7 Series Slave Serial SPI Driver4 *5 * Copyright (C) 2017 DENX Software Engineering6 *7 * Anatolij Gustschin <agust@denx.de>8 *9 * Manage Xilinx FPGA firmware that is loaded over SPI using10 * the slave serial configuration interface.11 */12 13#include "xilinx-core.h"14 15#include <linux/module.h>16#include <linux/mod_devicetable.h>17#include <linux/of.h>18#include <linux/spi/spi.h>19 20static int xilinx_spi_write(struct xilinx_fpga_core *core, const char *buf,21 size_t count)22{23 struct spi_device *spi = to_spi_device(core->dev);24 const char *fw_data = buf;25 const char *fw_data_end = fw_data + count;26 27 while (fw_data < fw_data_end) {28 size_t remaining, stride;29 int ret;30 31 remaining = fw_data_end - fw_data;32 stride = min_t(size_t, remaining, SZ_4K);33 34 ret = spi_write(spi, fw_data, stride);35 if (ret) {36 dev_err(core->dev, "SPI error in firmware write: %d\n",37 ret);38 return ret;39 }40 fw_data += stride;41 }42 43 return 0;44}45 46static int xilinx_spi_probe(struct spi_device *spi)47{48 struct xilinx_fpga_core *core;49 50 core = devm_kzalloc(&spi->dev, sizeof(*core), GFP_KERNEL);51 if (!core)52 return -ENOMEM;53 54 core->dev = &spi->dev;55 core->write = xilinx_spi_write;56 57 return xilinx_core_probe(core);58}59 60#ifdef CONFIG_OF61static const struct of_device_id xlnx_spi_of_match[] = {62 {63 .compatible = "xlnx,fpga-slave-serial",64 },65 {}66};67MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);68#endif69 70static struct spi_driver xilinx_slave_spi_driver = {71 .driver = {72 .name = "xlnx-slave-spi",73 .of_match_table = of_match_ptr(xlnx_spi_of_match),74 },75 .probe = xilinx_spi_probe,76};77 78module_spi_driver(xilinx_slave_spi_driver)79 80MODULE_LICENSE("GPL v2");81MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");82MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");83