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