fifo_icap.c (11902B)
1/***************************************************************************** 2 * 3 * Author: Xilinx, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" 11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND 12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, 13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, 14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION 15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, 16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE 17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY 18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE 19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR 20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF 21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE. 23 * 24 * (c) Copyright 2007-2008 Xilinx Inc. 25 * All rights reserved. 26 * 27 * You should have received a copy of the GNU General Public License along 28 * with this program; if not, write to the Free Software Foundation, Inc., 29 * 675 Mass Ave, Cambridge, MA 02139, USA. 30 * 31 *****************************************************************************/ 32 33#include "fifo_icap.h" 34 35/* Register offsets for the XHwIcap device. */ 36#define XHI_GIER_OFFSET 0x1C /* Device Global Interrupt Enable Reg */ 37#define XHI_IPISR_OFFSET 0x20 /* Interrupt Status Register */ 38#define XHI_IPIER_OFFSET 0x28 /* Interrupt Enable Register */ 39#define XHI_WF_OFFSET 0x100 /* Write FIFO */ 40#define XHI_RF_OFFSET 0x104 /* Read FIFO */ 41#define XHI_SZ_OFFSET 0x108 /* Size Register */ 42#define XHI_CR_OFFSET 0x10C /* Control Register */ 43#define XHI_SR_OFFSET 0x110 /* Status Register */ 44#define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */ 45#define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */ 46 47/* Device Global Interrupt Enable Register (GIER) bit definitions */ 48 49#define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */ 50 51/** 52 * HwIcap Device Interrupt Status/Enable Registers 53 * 54 * Interrupt Status Register (IPISR) : This register holds the 55 * interrupt status flags for the device. These bits are toggle on 56 * write. 57 * 58 * Interrupt Enable Register (IPIER) : This register is used to enable 59 * interrupt sources for the device. 60 * Writing a '1' to a bit enables the corresponding interrupt. 61 * Writing a '0' to a bit disables the corresponding interrupt. 62 * 63 * IPISR/IPIER registers have the same bit definitions and are only defined 64 * once. 65 */ 66#define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */ 67#define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */ 68#define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */ 69#define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */ 70#define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */ 71 72/* Control Register (CR) */ 73#define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */ 74#define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */ 75#define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */ 76#define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */ 77 78 79#define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */ 80#define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */ 81/* The maximum amount we can request from fifo_icap_get_configuration 82 at once, in bytes. */ 83#define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF 84 85 86/** 87 * fifo_icap_fifo_write - Write data to the write FIFO. 88 * @drvdata: a pointer to the drvdata. 89 * @data: the 32-bit value to be written to the FIFO. 90 * 91 * This function will silently fail if the fifo is full. 92 **/ 93static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata, 94 u32 data) 95{ 96 dev_dbg(drvdata->dev, "fifo_write: %x\n", data); 97 out_be32(drvdata->base_address + XHI_WF_OFFSET, data); 98} 99 100/** 101 * fifo_icap_fifo_read - Read data from the Read FIFO. 102 * @drvdata: a pointer to the drvdata. 103 * 104 * This function will silently fail if the fifo is empty. 105 **/ 106static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata) 107{ 108 u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET); 109 dev_dbg(drvdata->dev, "fifo_read: %x\n", data); 110 return data; 111} 112 113/** 114 * fifo_icap_set_read_size - Set the size register. 115 * @drvdata: a pointer to the drvdata. 116 * @data: the size of the following read transaction, in words. 117 **/ 118static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, 119 u32 data) 120{ 121 out_be32(drvdata->base_address + XHI_SZ_OFFSET, data); 122} 123 124/** 125 * fifo_icap_start_config - Initiate a configuration (write) to the device. 126 * @drvdata: a pointer to the drvdata. 127 **/ 128static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) 129{ 130 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK); 131 dev_dbg(drvdata->dev, "configuration started\n"); 132} 133 134/** 135 * fifo_icap_start_readback - Initiate a readback from the device. 136 * @drvdata: a pointer to the drvdata. 137 **/ 138static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) 139{ 140 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK); 141 dev_dbg(drvdata->dev, "readback started\n"); 142} 143 144/** 145 * fifo_icap_get_status - Get the contents of the status register. 146 * @drvdata: a pointer to the drvdata. 147 * 148 * The status register contains the ICAP status and the done bit. 149 * 150 * D8 - cfgerr 151 * D7 - dalign 152 * D6 - rip 153 * D5 - in_abort_l 154 * D4 - Always 1 155 * D3 - Always 1 156 * D2 - Always 1 157 * D1 - Always 1 158 * D0 - Done bit 159 **/ 160u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata) 161{ 162 u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); 163 dev_dbg(drvdata->dev, "Getting status = %x\n", status); 164 return status; 165} 166 167/** 168 * fifo_icap_busy - Return true if the ICAP is still processing a transaction. 169 * @drvdata: a pointer to the drvdata. 170 **/ 171static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) 172{ 173 u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); 174 return (status & XHI_SR_DONE_MASK) ? 0 : 1; 175} 176 177/** 178 * fifo_icap_write_fifo_vacancy - Query the write fifo available space. 179 * @drvdata: a pointer to the drvdata. 180 * 181 * Return the number of words that can be safely pushed into the write fifo. 182 **/ 183static inline u32 fifo_icap_write_fifo_vacancy( 184 struct hwicap_drvdata *drvdata) 185{ 186 return in_be32(drvdata->base_address + XHI_WFV_OFFSET); 187} 188 189/** 190 * fifo_icap_read_fifo_occupancy - Query the read fifo available data. 191 * @drvdata: a pointer to the drvdata. 192 * 193 * Return the number of words that can be safely read from the read fifo. 194 **/ 195static inline u32 fifo_icap_read_fifo_occupancy( 196 struct hwicap_drvdata *drvdata) 197{ 198 return in_be32(drvdata->base_address + XHI_RFO_OFFSET); 199} 200 201/** 202 * fifo_icap_set_configuration - Send configuration data to the ICAP. 203 * @drvdata: a pointer to the drvdata. 204 * @frame_buffer: a pointer to the data to be written to the 205 * ICAP device. 206 * @num_words: the number of words (32 bit) to write to the ICAP 207 * device. 208 209 * This function writes the given user data to the Write FIFO in 210 * polled mode and starts the transfer of the data to 211 * the ICAP device. 212 **/ 213int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata, 214 u32 *frame_buffer, u32 num_words) 215{ 216 217 u32 write_fifo_vacancy = 0; 218 u32 retries = 0; 219 u32 remaining_words; 220 221 dev_dbg(drvdata->dev, "fifo_set_configuration\n"); 222 223 /* 224 * Check if the ICAP device is Busy with the last Read/Write 225 */ 226 if (fifo_icap_busy(drvdata)) 227 return -EBUSY; 228 229 /* 230 * Set up the buffer pointer and the words to be transferred. 231 */ 232 remaining_words = num_words; 233 234 while (remaining_words > 0) { 235 /* 236 * Wait until we have some data in the fifo. 237 */ 238 while (write_fifo_vacancy == 0) { 239 write_fifo_vacancy = 240 fifo_icap_write_fifo_vacancy(drvdata); 241 retries++; 242 if (retries > XHI_MAX_RETRIES) 243 return -EIO; 244 } 245 246 /* 247 * Write data into the Write FIFO. 248 */ 249 while ((write_fifo_vacancy != 0) && 250 (remaining_words > 0)) { 251 fifo_icap_fifo_write(drvdata, *frame_buffer); 252 253 remaining_words--; 254 write_fifo_vacancy--; 255 frame_buffer++; 256 } 257 /* Start pushing whatever is in the FIFO into the ICAP. */ 258 fifo_icap_start_config(drvdata); 259 } 260 261 /* Wait until the write has finished. */ 262 while (fifo_icap_busy(drvdata)) { 263 retries++; 264 if (retries > XHI_MAX_RETRIES) 265 break; 266 } 267 268 dev_dbg(drvdata->dev, "done fifo_set_configuration\n"); 269 270 /* 271 * If the requested number of words have not been read from 272 * the device then indicate failure. 273 */ 274 if (remaining_words != 0) 275 return -EIO; 276 277 return 0; 278} 279 280/** 281 * fifo_icap_get_configuration - Read configuration data from the device. 282 * @drvdata: a pointer to the drvdata. 283 * @data: Address of the data representing the partial bitstream 284 * @size: the size of the partial bitstream in 32 bit words. 285 * 286 * This function reads the specified number of words from the ICAP device in 287 * the polled mode. 288 */ 289int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata, 290 u32 *frame_buffer, u32 num_words) 291{ 292 293 u32 read_fifo_occupancy = 0; 294 u32 retries = 0; 295 u32 *data = frame_buffer; 296 u32 remaining_words; 297 u32 words_to_read; 298 299 dev_dbg(drvdata->dev, "fifo_get_configuration\n"); 300 301 /* 302 * Check if the ICAP device is Busy with the last Write/Read 303 */ 304 if (fifo_icap_busy(drvdata)) 305 return -EBUSY; 306 307 remaining_words = num_words; 308 309 while (remaining_words > 0) { 310 words_to_read = remaining_words; 311 /* The hardware has a limit on the number of words 312 that can be read at one time. */ 313 if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS) 314 words_to_read = XHI_MAX_READ_TRANSACTION_WORDS; 315 316 remaining_words -= words_to_read; 317 318 fifo_icap_set_read_size(drvdata, words_to_read); 319 fifo_icap_start_readback(drvdata); 320 321 while (words_to_read > 0) { 322 /* Wait until we have some data in the fifo. */ 323 while (read_fifo_occupancy == 0) { 324 read_fifo_occupancy = 325 fifo_icap_read_fifo_occupancy(drvdata); 326 retries++; 327 if (retries > XHI_MAX_RETRIES) 328 return -EIO; 329 } 330 331 if (read_fifo_occupancy > words_to_read) 332 read_fifo_occupancy = words_to_read; 333 334 words_to_read -= read_fifo_occupancy; 335 336 /* Read the data from the Read FIFO. */ 337 while (read_fifo_occupancy != 0) { 338 *data++ = fifo_icap_fifo_read(drvdata); 339 read_fifo_occupancy--; 340 } 341 } 342 } 343 344 dev_dbg(drvdata->dev, "done fifo_get_configuration\n"); 345 346 return 0; 347} 348 349/** 350 * buffer_icap_reset - Reset the logic of the icap device. 351 * @drvdata: a pointer to the drvdata. 352 * 353 * This function forces the software reset of the complete HWICAP device. 354 * All the registers will return to the default value and the FIFO is also 355 * flushed as a part of this software reset. 356 */ 357void fifo_icap_reset(struct hwicap_drvdata *drvdata) 358{ 359 u32 reg_data; 360 /* 361 * Reset the device by setting/clearing the RESET bit in the 362 * Control Register. 363 */ 364 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET); 365 366 out_be32(drvdata->base_address + XHI_CR_OFFSET, 367 reg_data | XHI_CR_SW_RESET_MASK); 368 369 out_be32(drvdata->base_address + XHI_CR_OFFSET, 370 reg_data & (~XHI_CR_SW_RESET_MASK)); 371 372} 373 374/** 375 * fifo_icap_flush_fifo - This function flushes the FIFOs in the device. 376 * @drvdata: a pointer to the drvdata. 377 */ 378void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata) 379{ 380 u32 reg_data; 381 /* 382 * Flush the FIFO by setting/clearing the FIFO Clear bit in the 383 * Control Register. 384 */ 385 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET); 386 387 out_be32(drvdata->base_address + XHI_CR_OFFSET, 388 reg_data | XHI_CR_FIFO_CLR_MASK); 389 390 out_be32(drvdata->base_address + XHI_CR_OFFSET, 391 reg_data & (~XHI_CR_FIFO_CLR_MASK)); 392} 393