[SCSI] qla2xxx: Add ISP24xx definitions.
[linux-2.6.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         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
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         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
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         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
89         uint32_t word;
90
91         /* Release NVRAM write protection. */
92         if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
93                 /* Write enable. */
94                 qla2x00_nv_write(ha, NVR_DATA_OUT);
95                 qla2x00_nv_write(ha, 0);
96                 qla2x00_nv_write(ha, 0);
97                 for (word = 0; word < 8; word++)
98                         qla2x00_nv_write(ha, NVR_DATA_OUT);
99
100                 qla2x00_nv_deselect(ha);
101
102                 /* Enable protection register. */
103                 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
104                 qla2x00_nv_write(ha, NVR_PR_ENABLE);
105                 qla2x00_nv_write(ha, NVR_PR_ENABLE);
106                 for (word = 0; word < 8; word++)
107                         qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
108
109                 qla2x00_nv_deselect(ha);
110
111                 /* Clear protection register (ffff is cleared). */
112                 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
113                 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
114                 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
115                 for (word = 0; word < 8; word++)
116                         qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
117
118                 qla2x00_nv_deselect(ha);
119
120                 /* Wait for NVRAM to become ready. */
121                 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
122                 do {
123                         NVRAM_DELAY();
124                         word = RD_REG_WORD(&reg->nvram);
125                 } while ((word & NVR_DATA_IN) == 0);
126         }
127 }
128
129 /**
130  * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
131  *      request routine to get the word from NVRAM.
132  * @ha: HA context
133  * @addr: Address in NVRAM to read
134  *
135  * Returns the word read from nvram @addr.
136  */
137 uint16_t
138 qla2x00_get_nvram_word(scsi_qla_host_t *ha, uint32_t addr)
139 {
140         uint16_t        data;
141         uint32_t        nv_cmd;
142
143         nv_cmd = addr << 16;
144         nv_cmd |= NV_READ_OP;
145         data = qla2x00_nvram_request(ha, nv_cmd);
146
147         return (data);
148 }
149
150 /**
151  * qla2x00_write_nvram_word() - Write NVRAM data.
152  * @ha: HA context
153  * @addr: Address in NVRAM to write
154  * @data: word to program
155  */
156 void
157 qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
158 {
159         int count;
160         uint16_t word;
161         uint32_t nv_cmd;
162         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
163
164         qla2x00_nv_write(ha, NVR_DATA_OUT);
165         qla2x00_nv_write(ha, 0);
166         qla2x00_nv_write(ha, 0);
167
168         for (word = 0; word < 8; word++)
169                 qla2x00_nv_write(ha, NVR_DATA_OUT);
170
171         qla2x00_nv_deselect(ha);
172
173         /* Write data */
174         nv_cmd = (addr << 16) | NV_WRITE_OP;
175         nv_cmd |= data;
176         nv_cmd <<= 5;
177         for (count = 0; count < 27; count++) {
178                 if (nv_cmd & BIT_31)
179                         qla2x00_nv_write(ha, NVR_DATA_OUT);
180                 else
181                         qla2x00_nv_write(ha, 0);
182
183                 nv_cmd <<= 1;
184         }
185
186         qla2x00_nv_deselect(ha);
187
188         /* Wait for NVRAM to become ready */
189         WRT_REG_WORD(&reg->nvram, NVR_SELECT);
190         do {
191                 NVRAM_DELAY();
192                 word = RD_REG_WORD(&reg->nvram);
193         } while ((word & NVR_DATA_IN) == 0);
194
195         qla2x00_nv_deselect(ha);
196
197         /* Disable writes */
198         qla2x00_nv_write(ha, NVR_DATA_OUT);
199         for (count = 0; count < 10; count++)
200                 qla2x00_nv_write(ha, 0);
201
202         qla2x00_nv_deselect(ha);
203 }
204
205 /**
206  * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
207  *      NVRAM.
208  * @ha: HA context
209  * @nv_cmd: NVRAM command
210  *
211  * Bit definitions for NVRAM command:
212  *
213  *      Bit 26     = start bit
214  *      Bit 25, 24 = opcode
215  *      Bit 23-16  = address
216  *      Bit 15-0   = write data
217  *
218  * Returns the word read from nvram @addr.
219  */
220 static uint16_t
221 qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
222 {
223         uint8_t         cnt;
224         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
225         uint16_t        data = 0;
226         uint16_t        reg_data;
227
228         /* Send command to NVRAM. */
229         nv_cmd <<= 5;
230         for (cnt = 0; cnt < 11; cnt++) {
231                 if (nv_cmd & BIT_31)
232                         qla2x00_nv_write(ha, NVR_DATA_OUT);
233                 else
234                         qla2x00_nv_write(ha, 0);
235                 nv_cmd <<= 1;
236         }
237
238         /* Read data from NVRAM. */
239         for (cnt = 0; cnt < 16; cnt++) {
240                 WRT_REG_WORD(&reg->nvram, NVR_SELECT | NVR_CLOCK);
241                 NVRAM_DELAY();
242                 data <<= 1;
243                 reg_data = RD_REG_WORD(&reg->nvram);
244                 if (reg_data & NVR_DATA_IN)
245                         data |= BIT_0;
246                 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
247                 RD_REG_WORD(&reg->nvram);       /* PCI Posting. */
248                 NVRAM_DELAY();
249         }
250
251         /* Deselect chip. */
252         WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
253         RD_REG_WORD(&reg->nvram);               /* PCI Posting. */
254         NVRAM_DELAY();
255
256         return (data);
257 }
258
259 /**
260  * qla2x00_nv_write() - Clean NVRAM operations.
261  * @ha: HA context
262  */
263 static void
264 qla2x00_nv_deselect(scsi_qla_host_t *ha)
265 {
266         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
267
268         WRT_REG_WORD(&reg->nvram, NVR_DESELECT);
269         RD_REG_WORD(&reg->nvram);               /* PCI Posting. */
270         NVRAM_DELAY();
271 }
272
273 /**
274  * qla2x00_nv_write() - Prepare for NVRAM read/write operation.
275  * @ha: HA context
276  * @data: Serial interface selector
277  */
278 static void
279 qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
280 {
281         struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
282
283         WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
284         RD_REG_WORD(&reg->nvram);               /* PCI Posting. */
285         NVRAM_DELAY();
286         WRT_REG_WORD(&reg->nvram, data | NVR_SELECT| NVR_CLOCK |
287             NVR_WRT_ENABLE);
288         RD_REG_WORD(&reg->nvram);               /* PCI Posting. */
289         NVRAM_DELAY();
290         WRT_REG_WORD(&reg->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
291         RD_REG_WORD(&reg->nvram);               /* PCI Posting. */
292         NVRAM_DELAY();
293 }
294