Commit fab6266e82a8981cccec55af47589665daf69fb6

Authored by Alan Tull
Committed by Greg Kroah-Hartman
1 parent 6a8c3be7ec

fpga manager: add driver for socfpga fpga manager

Add driver to fpga manager framework to allow configuration
of FPGA in Altera SoCFPGA parts.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 3 changed files with 627 additions and 0 deletions Side-by-side Diff

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