Path: blob/master/drivers/char/xilinx_hwicap/buffer_icap.c
26289 views
/*****************************************************************************1*2* Author: Xilinx, Inc.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License as published by the6* Free Software Foundation; either version 2 of the License, or (at your7* option) any later version.8*9* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"10* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND11* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,12* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,13* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION14* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,15* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE16* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY17* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE18* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR19* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF20* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE.22*23* (c) Copyright 2003-2008 Xilinx Inc.24* All rights reserved.25*26* You should have received a copy of the GNU General Public License along27* with this program; if not, write to the Free Software Foundation, Inc.,28* 675 Mass Ave, Cambridge, MA 02139, USA.29*30*****************************************************************************/3132#include "buffer_icap.h"3334/* Indicates how many bytes will fit in a buffer. (1 BRAM) */35#define XHI_MAX_BUFFER_BYTES 204836#define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2)3738/* File access and error constants */39#define XHI_DEVICE_READ_ERROR -140#define XHI_DEVICE_WRITE_ERROR -241#define XHI_BUFFER_OVERFLOW_ERROR -34243#define XHI_DEVICE_READ 0x144#define XHI_DEVICE_WRITE 0x04546/* Constants for checking transfer status */47#define XHI_CYCLE_DONE 048#define XHI_CYCLE_EXECUTING 14950/* buffer_icap register offsets */5152/* Size of transfer, read & write */53#define XHI_SIZE_REG_OFFSET 0x800L54/* offset into bram, read & write */55#define XHI_BRAM_OFFSET_REG_OFFSET 0x804L56/* Read not Configure, direction of transfer. Write only */57#define XHI_RNC_REG_OFFSET 0x808L58/* Indicates transfer complete. Read only */59#define XHI_STATUS_REG_OFFSET 0x80CL6061/* Constants for setting the RNC register */62#define XHI_CONFIGURE 0x0UL63#define XHI_READBACK 0x1UL6465/* Constants for the Done register */66#define XHI_NOT_FINISHED 0x0UL67#define XHI_FINISHED 0x1UL6869#define XHI_BUFFER_START 07071/**72* buffer_icap_get_status - Get the contents of the status register.73* @drvdata: a pointer to the drvdata.74*75* The status register contains the ICAP status and the done bit.76*77* D8 - cfgerr78* D7 - dalign79* D6 - rip80* D5 - in_abort_l81* D4 - Always 182* D3 - Always 183* D2 - Always 184* D1 - Always 185* D0 - Done bit86**/87u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)88{89return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);90}9192/**93* buffer_icap_get_bram - Reads data from the storage buffer bram.94* @base_address: contains the base address of the component.95* @offset: The word offset from which the data should be read.96*97* A bram is used as a configuration memory cache. One frame of data can98* be stored in this "storage buffer".99**/100static inline u32 buffer_icap_get_bram(void __iomem *base_address,101u32 offset)102{103return in_be32(base_address + (offset << 2));104}105106/**107* buffer_icap_busy - Return true if the icap device is busy108* @base_address: is the base address of the device109*110* The queries the low order bit of the status register, which111* indicates whether the current configuration or readback operation112* has completed.113**/114static inline bool buffer_icap_busy(void __iomem *base_address)115{116u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);117return (status & 1) == XHI_NOT_FINISHED;118}119120/**121* buffer_icap_set_size - Set the size register.122* @base_address: is the base address of the device123* @data: The size in bytes.124*125* The size register holds the number of 8 bit bytes to transfer between126* bram and the icap (or icap to bram).127**/128static inline void buffer_icap_set_size(void __iomem *base_address,129u32 data)130{131out_be32(base_address + XHI_SIZE_REG_OFFSET, data);132}133134/**135* buffer_icap_set_offset - Set the bram offset register.136* @base_address: contains the base address of the device.137* @data: is the value to be written to the data register.138*139* The bram offset register holds the starting bram address to transfer140* data from during configuration or write data to during readback.141**/142static inline void buffer_icap_set_offset(void __iomem *base_address,143u32 data)144{145out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);146}147148/**149* buffer_icap_set_rnc - Set the RNC (Readback not Configure) register.150* @base_address: contains the base address of the device.151* @data: is the value to be written to the data register.152*153* The RNC register determines the direction of the data transfer. It154* controls whether a configuration or readback take place. Writing to155* this register initiates the transfer. A value of 1 initiates a156* readback while writing a value of 0 initiates a configuration.157**/158static inline void buffer_icap_set_rnc(void __iomem *base_address,159u32 data)160{161out_be32(base_address + XHI_RNC_REG_OFFSET, data);162}163164/**165* buffer_icap_set_bram - Write data to the storage buffer bram.166* @base_address: contains the base address of the component.167* @offset: The word offset at which the data should be written.168* @data: The value to be written to the bram offset.169*170* A bram is used as a configuration memory cache. One frame of data can171* be stored in this "storage buffer".172**/173static inline void buffer_icap_set_bram(void __iomem *base_address,174u32 offset, u32 data)175{176out_be32(base_address + (offset << 2), data);177}178179/**180* buffer_icap_device_read - Transfer bytes from ICAP to the storage buffer.181* @drvdata: a pointer to the drvdata.182* @offset: The storage buffer start address.183* @count: The number of words (32 bit) to read from the184* device (ICAP).185**/186static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,187u32 offset, u32 count)188{189190s32 retries = 0;191void __iomem *base_address = drvdata->base_address;192193if (buffer_icap_busy(base_address))194return -EBUSY;195196if ((offset + count) > XHI_MAX_BUFFER_INTS)197return -EINVAL;198199/* setSize count*4 to get bytes. */200buffer_icap_set_size(base_address, (count << 2));201buffer_icap_set_offset(base_address, offset);202buffer_icap_set_rnc(base_address, XHI_READBACK);203204while (buffer_icap_busy(base_address)) {205retries++;206if (retries > XHI_MAX_RETRIES)207return -EBUSY;208}209return 0;210211};212213/**214* buffer_icap_device_write - Transfer bytes from ICAP to the storage buffer.215* @drvdata: a pointer to the drvdata.216* @offset: The storage buffer start address.217* @count: The number of words (32 bit) to read from the218* device (ICAP).219**/220static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,221u32 offset, u32 count)222{223224s32 retries = 0;225void __iomem *base_address = drvdata->base_address;226227if (buffer_icap_busy(base_address))228return -EBUSY;229230if ((offset + count) > XHI_MAX_BUFFER_INTS)231return -EINVAL;232233/* setSize count*4 to get bytes. */234buffer_icap_set_size(base_address, count << 2);235buffer_icap_set_offset(base_address, offset);236buffer_icap_set_rnc(base_address, XHI_CONFIGURE);237238while (buffer_icap_busy(base_address)) {239retries++;240if (retries > XHI_MAX_RETRIES)241return -EBUSY;242}243return 0;244245};246247/**248* buffer_icap_reset - Reset the logic of the icap device.249* @drvdata: a pointer to the drvdata.250*251* Writing to the status register resets the ICAP logic in an internal252* version of the core. For the version of the core published in EDK,253* this is a noop.254**/255void buffer_icap_reset(struct hwicap_drvdata *drvdata)256{257out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);258}259260/**261* buffer_icap_set_configuration - Load a partial bitstream from system memory.262* @drvdata: a pointer to the drvdata.263* @data: Kernel address of the partial bitstream.264* @size: the size of the partial bitstream in 32 bit words.265**/266int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,267u32 size)268{269int status;270s32 buffer_count = 0;271bool dirty = false;272u32 i;273void __iomem *base_address = drvdata->base_address;274275/* Loop through all the data */276for (i = 0, buffer_count = 0; i < size; i++) {277278/* Copy data to bram */279buffer_icap_set_bram(base_address, buffer_count, data[i]);280dirty = true;281282if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {283buffer_count++;284continue;285}286287/* Write data to ICAP */288status = buffer_icap_device_write(289drvdata,290XHI_BUFFER_START,291XHI_MAX_BUFFER_INTS);292if (status != 0) {293/* abort. */294buffer_icap_reset(drvdata);295return status;296}297298buffer_count = 0;299dirty = false;300}301302/* Write unwritten data to ICAP */303if (dirty) {304/* Write data to ICAP */305status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,306buffer_count);307if (status != 0) {308/* abort. */309buffer_icap_reset(drvdata);310}311return status;312}313314return 0;315};316317/**318* buffer_icap_get_configuration - Read configuration data from the device.319* @drvdata: a pointer to the drvdata.320* @data: Address of the data representing the partial bitstream321* @size: the size of the partial bitstream in 32 bit words.322**/323int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,324u32 size)325{326int status;327s32 buffer_count = 0;328u32 i;329void __iomem *base_address = drvdata->base_address;330331/* Loop through all the data */332for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {333if (buffer_count == XHI_MAX_BUFFER_INTS) {334u32 words_remaining = size - i;335u32 words_to_read =336words_remaining <337XHI_MAX_BUFFER_INTS ? words_remaining :338XHI_MAX_BUFFER_INTS;339340/* Read data from ICAP */341status = buffer_icap_device_read(342drvdata,343XHI_BUFFER_START,344words_to_read);345if (status != 0) {346/* abort. */347buffer_icap_reset(drvdata);348return status;349}350351buffer_count = 0;352}353354/* Copy data from bram */355data[i] = buffer_icap_get_bram(base_address, buffer_count);356buffer_count++;357}358359return 0;360};361362363