Back to home page

OSCL-LXR

 
 

    


0001 /*****************************************************************************
0002  *
0003  *     Author: Xilinx, Inc.
0004  *
0005  *     This program is free software; you can redistribute it and/or modify it
0006  *     under the terms of the GNU General Public License as published by the
0007  *     Free Software Foundation; either version 2 of the License, or (at your
0008  *     option) any later version.
0009  *
0010  *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
0011  *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
0012  *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,
0013  *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
0014  *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
0015  *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
0016  *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
0017  *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
0018  *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
0019  *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
0020  *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
0021  *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
0022  *     FOR A PARTICULAR PURPOSE.
0023  *
0024  *     (c) Copyright 2003-2008 Xilinx Inc.
0025  *     All rights reserved.
0026  *
0027  *     You should have received a copy of the GNU General Public License along
0028  *     with this program; if not, write to the Free Software Foundation, Inc.,
0029  *     675 Mass Ave, Cambridge, MA 02139, USA.
0030  *
0031  *****************************************************************************/
0032 
0033 #include "buffer_icap.h"
0034 
0035 /* Indicates how many bytes will fit in a buffer. (1 BRAM) */
0036 #define XHI_MAX_BUFFER_BYTES        2048
0037 #define XHI_MAX_BUFFER_INTS         (XHI_MAX_BUFFER_BYTES >> 2)
0038 
0039 /* File access and error constants */
0040 #define XHI_DEVICE_READ_ERROR       -1
0041 #define XHI_DEVICE_WRITE_ERROR      -2
0042 #define XHI_BUFFER_OVERFLOW_ERROR   -3
0043 
0044 #define XHI_DEVICE_READ             0x1
0045 #define XHI_DEVICE_WRITE            0x0
0046 
0047 /* Constants for checking transfer status */
0048 #define XHI_CYCLE_DONE              0
0049 #define XHI_CYCLE_EXECUTING         1
0050 
0051 /* buffer_icap register offsets */
0052 
0053 /* Size of transfer, read & write */
0054 #define XHI_SIZE_REG_OFFSET        0x800L
0055 /* offset into bram, read & write */
0056 #define XHI_BRAM_OFFSET_REG_OFFSET 0x804L
0057 /* Read not Configure, direction of transfer.  Write only */
0058 #define XHI_RNC_REG_OFFSET         0x808L
0059 /* Indicates transfer complete. Read only */
0060 #define XHI_STATUS_REG_OFFSET      0x80CL
0061 
0062 /* Constants for setting the RNC register */
0063 #define XHI_CONFIGURE              0x0UL
0064 #define XHI_READBACK               0x1UL
0065 
0066 /* Constants for the Done register */
0067 #define XHI_NOT_FINISHED           0x0UL
0068 #define XHI_FINISHED               0x1UL
0069 
0070 #define XHI_BUFFER_START 0
0071 
0072 /**
0073  * buffer_icap_get_status - Get the contents of the status register.
0074  * @drvdata: a pointer to the drvdata.
0075  *
0076  * The status register contains the ICAP status and the done bit.
0077  *
0078  * D8 - cfgerr
0079  * D7 - dalign
0080  * D6 - rip
0081  * D5 - in_abort_l
0082  * D4 - Always 1
0083  * D3 - Always 1
0084  * D2 - Always 1
0085  * D1 - Always 1
0086  * D0 - Done bit
0087  **/
0088 u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
0089 {
0090     return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
0091 }
0092 
0093 /**
0094  * buffer_icap_get_bram - Reads data from the storage buffer bram.
0095  * @base_address: contains the base address of the component.
0096  * @offset: The word offset from which the data should be read.
0097  *
0098  * A bram is used as a configuration memory cache.  One frame of data can
0099  * be stored in this "storage buffer".
0100  **/
0101 static inline u32 buffer_icap_get_bram(void __iomem *base_address,
0102         u32 offset)
0103 {
0104     return in_be32(base_address + (offset << 2));
0105 }
0106 
0107 /**
0108  * buffer_icap_busy - Return true if the icap device is busy
0109  * @base_address: is the base address of the device
0110  *
0111  * The queries the low order bit of the status register, which
0112  * indicates whether the current configuration or readback operation
0113  * has completed.
0114  **/
0115 static inline bool buffer_icap_busy(void __iomem *base_address)
0116 {
0117     u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
0118     return (status & 1) == XHI_NOT_FINISHED;
0119 }
0120 
0121 /**
0122  * buffer_icap_set_size - Set the size register.
0123  * @base_address: is the base address of the device
0124  * @data: The size in bytes.
0125  *
0126  * The size register holds the number of 8 bit bytes to transfer between
0127  * bram and the icap (or icap to bram).
0128  **/
0129 static inline void buffer_icap_set_size(void __iomem *base_address,
0130         u32 data)
0131 {
0132     out_be32(base_address + XHI_SIZE_REG_OFFSET, data);
0133 }
0134 
0135 /**
0136  * buffer_icap_set_offset - Set the bram offset register.
0137  * @base_address: contains the base address of the device.
0138  * @data: is the value to be written to the data register.
0139  *
0140  * The bram offset register holds the starting bram address to transfer
0141  * data from during configuration or write data to during readback.
0142  **/
0143 static inline void buffer_icap_set_offset(void __iomem *base_address,
0144         u32 data)
0145 {
0146     out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);
0147 }
0148 
0149 /**
0150  * buffer_icap_set_rnc - Set the RNC (Readback not Configure) register.
0151  * @base_address: contains the base address of the device.
0152  * @data: is the value to be written to the data register.
0153  *
0154  * The RNC register determines the direction of the data transfer.  It
0155  * controls whether a configuration or readback take place.  Writing to
0156  * this register initiates the transfer.  A value of 1 initiates a
0157  * readback while writing a value of 0 initiates a configuration.
0158  **/
0159 static inline void buffer_icap_set_rnc(void __iomem *base_address,
0160         u32 data)
0161 {
0162     out_be32(base_address + XHI_RNC_REG_OFFSET, data);
0163 }
0164 
0165 /**
0166  * buffer_icap_set_bram - Write data to the storage buffer bram.
0167  * @base_address: contains the base address of the component.
0168  * @offset: The word offset at which the data should be written.
0169  * @data: The value to be written to the bram offset.
0170  *
0171  * A bram is used as a configuration memory cache.  One frame of data can
0172  * be stored in this "storage buffer".
0173  **/
0174 static inline void buffer_icap_set_bram(void __iomem *base_address,
0175         u32 offset, u32 data)
0176 {
0177     out_be32(base_address + (offset << 2), data);
0178 }
0179 
0180 /**
0181  * buffer_icap_device_read - Transfer bytes from ICAP to the storage buffer.
0182  * @drvdata: a pointer to the drvdata.
0183  * @offset: The storage buffer start address.
0184  * @count: The number of words (32 bit) to read from the
0185  *           device (ICAP).
0186  **/
0187 static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
0188         u32 offset, u32 count)
0189 {
0190 
0191     s32 retries = 0;
0192     void __iomem *base_address = drvdata->base_address;
0193 
0194     if (buffer_icap_busy(base_address))
0195         return -EBUSY;
0196 
0197     if ((offset + count) > XHI_MAX_BUFFER_INTS)
0198         return -EINVAL;
0199 
0200     /* setSize count*4 to get bytes. */
0201     buffer_icap_set_size(base_address, (count << 2));
0202     buffer_icap_set_offset(base_address, offset);
0203     buffer_icap_set_rnc(base_address, XHI_READBACK);
0204 
0205     while (buffer_icap_busy(base_address)) {
0206         retries++;
0207         if (retries > XHI_MAX_RETRIES)
0208             return -EBUSY;
0209     }
0210     return 0;
0211 
0212 };
0213 
0214 /**
0215  * buffer_icap_device_write - Transfer bytes from ICAP to the storage buffer.
0216  * @drvdata: a pointer to the drvdata.
0217  * @offset: The storage buffer start address.
0218  * @count: The number of words (32 bit) to read from the
0219  *           device (ICAP).
0220  **/
0221 static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
0222         u32 offset, u32 count)
0223 {
0224 
0225     s32 retries = 0;
0226     void __iomem *base_address = drvdata->base_address;
0227 
0228     if (buffer_icap_busy(base_address))
0229         return -EBUSY;
0230 
0231     if ((offset + count) > XHI_MAX_BUFFER_INTS)
0232         return -EINVAL;
0233 
0234     /* setSize count*4 to get bytes. */
0235     buffer_icap_set_size(base_address, count << 2);
0236     buffer_icap_set_offset(base_address, offset);
0237     buffer_icap_set_rnc(base_address, XHI_CONFIGURE);
0238 
0239     while (buffer_icap_busy(base_address)) {
0240         retries++;
0241         if (retries > XHI_MAX_RETRIES)
0242             return -EBUSY;
0243     }
0244     return 0;
0245 
0246 };
0247 
0248 /**
0249  * buffer_icap_reset - Reset the logic of the icap device.
0250  * @drvdata: a pointer to the drvdata.
0251  *
0252  * Writing to the status register resets the ICAP logic in an internal
0253  * version of the core.  For the version of the core published in EDK,
0254  * this is a noop.
0255  **/
0256 void buffer_icap_reset(struct hwicap_drvdata *drvdata)
0257 {
0258     out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);
0259 }
0260 
0261 /**
0262  * buffer_icap_set_configuration - Load a partial bitstream from system memory.
0263  * @drvdata: a pointer to the drvdata.
0264  * @data: Kernel address of the partial bitstream.
0265  * @size: the size of the partial bitstream in 32 bit words.
0266  **/
0267 int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
0268                  u32 size)
0269 {
0270     int status;
0271     s32 buffer_count = 0;
0272     bool dirty = false;
0273     u32 i;
0274     void __iomem *base_address = drvdata->base_address;
0275 
0276     /* Loop through all the data */
0277     for (i = 0, buffer_count = 0; i < size; i++) {
0278 
0279         /* Copy data to bram */
0280         buffer_icap_set_bram(base_address, buffer_count, data[i]);
0281         dirty = true;
0282 
0283         if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {
0284             buffer_count++;
0285             continue;
0286         }
0287 
0288         /* Write data to ICAP */
0289         status = buffer_icap_device_write(
0290                 drvdata,
0291                 XHI_BUFFER_START,
0292                 XHI_MAX_BUFFER_INTS);
0293         if (status != 0) {
0294             /* abort. */
0295             buffer_icap_reset(drvdata);
0296             return status;
0297         }
0298 
0299         buffer_count = 0;
0300         dirty = false;
0301     }
0302 
0303     /* Write unwritten data to ICAP */
0304     if (dirty) {
0305         /* Write data to ICAP */
0306         status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,
0307                          buffer_count);
0308         if (status != 0) {
0309             /* abort. */
0310             buffer_icap_reset(drvdata);
0311         }
0312         return status;
0313     }
0314 
0315     return 0;
0316 };
0317 
0318 /**
0319  * buffer_icap_get_configuration - Read configuration data from the device.
0320  * @drvdata: a pointer to the drvdata.
0321  * @data: Address of the data representing the partial bitstream
0322  * @size: the size of the partial bitstream in 32 bit words.
0323  **/
0324 int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
0325                  u32 size)
0326 {
0327     int status;
0328     s32 buffer_count = 0;
0329     u32 i;
0330     void __iomem *base_address = drvdata->base_address;
0331 
0332     /* Loop through all the data */
0333     for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {
0334         if (buffer_count == XHI_MAX_BUFFER_INTS) {
0335             u32 words_remaining = size - i;
0336             u32 words_to_read =
0337                 words_remaining <
0338                 XHI_MAX_BUFFER_INTS ? words_remaining :
0339                 XHI_MAX_BUFFER_INTS;
0340 
0341             /* Read data from ICAP */
0342             status = buffer_icap_device_read(
0343                     drvdata,
0344                     XHI_BUFFER_START,
0345                     words_to_read);
0346             if (status != 0) {
0347                 /* abort. */
0348                 buffer_icap_reset(drvdata);
0349                 return status;
0350             }
0351 
0352             buffer_count = 0;
0353         }
0354 
0355         /* Copy data from bram */
0356         data[i] = buffer_icap_get_bram(base_address, buffer_count);
0357         buffer_count++;
0358     }
0359 
0360     return 0;
0361 };