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