413 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Microchip Polarfire FPGA programming over slave SPI interface.4 */5 6#include <linux/unaligned.h>7#include <linux/delay.h>8#include <linux/fpga/fpga-mgr.h>9#include <linux/iopoll.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/spi/spi.h>13 14#define MPF_SPI_ISC_ENABLE 0x0B15#define MPF_SPI_ISC_DISABLE 0x0C16#define MPF_SPI_READ_STATUS 0x0017#define MPF_SPI_READ_DATA 0x0118#define MPF_SPI_FRAME_INIT 0xAE19#define MPF_SPI_FRAME 0xEE20#define MPF_SPI_PRG_MODE 0x0121#define MPF_SPI_RELEASE 0x2322 23#define MPF_SPI_FRAME_SIZE 1624 25#define MPF_HEADER_SIZE_OFFSET 2426#define MPF_DATA_SIZE_OFFSET 5527 28#define MPF_LOOKUP_TABLE_RECORD_SIZE 929#define MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET 030#define MPF_LOOKUP_TABLE_BLOCK_START_OFFSET 131 32#define MPF_COMPONENTS_SIZE_ID 533#define MPF_BITSTREAM_ID 834 35#define MPF_BITS_PER_COMPONENT_SIZE 2236 37#define MPF_STATUS_POLL_TIMEOUT (2 * USEC_PER_SEC)38#define MPF_STATUS_BUSY BIT(0)39#define MPF_STATUS_READY BIT(1)40#define MPF_STATUS_SPI_VIOLATION BIT(2)41#define MPF_STATUS_SPI_ERROR BIT(3)42 43struct mpf_priv {44 struct spi_device *spi;45 bool program_mode;46 u8 tx __aligned(ARCH_KMALLOC_MINALIGN);47 u8 rx;48};49 50static int mpf_read_status(struct mpf_priv *priv)51{52 /*53 * HW status is returned on MISO in the first byte after CS went54 * active. However, first reading can be inadequate, so we submit55 * two identical SPI transfers and use result of the later one.56 */57 struct spi_transfer xfers[2] = {58 {59 .tx_buf = &priv->tx,60 .rx_buf = &priv->rx,61 .len = 1,62 .cs_change = 1,63 }, {64 .tx_buf = &priv->tx,65 .rx_buf = &priv->rx,66 .len = 1,67 },68 };69 u8 status;70 int ret;71 72 priv->tx = MPF_SPI_READ_STATUS;73 74 ret = spi_sync_transfer(priv->spi, xfers, 2);75 if (ret)76 return ret;77 78 status = priv->rx;79 80 if ((status & MPF_STATUS_SPI_VIOLATION) ||81 (status & MPF_STATUS_SPI_ERROR))82 return -EIO;83 84 return status;85}86 87static enum fpga_mgr_states mpf_ops_state(struct fpga_manager *mgr)88{89 struct mpf_priv *priv = mgr->priv;90 bool program_mode;91 int status;92 93 program_mode = priv->program_mode;94 status = mpf_read_status(priv);95 96 if (!program_mode && !status)97 return FPGA_MGR_STATE_OPERATING;98 99 return FPGA_MGR_STATE_UNKNOWN;100}101 102static int mpf_ops_parse_header(struct fpga_manager *mgr,103 struct fpga_image_info *info,104 const char *buf, size_t count)105{106 size_t component_size_byte_num, component_size_byte_off,107 components_size_start, bitstream_start,108 block_id_offset, block_start_offset;109 u8 header_size, blocks_num, block_id;110 u32 block_start, component_size;111 u16 components_num, i;112 113 if (!buf) {114 dev_err(&mgr->dev, "Image buffer is not provided\n");115 return -EINVAL;116 }117 118 header_size = *(buf + MPF_HEADER_SIZE_OFFSET);119 if (header_size > count) {120 info->header_size = header_size;121 return -EAGAIN;122 }123 124 /*125 * Go through look-up table to find out where actual bitstream starts126 * and where sizes of components of the bitstream lies.127 */128 blocks_num = *(buf + header_size - 1);129 block_id_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET;130 block_start_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_START_OFFSET;131 132 header_size += blocks_num * MPF_LOOKUP_TABLE_RECORD_SIZE;133 if (header_size > count) {134 info->header_size = header_size;135 return -EAGAIN;136 }137 138 components_size_start = 0;139 bitstream_start = 0;140 141 while (blocks_num--) {142 block_id = *(buf + block_id_offset);143 block_start = get_unaligned_le32(buf + block_start_offset);144 145 switch (block_id) {146 case MPF_BITSTREAM_ID:147 bitstream_start = block_start;148 info->header_size = block_start;149 if (block_start > count)150 return -EAGAIN;151 152 break;153 case MPF_COMPONENTS_SIZE_ID:154 components_size_start = block_start;155 break;156 default:157 break;158 }159 160 if (bitstream_start && components_size_start)161 break;162 163 block_id_offset += MPF_LOOKUP_TABLE_RECORD_SIZE;164 block_start_offset += MPF_LOOKUP_TABLE_RECORD_SIZE;165 }166 167 if (!bitstream_start || !components_size_start) {168 dev_err(&mgr->dev, "Failed to parse header look-up table\n");169 return -EFAULT;170 }171 172 /*173 * Parse bitstream size.174 * Sizes of components of the bitstream are 22-bits long placed next175 * to each other. Image header should be extended by now up to where176 * actual bitstream starts, so no need for overflow check anymore.177 */178 components_num = get_unaligned_le16(buf + MPF_DATA_SIZE_OFFSET);179 180 for (i = 0; i < components_num; i++) {181 component_size_byte_num =182 (i * MPF_BITS_PER_COMPONENT_SIZE) / BITS_PER_BYTE;183 component_size_byte_off =184 (i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE;185 186 component_size = get_unaligned_le32(buf +187 components_size_start +188 component_size_byte_num);189 component_size >>= component_size_byte_off;190 component_size &= GENMASK(MPF_BITS_PER_COMPONENT_SIZE - 1, 0);191 192 info->data_size += component_size * MPF_SPI_FRAME_SIZE;193 }194 195 return 0;196}197 198static int mpf_poll_status(struct mpf_priv *priv, u8 mask)199{200 int ret, status;201 202 /*203 * Busy poll HW status. Polling stops if any of the following204 * conditions are met:205 * - timeout is reached206 * - mpf_read_status() returns an error207 * - busy bit is cleared AND mask bits are set208 */209 ret = read_poll_timeout(mpf_read_status, status,210 (status < 0) ||211 ((status & (MPF_STATUS_BUSY | mask)) == mask),212 0, MPF_STATUS_POLL_TIMEOUT, false, priv);213 if (ret < 0)214 return ret;215 216 return status;217}218 219static int mpf_spi_write(struct mpf_priv *priv, const void *buf, size_t buf_size)220{221 int status = mpf_poll_status(priv, 0);222 223 if (status < 0)224 return status;225 226 return spi_write_then_read(priv->spi, buf, buf_size, NULL, 0);227}228 229static int mpf_spi_write_then_read(struct mpf_priv *priv,230 const void *txbuf, size_t txbuf_size,231 void *rxbuf, size_t rxbuf_size)232{233 const u8 read_command[] = { MPF_SPI_READ_DATA };234 int ret;235 236 ret = mpf_spi_write(priv, txbuf, txbuf_size);237 if (ret)238 return ret;239 240 ret = mpf_poll_status(priv, MPF_STATUS_READY);241 if (ret < 0)242 return ret;243 244 return spi_write_then_read(priv->spi, read_command, sizeof(read_command),245 rxbuf, rxbuf_size);246}247 248static int mpf_ops_write_init(struct fpga_manager *mgr,249 struct fpga_image_info *info, const char *buf,250 size_t count)251{252 const u8 program_mode[] = { MPF_SPI_FRAME_INIT, MPF_SPI_PRG_MODE };253 const u8 isc_en_command[] = { MPF_SPI_ISC_ENABLE };254 struct mpf_priv *priv = mgr->priv;255 struct device *dev = &mgr->dev;256 u32 isc_ret = 0;257 int ret;258 259 if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {260 dev_err(dev, "Partial reconfiguration is not supported\n");261 return -EOPNOTSUPP;262 }263 264 ret = mpf_spi_write_then_read(priv, isc_en_command, sizeof(isc_en_command),265 &isc_ret, sizeof(isc_ret));266 if (ret || isc_ret) {267 dev_err(dev, "Failed to enable ISC: spi_ret %d, isc_ret %u\n",268 ret, isc_ret);269 return -EFAULT;270 }271 272 ret = mpf_spi_write(priv, program_mode, sizeof(program_mode));273 if (ret) {274 dev_err(dev, "Failed to enter program mode: %d\n", ret);275 return ret;276 }277 278 priv->program_mode = true;279 280 return 0;281}282 283static int mpf_spi_frame_write(struct mpf_priv *priv, const char *buf)284{285 struct spi_transfer xfers[2] = {286 {287 .tx_buf = &priv->tx,288 .len = 1,289 }, {290 .tx_buf = buf,291 .len = MPF_SPI_FRAME_SIZE,292 },293 };294 int ret;295 296 ret = mpf_poll_status(priv, 0);297 if (ret < 0)298 return ret;299 300 priv->tx = MPF_SPI_FRAME;301 302 return spi_sync_transfer(priv->spi, xfers, ARRAY_SIZE(xfers));303}304 305static int mpf_ops_write(struct fpga_manager *mgr, const char *buf, size_t count)306{307 struct mpf_priv *priv = mgr->priv;308 struct device *dev = &mgr->dev;309 int ret, i;310 311 if (count % MPF_SPI_FRAME_SIZE) {312 dev_err(dev, "Bitstream size is not a multiple of %d\n",313 MPF_SPI_FRAME_SIZE);314 return -EINVAL;315 }316 317 for (i = 0; i < count / MPF_SPI_FRAME_SIZE; i++) {318 ret = mpf_spi_frame_write(priv, buf + i * MPF_SPI_FRAME_SIZE);319 if (ret) {320 dev_err(dev, "Failed to write bitstream frame %d/%zu\n",321 i, count / MPF_SPI_FRAME_SIZE);322 return ret;323 }324 }325 326 return 0;327}328 329static int mpf_ops_write_complete(struct fpga_manager *mgr,330 struct fpga_image_info *info)331{332 const u8 isc_dis_command[] = { MPF_SPI_ISC_DISABLE };333 const u8 release_command[] = { MPF_SPI_RELEASE };334 struct mpf_priv *priv = mgr->priv;335 struct device *dev = &mgr->dev;336 int ret;337 338 ret = mpf_spi_write(priv, isc_dis_command, sizeof(isc_dis_command));339 if (ret) {340 dev_err(dev, "Failed to disable ISC: %d\n", ret);341 return ret;342 }343 344 usleep_range(1000, 2000);345 346 ret = mpf_spi_write(priv, release_command, sizeof(release_command));347 if (ret) {348 dev_err(dev, "Failed to exit program mode: %d\n", ret);349 return ret;350 }351 352 priv->program_mode = false;353 354 return 0;355}356 357static const struct fpga_manager_ops mpf_ops = {358 .state = mpf_ops_state,359 .initial_header_size = 71,360 .skip_header = true,361 .parse_header = mpf_ops_parse_header,362 .write_init = mpf_ops_write_init,363 .write = mpf_ops_write,364 .write_complete = mpf_ops_write_complete,365};366 367static int mpf_probe(struct spi_device *spi)368{369 struct device *dev = &spi->dev;370 struct fpga_manager *mgr;371 struct mpf_priv *priv;372 373 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);374 if (!priv)375 return -ENOMEM;376 377 priv->spi = spi;378 379 mgr = devm_fpga_mgr_register(dev, "Microchip Polarfire SPI FPGA Manager",380 &mpf_ops, priv);381 382 return PTR_ERR_OR_ZERO(mgr);383}384 385static const struct spi_device_id mpf_spi_ids[] = {386 { .name = "mpf-spi-fpga-mgr", },387 {},388};389MODULE_DEVICE_TABLE(spi, mpf_spi_ids);390 391#if IS_ENABLED(CONFIG_OF)392static const struct of_device_id mpf_of_ids[] = {393 { .compatible = "microchip,mpf-spi-fpga-mgr" },394 {},395};396MODULE_DEVICE_TABLE(of, mpf_of_ids);397#endif /* IS_ENABLED(CONFIG_OF) */398 399static struct spi_driver mpf_driver = {400 .probe = mpf_probe,401 .id_table = mpf_spi_ids,402 .driver = {403 .name = "microchip_mpf_spi_fpga_mgr",404 .of_match_table = of_match_ptr(mpf_of_ids),405 },406};407 408module_spi_driver(mpf_driver);409 410MODULE_DESCRIPTION("Microchip Polarfire SPI FPGA Manager");411MODULE_AUTHOR("Ivan Bornyakov <i.bornyakov@metrotek.ru>");412MODULE_LICENSE("GPL");413