cregit-Linux how code gets into the kernel

Release 4.14 drivers/fpga/altera-pr-ip-core.c

Directory: drivers/fpga
/*
 * Driver for Altera Partial Reconfiguration IP Core
 *
 * Copyright (C) 2016-2017 Intel Corporation
 *
 * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation
 *  by Alan Tull <atull@opensource.altera.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <linux/delay.h>
#include <linux/fpga/altera-pr-ip-core.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/module.h>


#define ALT_PR_DATA_OFST		0x00

#define ALT_PR_CSR_OFST			0x04


#define ALT_PR_CSR_PR_START		BIT(0)

#define ALT_PR_CSR_STATUS_SFT		2

#define ALT_PR_CSR_STATUS_MSK		(7 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_NRESET	(0 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_PR_ERR	(1 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_CRC_ERR	(2 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_BAD_BITS	(3 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_PR_IN_PROG	(4 << ALT_PR_CSR_STATUS_SFT)

#define ALT_PR_CSR_STATUS_PR_SUCCESS	(5 << ALT_PR_CSR_STATUS_SFT)


struct alt_pr_priv {
	
void __iomem *reg_base;
};


static enum fpga_mgr_states alt_pr_fpga_state(struct fpga_manager *mgr) { struct alt_pr_priv *priv = mgr->priv; const char *err = "unknown"; enum fpga_mgr_states ret = FPGA_MGR_STATE_UNKNOWN; u32 val; val = readl(priv->reg_base + ALT_PR_CSR_OFST); val &= ALT_PR_CSR_STATUS_MSK; switch (val) { case ALT_PR_CSR_STATUS_NRESET: return FPGA_MGR_STATE_RESET; case ALT_PR_CSR_STATUS_PR_ERR: err = "pr error"; ret = FPGA_MGR_STATE_WRITE_ERR; break; case ALT_PR_CSR_STATUS_CRC_ERR: err = "crc error"; ret = FPGA_MGR_STATE_WRITE_ERR; break; case ALT_PR_CSR_STATUS_BAD_BITS: err = "bad bits"; ret = FPGA_MGR_STATE_WRITE_ERR; break; case ALT_PR_CSR_STATUS_PR_IN_PROG: return FPGA_MGR_STATE_WRITE; case ALT_PR_CSR_STATUS_PR_SUCCESS: return FPGA_MGR_STATE_OPERATING; default: break; } dev_err(&mgr->dev, "encountered error code %d (%s) in %s()\n", val, err, __func__); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach133100.00%1100.00%
Total133100.00%1100.00%


static int alt_pr_fpga_write_init(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { struct alt_pr_priv *priv = mgr->priv; u32 val; if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { dev_err(&mgr->dev, "%s Partial Reconfiguration flag not set\n", __func__); return -EINVAL; } val = readl(priv->reg_base + ALT_PR_CSR_OFST); if (val & ALT_PR_CSR_PR_START) { dev_err(&mgr->dev, "%s Partial Reconfiguration already started\n", __func__); return -EINVAL; } writel(val | ALT_PR_CSR_PR_START, priv->reg_base + ALT_PR_CSR_OFST); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach116100.00%1100.00%
Total116100.00%1100.00%


static int alt_pr_fpga_write(struct fpga_manager *mgr, const char *buf, size_t count) { struct alt_pr_priv *priv = mgr->priv; u32 *buffer_32 = (u32 *)buf; size_t i = 0; if (count <= 0) return -EINVAL; /* Write out the complete 32-bit chunks */ while (count >= sizeof(u32)) { writel(buffer_32[i++], priv->reg_base); count -= sizeof(u32); } /* Write out remaining non 32-bit chunks */ switch (count) { case 3: writel(buffer_32[i++] & 0x00ffffff, priv->reg_base); break; case 2: writel(buffer_32[i++] & 0x0000ffff, priv->reg_base); break; case 1: writel(buffer_32[i++] & 0x000000ff, priv->reg_base); break; case 0: break; default: /* This will never happen */ return -EFAULT; } if (alt_pr_fpga_state(mgr) == FPGA_MGR_STATE_WRITE_ERR) return -EIO; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach175100.00%1100.00%
Total175100.00%1100.00%


static int alt_pr_fpga_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) { u32 i = 0; do { switch (alt_pr_fpga_state(mgr)) { case FPGA_MGR_STATE_WRITE_ERR: return -EIO; case FPGA_MGR_STATE_OPERATING: dev_info(&mgr->dev, "successful partial reconfiguration\n"); return 0; default: break; } udelay(1); } while (info->config_complete_timeout_us > i++); dev_err(&mgr->dev, "timed out waiting for write to complete\n"); return -ETIMEDOUT; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach87100.00%1100.00%
Total87100.00%1100.00%

static const struct fpga_manager_ops alt_pr_ops = { .state = alt_pr_fpga_state, .write_init = alt_pr_fpga_write_init, .write = alt_pr_fpga_write, .write_complete = alt_pr_fpga_write_complete, };
int alt_pr_register(struct device *dev, void __iomem *reg_base) { struct alt_pr_priv *priv; u32 val; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->reg_base = reg_base; val = readl(priv->reg_base + ALT_PR_CSR_OFST); dev_dbg(dev, "%s status=%d start=%d\n", __func__, (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT, (int)(val & ALT_PR_CSR_PR_START)); return fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv); }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach106100.00%1100.00%
Total106100.00%1100.00%

EXPORT_SYMBOL_GPL(alt_pr_register);
int alt_pr_unregister(struct device *dev) { dev_dbg(dev, "%s\n", __func__); fpga_mgr_unregister(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL_GPL(alt_pr_unregister); MODULE_AUTHOR("Matthew Gerlach <matthew.gerlach@linux.intel.com>"); MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Core"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Matthew Gerlach764100.00%1100.00%
Total764100.00%1100.00%
Directory: drivers/fpga
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.