Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fpga-manager: Add Socfpga Arria10 support

Add low level driver to support reprogramming FPGAs for Altera
SoCFPGA Arria10.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Tull and committed by
Greg Kroah-Hartman
acbb910a ca24a648

+563
+6
drivers/fpga/Kconfig
··· 26 26 help 27 27 FPGA manager driver support for Altera SOCFPGA. 28 28 29 + config FPGA_MGR_SOCFPGA_A10 30 + tristate "Altera SoCFPGA Arria10" 31 + depends on ARCH_SOCFPGA 32 + help 33 + FPGA manager driver support for Altera Arria10 SoCFPGA. 34 + 29 35 config FPGA_MGR_ZYNQ_FPGA 30 36 tristate "Xilinx Zynq FPGA" 31 37 depends on ARCH_ZYNQ || COMPILE_TEST
+1
drivers/fpga/Makefile
··· 7 7 8 8 # FPGA Manager Drivers 9 9 obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o 10 + obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o 10 11 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o 11 12 12 13 # FPGA Bridge Drivers
+556
drivers/fpga/socfpga-a10.c
··· 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 + .state = socfpga_a10_fpga_state, 474 + .write_init = socfpga_a10_fpga_write_init, 475 + .write = socfpga_a10_fpga_write, 476 + .write_complete = socfpga_a10_fpga_write_complete, 477 + }; 478 + 479 + static int socfpga_a10_fpga_probe(struct platform_device *pdev) 480 + { 481 + struct device *dev = &pdev->dev; 482 + struct a10_fpga_priv *priv; 483 + void __iomem *reg_base; 484 + struct resource *res; 485 + int ret; 486 + 487 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 488 + if (!priv) 489 + return -ENOMEM; 490 + 491 + /* First mmio base is for register access */ 492 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 493 + reg_base = devm_ioremap_resource(dev, res); 494 + if (IS_ERR(reg_base)) 495 + return PTR_ERR(reg_base); 496 + 497 + /* Second mmio base is for writing FPGA image data */ 498 + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 499 + priv->fpga_data_addr = devm_ioremap_resource(dev, res); 500 + if (IS_ERR(priv->fpga_data_addr)) 501 + return PTR_ERR(priv->fpga_data_addr); 502 + 503 + /* regmap for register access */ 504 + priv->regmap = devm_regmap_init_mmio(dev, reg_base, 505 + &socfpga_a10_fpga_regmap_config); 506 + if (IS_ERR(priv->regmap)) 507 + return -ENODEV; 508 + 509 + priv->clk = devm_clk_get(dev, NULL); 510 + if (IS_ERR(priv->clk)) { 511 + dev_err(dev, "no clock specified\n"); 512 + return PTR_ERR(priv->clk); 513 + } 514 + 515 + ret = clk_prepare_enable(priv->clk); 516 + if (ret) { 517 + dev_err(dev, "could not enable clock\n"); 518 + return -EBUSY; 519 + } 520 + 521 + return fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager", 522 + &socfpga_a10_fpga_mgr_ops, priv); 523 + } 524 + 525 + static int socfpga_a10_fpga_remove(struct platform_device *pdev) 526 + { 527 + struct fpga_manager *mgr = platform_get_drvdata(pdev); 528 + struct a10_fpga_priv *priv = mgr->priv; 529 + 530 + fpga_mgr_unregister(&pdev->dev); 531 + clk_disable_unprepare(priv->clk); 532 + 533 + return 0; 534 + } 535 + 536 + static const struct of_device_id socfpga_a10_fpga_of_match[] = { 537 + { .compatible = "altr,socfpga-a10-fpga-mgr", }, 538 + {}, 539 + }; 540 + 541 + MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match); 542 + 543 + static struct platform_driver socfpga_a10_fpga_driver = { 544 + .probe = socfpga_a10_fpga_probe, 545 + .remove = socfpga_a10_fpga_remove, 546 + .driver = { 547 + .name = "socfpga_a10_fpga_manager", 548 + .of_match_table = socfpga_a10_fpga_of_match, 549 + }, 550 + }; 551 + 552 + module_platform_driver(socfpga_a10_fpga_driver); 553 + 554 + MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>"); 555 + MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager"); 556 + MODULE_LICENSE("GPL v2");