10e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
20e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * CARMA Board DATA-FPGA Programmer
30e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
40e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Copyright (c) 2009-2011 Ira W. Snyder <iws@ovro.caltech.edu>
50e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
60e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * This program is free software; you can redistribute it and/or modify it
70e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * under the terms of the GNU General Public License as published by the
80e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Free Software Foundation; either version 2 of the License, or (at your
90e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * option) any later version.
100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/dma-mapping.h>
130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/of_platform.h>
140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/completion.h>
150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/miscdevice.h>
160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/dmaengine.h>
170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/interrupt.h>
180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/highmem.h>
190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/kernel.h>
200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/module.h>
210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/mutex.h>
220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/delay.h>
230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/init.h>
240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/leds.h>
250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/slab.h>
260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/kref.h>
270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/fs.h>
280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <linux/io.h>
290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <media/videobuf-dma-sg.h>
310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/* MPC8349EMDS specific get_immrbase() */
330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#include <sysdev/fsl_soc.h>
340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic const char drv_name[] = "carma-fpga-program";
360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Firmware images are always this exact size
390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * 12849552 bytes for a CARMA Digitizer Board (EP2S90 FPGAs)
410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * 18662880 bytes for a CARMA Correlator Board (EP2S130 FPGAs)
420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FW_SIZE_EP2S90		12849552
440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FW_SIZE_EP2S130		18662880
450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstruct fpga_dev {
470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct miscdevice miscdev;
480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Reference count */
500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct kref ref;
510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Device Registers */
530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct device *dev;
540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	void __iomem *regs;
550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	void __iomem *immr;
560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Freescale DMA Device */
580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct dma_chan *chan;
590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Interrupts */
610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int irq, status;
620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct completion completion;
630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* FPGA Bitfile */
650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct mutex lock;
660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct videobuf_dmabuf vb;
680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	bool vb_allocated;
690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* max size and written bytes */
710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	size_t fw_size;
720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	size_t bytes;
730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * FPGA Bitfile Helpers
770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_drop_firmware_data() - drop the bitfile image from memory
810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * LOCKING: must hold priv->lock
840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_drop_firmware_data(struct fpga_dev *priv)
860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	videobuf_dma_free(&priv->vb);
880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->vb_allocated = false;
890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->bytes = 0;
900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Private Data Reference Count
940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_dev_remove(struct kref *ref)
970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = container_of(ref, struct fpga_dev, ref);
990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* free any firmware image that was not programmed */
1010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_drop_firmware_data(priv);
1020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	mutex_destroy(&priv->lock);
1040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kfree(priv);
1050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
1080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * LED Trigger (could be a seperate module)
1090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
1100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
1120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * NOTE: this whole thing does have the problem that whenever the led's are
1130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * NOTE: first set to use the fpga trigger, they could be in the wrong state
1140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
1150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira SnyderDEFINE_LED_TRIGGER(ledtrig_fpga);
1170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void ledtrig_fpga_programmed(bool enabled)
1190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (enabled)
1210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		led_trigger_event(ledtrig_fpga, LED_FULL);
1220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	else
1230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		led_trigger_event(ledtrig_fpga, LED_OFF);
1240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
1270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * FPGA Register Helpers
1280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
1290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/* Register Definitions */
1310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_CONTROL		0x40
1320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_STATUS		0x44
1330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_FIFO_SIZE		0x48
1340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_FIFO_USED		0x4C
1350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_TOTAL_BYTE_COUNT	0x50
1360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_CONFIG_CUR_BYTE_COUNT	0x54
1370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FPGA_FIFO_ADDRESS		0x3000
1390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_fifo_size(void __iomem *regs)
1410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ioread32be(regs + FPGA_CONFIG_FIFO_SIZE);
1430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CFG_STATUS_ERR_MASK	0xfffe
1460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_config_error(void __iomem *regs)
1480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ioread32be(regs + FPGA_CONFIG_STATUS) & CFG_STATUS_ERR_MASK;
1500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_fifo_empty(void __iomem *regs)
1530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ioread32be(regs + FPGA_CONFIG_FIFO_USED) == 0;
1550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_fifo_write(void __iomem *regs, u32 val)
1580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(val, regs + FPGA_FIFO_ADDRESS);
1600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_set_byte_count(void __iomem *regs, u32 count)
1630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(count, regs + FPGA_CONFIG_TOTAL_BYTE_COUNT);
1650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CFG_CTL_ENABLE	(1 << 0)
1680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CFG_CTL_RESET	(1 << 1)
1690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CFG_CTL_DMA	(1 << 2)
1700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_programmer_enable(struct fpga_dev *priv, bool dma)
1720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u32 val;
1740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = (dma) ? (CFG_CTL_ENABLE | CFG_CTL_DMA) : CFG_CTL_ENABLE;
1760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(val, priv->regs + FPGA_CONFIG_CONTROL);
1770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_programmer_disable(struct fpga_dev *priv)
1800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(0x0, priv->regs + FPGA_CONFIG_CONTROL);
1820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
1830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_dump_registers(struct fpga_dev *priv)
1850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
1860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u32 control, status, size, used, total, curr;
1870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* good status: do nothing */
1890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (priv->status == 0)
1900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return;
1910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
1920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Dump all status registers */
1930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	control = ioread32be(priv->regs + FPGA_CONFIG_CONTROL);
1940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	status = ioread32be(priv->regs + FPGA_CONFIG_STATUS);
1950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	size = ioread32be(priv->regs + FPGA_CONFIG_FIFO_SIZE);
1960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	used = ioread32be(priv->regs + FPGA_CONFIG_FIFO_USED);
1970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	total = ioread32be(priv->regs + FPGA_CONFIG_TOTAL_BYTE_COUNT);
1980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	curr = ioread32be(priv->regs + FPGA_CONFIG_CUR_BYTE_COUNT);
1990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "Configuration failed, dumping status registers\n");
2010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "Control:    0x%.8x\n", control);
2020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "Status:     0x%.8x\n", status);
2030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "FIFO Size:  0x%.8x\n", size);
2040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "FIFO Used:  0x%.8x\n", used);
2050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "FIFO Total: 0x%.8x\n", total);
2060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_err(priv->dev, "FIFO Curr:  0x%.8x\n", curr);
2070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
2080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
2100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * FPGA Power Supply Code
2110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
2120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CTL_PWR_CONTROL		0x2006
2140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CTL_PWR_STATUS		0x200A
2150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CTL_PWR_FAIL		0x200B
2160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define PWR_CONTROL_ENABLE	0x01
2180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define PWR_STATUS_ERROR_MASK	0x10
2200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define PWR_STATUS_GOOD		0x0f
2210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
2230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Determine if the FPGA power is good for all supplies
2240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
2250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic bool fpga_power_good(struct fpga_dev *priv)
2260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
2270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u8 val;
2280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = ioread8(priv->regs + CTL_PWR_STATUS);
2300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (val & PWR_STATUS_ERROR_MASK)
2310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return false;
2320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return val == PWR_STATUS_GOOD;
2340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
2350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
2370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Disable the FPGA power supplies
2380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
2390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void fpga_disable_power_supplies(struct fpga_dev *priv)
2400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
2410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned long start;
2420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u8 val;
2430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite8(0x0, priv->regs + CTL_PWR_CONTROL);
2450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
2470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * Wait 500ms for the power rails to discharge
2480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
2490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * Without this delay, the CTL-CPLD state machine can get into a
2500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * state where it is waiting for the power-goods to assert, but they
2510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * never do. This only happens when enabling and disabling the
2520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * power sequencer very rapidly.
2530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
2540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * The loop below will also wait for the power goods to de-assert,
2550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * but testing has shown that they are always disabled by the time
2560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * the sleep completes. However, omitting the sleep and only waiting
2570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * for the power-goods to de-assert was not sufficient to ensure
2580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * that the power sequencer would not wedge itself.
2590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
2600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	msleep(500);
2610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	start = jiffies;
2630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	while (time_before(jiffies, start + HZ)) {
2640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		val = ioread8(priv->regs + CTL_PWR_STATUS);
2650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		if (!(val & PWR_STATUS_GOOD))
2660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			break;
2670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		usleep_range(5000, 10000);
2690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
2700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = ioread8(priv->regs + CTL_PWR_STATUS);
2720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (val & PWR_STATUS_GOOD) {
2730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "power disable failed: "
2740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				   "power goods: status 0x%.2x\n", val);
2750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
2760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (val & PWR_STATUS_ERROR_MASK) {
2780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "power disable failed: "
2790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				   "alarm bit set: status 0x%.2x\n", val);
2800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
2810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
2820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
2840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_enable_power_supplies() - enable the DATA-FPGA power supplies
2850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
2860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
2870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Enable the DATA-FPGA power supplies, waiting up to 1 second for
2880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * them to enable successfully.
2890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
2900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Returns 0 on success, -ERRNO otherwise
2910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
2920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_enable_power_supplies(struct fpga_dev *priv)
2930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
2940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned long start = jiffies;
2950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
2960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (fpga_power_good(priv)) {
2970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_dbg(priv->dev, "power was already good\n");
2980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return 0;
2990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
3000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite8(PWR_CONTROL_ENABLE, priv->regs + CTL_PWR_CONTROL);
3020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	while (time_before(jiffies, start + HZ)) {
3030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		if (fpga_power_good(priv))
3040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			return 0;
3050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		usleep_range(5000, 10000);
3070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
3080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return fpga_power_good(priv) ? 0 : -ETIMEDOUT;
3100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
3110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
3130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Determine if the FPGA power supplies are all enabled
3140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
3150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic bool fpga_power_enabled(struct fpga_dev *priv)
3160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
3170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u8 val;
3180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = ioread8(priv->regs + CTL_PWR_CONTROL);
3200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (val & PWR_CONTROL_ENABLE)
3210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return true;
3220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return false;
3240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
3250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
3270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Determine if the FPGA's are programmed and running correctly
3280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
3290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic bool fpga_running(struct fpga_dev *priv)
3300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
3310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!fpga_power_good(priv))
3320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return false;
3330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Check the config done bit */
3350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ioread32be(priv->regs + FPGA_CONFIG_STATUS) & (1 << 18);
3360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
3370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
3390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * FPGA Programming Code
3400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
3410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
3430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_program_block() - put a block of data into the programmer's FIFO
3440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
3450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @buf: the data to program
3460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @count: the length of data to program (must be a multiple of 4 bytes)
3470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
3480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Returns 0 on success, -ERRNO otherwise
3490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
3500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_program_block(struct fpga_dev *priv, void *buf, size_t count)
3510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
3520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u32 *data = buf;
3530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int size = fpga_fifo_size(priv->regs);
3540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int i, len;
3550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned long timeout;
3560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* enforce correct data length for the FIFO */
3580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	BUG_ON(count % 4 != 0);
3590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	while (count > 0) {
3610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		/* Get the size of the block to write (maximum is FIFO_SIZE) */
3630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		len = min_t(size_t, count, size);
3640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		timeout = jiffies + HZ / 4;
3650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		/* Write the block */
3670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		for (i = 0; i < len / 4; i++)
3680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			fpga_fifo_write(priv->regs, data[i]);
3690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		/* Update the amounts left */
3710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		count -= len;
3720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		data += len / 4;
3730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		/* Wait for the fifo to empty */
3750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		while (true) {
3760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			if (fpga_fifo_empty(priv->regs)) {
3780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				break;
3790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			} else {
3800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				dev_dbg(priv->dev, "Fifo not empty\n");
3810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				cpu_relax();
3820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			}
3830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			if (fpga_config_error(priv->regs)) {
3850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				dev_err(priv->dev, "Error detected\n");
3860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				return -EIO;
3870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			}
3880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			if (time_after(jiffies, timeout)) {
3900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				dev_err(priv->dev, "Fifo drain timeout\n");
3910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				return -ETIMEDOUT;
3920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			}
3930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			usleep_range(5000, 10000);
3950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		}
3960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
3970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
3980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
3990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
4000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
4020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_program_cpu() - program the DATA-FPGA's using the CPU
4030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
4040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
4050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * This is useful when the DMA programming method fails. It is possible to
4060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * wedge the Freescale DMA controller such that the DMA programming method
4070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * always fails. This method has always succeeded.
4080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
4090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Returns 0 on success, -ERRNO otherwise
4100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
4110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic noinline int fpga_program_cpu(struct fpga_dev *priv)
4120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
4130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
4140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Disable the programmer */
4160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_disable(priv);
4170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Set the total byte count */
4190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_set_byte_count(priv->regs, priv->bytes);
4200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "total byte count %u bytes\n", priv->bytes);
4210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Enable the controller for programming */
4230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_enable(priv, false);
4240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "enabled the controller\n");
4250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Write each chunk of the FPGA bitfile to FPGA programmer */
4270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = fpga_program_block(priv, priv->vb.vaddr, priv->bytes);
4280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret)
4290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_disable_controller;
4300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Wait for the interrupt handler to signal that programming finished */
4320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
4330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!ret) {
4340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Timed out waiting for completion\n");
4350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ETIMEDOUT;
4360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_disable_controller;
4370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
4380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Retrieve the status from the interrupt handler */
4400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = priv->status;
4410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_disable_controller:
4430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_disable(priv);
4440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ret;
4450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
4460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FIFO_DMA_ADDRESS	0xf0003000
4480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define FIFO_MAX_LEN		4096
4490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
4510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_program_dma() - program the DATA-FPGA's using the DMA engine
4520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
4530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
4540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Program the DATA-FPGA's using the Freescale DMA engine. This requires that
4550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * the engine is programmed such that the hardware DMA request lines can
4560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * control the entire DMA transaction. The system controller FPGA then
4570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * completely offloads the programming from the CPU.
4580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
4590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Returns 0 on success, -ERRNO otherwise
4600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
4610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic noinline int fpga_program_dma(struct fpga_dev *priv)
4620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
4630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct videobuf_dmabuf *vb = &priv->vb;
4640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct dma_chan *chan = priv->chan;
4650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct dma_async_tx_descriptor *tx;
4660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	size_t num_pages, len, avail = 0;
4670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct dma_slave_config config;
4680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct scatterlist *sg;
4690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct sg_table table;
4700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cookie_t cookie;
4710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret, i;
4720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Disable the programmer */
4740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_disable(priv);
4750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Allocate a scatterlist for the DMA destination */
4770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	num_pages = DIV_ROUND_UP(priv->bytes, FIFO_MAX_LEN);
4780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = sg_alloc_table(&table, num_pages, GFP_KERNEL);
4790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
4800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Unable to allocate dst scatterlist\n");
4810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
4820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_return;
4830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
4840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
4850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
4860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * This is an ugly hack
4870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
4880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * We fill in a scatterlist as if it were mapped for DMA. This is
4890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * necessary because there exists no better structure for this
4900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * inside the kernel code.
4910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
4920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * As an added bonus, we can use the DMAEngine API for all of this,
4930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * rather than inventing another extremely similar API.
4940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
4950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	avail = priv->bytes;
4960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	for_each_sg(table.sgl, sg, num_pages, i) {
4970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		len = min_t(size_t, avail, FIFO_MAX_LEN);
4980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		sg_dma_address(sg) = FIFO_DMA_ADDRESS;
4990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		sg_dma_len(sg) = len;
5000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		avail -= len;
5020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Map the buffer for DMA */
5050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = videobuf_dma_map(priv->dev, &priv->vb);
5060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
5070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Unable to map buffer for DMA\n");
5080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_free_table;
5090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
5120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * Configure the DMA channel to transfer FIFO_SIZE / 2 bytes per
5130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * transaction, and then put it under external control
5140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
5150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	memset(&config, 0, sizeof(config));
5161d0c81e876fe04295ef5df387ba057bf9cfae3d8Vinod Koul	config.direction = DMA_MEM_TO_DEV;
5170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
5180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4;
5190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG,
5200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder					   (unsigned long)&config);
5210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
5220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "DMA slave configuration failed\n");
5230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_dma_unmap;
5240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = chan->device->device_control(chan, FSLDMA_EXTERNAL_START, 1);
5270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
5280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "DMA external control setup failed\n");
5290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_dma_unmap;
5300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* setup and submit the DMA transaction */
5330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	tx = chan->device->device_prep_dma_sg(chan,
5340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder					      table.sgl, num_pages,
5350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder					      vb->sglist, vb->sglen, 0);
5360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!tx) {
5370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Unable to prep DMA transaction\n");
5380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
5390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_dma_unmap;
5400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	cookie = tx->tx_submit(tx);
5430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (dma_submit_error(cookie)) {
5440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Unable to submit DMA transaction\n");
5450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
5460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_dma_unmap;
5470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_async_memcpy_issue_pending(chan);
5500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Set the total byte count */
5520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_set_byte_count(priv->regs, priv->bytes);
5530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "total byte count %u bytes\n", priv->bytes);
5540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Enable the controller for DMA programming */
5560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_enable(priv, true);
5570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "enabled the controller\n");
5580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Wait for the interrupt handler to signal that programming finished */
5600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
5610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!ret) {
5620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Timed out waiting for completion\n");
5630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ETIMEDOUT;
5640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_disable_controller;
5650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
5660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Retrieve the status from the interrupt handler */
5680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = priv->status;
5690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_disable_controller:
5710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_disable(priv);
5720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_dma_unmap:
5730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	videobuf_dma_unmap(priv->dev, vb);
5740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_free_table:
5750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	sg_free_table(&table);
5760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_return:
5770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ret;
5780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
5790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
5810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Interrupt Handling
5820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
5830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic irqreturn_t fpga_irq(int irq, void *dev_id)
5850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
5860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_id;
5870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Save the status */
5890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->status = fpga_config_error(priv->regs) ? -EIO : 0;
5900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "INTERRUPT status %d\n", priv->status);
5910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_dump_registers(priv);
5920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Disabling the programmer clears the interrupt */
5940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_programmer_disable(priv);
5950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Notify any waiters */
5970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	complete(&priv->completion);
5980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
5990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return IRQ_HANDLED;
6000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
6010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
6030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * SYSFS Helpers
6040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
6050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/**
6070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * fpga_do_stop() - deconfigure (reset) the DATA-FPGA's
6080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * @priv: the driver's private data structure
6090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder *
6100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * LOCKING: must hold priv->lock
6110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
6120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_do_stop(struct fpga_dev *priv)
6130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
6140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u32 val;
6150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Set the led to unprogrammed */
6170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ledtrig_fpga_programmed(false);
6180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Pulse the config line to reset the FPGA's */
6200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = CFG_CTL_ENABLE | CFG_CTL_RESET;
6210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(val, priv->regs + FPGA_CONFIG_CONTROL);
6220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iowrite32be(0x0, priv->regs + FPGA_CONFIG_CONTROL);
6230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
6250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
6260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic noinline int fpga_do_program(struct fpga_dev *priv)
6280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
6290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
6300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (priv->bytes != priv->fw_size) {
6320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Incorrect bitfile size: got %zu bytes, "
6330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				   "should be %zu bytes\n",
6340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder				   priv->bytes, priv->fw_size);
6350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
6360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
6370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!fpga_power_enabled(priv)) {
6390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Power not enabled\n");
6400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
6410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
6420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!fpga_power_good(priv)) {
6440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Power not good\n");
6450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
6460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
6470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Set the LED to unprogrammed */
6490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ledtrig_fpga_programmed(false);
6500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Try to program the FPGA's using DMA */
6520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = fpga_program_dma(priv);
6530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* If DMA failed or doesn't exist, try with CPU */
6550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
6560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_warn(priv->dev, "Falling back to CPU programming\n");
6570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = fpga_program_cpu(priv);
6580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
6590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
6610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "Unable to program FPGA's\n");
6620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return ret;
6630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
6640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Drop the firmware bitfile from memory */
6660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_drop_firmware_data(priv);
6670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_dbg(priv->dev, "FPGA programming successful\n");
6690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ledtrig_fpga_programmed(true);
6700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
6720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
6730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
6750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * File Operations
6760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
6770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_open(struct inode *inode, struct file *filp)
6790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
6800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
6810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * The miscdevice layer puts our struct miscdevice into the
6820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * filp->private_data field. We use this to find our private
6830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * data and then overwrite it with our own private structure.
6840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
6850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = container_of(filp->private_data,
6860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder					     struct fpga_dev, miscdev);
6870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned int nr_pages;
6880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
6890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* We only allow one process at a time */
6910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = mutex_lock_interruptible(&priv->lock);
6920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret)
6930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return ret;
6940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	filp->private_data = priv;
6960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kref_get(&priv->ref);
6970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
6980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Truncation: drop any existing data */
6990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (filp->f_flags & O_TRUNC)
7000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		priv->bytes = 0;
7010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Check if we have already allocated a buffer */
7030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (priv->vb_allocated)
7040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return 0;
7050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Allocate a buffer to hold enough data for the bitfile */
7070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE);
7080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = videobuf_dma_init_kernel(&priv->vb, DMA_TO_DEVICE, nr_pages);
7090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
7100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(priv->dev, "unable to allocate data buffer\n");
7110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		mutex_unlock(&priv->lock);
7120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		kref_put(&priv->ref, fpga_dev_remove);
7130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return ret;
7140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
7150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->vb_allocated = true;
7170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
7180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
7190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_release(struct inode *inode, struct file *filp)
7210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
7220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = filp->private_data;
7230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	mutex_unlock(&priv->lock);
7250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kref_put(&priv->ref, fpga_dev_remove);
7260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
7270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
7280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t fpga_write(struct file *filp, const char __user *buf,
7300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			  size_t count, loff_t *f_pos)
7310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
7320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = filp->private_data;
7330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* FPGA bitfiles have an exact size: disallow anything else */
7350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (priv->bytes >= priv->fw_size)
7360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -ENOSPC;
7370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	count = min_t(size_t, priv->fw_size - priv->bytes, count);
7390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (copy_from_user(priv->vb.vaddr + priv->bytes, buf, count))
7400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EFAULT;
7410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->bytes += count;
7430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return count;
7440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
7450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,
7470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			 loff_t *f_pos)
7480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
7490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = filp->private_data;
7500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	count = min_t(size_t, priv->bytes - *f_pos, count);
7520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (copy_to_user(buf, priv->vb.vaddr + *f_pos, count))
7530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EFAULT;
7540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	*f_pos += count;
7560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return count;
7570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
7580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic loff_t fpga_llseek(struct file *filp, loff_t offset, int origin)
7600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
7610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = filp->private_data;
7620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	loff_t newpos;
7630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* only read-only opens are allowed to seek */
7650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
7660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
7670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	switch (origin) {
7690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	case SEEK_SET: /* seek relative to the beginning of the file */
7700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		newpos = offset;
7710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		break;
7720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	case SEEK_CUR: /* seek relative to current position in the file */
7730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		newpos = filp->f_pos + offset;
7740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		break;
7750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	case SEEK_END: /* seek relative to the end of the file */
7760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		newpos = priv->fw_size - offset;
7770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		break;
7780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	default:
7790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
7800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
7810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* check for sanity */
7830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (newpos > priv->fw_size)
7840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
7850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	filp->f_pos = newpos;
7870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return newpos;
7880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
7890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic const struct file_operations fpga_fops = {
7910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.open		= fpga_open,
7920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.release	= fpga_release,
7930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.write		= fpga_write,
7940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.read		= fpga_read,
7950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.llseek		= fpga_llseek,
7960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
7970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
7980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
7990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Device Attributes
8000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
8010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t pfail_show(struct device *dev, struct device_attribute *attr,
8030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			  char *buf)
8040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u8 val;
8070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	val = ioread8(priv->regs + CTL_PWR_FAIL);
8090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return snprintf(buf, PAGE_SIZE, "0x%.2x\n", val);
8100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t pgood_show(struct device *dev, struct device_attribute *attr,
8130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			  char *buf)
8140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_power_good(priv));
8170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t penable_show(struct device *dev, struct device_attribute *attr,
8200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			    char *buf)
8210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_power_enabled(priv));
8240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t penable_store(struct device *dev, struct device_attribute *attr,
8270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			     const char *buf, size_t count)
8280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned long val;
8310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
8320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (strict_strtoul(buf, 0, &val))
8340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
8350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (val) {
8370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = fpga_enable_power_supplies(priv);
8380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		if (ret)
8390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			return ret;
8400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	} else {
8410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		fpga_do_stop(priv);
8420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		fpga_disable_power_supplies(priv);
8430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
8440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return count;
8460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t program_show(struct device *dev, struct device_attribute *attr,
8490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			    char *buf)
8500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_running(priv));
8530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic ssize_t program_store(struct device *dev, struct device_attribute *attr,
8560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			     const char *buf, size_t count)
8570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
8580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(dev);
8590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	unsigned long val;
8600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
8610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (strict_strtoul(buf, 0, &val))
8630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -EINVAL;
8640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* We can't have an image writer and be programming simultaneously */
8660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (mutex_lock_interruptible(&priv->lock))
8670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		return -ERESTARTSYS;
8680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Program or Reset the FPGA's */
8700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = val ? fpga_do_program(priv) : fpga_do_stop(priv);
8710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret)
8720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_unlock;
8730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Success */
8750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = count;
8760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_unlock:
8780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	mutex_unlock(&priv->lock);
8790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ret;
8800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
8810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic DEVICE_ATTR(power_fail, S_IRUGO, pfail_show, NULL);
8830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic DEVICE_ATTR(power_good, S_IRUGO, pgood_show, NULL);
8840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic DEVICE_ATTR(power_enable, S_IRUGO | S_IWUSR,
8850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		   penable_show, penable_store);
8860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic DEVICE_ATTR(program, S_IRUGO | S_IWUSR,
8880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		   program_show, program_store);
8890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic struct attribute *fpga_attributes[] = {
8910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	&dev_attr_power_fail.attr,
8920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	&dev_attr_power_good.attr,
8930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	&dev_attr_power_enable.attr,
8940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	&dev_attr_program.attr,
8950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	NULL,
8960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
8970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
8980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic const struct attribute_group fpga_attr_group = {
8990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.attrs = fpga_attributes,
9000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
9010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
9030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * OpenFirmware Device Subsystem
9040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
9050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define SYS_REG_VERSION		0x00
9070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define SYS_REG_GEOGRAPHIC	0x10
9080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic bool dma_filter(struct dma_chan *chan, void *data)
9100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
9110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
9120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * DMA Channel #0 is the only acceptable device
9130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
9140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * This probably won't survive an unload/load cycle of the Freescale
9150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * DMAEngine driver, but that won't be a problem
9160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
9170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return chan->chan_id == 0 && chan->device->dev_id == 0;
9180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
9190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int fpga_of_remove(struct platform_device *op)
9210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
9220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv = dev_get_drvdata(&op->dev);
9230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct device *this_device = priv->miscdev.this_device;
9240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	sysfs_remove_group(&this_device->kobj, &fpga_attr_group);
9260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	misc_deregister(&priv->miscdev);
9270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	free_irq(priv->irq, priv);
9290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	irq_dispose_mapping(priv->irq);
9300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* make sure the power supplies are off */
9320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_disable_power_supplies(priv);
9330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* unmap registers */
9350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iounmap(priv->immr);
9360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iounmap(priv->regs);
9370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_release_channel(priv->chan);
9390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* drop our reference to the private data structure */
9410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kref_put(&priv->ref, fpga_dev_remove);
9420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
9430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
9440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/* CTL-CPLD Version Register */
9460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder#define CTL_CPLD_VERSION	0x2000
9470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9484933402075d4f38a82c491a4afca6ca7661aa0a8Al Virostatic int fpga_of_probe(struct platform_device *op)
9490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
9500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct device_node *of_node = op->dev.of_node;
9510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct device *this_device;
9520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	struct fpga_dev *priv;
9530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_mask_t mask;
9540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	u32 ver;
9550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	int ret;
9560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Allocate private data */
9580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
9590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!priv) {
9600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to allocate private data\n");
9610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
9620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_return;
9630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
9640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Setup the miscdevice */
9660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
9670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->miscdev.name = drv_name;
9680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->miscdev.fops = &fpga_fops;
9690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kref_init(&priv->ref);
9710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_set_drvdata(&op->dev, priv);
9730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->dev = &op->dev;
9740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	mutex_init(&priv->lock);
9750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	init_completion(&priv->completion);
9760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	videobuf_dma_init(&priv->vb);
9770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_set_drvdata(priv->dev, priv);
9790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_zero(mask);
9800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_set(DMA_MEMCPY, mask);
9810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_set(DMA_INTERRUPT, mask);
9820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_set(DMA_SLAVE, mask);
9830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_cap_set(DMA_SG, mask);
9840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Get control of DMA channel #0 */
9860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->chan = dma_request_channel(mask, dma_filter, NULL);
9870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!priv->chan) {
9880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to acquire DMA channel #0\n");
9890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENODEV;
9900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_free_priv;
9910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
9920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
9930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Remap the registers for use */
9940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->regs = of_iomap(of_node, 0);
9950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!priv->regs) {
9960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to ioremap registers\n");
9970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
9980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_dma_release_channel;
9990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Remap the IMMR for use */
10020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->immr = ioremap(get_immrbase(), 0x100000);
10030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (!priv->immr) {
10040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to ioremap IMMR\n");
10050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENOMEM;
10060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_unmap_regs;
10070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10090e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
10100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * Check that external DMA is configured
10110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
10120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * U-Boot does this for us, but we should check it and bail out if
10130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * there is a problem. Failing to have this register setup correctly
10140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * will cause the DMA controller to transfer a single cacheline
10150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * worth of data, then wedge itself.
10160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
10170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if ((ioread32be(priv->immr + 0x114) & 0xE00) != 0xE00) {
10180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "External DMA control not configured\n");
10190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENODEV;
10200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_unmap_immr;
10210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/*
10240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * Check the CTL-CPLD version
10250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
10260e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * This driver uses the CTL-CPLD DATA-FPGA power sequencer, and we
10270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * don't want to run on any version of the CTL-CPLD that does not use
10280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * a compatible register layout.
10290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 *
10300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * v2: changed register layout, added power sequencer
10310e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 * v3: added glitch filter on the i2c overcurrent/overtemp outputs
10320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	 */
10330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ver = ioread8(priv->regs + CTL_CPLD_VERSION);
10340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ver != 0x02 && ver != 0x03) {
10350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "CTL-CPLD is not version 0x02 or 0x03!\n");
10360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENODEV;
10370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_unmap_immr;
10380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Set the exact size that the firmware image should be */
10410e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ver = ioread32be(priv->regs + SYS_REG_VERSION);
10420e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->fw_size = (ver & (1 << 18)) ? FW_SIZE_EP2S130 : FW_SIZE_EP2S90;
10430e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10440e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Find the correct IRQ number */
10450e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	priv->irq = irq_of_parse_and_map(of_node, 0);
10460e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (priv->irq == NO_IRQ) {
10470e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to find IRQ line\n");
10480e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENODEV;
10490e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_unmap_immr;
10500e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10510e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10520e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Request the IRQ */
10530e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = request_irq(priv->irq, fpga_irq, IRQF_SHARED, drv_name, priv);
10540e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
10550e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to request IRQ %d\n", priv->irq);
10560e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		ret = -ENODEV;
10570e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_irq_dispose_mapping;
10580e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10590e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10600e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Reset and stop the FPGA's, just in case */
10610e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	fpga_do_stop(priv);
10620e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10630e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Register the miscdevice */
10640e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = misc_register(&priv->miscdev);
10650e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
10660e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to register miscdevice\n");
10670e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_free_irq;
10680e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10690e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10700e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	/* Create the sysfs files */
10710e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	this_device = priv->miscdev.this_device;
10720e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_set_drvdata(this_device, priv);
10730e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	ret = sysfs_create_group(&this_device->kobj, &fpga_attr_group);
10740e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	if (ret) {
10750e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		dev_err(&op->dev, "Unable to create sysfs files\n");
10760e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		goto out_misc_deregister;
10770e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	}
10780e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10790e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dev_info(priv->dev, "CARMA FPGA Programmer: %s rev%s with %s FPGAs\n",
10800e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			(ver & (1 << 17)) ? "Correlator" : "Digitizer",
10810e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			(ver & (1 << 16)) ? "B" : "A",
10820e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder			(ver & (1 << 18)) ? "EP2S130" : "EP2S90");
10830e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10840e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return 0;
10850e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
10860e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_misc_deregister:
10870e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	misc_deregister(&priv->miscdev);
10880e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_free_irq:
10890e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	free_irq(priv->irq, priv);
10900e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_irq_dispose_mapping:
10910e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	irq_dispose_mapping(priv->irq);
10920e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_unmap_immr:
10930e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iounmap(priv->immr);
10940e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_unmap_regs:
10950e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	iounmap(priv->regs);
10960e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_dma_release_channel:
10970e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	dma_release_channel(priv->chan);
10980e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_free_priv:
10990e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	kref_put(&priv->ref, fpga_dev_remove);
11000e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderout_return:
11010e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	return ret;
11020e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
11030e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11040e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic struct of_device_id fpga_of_match[] = {
11050e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	{ .compatible = "carma,fpga-programmer", },
11060e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	{},
11070e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
11080e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11094933402075d4f38a82c491a4afca6ca7661aa0a8Al Virostatic struct platform_driver fpga_of_driver = {
11100e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.probe		= fpga_of_probe,
11110e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.remove		= fpga_of_remove,
11120e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	.driver		= {
11130e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		.name		= drv_name,
11140e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		.of_match_table	= fpga_of_match,
11150e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder		.owner		= THIS_MODULE,
11160e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	},
11170e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder};
11180e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11190e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder/*
11200e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder * Module Init / Exit
11210e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder */
11220e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11230e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic int __init fpga_init(void)
11240e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
11250e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	led_trigger_register_simple("fpga", &ledtrig_fpga);
11264933402075d4f38a82c491a4afca6ca7661aa0a8Al Viro	return platform_driver_register(&fpga_of_driver);
11270e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
11280e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11290e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyderstatic void __exit fpga_exit(void)
11300e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder{
11314933402075d4f38a82c491a4afca6ca7661aa0a8Al Viro	platform_driver_unregister(&fpga_of_driver);
11320e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder	led_trigger_unregister_simple(ledtrig_fpga);
11330e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder}
11340e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11350e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira SnyderMODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
11360e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira SnyderMODULE_DESCRIPTION("CARMA Board DATA-FPGA Programmer");
11370e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira SnyderMODULE_LICENSE("GPL");
11380e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snyder
11390e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snydermodule_init(fpga_init);
11400e1d715b5b982ee0099f3fbf6ad47dc8bda518a6Ira Snydermodule_exit(fpga_exit);
1141