buffer_icap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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 2003-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. #include "buffer_icap.h"
  33. /* Indicates how many bytes will fit in a buffer. (1 BRAM) */
  34. #define XHI_MAX_BUFFER_BYTES 2048
  35. #define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2)
  36. /* File access and error constants */
  37. #define XHI_DEVICE_READ_ERROR -1
  38. #define XHI_DEVICE_WRITE_ERROR -2
  39. #define XHI_BUFFER_OVERFLOW_ERROR -3
  40. #define XHI_DEVICE_READ 0x1
  41. #define XHI_DEVICE_WRITE 0x0
  42. /* Constants for checking transfer status */
  43. #define XHI_CYCLE_DONE 0
  44. #define XHI_CYCLE_EXECUTING 1
  45. /* buffer_icap register offsets */
  46. /* Size of transfer, read & write */
  47. #define XHI_SIZE_REG_OFFSET 0x800L
  48. /* offset into bram, read & write */
  49. #define XHI_BRAM_OFFSET_REG_OFFSET 0x804L
  50. /* Read not Configure, direction of transfer. Write only */
  51. #define XHI_RNC_REG_OFFSET 0x808L
  52. /* Indicates transfer complete. Read only */
  53. #define XHI_STATUS_REG_OFFSET 0x80CL
  54. /* Constants for setting the RNC register */
  55. #define XHI_CONFIGURE 0x0UL
  56. #define XHI_READBACK 0x1UL
  57. /* Constants for the Done register */
  58. #define XHI_NOT_FINISHED 0x0UL
  59. #define XHI_FINISHED 0x1UL
  60. #define XHI_BUFFER_START 0
  61. /**
  62. * buffer_icap_get_status - Get the contents of the status register.
  63. * @drvdata: a pointer to the drvdata.
  64. *
  65. * The status register contains the ICAP status and the done bit.
  66. *
  67. * D8 - cfgerr
  68. * D7 - dalign
  69. * D6 - rip
  70. * D5 - in_abort_l
  71. * D4 - Always 1
  72. * D3 - Always 1
  73. * D2 - Always 1
  74. * D1 - Always 1
  75. * D0 - Done bit
  76. **/
  77. u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
  78. {
  79. return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
  80. }
  81. /**
  82. * buffer_icap_get_bram - Reads data from the storage buffer bram.
  83. * @base_address: contains the base address of the component.
  84. * @offset: The word offset from which the data should be read.
  85. *
  86. * A bram is used as a configuration memory cache. One frame of data can
  87. * be stored in this "storage buffer".
  88. **/
  89. static inline u32 buffer_icap_get_bram(void __iomem *base_address,
  90. u32 offset)
  91. {
  92. return in_be32(base_address + (offset << 2));
  93. }
  94. /**
  95. * buffer_icap_busy - Return true if the icap device is busy
  96. * @base_address: is the base address of the device
  97. *
  98. * The queries the low order bit of the status register, which
  99. * indicates whether the current configuration or readback operation
  100. * has completed.
  101. **/
  102. static inline bool buffer_icap_busy(void __iomem *base_address)
  103. {
  104. u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
  105. return (status & 1) == XHI_NOT_FINISHED;
  106. }
  107. /**
  108. * buffer_icap_set_size - Set the size register.
  109. * @base_address: is the base address of the device
  110. * @data: The size in bytes.
  111. *
  112. * The size register holds the number of 8 bit bytes to transfer between
  113. * bram and the icap (or icap to bram).
  114. **/
  115. static inline void buffer_icap_set_size(void __iomem *base_address,
  116. u32 data)
  117. {
  118. out_be32(base_address + XHI_SIZE_REG_OFFSET, data);
  119. }
  120. /**
  121. * buffer_icap_set_offset - Set the bram offset register.
  122. * @base_address: contains the base address of the device.
  123. * @data: is the value to be written to the data register.
  124. *
  125. * The bram offset register holds the starting bram address to transfer
  126. * data from during configuration or write data to during readback.
  127. **/
  128. static inline void buffer_icap_set_offset(void __iomem *base_address,
  129. u32 data)
  130. {
  131. out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);
  132. }
  133. /**
  134. * buffer_icap_set_rnc - Set the RNC (Readback not Configure) register.
  135. * @base_address: contains the base address of the device.
  136. * @data: is the value to be written to the data register.
  137. *
  138. * The RNC register determines the direction of the data transfer. It
  139. * controls whether a configuration or readback take place. Writing to
  140. * this register initiates the transfer. A value of 1 initiates a
  141. * readback while writing a value of 0 initiates a configuration.
  142. **/
  143. static inline void buffer_icap_set_rnc(void __iomem *base_address,
  144. u32 data)
  145. {
  146. out_be32(base_address + XHI_RNC_REG_OFFSET, data);
  147. }
  148. /**
  149. * buffer_icap_set_bram - Write data to the storage buffer bram.
  150. * @base_address: contains the base address of the component.
  151. * @offset: The word offset at which the data should be written.
  152. * @data: The value to be written to the bram offset.
  153. *
  154. * A bram is used as a configuration memory cache. One frame of data can
  155. * be stored in this "storage buffer".
  156. **/
  157. static inline void buffer_icap_set_bram(void __iomem *base_address,
  158. u32 offset, u32 data)
  159. {
  160. out_be32(base_address + (offset << 2), data);
  161. }
  162. /**
  163. * buffer_icap_device_read - Transfer bytes from ICAP to the storage buffer.
  164. * @drvdata: a pointer to the drvdata.
  165. * @offset: The storage buffer start address.
  166. * @count: The number of words (32 bit) to read from the
  167. * device (ICAP).
  168. **/
  169. static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
  170. u32 offset, u32 count)
  171. {
  172. s32 retries = 0;
  173. void __iomem *base_address = drvdata->base_address;
  174. if (buffer_icap_busy(base_address))
  175. return -EBUSY;
  176. if ((offset + count) > XHI_MAX_BUFFER_INTS)
  177. return -EINVAL;
  178. /* setSize count*4 to get bytes. */
  179. buffer_icap_set_size(base_address, (count << 2));
  180. buffer_icap_set_offset(base_address, offset);
  181. buffer_icap_set_rnc(base_address, XHI_READBACK);
  182. while (buffer_icap_busy(base_address)) {
  183. retries++;
  184. if (retries > XHI_MAX_RETRIES)
  185. return -EBUSY;
  186. }
  187. return 0;
  188. };
  189. /**
  190. * buffer_icap_device_write - Transfer bytes from ICAP to the storage buffer.
  191. * @drvdata: a pointer to the drvdata.
  192. * @offset: The storage buffer start address.
  193. * @count: The number of words (32 bit) to read from the
  194. * device (ICAP).
  195. **/
  196. static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
  197. u32 offset, u32 count)
  198. {
  199. s32 retries = 0;
  200. void __iomem *base_address = drvdata->base_address;
  201. if (buffer_icap_busy(base_address))
  202. return -EBUSY;
  203. if ((offset + count) > XHI_MAX_BUFFER_INTS)
  204. return -EINVAL;
  205. /* setSize count*4 to get bytes. */
  206. buffer_icap_set_size(base_address, count << 2);
  207. buffer_icap_set_offset(base_address, offset);
  208. buffer_icap_set_rnc(base_address, XHI_CONFIGURE);
  209. while (buffer_icap_busy(base_address)) {
  210. retries++;
  211. if (retries > XHI_MAX_RETRIES)
  212. return -EBUSY;
  213. }
  214. return 0;
  215. };
  216. /**
  217. * buffer_icap_reset - Reset the logic of the icap device.
  218. * @drvdata: a pointer to the drvdata.
  219. *
  220. * Writing to the status register resets the ICAP logic in an internal
  221. * version of the core. For the version of the core published in EDK,
  222. * this is a noop.
  223. **/
  224. void buffer_icap_reset(struct hwicap_drvdata *drvdata)
  225. {
  226. out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);
  227. }
  228. /**
  229. * buffer_icap_set_configuration - Load a partial bitstream from system memory.
  230. * @drvdata: a pointer to the drvdata.
  231. * @data: Kernel address of the partial bitstream.
  232. * @size: the size of the partial bitstream in 32 bit words.
  233. **/
  234. int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
  235. u32 size)
  236. {
  237. int status;
  238. s32 buffer_count = 0;
  239. s32 num_writes = 0;
  240. bool dirty = false;
  241. u32 i;
  242. void __iomem *base_address = drvdata->base_address;
  243. /* Loop through all the data */
  244. for (i = 0, buffer_count = 0; i < size; i++) {
  245. /* Copy data to bram */
  246. buffer_icap_set_bram(base_address, buffer_count, data[i]);
  247. dirty = true;
  248. if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {
  249. buffer_count++;
  250. continue;
  251. }
  252. /* Write data to ICAP */
  253. status = buffer_icap_device_write(
  254. drvdata,
  255. XHI_BUFFER_START,
  256. XHI_MAX_BUFFER_INTS);
  257. if (status != 0) {
  258. /* abort. */
  259. buffer_icap_reset(drvdata);
  260. return status;
  261. }
  262. buffer_count = 0;
  263. num_writes++;
  264. dirty = false;
  265. }
  266. /* Write unwritten data to ICAP */
  267. if (dirty) {
  268. /* Write data to ICAP */
  269. status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,
  270. buffer_count);
  271. if (status != 0) {
  272. /* abort. */
  273. buffer_icap_reset(drvdata);
  274. }
  275. return status;
  276. }
  277. return 0;
  278. };
  279. /**
  280. * buffer_icap_get_configuration - Read configuration data from the device.
  281. * @drvdata: a pointer to the drvdata.
  282. * @data: Address of the data representing the partial bitstream
  283. * @size: the size of the partial bitstream in 32 bit words.
  284. **/
  285. int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
  286. u32 size)
  287. {
  288. int status;
  289. s32 buffer_count = 0;
  290. s32 read_count = 0;
  291. u32 i;
  292. void __iomem *base_address = drvdata->base_address;
  293. /* Loop through all the data */
  294. for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {
  295. if (buffer_count == XHI_MAX_BUFFER_INTS) {
  296. u32 words_remaining = size - i;
  297. u32 words_to_read =
  298. words_remaining <
  299. XHI_MAX_BUFFER_INTS ? words_remaining :
  300. XHI_MAX_BUFFER_INTS;
  301. /* Read data from ICAP */
  302. status = buffer_icap_device_read(
  303. drvdata,
  304. XHI_BUFFER_START,
  305. words_to_read);
  306. if (status != 0) {
  307. /* abort. */
  308. buffer_icap_reset(drvdata);
  309. return status;
  310. }
  311. buffer_count = 0;
  312. read_count++;
  313. }
  314. /* Copy data from bram */
  315. data[i] = buffer_icap_get_bram(base_address, buffer_count);
  316. buffer_count++;
  317. }
  318. return 0;
  319. };