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