cregit-Linux how code gets into the kernel

Release 4.14 drivers/fpga/ts73xx-fpga.c

Directory: drivers/fpga
/*
 * Technologic Systems TS-73xx SBC FPGA loader
 *
 * Copyright (C) 2016 Florian Fainelli <f.fainelli@gmail.com>
 *
 * FPGA Manager Driver for the on-board Altera Cyclone II FPGA found on
 * TS-7300, heavily based on load_fpga.c in their vendor tree.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that 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.
 */

#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/iopoll.h>
#include <linux/fpga/fpga-mgr.h>


#define TS73XX_FPGA_DATA_REG		0

#define TS73XX_FPGA_CONFIG_REG		1


#define TS73XX_FPGA_WRITE_DONE		0x1

#define TS73XX_FPGA_WRITE_DONE_TIMEOUT	1000	
/* us */

#define TS73XX_FPGA_RESET		0x2

#define TS73XX_FPGA_RESET_LOW_DELAY	30	
/* us */

#define TS73XX_FPGA_RESET_HIGH_DELAY	80	
/* us */

#define TS73XX_FPGA_LOAD_OK		0x4

#define TS73XX_FPGA_CONFIG_LOAD		0x8


struct ts73xx_fpga_priv {
	
void __iomem	*io_base;
	
struct device	*dev;
};


static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr) { return FPGA_MGR_STATE_UNKNOWN; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli15100.00%1100.00%
Total15100.00%1100.00%


static int ts73xx_fpga_write_init(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { struct ts73xx_fpga_priv *priv = mgr->priv; /* Reset the FPGA */ writeb(0, priv->io_base + TS73XX_FPGA_CONFIG_REG); udelay(TS73XX_FPGA_RESET_LOW_DELAY); writeb(TS73XX_FPGA_RESET, priv->io_base + TS73XX_FPGA_CONFIG_REG); udelay(TS73XX_FPGA_RESET_HIGH_DELAY); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli69100.00%1100.00%
Total69100.00%1100.00%


static int ts73xx_fpga_write(struct fpga_manager *mgr, const char *buf, size_t count) { struct ts73xx_fpga_priv *priv = mgr->priv; size_t i = 0; int ret; u8 reg; while (count--) { ret = readb_poll_timeout(priv->io_base + TS73XX_FPGA_CONFIG_REG, reg, !(reg & TS73XX_FPGA_WRITE_DONE), 1, TS73XX_FPGA_WRITE_DONE_TIMEOUT); if (ret < 0) return ret; writeb(buf[i], priv->io_base + TS73XX_FPGA_DATA_REG); i++; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli99100.00%1100.00%
Total99100.00%1100.00%


static int ts73xx_fpga_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) { struct ts73xx_fpga_priv *priv = mgr->priv; u8 reg; usleep_range(1000, 2000); reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG); reg |= TS73XX_FPGA_CONFIG_LOAD; writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG); usleep_range(1000, 2000); reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG); reg &= ~TS73XX_FPGA_CONFIG_LOAD; writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG); reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG); if ((reg & TS73XX_FPGA_LOAD_OK) != TS73XX_FPGA_LOAD_OK) return -ETIMEDOUT; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli123100.00%1100.00%
Total123100.00%1100.00%

static const struct fpga_manager_ops ts73xx_fpga_ops = { .state = ts73xx_fpga_state, .write_init = ts73xx_fpga_write_init, .write = ts73xx_fpga_write, .write_complete = ts73xx_fpga_write_complete, };
static int ts73xx_fpga_probe(struct platform_device *pdev) { struct device *kdev = &pdev->dev; struct ts73xx_fpga_priv *priv; struct resource *res; priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->dev = kdev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->io_base = devm_ioremap_resource(kdev, res); if (IS_ERR(priv->io_base)) { dev_err(kdev, "unable to remap registers\n"); return PTR_ERR(priv->io_base); } return fpga_mgr_register(kdev, "TS-73xx FPGA Manager", &ts73xx_fpga_ops, priv); }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli122100.00%1100.00%
Total122100.00%1100.00%


static int ts73xx_fpga_remove(struct platform_device *pdev) { fpga_mgr_unregister(&pdev->dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli22100.00%1100.00%
Total22100.00%1100.00%

static struct platform_driver ts73xx_fpga_driver = { .driver = { .name = "ts73xx-fpga-mgr", }, .probe = ts73xx_fpga_probe, .remove = ts73xx_fpga_remove, }; module_platform_driver(ts73xx_fpga_driver); MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>"); MODULE_DESCRIPTION("TS-73xx FPGA Manager driver"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Florian Fainelli601100.00%1100.00%
Total601100.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.