xref: /linux/drivers/scsi/qla2xxx/qla_sup.c (revision 776cfebb430c7b22c208b1b17add97f354d97cab)
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 
20 #include "qla_def.h"
21 
22 #include <linux/delay.h>
23 #include <asm/uaccess.h>
24 
25 static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);
26 static void qla2x00_nv_deselect(scsi_qla_host_t *);
27 static void qla2x00_nv_write(scsi_qla_host_t *, uint16_t);
28 
29 /*
30  * NVRAM support routines
31  */
32 
33 /**
34  * qla2x00_lock_nvram_access() -
35  * @ha: HA context
36  */
37 void
38 qla2x00_lock_nvram_access(scsi_qla_host_t *ha)
39 {
40 	uint16_t data;
41 	device_reg_t __iomem *reg = ha->iobase;
42 
43 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
44 		data = RD_REG_WORD(&reg->nvram);
45 		while (data & NVR_BUSY) {
46 			udelay(100);
47 			data = RD_REG_WORD(&reg->nvram);
48 		}
49 
50 		/* Lock resource */
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 		while ((data & BIT_0) == 0) {
56 			/* Lock failed */
57 			udelay(100);
58 			WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0x1);
59 			RD_REG_WORD(&reg->u.isp2300.host_semaphore);
60 			udelay(5);
61 			data = RD_REG_WORD(&reg->u.isp2300.host_semaphore);
62 		}
63 	}
64 }
65 
66 /**
67  * qla2x00_unlock_nvram_access() -
68  * @ha: HA context
69  */
70 void
71 qla2x00_unlock_nvram_access(scsi_qla_host_t *ha)
72 {
73 	device_reg_t __iomem *reg = ha->iobase;
74 
75 	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
76 		WRT_REG_WORD(&reg->u.isp2300.host_semaphore, 0);
77 		RD_REG_WORD(&reg->u.isp2300.host_semaphore);
78 	}
79 }
80 
81 /**
82  * qla2x00_release_nvram_protection() -
83  * @ha: HA context
84  */
85 void
86 qla2x00_release_nvram_protection(scsi_qla_host_t *ha)
87 {
88 	device_reg_t __iomem *reg;
89 	uint32_t word;
90 
91 	reg = ha->iobase;
92 
93 	/* Release NVRAM write protection. */
94 	if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
95 		/* Write enable. */
96 		qla2x00_nv_write(ha, NVR_DATA_OUT);
97 		qla2x00_nv_write(ha, 0);
98 		qla2x00_nv_write(ha, 0);
99 		for (word = 0; word < 8; word++)
100 			qla2x00_nv_write(ha, NVR_DATA_OUT);
101 
102 		qla2x00_nv_deselect(ha);
103 
104 		/* Enable protection register. */
105 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
106 		qla2x00_nv_write(ha, NVR_PR_ENABLE);
107 		qla2x00_nv_write(ha, NVR_PR_ENABLE);
108 		for (word = 0; word < 8; word++)
109 			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
110 
111 		qla2x00_nv_deselect(ha);
112 
113 		/* Clear protection register (ffff is cleared). */
114 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
115 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
116 		qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
117 		for (word = 0; word < 8; word++)
118 			qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
119 
120 		qla2x00_nv_deselect(ha);
121 
122 		/* Wait for NVRAM to become ready. */
123 		WRT_REG_WORD(&reg->nvram, NVR_SELECT);
124 		do {
125 			NVRAM_DELAY();
126 			word = RD_REG_WORD(&reg->nvram);
127 		} while ((word & NVR_DATA_IN) == 0);
128 	}
129 }
130 
131 /**
132  * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
133  *	request routine to get the word from NVRAM.
134  * @ha: HA context
135  * @addr: Address in NVRAM to read
136  *
137  * Returns the word read from nvram @addr.
138  */
139 uint16_t
140 qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr)
141 {
142 	uint16_t	data;
143 	uint32_t	nv_cmd;
144 
145 	nv_cmd = addr << 16;
146 	nv_cmd |= NV_READ_OP;
147 	data = qla2x00_nvram_request(ha, nv_cmd);
148 
149 	return (data);
150 }
151 
152 /**
153  * qla2x00_write_nvram_word() - Write NVRAM data.
154  * @ha: HA context
155  * @addr: Address in NVRAM to write
156  * @data: word to program
157  */
158 void
159 qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
160 {
161 	int count;
162 	uint16_t word;
163 	uint32_t nv_cmd;
164 	device_reg_t __iomem *reg = ha->iobase;
165 
166 	qla2x00_nv_write(ha, NVR_DATA_OUT);
167 	qla2x00_nv_write(ha, 0);
168 	qla2x00_nv_write(ha, 0);
169 
170 	for (word = 0; word < 8; word++)
171 		qla2x00_nv_write(ha, NVR_DATA_OUT);
172 
173 	qla2x00_nv_deselect(ha);
174 
175 	/* Write data */
176 	nv_cmd = (addr << 16) | NV_WRITE_OP;
177 	nv_cmd |= data;
178 	nv_cmd <<= 5;
179 	for (count = 0; count < 27; count++) {
180 		if (nv_cmd & BIT_31)
181 			qla2x00_nv_write(ha, NVR_DATA_OUT);
182 		else
183 			qla2x00_nv_write(ha, 0);
184 
185 		nv_cmd <<= 1;
186 	}
187 
188 	qla2x00_nv_deselect(ha);
189 
190 	/* Wait for NVRAM to become ready */
191 	WRT_REG_WORD(&reg->nvram, NVR_SELECT);
192 	do {
193 		NVRAM_DELAY();
194 		word = RD_REG_WORD(&reg->nvram);
195 	} while ((word & NVR_DATA_IN) == 0);
196 
197 	qla2x00_nv_deselect(ha);
198 
199 	/* Disable writes */
200 	qla2x00_nv_write(ha, NVR_DATA_OUT);
201 	for (count = 0; count < 10; count++)
202 		qla2x00_nv_write(ha, 0);
203 
204 	qla2x00_nv_deselect(ha);
205 }
206 
207 /**
208  * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
209  *	NVRAM.
210  * @ha: HA context
211  * @nv_cmd: NVRAM command
212  *
213  * Bit definitions for NVRAM command:
214  *
215  *	Bit 26     = start bit
216  *	Bit 25, 24 = opcode
217  *	Bit 23-16  = address
218  *	Bit 15-0   = write data
219  *
220  * Returns the word read from nvram @addr.
221  */
222 static uint16_t
223 qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
224 {
225 	uint8_t		cnt;
226 	device_reg_t __iomem *reg = ha->iobase;
227 	uint16_t	data = 0;
228 	uint16_t	reg_data;
229 
230 	/* Send command to NVRAM. */
231 	nv_cmd <<= 5;
232 	for (cnt = 0; cnt < 11; cnt++) {
233 		if (nv_cmd & BIT_31)
234 			qla2x00_nv_write(ha, NVR_DATA_OUT);
235 		else
236 			qla2x00_nv_write(ha, 0);
237 		nv_cmd <<= 1;
238 	}
239 
240 	/* Read data from NVRAM. */
241 	for (cnt = 0; cnt < 16; cnt++) {
242 		WRT_REG_WORD(&reg->nvram, NVR_SELECT | NVR_CLOCK);
243 		NVRAM_DELAY();
244 		data <<= 1;
245 		reg_data = RD_REG_WORD(&reg->nvram);
246 		if (reg_data & NVR_DATA_IN)
247 			data |= BIT_0;
248 		WRT_REG_WORD(&reg->nvram, NVR_SELECT);
249 		RD_REG_WORD(&reg->nvram);	/* PCI Posting. */
250 		NVRAM_DELAY();
251 	}
252 
253 	/* Deselect chip. */
254 	WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
255 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
256 	NVRAM_DELAY();
257 
258 	return (data);
259 }
260 
261 /**
262  * qla2x00_nv_write() - Clean NVRAM operations.
263  * @ha: HA context
264  */
265 static void
266 qla2x00_nv_deselect(scsi_qla_host_t *ha)
267 {
268 	device_reg_t __iomem *reg = ha->iobase;
269 
270 	WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
271 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
272 	NVRAM_DELAY();
273 }
274 
275 /**
276  * qla2x00_nv_write() - Prepare for NVRAM read/write operation.
277  * @ha: HA context
278  * @data: Serial interface selector
279  */
280 static void
281 qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
282 {
283 	device_reg_t __iomem *reg = ha->iobase;
284 
285 	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
286 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
287 	NVRAM_DELAY();
288 	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT| NVR_CLOCK |
289 	    NVR_WRT_ENABLE);
290 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
291 	NVRAM_DELAY();
292 	WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
293 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
294 	NVRAM_DELAY();
295 }
296 
297