230 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Common parts of the Xilinx Spartan6 and 7 Series FPGA manager drivers.4 *5 * Copyright (C) 2017 DENX Software Engineering6 *7 * Anatolij Gustschin <agust@denx.de>8 */9 10#include "xilinx-core.h"11 12#include <linux/delay.h>13#include <linux/fpga/fpga-mgr.h>14#include <linux/gpio/consumer.h>15#include <linux/of.h>16 17static int get_done_gpio(struct fpga_manager *mgr)18{19 struct xilinx_fpga_core *core = mgr->priv;20 int ret;21 22 ret = gpiod_get_value(core->done);23 if (ret < 0)24 dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret);25 26 return ret;27}28 29static enum fpga_mgr_states xilinx_core_state(struct fpga_manager *mgr)30{31 if (!get_done_gpio(mgr))32 return FPGA_MGR_STATE_RESET;33 34 return FPGA_MGR_STATE_UNKNOWN;35}36 37/**38 * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait39 * a given delay if the pin is unavailable40 *41 * @mgr: The FPGA manager object42 * @value: Value INIT_B to wait for (1 = asserted = low)43 * @alt_udelay: Delay to wait if the INIT_B GPIO is not available44 *45 * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if46 * too much time passed waiting for that. If no INIT_B GPIO is available47 * then always return 0.48 */49static int wait_for_init_b(struct fpga_manager *mgr, int value,50 unsigned long alt_udelay)51{52 struct xilinx_fpga_core *core = mgr->priv;53 unsigned long timeout = jiffies + msecs_to_jiffies(1000);54 55 if (core->init_b) {56 while (time_before(jiffies, timeout)) {57 int ret = gpiod_get_value(core->init_b);58 59 if (ret == value)60 return 0;61 62 if (ret < 0) {63 dev_err(&mgr->dev,64 "Error reading INIT_B (%d)\n", ret);65 return ret;66 }67 68 usleep_range(100, 400);69 }70 71 dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n",72 value ? "assert" : "deassert");73 return -ETIMEDOUT;74 }75 76 udelay(alt_udelay);77 78 return 0;79}80 81static int xilinx_core_write_init(struct fpga_manager *mgr,82 struct fpga_image_info *info, const char *buf,83 size_t count)84{85 struct xilinx_fpga_core *core = mgr->priv;86 int err;87 88 if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {89 dev_err(&mgr->dev, "Partial reconfiguration not supported\n");90 return -EINVAL;91 }92 93 gpiod_set_value(core->prog_b, 1);94 95 err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */96 if (err) {97 gpiod_set_value(core->prog_b, 0);98 return err;99 }100 101 gpiod_set_value(core->prog_b, 0);102 103 err = wait_for_init_b(mgr, 0, 0);104 if (err)105 return err;106 107 if (get_done_gpio(mgr)) {108 dev_err(&mgr->dev, "Unexpected DONE pin state...\n");109 return -EIO;110 }111 112 /* program latency */113 usleep_range(7500, 7600);114 return 0;115}116 117static int xilinx_core_write(struct fpga_manager *mgr, const char *buf,118 size_t count)119{120 struct xilinx_fpga_core *core = mgr->priv;121 122 return core->write(core, buf, count);123}124 125static int xilinx_core_write_complete(struct fpga_manager *mgr,126 struct fpga_image_info *info)127{128 struct xilinx_fpga_core *core = mgr->priv;129 unsigned long timeout =130 jiffies + usecs_to_jiffies(info->config_complete_timeout_us);131 bool expired = false;132 int done;133 int ret;134 const char padding[1] = { 0xff };135 136 /*137 * This loop is carefully written such that if the driver is138 * scheduled out for more than 'timeout', we still check for DONE139 * before giving up and we apply 8 extra CCLK cycles in all cases.140 */141 while (!expired) {142 expired = time_after(jiffies, timeout);143 144 done = get_done_gpio(mgr);145 if (done < 0)146 return done;147 148 ret = core->write(core, padding, sizeof(padding));149 if (ret)150 return ret;151 152 if (done)153 return 0;154 }155 156 if (core->init_b) {157 ret = gpiod_get_value(core->init_b);158 159 if (ret < 0) {160 dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret);161 return ret;162 }163 164 dev_err(&mgr->dev,165 ret ? "CRC error or invalid device\n" :166 "Missing sync word or incomplete bitstream\n");167 } else {168 dev_err(&mgr->dev, "Timeout after config data transfer\n");169 }170 171 return -ETIMEDOUT;172}173 174static inline struct gpio_desc *175xilinx_core_devm_gpiod_get(struct device *dev, const char *con_id,176 const char *legacy_con_id, enum gpiod_flags flags)177{178 struct gpio_desc *desc;179 180 desc = devm_gpiod_get(dev, con_id, flags);181 if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT &&182 of_device_is_compatible(dev->of_node, "xlnx,fpga-slave-serial"))183 desc = devm_gpiod_get(dev, legacy_con_id, flags);184 185 return desc;186}187 188static const struct fpga_manager_ops xilinx_core_ops = {189 .state = xilinx_core_state,190 .write_init = xilinx_core_write_init,191 .write = xilinx_core_write,192 .write_complete = xilinx_core_write_complete,193};194 195int xilinx_core_probe(struct xilinx_fpga_core *core)196{197 struct fpga_manager *mgr;198 199 if (!core || !core->dev || !core->write)200 return -EINVAL;201 202 /* PROGRAM_B is active low */203 core->prog_b = xilinx_core_devm_gpiod_get(core->dev, "prog", "prog_b",204 GPIOD_OUT_LOW);205 if (IS_ERR(core->prog_b))206 return dev_err_probe(core->dev, PTR_ERR(core->prog_b),207 "Failed to get PROGRAM_B gpio\n");208 209 core->init_b = xilinx_core_devm_gpiod_get(core->dev, "init", "init-b",210 GPIOD_IN);211 if (IS_ERR(core->init_b))212 return dev_err_probe(core->dev, PTR_ERR(core->init_b),213 "Failed to get INIT_B gpio\n");214 215 core->done = devm_gpiod_get(core->dev, "done", GPIOD_IN);216 if (IS_ERR(core->done))217 return dev_err_probe(core->dev, PTR_ERR(core->done),218 "Failed to get DONE gpio\n");219 220 mgr = devm_fpga_mgr_register(core->dev,221 "Xilinx Slave Serial FPGA Manager",222 &xilinx_core_ops, core);223 return PTR_ERR_OR_ZERO(mgr);224}225EXPORT_SYMBOL_GPL(xilinx_core_probe);226 227MODULE_LICENSE("GPL");228MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");229MODULE_DESCRIPTION("Xilinx 7 Series FPGA manager core");230