550 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * FPGA Manager Driver for Altera Arria10 SoCFPGA4 *5 * Copyright (C) 2015-2016 Altera Corporation6 */7#include <linux/clk.h>8#include <linux/device.h>9#include <linux/delay.h>10#include <linux/fpga/fpga-mgr.h>11#include <linux/io.h>12#include <linux/module.h>13#include <linux/of_address.h>14#include <linux/regmap.h>15 16#define A10_FPGAMGR_DCLKCNT_OFST 0x0817#define A10_FPGAMGR_DCLKSTAT_OFST 0x0c18#define A10_FPGAMGR_IMGCFG_CTL_00_OFST 0x7019#define A10_FPGAMGR_IMGCFG_CTL_01_OFST 0x7420#define A10_FPGAMGR_IMGCFG_CTL_02_OFST 0x7821#define A10_FPGAMGR_IMGCFG_STAT_OFST 0x8022 23#define A10_FPGAMGR_DCLKSTAT_DCLKDONE BIT(0)24 25#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG BIT(0)26#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS BIT(1)27#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE BIT(2)28#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG BIT(8)29#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE BIT(16)30#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE BIT(24)31 32#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG BIT(0)33#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST BIT(16)34#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE BIT(24)35 36#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL BIT(0)37#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK (BIT(16) | BIT(17))38#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT 1639#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH BIT(24)40#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT 2441 42#define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR BIT(0)43#define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE BIT(1)44#define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE BIT(2)45#define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN BIT(4)46#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN BIT(6)47#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY BIT(9)48#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE BIT(10)49#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR BIT(11)50#define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN BIT(12)51#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK (BIT(16) | BIT(17) | BIT(18))52#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT 1653 54/* FPGA CD Ratio Value */55#define CDRATIO_x1 0x056#define CDRATIO_x2 0x157#define CDRATIO_x4 0x258#define CDRATIO_x8 0x359 60/* Configuration width 16/32 bit */61#define CFGWDTH_32 162#define CFGWDTH_16 063 64/*65 * struct a10_fpga_priv - private data for fpga manager66 * @regmap: regmap for register access67 * @fpga_data_addr: iomap for single address data register to FPGA68 * @clk: clock69 */70struct a10_fpga_priv {71 struct regmap *regmap;72 void __iomem *fpga_data_addr;73 struct clk *clk;74};75 76static bool socfpga_a10_fpga_writeable_reg(struct device *dev, unsigned int reg)77{78 switch (reg) {79 case A10_FPGAMGR_DCLKCNT_OFST:80 case A10_FPGAMGR_DCLKSTAT_OFST:81 case A10_FPGAMGR_IMGCFG_CTL_00_OFST:82 case A10_FPGAMGR_IMGCFG_CTL_01_OFST:83 case A10_FPGAMGR_IMGCFG_CTL_02_OFST:84 return true;85 }86 return false;87}88 89static bool socfpga_a10_fpga_readable_reg(struct device *dev, unsigned int reg)90{91 switch (reg) {92 case A10_FPGAMGR_DCLKCNT_OFST:93 case A10_FPGAMGR_DCLKSTAT_OFST:94 case A10_FPGAMGR_IMGCFG_CTL_00_OFST:95 case A10_FPGAMGR_IMGCFG_CTL_01_OFST:96 case A10_FPGAMGR_IMGCFG_CTL_02_OFST:97 case A10_FPGAMGR_IMGCFG_STAT_OFST:98 return true;99 }100 return false;101}102 103static const struct regmap_config socfpga_a10_fpga_regmap_config = {104 .reg_bits = 32,105 .reg_stride = 4,106 .val_bits = 32,107 .writeable_reg = socfpga_a10_fpga_writeable_reg,108 .readable_reg = socfpga_a10_fpga_readable_reg,109 .max_register = A10_FPGAMGR_IMGCFG_STAT_OFST,110 .cache_type = REGCACHE_NONE,111};112 113/*114 * from the register map description of cdratio in imgcfg_ctrl_02:115 * Normal Configuration : 32bit Passive Parallel116 * Partial Reconfiguration : 16bit Passive Parallel117 */118static void socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv *priv,119 int width)120{121 width <<= A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT;122 123 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,124 A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, width);125}126 127static void socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv *priv,128 u32 count)129{130 u32 val;131 132 /* Clear any existing DONE status. */133 regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,134 A10_FPGAMGR_DCLKSTAT_DCLKDONE);135 136 /* Issue the DCLK regmap. */137 regmap_write(priv->regmap, A10_FPGAMGR_DCLKCNT_OFST, count);138 139 /* wait till the dclkcnt done */140 regmap_read_poll_timeout(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, val,141 val, 1, 100);142 143 /* Clear DONE status. */144 regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,145 A10_FPGAMGR_DCLKSTAT_DCLKDONE);146}147 148#define RBF_ENCRYPTION_MODE_OFFSET 69149#define RBF_DECOMPRESS_OFFSET 229150 151static int socfpga_a10_fpga_encrypted(u32 *buf32, size_t buf32_size)152{153 if (buf32_size < RBF_ENCRYPTION_MODE_OFFSET + 1)154 return -EINVAL;155 156 /* Is the bitstream encrypted? */157 return ((buf32[RBF_ENCRYPTION_MODE_OFFSET] >> 2) & 3) != 0;158}159 160static int socfpga_a10_fpga_compressed(u32 *buf32, size_t buf32_size)161{162 if (buf32_size < RBF_DECOMPRESS_OFFSET + 1)163 return -EINVAL;164 165 /* Is the bitstream compressed? */166 return !((buf32[RBF_DECOMPRESS_OFFSET] >> 1) & 1);167}168 169static unsigned int socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width,170 bool encrypt, bool compress)171{172 unsigned int cd_ratio;173 174 /*175 * cd ratio is dependent on cfg width and whether the bitstream176 * is encrypted and/or compressed.177 *178 * | width | encr. | compr. | cd ratio |179 * | 16 | 0 | 0 | 1 |180 * | 16 | 0 | 1 | 4 |181 * | 16 | 1 | 0 | 2 |182 * | 16 | 1 | 1 | 4 |183 * | 32 | 0 | 0 | 1 |184 * | 32 | 0 | 1 | 8 |185 * | 32 | 1 | 0 | 4 |186 * | 32 | 1 | 1 | 8 |187 */188 if (!compress && !encrypt)189 return CDRATIO_x1;190 191 if (compress)192 cd_ratio = CDRATIO_x4;193 else194 cd_ratio = CDRATIO_x2;195 196 /* If 32 bit, double the cd ratio by incrementing the field */197 if (cfg_width == CFGWDTH_32)198 cd_ratio += 1;199 200 return cd_ratio;201}202 203static int socfpga_a10_fpga_set_cdratio(struct fpga_manager *mgr,204 unsigned int cfg_width,205 const char *buf, size_t count)206{207 struct a10_fpga_priv *priv = mgr->priv;208 unsigned int cd_ratio;209 int encrypt, compress;210 211 encrypt = socfpga_a10_fpga_encrypted((u32 *)buf, count / 4);212 if (encrypt < 0)213 return -EINVAL;214 215 compress = socfpga_a10_fpga_compressed((u32 *)buf, count / 4);216 if (compress < 0)217 return -EINVAL;218 219 cd_ratio = socfpga_a10_fpga_get_cd_ratio(cfg_width, encrypt, compress);220 221 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,222 A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK,223 cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT);224 225 return 0;226}227 228static u32 socfpga_a10_fpga_read_stat(struct a10_fpga_priv *priv)229{230 u32 val;231 232 regmap_read(priv->regmap, A10_FPGAMGR_IMGCFG_STAT_OFST, &val);233 234 return val;235}236 237static int socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv *priv)238{239 u32 reg, i;240 241 for (i = 0; i < 10 ; i++) {242 reg = socfpga_a10_fpga_read_stat(priv);243 244 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)245 return -EINVAL;246 247 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)248 return 0;249 }250 251 return -ETIMEDOUT;252}253 254static int socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv *priv)255{256 u32 reg, i;257 258 for (i = 0; i < 10 ; i++) {259 reg = socfpga_a10_fpga_read_stat(priv);260 261 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)262 return -EINVAL;263 264 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE)265 return 0;266 }267 268 return -ETIMEDOUT;269}270 271/* Start the FPGA programming by initialize the FPGA Manager */272static int socfpga_a10_fpga_write_init(struct fpga_manager *mgr,273 struct fpga_image_info *info,274 const char *buf, size_t count)275{276 struct a10_fpga_priv *priv = mgr->priv;277 unsigned int cfg_width;278 u32 msel, stat, mask;279 int ret;280 281 if (info->flags & FPGA_MGR_PARTIAL_RECONFIG)282 cfg_width = CFGWDTH_16;283 else284 return -EINVAL;285 286 /* Check for passive parallel (msel == 000 or 001) */287 msel = socfpga_a10_fpga_read_stat(priv);288 msel &= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK;289 msel >>= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT;290 if ((msel != 0) && (msel != 1)) {291 dev_dbg(&mgr->dev, "Fail: invalid msel=%d\n", msel);292 return -EINVAL;293 }294 295 /* Make sure no external devices are interfering */296 stat = socfpga_a10_fpga_read_stat(priv);297 mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN |298 A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN;299 if ((stat & mask) != mask)300 return -EINVAL;301 302 /* Set cfg width */303 socfpga_a10_fpga_set_cfg_width(priv, cfg_width);304 305 /* Determine cd ratio from bitstream header and set cd ratio */306 ret = socfpga_a10_fpga_set_cdratio(mgr, cfg_width, buf, count);307 if (ret)308 return ret;309 310 /*311 * Clear s2f_nce to enable chip select. Leave pr_request312 * unasserted and override disabled.313 */314 regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,315 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);316 317 /* Set cfg_ctrl to enable s2f dclk and data */318 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,319 A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL,320 A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL);321 322 /*323 * Disable overrides not needed for pr.324 * s2f_config==1 leaves reset deasseted.325 */326 regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_00_OFST,327 A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG |328 A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS |329 A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE |330 A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG);331 332 /* Enable override for data, dclk, nce, and pr_request to CSS */333 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,334 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0);335 336 /* Send some clocks to clear out any errors */337 socfpga_a10_fpga_generate_dclks(priv, 256);338 339 /* Assert pr_request */340 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,341 A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST,342 A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST);343 344 /* Provide 2048 DCLKs before starting the config data streaming. */345 socfpga_a10_fpga_generate_dclks(priv, 0x7ff);346 347 /* Wait for pr_ready */348 return socfpga_a10_fpga_wait_for_pr_ready(priv);349}350 351/*352 * write data to the FPGA data register353 */354static int socfpga_a10_fpga_write(struct fpga_manager *mgr, const char *buf,355 size_t count)356{357 struct a10_fpga_priv *priv = mgr->priv;358 u32 *buffer_32 = (u32 *)buf;359 size_t i = 0;360 361 if (count <= 0)362 return -EINVAL;363 364 /* Write out the complete 32-bit chunks */365 while (count >= sizeof(u32)) {366 writel(buffer_32[i++], priv->fpga_data_addr);367 count -= sizeof(u32);368 }369 370 /* Write out remaining non 32-bit chunks */371 switch (count) {372 case 3:373 writel(buffer_32[i++] & 0x00ffffff, priv->fpga_data_addr);374 break;375 case 2:376 writel(buffer_32[i++] & 0x0000ffff, priv->fpga_data_addr);377 break;378 case 1:379 writel(buffer_32[i++] & 0x000000ff, priv->fpga_data_addr);380 break;381 case 0:382 break;383 default:384 /* This will never happen */385 return -EFAULT;386 }387 388 return 0;389}390 391static int socfpga_a10_fpga_write_complete(struct fpga_manager *mgr,392 struct fpga_image_info *info)393{394 struct a10_fpga_priv *priv = mgr->priv;395 u32 reg;396 int ret;397 398 /* Wait for pr_done */399 ret = socfpga_a10_fpga_wait_for_pr_done(priv);400 401 /* Clear pr_request */402 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,403 A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0);404 405 /* Send some clocks to clear out any errors */406 socfpga_a10_fpga_generate_dclks(priv, 256);407 408 /* Disable s2f dclk and data */409 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,410 A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0);411 412 /* Deassert chip select */413 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,414 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE,415 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE);416 417 /* Disable data, dclk, nce, and pr_request override to CSS */418 regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,419 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG,420 A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);421 422 /* Return any errors regarding pr_done or pr_error */423 if (ret)424 return ret;425 426 /* Final check */427 reg = socfpga_a10_fpga_read_stat(priv);428 429 if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) ||430 ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) ||431 ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) {432 dev_dbg(&mgr->dev,433 "Timeout in final check. Status=%08xf\n", reg);434 return -ETIMEDOUT;435 }436 437 return 0;438}439 440static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr)441{442 struct a10_fpga_priv *priv = mgr->priv;443 u32 reg = socfpga_a10_fpga_read_stat(priv);444 445 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE)446 return FPGA_MGR_STATE_OPERATING;447 448 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)449 return FPGA_MGR_STATE_WRITE;450 451 if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR)452 return FPGA_MGR_STATE_WRITE_COMPLETE_ERR;453 454 if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)455 return FPGA_MGR_STATE_RESET;456 457 return FPGA_MGR_STATE_UNKNOWN;458}459 460static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {461 .initial_header_size = (RBF_DECOMPRESS_OFFSET + 1) * 4,462 .state = socfpga_a10_fpga_state,463 .write_init = socfpga_a10_fpga_write_init,464 .write = socfpga_a10_fpga_write,465 .write_complete = socfpga_a10_fpga_write_complete,466};467 468static int socfpga_a10_fpga_probe(struct platform_device *pdev)469{470 struct device *dev = &pdev->dev;471 struct a10_fpga_priv *priv;472 void __iomem *reg_base;473 struct fpga_manager *mgr;474 int ret;475 476 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);477 if (!priv)478 return -ENOMEM;479 480 /* First mmio base is for register access */481 reg_base = devm_platform_ioremap_resource(pdev, 0);482 if (IS_ERR(reg_base))483 return PTR_ERR(reg_base);484 485 /* Second mmio base is for writing FPGA image data */486 priv->fpga_data_addr = devm_platform_ioremap_resource(pdev, 1);487 if (IS_ERR(priv->fpga_data_addr))488 return PTR_ERR(priv->fpga_data_addr);489 490 /* regmap for register access */491 priv->regmap = devm_regmap_init_mmio(dev, reg_base,492 &socfpga_a10_fpga_regmap_config);493 if (IS_ERR(priv->regmap))494 return -ENODEV;495 496 priv->clk = devm_clk_get(dev, NULL);497 if (IS_ERR(priv->clk)) {498 dev_err(dev, "no clock specified\n");499 return PTR_ERR(priv->clk);500 }501 502 ret = clk_prepare_enable(priv->clk);503 if (ret) {504 dev_err(dev, "could not enable clock\n");505 return -EBUSY;506 }507 508 mgr = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",509 &socfpga_a10_fpga_mgr_ops, priv);510 if (IS_ERR(mgr)) {511 clk_disable_unprepare(priv->clk);512 return PTR_ERR(mgr);513 }514 515 platform_set_drvdata(pdev, mgr);516 517 return 0;518}519 520static void socfpga_a10_fpga_remove(struct platform_device *pdev)521{522 struct fpga_manager *mgr = platform_get_drvdata(pdev);523 struct a10_fpga_priv *priv = mgr->priv;524 525 fpga_mgr_unregister(mgr);526 clk_disable_unprepare(priv->clk);527}528 529static const struct of_device_id socfpga_a10_fpga_of_match[] = {530 { .compatible = "altr,socfpga-a10-fpga-mgr", },531 {},532};533 534MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);535 536static struct platform_driver socfpga_a10_fpga_driver = {537 .probe = socfpga_a10_fpga_probe,538 .remove_new = socfpga_a10_fpga_remove,539 .driver = {540 .name = "socfpga_a10_fpga_manager",541 .of_match_table = socfpga_a10_fpga_of_match,542 },543};544 545module_platform_driver(socfpga_a10_fpga_driver);546 547MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");548MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager");549MODULE_LICENSE("GPL v2");550