qla_sup.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /******************************************************************************
  2. * QLOGIC LINUX SOFTWARE
  3. *
  4. * QLogic ISP2x00 device driver for Linux 2.6.x
  5. * Copyright (C) 2003-2004 QLogic Corporation
  6. * (www.qlogic.com)
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2, or (at your option) any
  11. * later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. ******************************************************************************/
  19. #include "qla_def.h"
  20. #include <linux/delay.h>
  21. #include <asm/uaccess.h>
  22. static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);
  23. static void qla2x00_nv_deselect(scsi_qla_host_t *);
  24. static void qla2x00_nv_write(scsi_qla_host_t *, uint16_t);
  25. /*
  26. * NVRAM support routines
  27. */
  28. /**
  29. * qla2x00_lock_nvram_access() -
  30. * @ha: HA context
  31. */
  32. void
  33. qla2x00_lock_nvram_access(scsi_qla_host_t *ha)
  34. {
  35. uint16_t data;
  36. device_reg_t __iomem *reg = ha->iobase;
  37. if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
  38. data = RD_REG_WORD(&reg->nvram);
  39. while (data & NVR_BUSY) {
  40. udelay(100);
  41. data = RD_REG_WORD(&reg->nvram);
  42. }
  43. /* Lock resource */
  44. WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0x1);
  45. RD_REG_WORD(&reg->u.isp2300.host_semaphore);
  46. udelay(5);
  47. data = RD_REG_WORD(&reg->u.isp2300.host_semaphore);
  48. while ((data & BIT_0) == 0) {
  49. /* Lock failed */
  50. udelay(100);
  51. WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0x1);
  52. RD_REG_WORD(&reg->u.isp2300.host_semaphore);
  53. udelay(5);
  54. data = RD_REG_WORD(&reg->u.isp2300.host_semaphore);
  55. }
  56. }
  57. }
  58. /**
  59. * qla2x00_unlock_nvram_access() -
  60. * @ha: HA context
  61. */
  62. void
  63. qla2x00_unlock_nvram_access(scsi_qla_host_t *ha)
  64. {
  65. device_reg_t __iomem *reg = ha->iobase;
  66. if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
  67. WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0);
  68. RD_REG_WORD(&reg->u.isp2300.host_semaphore);
  69. }
  70. }
  71. /**
  72. * qla2x00_release_nvram_protection() -
  73. * @ha: HA context
  74. */
  75. void
  76. qla2x00_release_nvram_protection(scsi_qla_host_t *ha)
  77. {
  78. device_reg_t __iomem *reg;
  79. uint32_t word;
  80. reg = ha->iobase;
  81. /* Release NVRAM write protection. */
  82. if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
  83. /* Write enable. */
  84. qla2x00_nv_write(ha, NVR_DATA_OUT);
  85. qla2x00_nv_write(ha, 0);
  86. qla2x00_nv_write(ha, 0);
  87. for (word = 0; word < 8; word++)
  88. qla2x00_nv_write(ha, NVR_DATA_OUT);
  89. qla2x00_nv_deselect(ha);
  90. /* Enable protection register. */
  91. qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
  92. qla2x00_nv_write(ha, NVR_PR_ENABLE);
  93. qla2x00_nv_write(ha, NVR_PR_ENABLE);
  94. for (word = 0; word < 8; word++)
  95. qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
  96. qla2x00_nv_deselect(ha);
  97. /* Clear protection register (ffff is cleared). */
  98. qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
  99. qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
  100. qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
  101. for (word = 0; word < 8; word++)
  102. qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
  103. qla2x00_nv_deselect(ha);
  104. /* Wait for NVRAM to become ready. */
  105. WRT_REG_WORD(&reg->nvram, NVR_SELECT);
  106. do {
  107. NVRAM_DELAY();
  108. word = RD_REG_WORD(&reg->nvram);
  109. } while ((word & NVR_DATA_IN) == 0);
  110. }
  111. }
  112. /**
  113. * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
  114. * request routine to get the word from NVRAM.
  115. * @ha: HA context
  116. * @addr: Address in NVRAM to read
  117. *
  118. * Returns the word read from nvram @addr.
  119. */
  120. uint16_t
  121. qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr)
  122. {
  123. uint16_t data;
  124. uint32_t nv_cmd;
  125. nv_cmd = addr << 16;
  126. nv_cmd |= NV_READ_OP;
  127. data = qla2x00_nvram_request(ha, nv_cmd);
  128. return (data);
  129. }
  130. /**
  131. * qla2x00_write_nvram_word() - Write NVRAM data.
  132. * @ha: HA context
  133. * @addr: Address in NVRAM to write
  134. * @data: word to program
  135. */
  136. void
  137. qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
  138. {
  139. int count;
  140. uint16_t word;
  141. uint32_t nv_cmd;
  142. device_reg_t __iomem *reg = ha->iobase;
  143. qla2x00_nv_write(ha, NVR_DATA_OUT);
  144. qla2x00_nv_write(ha, 0);
  145. qla2x00_nv_write(ha, 0);
  146. for (word = 0; word < 8; word++)
  147. qla2x00_nv_write(ha, NVR_DATA_OUT);
  148. qla2x00_nv_deselect(ha);
  149. /* Write data */
  150. nv_cmd = (addr << 16) | NV_WRITE_OP;
  151. nv_cmd |= data;
  152. nv_cmd <<= 5;
  153. for (count = 0; count < 27; count++) {
  154. if (nv_cmd & BIT_31)
  155. qla2x00_nv_write(ha, NVR_DATA_OUT);
  156. else
  157. qla2x00_nv_write(ha, 0);
  158. nv_cmd <<= 1;
  159. }
  160. qla2x00_nv_deselect(ha);
  161. /* Wait for NVRAM to become ready */
  162. WRT_REG_WORD(&reg->nvram, NVR_SELECT);
  163. do {
  164. NVRAM_DELAY();
  165. word = RD_REG_WORD(&reg->nvram);
  166. } while ((word & NVR_DATA_IN) == 0);
  167. qla2x00_nv_deselect(ha);
  168. /* Disable writes */
  169. qla2x00_nv_write(ha, NVR_DATA_OUT);
  170. for (count = 0; count < 10; count++)
  171. qla2x00_nv_write(ha, 0);
  172. qla2x00_nv_deselect(ha);
  173. }
  174. /**
  175. * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
  176. * NVRAM.
  177. * @ha: HA context
  178. * @nv_cmd: NVRAM command
  179. *
  180. * Bit definitions for NVRAM command:
  181. *
  182. * Bit 26 = start bit
  183. * Bit 25, 24 = opcode
  184. * Bit 23-16 = address
  185. * Bit 15-0 = write data
  186. *
  187. * Returns the word read from nvram @addr.
  188. */
  189. static uint16_t
  190. qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
  191. {
  192. uint8_t cnt;
  193. device_reg_t __iomem *reg = ha->iobase;
  194. uint16_t data = 0;
  195. uint16_t reg_data;
  196. /* Send command to NVRAM. */
  197. nv_cmd <<= 5;
  198. for (cnt = 0; cnt < 11; cnt++) {
  199. if (nv_cmd & BIT_31)
  200. qla2x00_nv_write(ha, NVR_DATA_OUT);
  201. else
  202. qla2x00_nv_write(ha, 0);
  203. nv_cmd <<= 1;
  204. }
  205. /* Read data from NVRAM. */
  206. for (cnt = 0; cnt < 16; cnt++) {
  207. WRT_REG_WORD(&reg->nvram, NVR_SELECT | NVR_CLOCK);
  208. NVRAM_DELAY();
  209. data <<= 1;
  210. reg_data = RD_REG_WORD(&reg->nvram);
  211. if (reg_data & NVR_DATA_IN)
  212. data |= BIT_0;
  213. WRT_REG_WORD(&reg->nvram, NVR_SELECT);
  214. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  215. NVRAM_DELAY();
  216. }
  217. /* Deselect chip. */
  218. WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
  219. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  220. NVRAM_DELAY();
  221. return (data);
  222. }
  223. /**
  224. * qla2x00_nv_write() - Clean NVRAM operations.
  225. * @ha: HA context
  226. */
  227. static void
  228. qla2x00_nv_deselect(scsi_qla_host_t *ha)
  229. {
  230. device_reg_t __iomem *reg = ha->iobase;
  231. WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
  232. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  233. NVRAM_DELAY();
  234. }
  235. /**
  236. * qla2x00_nv_write() - Prepare for NVRAM read/write operation.
  237. * @ha: HA context
  238. * @data: Serial interface selector
  239. */
  240. static void
  241. qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
  242. {
  243. device_reg_t __iomem *reg = ha->iobase;
  244. WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
  245. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  246. NVRAM_DELAY();
  247. WRT_REG_WORD(&reg->nvram, data | NVR_SELECT| NVR_CLOCK |
  248. NVR_WRT_ENABLE);
  249. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  250. NVRAM_DELAY();
  251. WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
  252. RD_REG_WORD(&reg->nvram); /* PCI Posting. */
  253. NVRAM_DELAY();
  254. }