FILE
socfpga.c
File preview with syntax highlighting.
linux-6.19.14/drivers/fpga/socfpga.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * FPGA Manager Driver for Altera SOCFPGA 4 * 5 * Copyright (C) 2013-2015 Altera Corporation 6 */ 7#include <linux/completion.h> 8#include <linux/delay.h> 9#include <linux/fpga/fpga-mgr.h> 10#include <linux/interrupt.h> 11#include <linux/io.h> 12#include <linux/module.h> 13#include <linux/of_address.h> 14#include <linux/of_irq.h> 15#include <linux/pm.h> 16 17/* Register offsets */ 18#define SOCFPGA_FPGMGR_STAT_OFST 0x0 19#define SOCFPGA_FPGMGR_CTL_OFST 0x4 20#define SOCFPGA_FPGMGR_DCLKCNT_OFST 0x8 21#define SOCFPGA_FPGMGR_DCLKSTAT_OFST 0xc 22#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST 0x830 23#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST 0x834 24#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST 0x838 25#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST 0x83c 26#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST 0x840 27#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST 0x844 28#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST 0x84c 29#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST 0x850 30 31/* Register bit defines */ 32/* SOCFPGA_FPGMGR_STAT register mode field values */ 33#define SOCFPGA_FPGMGR_STAT_POWER_UP 0x0 /*ramping*/ 34#define SOCFPGA_FPGMGR_STAT_RESET 0x1 35#define SOCFPGA_FPGMGR_STAT_CFG 0x2 36#define SOCFPGA_FPGMGR_STAT_INIT 0x3 37#define SOCFPGA_FPGMGR_STAT_USER_MODE 0x4 38#define SOCFPGA_FPGMGR_STAT_UNKNOWN 0x5 39#define SOCFPGA_FPGMGR_STAT_STATE_MASK 0x7 40/* This is a flag value that doesn't really happen in this register field */ 41#define SOCFPGA_FPGMGR_STAT_POWER_OFF 0x0 42 43#define MSEL_PP16_FAST_NOAES_NODC 0x0 44#define MSEL_PP16_FAST_AES_NODC 0x1 45#define MSEL_PP16_FAST_AESOPT_DC 0x2 46#define MSEL_PP16_SLOW_NOAES_NODC 0x4 47#define MSEL_PP16_SLOW_AES_NODC 0x5 48#define MSEL_PP16_SLOW_AESOPT_DC 0x6 49#define MSEL_PP32_FAST_NOAES_NODC 0x8 50#define MSEL_PP32_FAST_AES_NODC 0x9 51#define MSEL_PP32_FAST_AESOPT_DC 0xa 52#define MSEL_PP32_SLOW_NOAES_NODC 0xc 53#define MSEL_PP32_SLOW_AES_NODC 0xd 54#define MSEL_PP32_SLOW_AESOPT_DC 0xe 55#define SOCFPGA_FPGMGR_STAT_MSEL_MASK 0x000000f8 56#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT 3 57 58/* SOCFPGA_FPGMGR_CTL register */ 59#define SOCFPGA_FPGMGR_CTL_EN 0x00000001 60#define SOCFPGA_FPGMGR_CTL_NCE 0x00000002 61#define SOCFPGA_FPGMGR_CTL_NCFGPULL 0x00000004 62 63#define CDRATIO_X1 0x00000000 64#define CDRATIO_X2 0x00000040 65#define CDRATIO_X4 0x00000080 66#define CDRATIO_X8 0x000000c0 67#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK 0x000000c0 68 69#define SOCFPGA_FPGMGR_CTL_AXICFGEN 0x00000100 70 71#define CFGWDTH_16 0x00000000 72#define CFGWDTH_32 0x00000200 73#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK 0x00000200 74 75/* SOCFPGA_FPGMGR_DCLKSTAT register */ 76#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE 0x1 77 78/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */ 79#define SOCFPGA_FPGMGR_MON_NSTATUS 0x0001 80#define SOCFPGA_FPGMGR_MON_CONF_DONE 0x0002 81#define SOCFPGA_FPGMGR_MON_INIT_DONE 0x0004 82#define SOCFPGA_FPGMGR_MON_CRC_ERROR 0x0008 83#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE 0x0010 84#define SOCFPGA_FPGMGR_MON_PR_READY 0x0020 85#define SOCFPGA_FPGMGR_MON_PR_ERROR 0x0040 86#define SOCFPGA_FPGMGR_MON_PR_DONE 0x0080 87#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN 0x0100 88#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN 0x0200 89#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN 0x0400 90#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON 0x0800 91#define SOCFPGA_FPGMGR_MON_STATUS_MASK 0x0fff 92 93#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3 94#define SOCFPGA_RESUME_TIMEOUT 3 95 96/* In power-up order. Reverse for power-down. */ 97static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = { 98 "FPGA-1.5V", 99 "FPGA-1.1V", 100 "FPGA-2.5V", 101}; 102 103struct socfpga_fpga_priv { 104 void __iomem *fpga_base_addr; 105 void __iomem *fpga_data_addr; 106 struct completion status_complete; 107 int irq; 108}; 109 110struct cfgmgr_mode { 111 /* Values to set in the CTRL register */ 112 u32 ctrl; 113 114 /* flag that this table entry is a valid mode */ 115 bool valid; 116}; 117 118/* For SOCFPGA_FPGMGR_STAT_MSEL field */ 119static struct cfgmgr_mode cfgmgr_modes[] = { 120 [MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 }, 121 [MSEL_PP16_FAST_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 }, 122 [MSEL_PP16_FAST_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 }, 123 [MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 }, 124 [MSEL_PP16_SLOW_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 }, 125 [MSEL_PP16_SLOW_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 }, 126 [MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 }, 127 [MSEL_PP32_FAST_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 }, 128 [MSEL_PP32_FAST_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 }, 129 [MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 }, 130 [MSEL_PP32_SLOW_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 }, 131 [MSEL_PP32_SLOW_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 }, 132}; 133 134static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset) 135{ 136 return readl(priv->fpga_base_addr + reg_offset); 137} 138 139static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset, 140 u32 value) 141{ 142 writel(value, priv->fpga_base_addr + reg_offset); 143} 144 145static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv, 146 u32 reg_offset) 147{ 148 return __raw_readl(priv->fpga_base_addr + reg_offset); 149} 150 151static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv, 152 u32 reg_offset, u32 value) 153{ 154 __raw_writel(value, priv->fpga_base_addr + reg_offset); 155} 156 157static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value) 158{ 159 writel(value, priv->fpga_data_addr); 160} 161 162static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv, 163 u32 offset, u32 bits) 164{ 165 u32 val; 166 167 val = socfpga_fpga_readl(priv, offset); 168 val |= bits; 169 socfpga_fpga_writel(priv, offset, val); 170} 171 172static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv, 173 u32 offset, u32 bits) 174{ 175 u32 val; 176 177 val = socfpga_fpga_readl(priv, offset); 178 val &= ~bits; 179 socfpga_fpga_writel(priv, offset, val); 180} 181 182static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv) 183{ 184 return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) & 185 SOCFPGA_FPGMGR_MON_STATUS_MASK; 186} 187 188static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv) 189{ 190 u32 status = socfpga_fpga_mon_status_get(priv); 191 192 if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0) 193 return SOCFPGA_FPGMGR_STAT_POWER_OFF; 194 195 return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) & 196 SOCFPGA_FPGMGR_STAT_STATE_MASK; 197} 198 199static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv) 200{ 201 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST, 202 SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE); 203} 204 205/* 206 * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear 207 * the complete status. 208 */ 209static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv, 210 u32 count) 211{ 212 int timeout = 2; 213 u32 done; 214 215 /* Clear any existing DONE status. */ 216 if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST)) 217 socfpga_fpga_clear_done_status(priv); 218 219 /* Issue the DCLK count. */ 220 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count); 221 222 /* Poll DCLKSTAT to see if it completed in the timeout period. */ 223 do { 224 done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST); 225 if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) { 226 socfpga_fpga_clear_done_status(priv); 227 return 0; 228 } 229 udelay(1); 230 } while (timeout--); 231 232 return -ETIMEDOUT; 233} 234 235static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv, 236 u32 state) 237{ 238 int timeout = 2; 239 240 /* 241 * HW doesn't support an interrupt for changes in state, so poll to see 242 * if it matches the requested state within the timeout period. 243 */ 244 do { 245 if ((socfpga_fpga_state_get(priv) & state) != 0) 246 return 0; 247 msleep(20); 248 } while (timeout--); 249 250 return -ETIMEDOUT; 251} 252 253static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs) 254{ 255 /* set irqs to level sensitive */ 256 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0); 257 258 /* set interrupt polarity */ 259 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs); 260 261 /* clear irqs */ 262 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs); 263 264 /* unmask interrupts */ 265 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0); 266 267 /* enable interrupts */ 268 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs); 269} 270 271static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv) 272{ 273 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0); 274} 275 276static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id) 277{ 278 struct socfpga_fpga_priv *priv = dev_id; 279 u32 irqs, st; 280 bool conf_done, nstatus; 281 282 /* clear irqs */ 283 irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST); 284 285 socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs); 286 287 st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST); 288 conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0; 289 nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0; 290 291 /* success */ 292 if (conf_done && nstatus) { 293 /* disable irqs */ 294 socfpga_fpga_raw_writel(priv, 295 SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0); 296 complete(&priv->status_complete); 297 } 298 299 return IRQ_HANDLED; 300} 301 302static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv) 303{ 304 int ret = 0; 305 long time_left; 306 307 socfpga_fpga_disable_irqs(priv); 308 init_completion(&priv->status_complete); 309 socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE); 310 311 time_left = wait_for_completion_interruptible_timeout( 312 &priv->status_complete, 313 msecs_to_jiffies(10)); 314 if (time_left == 0) 315 ret = -ETIMEDOUT; 316 317 socfpga_fpga_disable_irqs(priv); 318 return ret; 319} 320 321static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv) 322{ 323 u32 msel; 324 325 msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST); 326 msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK; 327 msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT; 328 329 /* Check that this MSEL setting is supported */ 330 if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid) 331 return -EINVAL; 332 333 return msel; 334} 335 336static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv) 337{ 338 u32 ctrl_reg; 339 int mode; 340 341 /* get value from MSEL pins */ 342 mode = socfpga_fpga_cfg_mode_get(priv); 343 if (mode < 0) 344 return mode; 345 346 /* Adjust CTRL for the CDRATIO */ 347 ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST); 348 ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK; 349 ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK; 350 ctrl_reg |= cfgmgr_modes[mode].ctrl; 351 352 /* Set NCE to 0. */ 353 ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE; 354 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); 355 356 return 0; 357} 358 359static int socfpga_fpga_reset(struct fpga_manager *mgr) 360{ 361 struct socfpga_fpga_priv *priv = mgr->priv; 362 u32 ctrl_reg, status; 363 int ret; 364 365 /* 366 * Step 1: 367 * - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode 368 * - Set CTRL.NCE to 0 369 */ 370 ret = socfpga_fpga_cfg_mode_set(priv); 371 if (ret) 372 return ret; 373 374 /* Step 2: Set CTRL.EN to 1 */ 375 socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, 376 SOCFPGA_FPGMGR_CTL_EN); 377 378 /* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */ 379 ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST); 380 ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL; 381 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); 382 383 /* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */ 384 status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET); 385 386 /* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */ 387 ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL; 388 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); 389 390 /* Timeout waiting for reset */ 391 if (status) 392 return -ETIMEDOUT; 393 394 return 0; 395} 396 397/* 398 * Prepare the FPGA to receive the configuration data. 399 */ 400static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, 401 struct fpga_image_info *info, 402 const char *buf, size_t count) 403{ 404 struct socfpga_fpga_priv *priv = mgr->priv; 405 int ret; 406 407 if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { 408 dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); 409 return -EINVAL; 410 } 411 /* Steps 1 - 5: Reset the FPGA */ 412 ret = socfpga_fpga_reset(mgr); 413 if (ret) 414 return ret; 415 416 /* Step 6: Wait for FPGA to enter configuration phase */ 417 if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG)) 418 return -ETIMEDOUT; 419 420 /* Step 7: Clear nSTATUS interrupt */ 421 socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, 422 SOCFPGA_FPGMGR_MON_NSTATUS); 423 424 /* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */ 425 socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, 426 SOCFPGA_FPGMGR_CTL_AXICFGEN); 427 428 return 0; 429} 430 431/* 432 * Step 9: write data to the FPGA data register 433 */ 434static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr, 435 const char *buf, size_t count) 436{ 437 struct socfpga_fpga_priv *priv = mgr->priv; 438 u32 *buffer_32 = (u32 *)buf; 439 size_t i = 0; 440 441 if (count <= 0) 442 return -EINVAL; 443 444 /* Write out the complete 32-bit chunks. */ 445 while (count >= sizeof(u32)) { 446 socfpga_fpga_data_writel(priv, buffer_32[i++]); 447 count -= sizeof(u32); 448 } 449 450 /* Write out remaining non 32-bit chunks. */ 451 switch (count) { 452 case 3: 453 socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff); 454 break; 455 case 2: 456 socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff); 457 break; 458 case 1: 459 socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff); 460 break; 461 case 0: 462 break; 463 default: 464 /* This will never happen. */ 465 return -EFAULT; 466 } 467 468 return 0; 469} 470 471static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr, 472 struct fpga_image_info *info) 473{ 474 struct socfpga_fpga_priv *priv = mgr->priv; 475 u32 status; 476 477 /* 478 * Step 10: 479 * - Observe CONF_DONE and nSTATUS (active low) 480 * - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful 481 * - if CONF_DONE = 0 and nSTATUS = 0, configuration failed 482 */ 483 status = socfpga_fpga_wait_for_config_done(priv); 484 if (status) 485 return status; 486 487 /* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */ 488 socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, 489 SOCFPGA_FPGMGR_CTL_AXICFGEN); 490 491 /* 492 * Step 12: 493 * - Write 4 to DCLKCNT 494 * - Wait for STATUS.DCNTDONE = 1 495 * - Clear W1C bit in STATUS.DCNTDONE 496 */ 497 if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4)) 498 return -ETIMEDOUT; 499 500 /* Step 13: Wait for STATUS.MODE to report USER MODE */ 501 if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE)) 502 return -ETIMEDOUT; 503 504 /* Step 14: Set CTRL.EN to 0 */ 505 socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, 506 SOCFPGA_FPGMGR_CTL_EN); 507 508 return 0; 509} 510 511/* Translate state register values to FPGA framework state */ 512static const enum fpga_mgr_states socfpga_state_to_framework_state[] = { 513 [SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF, 514 [SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET, 515 [SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT, 516 [SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT, 517 [SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING, 518 [SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN, 519}; 520 521static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr) 522{ 523 struct socfpga_fpga_priv *priv = mgr->priv; 524 enum fpga_mgr_states ret; 525 u32 state; 526 527 state = socfpga_fpga_state_get(priv); 528 529 if (state < ARRAY_SIZE(socfpga_state_to_framework_state)) 530 ret = socfpga_state_to_framework_state[state]; 531 else 532 ret = FPGA_MGR_STATE_UNKNOWN; 533 534 return ret; 535} 536 537static const struct fpga_manager_ops socfpga_fpga_ops = { 538 .state = socfpga_fpga_ops_state, 539 .write_init = socfpga_fpga_ops_configure_init, 540 .write = socfpga_fpga_ops_configure_write, 541 .write_complete = socfpga_fpga_ops_configure_complete, 542}; 543 544static int socfpga_fpga_probe(struct platform_device *pdev) 545{ 546 struct device *dev = &pdev->dev; 547 struct socfpga_fpga_priv *priv; 548 struct fpga_manager *mgr; 549 int ret; 550 551 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 552 if (!priv) 553 return -ENOMEM; 554 555 priv->fpga_base_addr = devm_platform_ioremap_resource(pdev, 0); 556 if (IS_ERR(priv->fpga_base_addr)) 557 return PTR_ERR(priv->fpga_base_addr); 558 559 priv->fpga_data_addr = devm_platform_ioremap_resource(pdev, 1); 560 if (IS_ERR(priv->fpga_data_addr)) 561 return PTR_ERR(priv->fpga_data_addr); 562 563 priv->irq = platform_get_irq(pdev, 0); 564 if (priv->irq < 0) 565 return priv->irq; 566 567 ret = devm_request_irq(dev, priv->irq, socfpga_fpga_isr, 0, 568 dev_name(dev), priv); 569 if (ret) 570 return ret; 571 572 mgr = devm_fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", 573 &socfpga_fpga_ops, priv); 574 return PTR_ERR_OR_ZERO(mgr); 575} 576 577#ifdef CONFIG_OF 578static const struct of_device_id socfpga_fpga_of_match[] = { 579 { .compatible = "altr,socfpga-fpga-mgr", }, 580 {}, 581}; 582 583MODULE_DEVICE_TABLE(of, socfpga_fpga_of_match); 584#endif 585 586static struct platform_driver socfpga_fpga_driver = { 587 .probe = socfpga_fpga_probe, 588 .driver = { 589 .name = "socfpga_fpga_manager", 590 .of_match_table = of_match_ptr(socfpga_fpga_of_match), 591 }, 592}; 593 594module_platform_driver(socfpga_fpga_driver); 595 596MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>"); 597MODULE_DESCRIPTION("Altera SOCFPGA FPGA Manager"); 598MODULE_LICENSE("GPL v2");
~/
Read-only file preview.