Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2...
[pandora-kernel.git] / drivers / scsi / qla2xxx / qla_sup.c
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