ice40-spi.c (5438B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * FPGA Manager Driver for Lattice iCE40. 4 * 5 * Copyright (c) 2016 Joel Holdsworth 6 * 7 * This driver adds support to the FPGA manager for configuring the SRAM of 8 * Lattice iCE40 FPGAs through slave SPI. 9 */ 10 11#include <linux/fpga/fpga-mgr.h> 12#include <linux/gpio/consumer.h> 13#include <linux/module.h> 14#include <linux/of_gpio.h> 15#include <linux/spi/spi.h> 16#include <linux/stringify.h> 17 18#define ICE40_SPI_MAX_SPEED 25000000 /* Hz */ 19#define ICE40_SPI_MIN_SPEED 1000000 /* Hz */ 20 21#define ICE40_SPI_RESET_DELAY 1 /* us (>200ns) */ 22#define ICE40_SPI_HOUSEKEEPING_DELAY 1200 /* us */ 23 24#define ICE40_SPI_NUM_ACTIVATION_BYTES DIV_ROUND_UP(49, 8) 25 26struct ice40_fpga_priv { 27 struct spi_device *dev; 28 struct gpio_desc *reset; 29 struct gpio_desc *cdone; 30}; 31 32static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr) 33{ 34 struct ice40_fpga_priv *priv = mgr->priv; 35 36 return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING : 37 FPGA_MGR_STATE_UNKNOWN; 38} 39 40static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, 41 struct fpga_image_info *info, 42 const char *buf, size_t count) 43{ 44 struct ice40_fpga_priv *priv = mgr->priv; 45 struct spi_device *dev = priv->dev; 46 struct spi_message message; 47 struct spi_transfer assert_cs_then_reset_delay = { 48 .cs_change = 1, 49 .delay = { 50 .value = ICE40_SPI_RESET_DELAY, 51 .unit = SPI_DELAY_UNIT_USECS 52 } 53 }; 54 struct spi_transfer housekeeping_delay_then_release_cs = { 55 .delay = { 56 .value = ICE40_SPI_HOUSEKEEPING_DELAY, 57 .unit = SPI_DELAY_UNIT_USECS 58 } 59 }; 60 int ret; 61 62 if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { 63 dev_err(&dev->dev, 64 "Partial reconfiguration is not supported\n"); 65 return -ENOTSUPP; 66 } 67 68 /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ 69 spi_bus_lock(dev->master); 70 71 gpiod_set_value(priv->reset, 1); 72 73 spi_message_init(&message); 74 spi_message_add_tail(&assert_cs_then_reset_delay, &message); 75 ret = spi_sync_locked(dev, &message); 76 77 /* Come out of reset */ 78 gpiod_set_value(priv->reset, 0); 79 80 /* Abort if the chip-select failed */ 81 if (ret) 82 goto fail; 83 84 /* Check CDONE is de-asserted i.e. the FPGA is reset */ 85 if (gpiod_get_value(priv->cdone)) { 86 dev_err(&dev->dev, "Device reset failed, CDONE is asserted\n"); 87 ret = -EIO; 88 goto fail; 89 } 90 91 /* Wait for the housekeeping to complete, and release SS_B */ 92 spi_message_init(&message); 93 spi_message_add_tail(&housekeeping_delay_then_release_cs, &message); 94 ret = spi_sync_locked(dev, &message); 95 96fail: 97 spi_bus_unlock(dev->master); 98 99 return ret; 100} 101 102static int ice40_fpga_ops_write(struct fpga_manager *mgr, 103 const char *buf, size_t count) 104{ 105 struct ice40_fpga_priv *priv = mgr->priv; 106 107 return spi_write(priv->dev, buf, count); 108} 109 110static int ice40_fpga_ops_write_complete(struct fpga_manager *mgr, 111 struct fpga_image_info *info) 112{ 113 struct ice40_fpga_priv *priv = mgr->priv; 114 struct spi_device *dev = priv->dev; 115 const u8 padding[ICE40_SPI_NUM_ACTIVATION_BYTES] = {0}; 116 117 /* Check CDONE is asserted */ 118 if (!gpiod_get_value(priv->cdone)) { 119 dev_err(&dev->dev, 120 "CDONE was not asserted after firmware transfer\n"); 121 return -EIO; 122 } 123 124 /* Send of zero-padding to activate the firmware */ 125 return spi_write(dev, padding, sizeof(padding)); 126} 127 128static const struct fpga_manager_ops ice40_fpga_ops = { 129 .state = ice40_fpga_ops_state, 130 .write_init = ice40_fpga_ops_write_init, 131 .write = ice40_fpga_ops_write, 132 .write_complete = ice40_fpga_ops_write_complete, 133}; 134 135static int ice40_fpga_probe(struct spi_device *spi) 136{ 137 struct device *dev = &spi->dev; 138 struct ice40_fpga_priv *priv; 139 struct fpga_manager *mgr; 140 int ret; 141 142 priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); 143 if (!priv) 144 return -ENOMEM; 145 146 priv->dev = spi; 147 148 /* Check board setup data. */ 149 if (spi->max_speed_hz > ICE40_SPI_MAX_SPEED) { 150 dev_err(dev, "SPI speed is too high, maximum speed is " 151 __stringify(ICE40_SPI_MAX_SPEED) "\n"); 152 return -EINVAL; 153 } 154 155 if (spi->max_speed_hz < ICE40_SPI_MIN_SPEED) { 156 dev_err(dev, "SPI speed is too low, minimum speed is " 157 __stringify(ICE40_SPI_MIN_SPEED) "\n"); 158 return -EINVAL; 159 } 160 161 if (spi->mode & SPI_CPHA) { 162 dev_err(dev, "Bad SPI mode, CPHA not supported\n"); 163 return -EINVAL; 164 } 165 166 /* Set up the GPIOs */ 167 priv->cdone = devm_gpiod_get(dev, "cdone", GPIOD_IN); 168 if (IS_ERR(priv->cdone)) { 169 ret = PTR_ERR(priv->cdone); 170 dev_err(dev, "Failed to get CDONE GPIO: %d\n", ret); 171 return ret; 172 } 173 174 priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 175 if (IS_ERR(priv->reset)) { 176 ret = PTR_ERR(priv->reset); 177 dev_err(dev, "Failed to get CRESET_B GPIO: %d\n", ret); 178 return ret; 179 } 180 181 mgr = devm_fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager", 182 &ice40_fpga_ops, priv); 183 return PTR_ERR_OR_ZERO(mgr); 184} 185 186static const struct of_device_id ice40_fpga_of_match[] = { 187 { .compatible = "lattice,ice40-fpga-mgr", }, 188 {}, 189}; 190MODULE_DEVICE_TABLE(of, ice40_fpga_of_match); 191 192static const struct spi_device_id ice40_fpga_spi_ids[] = { 193 { .name = "ice40-fpga-mgr", }, 194 {}, 195}; 196MODULE_DEVICE_TABLE(spi, ice40_fpga_spi_ids); 197 198static struct spi_driver ice40_fpga_driver = { 199 .probe = ice40_fpga_probe, 200 .driver = { 201 .name = "ice40spi", 202 .of_match_table = of_match_ptr(ice40_fpga_of_match), 203 }, 204 .id_table = ice40_fpga_spi_ids, 205}; 206 207module_spi_driver(ice40_fpga_driver); 208 209MODULE_AUTHOR("Joel Holdsworth <joel@airwebreathe.org.uk>"); 210MODULE_DESCRIPTION("Lattice iCE40 FPGA Manager"); 211MODULE_LICENSE("GPL v2");