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 2007-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 "fifo_icap.h"
0034 
0035 /* Register offsets for the XHwIcap device. */
0036 #define XHI_GIER_OFFSET 0x1C  /* Device Global Interrupt Enable Reg */
0037 #define XHI_IPISR_OFFSET 0x20  /* Interrupt Status Register */
0038 #define XHI_IPIER_OFFSET 0x28  /* Interrupt Enable Register */
0039 #define XHI_WF_OFFSET 0x100 /* Write FIFO */
0040 #define XHI_RF_OFFSET 0x104 /* Read FIFO */
0041 #define XHI_SZ_OFFSET 0x108 /* Size Register */
0042 #define XHI_CR_OFFSET 0x10C /* Control Register */
0043 #define XHI_SR_OFFSET 0x110 /* Status Register */
0044 #define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */
0045 #define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */
0046 
0047 /* Device Global Interrupt Enable Register (GIER) bit definitions */
0048 
0049 #define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */
0050 
0051 /**
0052  * HwIcap Device Interrupt Status/Enable Registers
0053  *
0054  * Interrupt Status Register (IPISR) : This register holds the
0055  * interrupt status flags for the device. These bits are toggle on
0056  * write.
0057  *
0058  * Interrupt Enable Register (IPIER) : This register is used to enable
0059  * interrupt sources for the device.
0060  * Writing a '1' to a bit enables the corresponding interrupt.
0061  * Writing a '0' to a bit disables the corresponding interrupt.
0062  *
0063  * IPISR/IPIER registers have the same bit definitions and are only defined
0064  * once.
0065  */
0066 #define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */
0067 #define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */
0068 #define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */
0069 #define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */
0070 #define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */
0071 
0072 /* Control Register (CR) */
0073 #define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */
0074 #define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */
0075 #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */
0076 #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */
0077 
0078 
0079 #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */
0080 #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */
0081 /* The maximum amount we can request from fifo_icap_get_configuration
0082    at once, in bytes. */
0083 #define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF
0084 
0085 
0086 /**
0087  * fifo_icap_fifo_write - Write data to the write FIFO.
0088  * @drvdata: a pointer to the drvdata.
0089  * @data: the 32-bit value to be written to the FIFO.
0090  *
0091  * This function will silently fail if the fifo is full.
0092  **/
0093 static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,
0094         u32 data)
0095 {
0096     dev_dbg(drvdata->dev, "fifo_write: %x\n", data);
0097     out_be32(drvdata->base_address + XHI_WF_OFFSET, data);
0098 }
0099 
0100 /**
0101  * fifo_icap_fifo_read - Read data from the Read FIFO.
0102  * @drvdata: a pointer to the drvdata.
0103  *
0104  * This function will silently fail if the fifo is empty.
0105  **/
0106 static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)
0107 {
0108     u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET);
0109     dev_dbg(drvdata->dev, "fifo_read: %x\n", data);
0110     return data;
0111 }
0112 
0113 /**
0114  * fifo_icap_set_read_size - Set the size register.
0115  * @drvdata: a pointer to the drvdata.
0116  * @data: the size of the following read transaction, in words.
0117  **/
0118 static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,
0119         u32 data)
0120 {
0121     out_be32(drvdata->base_address + XHI_SZ_OFFSET, data);
0122 }
0123 
0124 /**
0125  * fifo_icap_start_config - Initiate a configuration (write) to the device.
0126  * @drvdata: a pointer to the drvdata.
0127  **/
0128 static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)
0129 {
0130     out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK);
0131     dev_dbg(drvdata->dev, "configuration started\n");
0132 }
0133 
0134 /**
0135  * fifo_icap_start_readback - Initiate a readback from the device.
0136  * @drvdata: a pointer to the drvdata.
0137  **/
0138 static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
0139 {
0140     out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK);
0141     dev_dbg(drvdata->dev, "readback started\n");
0142 }
0143 
0144 /**
0145  * fifo_icap_get_status - Get the contents of the status register.
0146  * @drvdata: a pointer to the drvdata.
0147  *
0148  * The status register contains the ICAP status and the done bit.
0149  *
0150  * D8 - cfgerr
0151  * D7 - dalign
0152  * D6 - rip
0153  * D5 - in_abort_l
0154  * D4 - Always 1
0155  * D3 - Always 1
0156  * D2 - Always 1
0157  * D1 - Always 1
0158  * D0 - Done bit
0159  **/
0160 u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
0161 {
0162     u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
0163     dev_dbg(drvdata->dev, "Getting status = %x\n", status);
0164     return status;
0165 }
0166 
0167 /**
0168  * fifo_icap_busy - Return true if the ICAP is still processing a transaction.
0169  * @drvdata: a pointer to the drvdata.
0170  **/
0171 static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
0172 {
0173     u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
0174     return (status & XHI_SR_DONE_MASK) ? 0 : 1;
0175 }
0176 
0177 /**
0178  * fifo_icap_write_fifo_vacancy - Query the write fifo available space.
0179  * @drvdata: a pointer to the drvdata.
0180  *
0181  * Return the number of words that can be safely pushed into the write fifo.
0182  **/
0183 static inline u32 fifo_icap_write_fifo_vacancy(
0184         struct hwicap_drvdata *drvdata)
0185 {
0186     return in_be32(drvdata->base_address + XHI_WFV_OFFSET);
0187 }
0188 
0189 /**
0190  * fifo_icap_read_fifo_occupancy - Query the read fifo available data.
0191  * @drvdata: a pointer to the drvdata.
0192  *
0193  * Return the number of words that can be safely read from the read fifo.
0194  **/
0195 static inline u32 fifo_icap_read_fifo_occupancy(
0196         struct hwicap_drvdata *drvdata)
0197 {
0198     return in_be32(drvdata->base_address + XHI_RFO_OFFSET);
0199 }
0200 
0201 /**
0202  * fifo_icap_set_configuration - Send configuration data to the ICAP.
0203  * @drvdata: a pointer to the drvdata.
0204  * @frame_buffer: a pointer to the data to be written to the
0205  *      ICAP device.
0206  * @num_words: the number of words (32 bit) to write to the ICAP
0207  *      device.
0208 
0209  * This function writes the given user data to the Write FIFO in
0210  * polled mode and starts the transfer of the data to
0211  * the ICAP device.
0212  **/
0213 int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
0214         u32 *frame_buffer, u32 num_words)
0215 {
0216 
0217     u32 write_fifo_vacancy = 0;
0218     u32 retries = 0;
0219     u32 remaining_words;
0220 
0221     dev_dbg(drvdata->dev, "fifo_set_configuration\n");
0222 
0223     /*
0224      * Check if the ICAP device is Busy with the last Read/Write
0225      */
0226     if (fifo_icap_busy(drvdata))
0227         return -EBUSY;
0228 
0229     /*
0230      * Set up the buffer pointer and the words to be transferred.
0231      */
0232     remaining_words = num_words;
0233 
0234     while (remaining_words > 0) {
0235         /*
0236          * Wait until we have some data in the fifo.
0237          */
0238         while (write_fifo_vacancy == 0) {
0239             write_fifo_vacancy =
0240                 fifo_icap_write_fifo_vacancy(drvdata);
0241             retries++;
0242             if (retries > XHI_MAX_RETRIES)
0243                 return -EIO;
0244         }
0245 
0246         /*
0247          * Write data into the Write FIFO.
0248          */
0249         while ((write_fifo_vacancy != 0) &&
0250                 (remaining_words > 0)) {
0251             fifo_icap_fifo_write(drvdata, *frame_buffer);
0252 
0253             remaining_words--;
0254             write_fifo_vacancy--;
0255             frame_buffer++;
0256         }
0257         /* Start pushing whatever is in the FIFO into the ICAP. */
0258         fifo_icap_start_config(drvdata);
0259     }
0260 
0261     /* Wait until the write has finished. */
0262     while (fifo_icap_busy(drvdata)) {
0263         retries++;
0264         if (retries > XHI_MAX_RETRIES)
0265             break;
0266     }
0267 
0268     dev_dbg(drvdata->dev, "done fifo_set_configuration\n");
0269 
0270     /*
0271      * If the requested number of words have not been read from
0272      * the device then indicate failure.
0273      */
0274     if (remaining_words != 0)
0275         return -EIO;
0276 
0277     return 0;
0278 }
0279 
0280 /**
0281  * fifo_icap_get_configuration - Read configuration data from the device.
0282  * @drvdata: a pointer to the drvdata.
0283  * @data: Address of the data representing the partial bitstream
0284  * @size: the size of the partial bitstream in 32 bit words.
0285  *
0286  * This function reads the specified number of words from the ICAP device in
0287  * the polled mode.
0288  */
0289 int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
0290         u32 *frame_buffer, u32 num_words)
0291 {
0292 
0293     u32 read_fifo_occupancy = 0;
0294     u32 retries = 0;
0295     u32 *data = frame_buffer;
0296     u32 remaining_words;
0297     u32 words_to_read;
0298 
0299     dev_dbg(drvdata->dev, "fifo_get_configuration\n");
0300 
0301     /*
0302      * Check if the ICAP device is Busy with the last Write/Read
0303      */
0304     if (fifo_icap_busy(drvdata))
0305         return -EBUSY;
0306 
0307     remaining_words = num_words;
0308 
0309     while (remaining_words > 0) {
0310         words_to_read = remaining_words;
0311         /* The hardware has a limit on the number of words
0312            that can be read at one time.  */
0313         if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS)
0314             words_to_read = XHI_MAX_READ_TRANSACTION_WORDS;
0315 
0316         remaining_words -= words_to_read;
0317 
0318         fifo_icap_set_read_size(drvdata, words_to_read);
0319         fifo_icap_start_readback(drvdata);
0320 
0321         while (words_to_read > 0) {
0322             /* Wait until we have some data in the fifo. */
0323             while (read_fifo_occupancy == 0) {
0324                 read_fifo_occupancy =
0325                     fifo_icap_read_fifo_occupancy(drvdata);
0326                 retries++;
0327                 if (retries > XHI_MAX_RETRIES)
0328                     return -EIO;
0329             }
0330 
0331             if (read_fifo_occupancy > words_to_read)
0332                 read_fifo_occupancy = words_to_read;
0333 
0334             words_to_read -= read_fifo_occupancy;
0335 
0336             /* Read the data from the Read FIFO. */
0337             while (read_fifo_occupancy != 0) {
0338                 *data++ = fifo_icap_fifo_read(drvdata);
0339                 read_fifo_occupancy--;
0340             }
0341         }
0342     }
0343 
0344     dev_dbg(drvdata->dev, "done fifo_get_configuration\n");
0345 
0346     return 0;
0347 }
0348 
0349 /**
0350  * buffer_icap_reset - Reset the logic of the icap device.
0351  * @drvdata: a pointer to the drvdata.
0352  *
0353  * This function forces the software reset of the complete HWICAP device.
0354  * All the registers will return to the default value and the FIFO is also
0355  * flushed as a part of this software reset.
0356  */
0357 void fifo_icap_reset(struct hwicap_drvdata *drvdata)
0358 {
0359     u32 reg_data;
0360     /*
0361      * Reset the device by setting/clearing the RESET bit in the
0362      * Control Register.
0363      */
0364     reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
0365 
0366     out_be32(drvdata->base_address + XHI_CR_OFFSET,
0367                 reg_data | XHI_CR_SW_RESET_MASK);
0368 
0369     out_be32(drvdata->base_address + XHI_CR_OFFSET,
0370                 reg_data & (~XHI_CR_SW_RESET_MASK));
0371 
0372 }
0373 
0374 /**
0375  * fifo_icap_flush_fifo - This function flushes the FIFOs in the device.
0376  * @drvdata: a pointer to the drvdata.
0377  */
0378 void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)
0379 {
0380     u32 reg_data;
0381     /*
0382      * Flush the FIFO by setting/clearing the FIFO Clear bit in the
0383      * Control Register.
0384      */
0385     reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
0386 
0387     out_be32(drvdata->base_address + XHI_CR_OFFSET,
0388                 reg_data | XHI_CR_FIFO_CLR_MASK);
0389 
0390     out_be32(drvdata->base_address + XHI_CR_OFFSET,
0391                 reg_data & (~XHI_CR_FIFO_CLR_MASK));
0392 }
0393