diff options
Diffstat (limited to 'drivers/net/sfc/io.h')
-rw-r--r-- | drivers/net/sfc/io.h | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/drivers/net/sfc/io.h b/drivers/net/sfc/io.h new file mode 100644 index 00000000000..751d1ec112c --- /dev/null +++ b/drivers/net/sfc/io.h | |||
@@ -0,0 +1,293 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005-2006 Fen Systems Ltd. | ||
4 | * Copyright 2006-2010 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #ifndef EFX_IO_H | ||
12 | #define EFX_IO_H | ||
13 | |||
14 | #include <linux/io.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | |||
17 | /************************************************************************** | ||
18 | * | ||
19 | * NIC register I/O | ||
20 | * | ||
21 | ************************************************************************** | ||
22 | * | ||
23 | * Notes on locking strategy: | ||
24 | * | ||
25 | * Most CSRs are 128-bit (oword) and therefore cannot be read or | ||
26 | * written atomically. Access from the host is buffered by the Bus | ||
27 | * Interface Unit (BIU). Whenever the host reads from the lowest | ||
28 | * address of such a register, or from the address of a different such | ||
29 | * register, the BIU latches the register's value. Subsequent reads | ||
30 | * from higher addresses of the same register will read the latched | ||
31 | * value. Whenever the host writes part of such a register, the BIU | ||
32 | * collects the written value and does not write to the underlying | ||
33 | * register until all 4 dwords have been written. A similar buffering | ||
34 | * scheme applies to host access to the NIC's 64-bit SRAM. | ||
35 | * | ||
36 | * Access to different CSRs and 64-bit SRAM words must be serialised, | ||
37 | * since interleaved access can result in lost writes or lost | ||
38 | * information from read-to-clear fields. We use efx_nic::biu_lock | ||
39 | * for this. (We could use separate locks for read and write, but | ||
40 | * this is not normally a performance bottleneck.) | ||
41 | * | ||
42 | * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are | ||
43 | * 128-bit but are special-cased in the BIU to avoid the need for | ||
44 | * locking in the host: | ||
45 | * | ||
46 | * - They are write-only. | ||
47 | * - The semantics of writing to these registers are such that | ||
48 | * replacing the low 96 bits with zero does not affect functionality. | ||
49 | * - If the host writes to the last dword address of such a register | ||
50 | * (i.e. the high 32 bits) the underlying register will always be | ||
51 | * written. If the collector and the current write together do not | ||
52 | * provide values for all 128 bits of the register, the low 96 bits | ||
53 | * will be written as zero. | ||
54 | * - If the host writes to the address of any other part of such a | ||
55 | * register while the collector already holds values for some other | ||
56 | * register, the write is discarded and the collector maintains its | ||
57 | * current state. | ||
58 | */ | ||
59 | |||
60 | #if BITS_PER_LONG == 64 | ||
61 | #define EFX_USE_QWORD_IO 1 | ||
62 | #endif | ||
63 | |||
64 | #ifdef EFX_USE_QWORD_IO | ||
65 | static inline void _efx_writeq(struct efx_nic *efx, __le64 value, | ||
66 | unsigned int reg) | ||
67 | { | ||
68 | __raw_writeq((__force u64)value, efx->membase + reg); | ||
69 | } | ||
70 | static inline __le64 _efx_readq(struct efx_nic *efx, unsigned int reg) | ||
71 | { | ||
72 | return (__force __le64)__raw_readq(efx->membase + reg); | ||
73 | } | ||
74 | #endif | ||
75 | |||
76 | static inline void _efx_writed(struct efx_nic *efx, __le32 value, | ||
77 | unsigned int reg) | ||
78 | { | ||
79 | __raw_writel((__force u32)value, efx->membase + reg); | ||
80 | } | ||
81 | static inline __le32 _efx_readd(struct efx_nic *efx, unsigned int reg) | ||
82 | { | ||
83 | return (__force __le32)__raw_readl(efx->membase + reg); | ||
84 | } | ||
85 | |||
86 | /* Write a normal 128-bit CSR, locking as appropriate. */ | ||
87 | static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value, | ||
88 | unsigned int reg) | ||
89 | { | ||
90 | unsigned long flags __attribute__ ((unused)); | ||
91 | |||
92 | netif_vdbg(efx, hw, efx->net_dev, | ||
93 | "writing register %x with " EFX_OWORD_FMT "\n", reg, | ||
94 | EFX_OWORD_VAL(*value)); | ||
95 | |||
96 | spin_lock_irqsave(&efx->biu_lock, flags); | ||
97 | #ifdef EFX_USE_QWORD_IO | ||
98 | _efx_writeq(efx, value->u64[0], reg + 0); | ||
99 | _efx_writeq(efx, value->u64[1], reg + 8); | ||
100 | #else | ||
101 | _efx_writed(efx, value->u32[0], reg + 0); | ||
102 | _efx_writed(efx, value->u32[1], reg + 4); | ||
103 | _efx_writed(efx, value->u32[2], reg + 8); | ||
104 | _efx_writed(efx, value->u32[3], reg + 12); | ||
105 | #endif | ||
106 | mmiowb(); | ||
107 | spin_unlock_irqrestore(&efx->biu_lock, flags); | ||
108 | } | ||
109 | |||
110 | /* Write 64-bit SRAM through the supplied mapping, locking as appropriate. */ | ||
111 | static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase, | ||
112 | efx_qword_t *value, unsigned int index) | ||
113 | { | ||
114 | unsigned int addr = index * sizeof(*value); | ||
115 | unsigned long flags __attribute__ ((unused)); | ||
116 | |||
117 | netif_vdbg(efx, hw, efx->net_dev, | ||
118 | "writing SRAM address %x with " EFX_QWORD_FMT "\n", | ||
119 | addr, EFX_QWORD_VAL(*value)); | ||
120 | |||
121 | spin_lock_irqsave(&efx->biu_lock, flags); | ||
122 | #ifdef EFX_USE_QWORD_IO | ||
123 | __raw_writeq((__force u64)value->u64[0], membase + addr); | ||
124 | #else | ||
125 | __raw_writel((__force u32)value->u32[0], membase + addr); | ||
126 | __raw_writel((__force u32)value->u32[1], membase + addr + 4); | ||
127 | #endif | ||
128 | mmiowb(); | ||
129 | spin_unlock_irqrestore(&efx->biu_lock, flags); | ||
130 | } | ||
131 | |||
132 | /* Write a 32-bit CSR or the last dword of a special 128-bit CSR */ | ||
133 | static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value, | ||
134 | unsigned int reg) | ||
135 | { | ||
136 | netif_vdbg(efx, hw, efx->net_dev, | ||
137 | "writing register %x with "EFX_DWORD_FMT"\n", | ||
138 | reg, EFX_DWORD_VAL(*value)); | ||
139 | |||
140 | /* No lock required */ | ||
141 | _efx_writed(efx, value->u32[0], reg); | ||
142 | } | ||
143 | |||
144 | /* Read a 128-bit CSR, locking as appropriate. */ | ||
145 | static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value, | ||
146 | unsigned int reg) | ||
147 | { | ||
148 | unsigned long flags __attribute__ ((unused)); | ||
149 | |||
150 | spin_lock_irqsave(&efx->biu_lock, flags); | ||
151 | value->u32[0] = _efx_readd(efx, reg + 0); | ||
152 | value->u32[1] = _efx_readd(efx, reg + 4); | ||
153 | value->u32[2] = _efx_readd(efx, reg + 8); | ||
154 | value->u32[3] = _efx_readd(efx, reg + 12); | ||
155 | spin_unlock_irqrestore(&efx->biu_lock, flags); | ||
156 | |||
157 | netif_vdbg(efx, hw, efx->net_dev, | ||
158 | "read from register %x, got " EFX_OWORD_FMT "\n", reg, | ||
159 | EFX_OWORD_VAL(*value)); | ||
160 | } | ||
161 | |||
162 | /* Read 64-bit SRAM through the supplied mapping, locking as appropriate. */ | ||
163 | static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase, | ||
164 | efx_qword_t *value, unsigned int index) | ||
165 | { | ||
166 | unsigned int addr = index * sizeof(*value); | ||
167 | unsigned long flags __attribute__ ((unused)); | ||
168 | |||
169 | spin_lock_irqsave(&efx->biu_lock, flags); | ||
170 | #ifdef EFX_USE_QWORD_IO | ||
171 | value->u64[0] = (__force __le64)__raw_readq(membase + addr); | ||
172 | #else | ||
173 | value->u32[0] = (__force __le32)__raw_readl(membase + addr); | ||
174 | value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4); | ||
175 | #endif | ||
176 | spin_unlock_irqrestore(&efx->biu_lock, flags); | ||
177 | |||
178 | netif_vdbg(efx, hw, efx->net_dev, | ||
179 | "read from SRAM address %x, got "EFX_QWORD_FMT"\n", | ||
180 | addr, EFX_QWORD_VAL(*value)); | ||
181 | } | ||
182 | |||
183 | /* Read a 32-bit CSR or SRAM */ | ||
184 | static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value, | ||
185 | unsigned int reg) | ||
186 | { | ||
187 | value->u32[0] = _efx_readd(efx, reg); | ||
188 | netif_vdbg(efx, hw, efx->net_dev, | ||
189 | "read from register %x, got "EFX_DWORD_FMT"\n", | ||
190 | reg, EFX_DWORD_VAL(*value)); | ||
191 | } | ||
192 | |||
193 | /* Write a 128-bit CSR forming part of a table */ | ||
194 | static inline void efx_writeo_table(struct efx_nic *efx, efx_oword_t *value, | ||
195 | unsigned int reg, unsigned int index) | ||
196 | { | ||
197 | efx_writeo(efx, value, reg + index * sizeof(efx_oword_t)); | ||
198 | } | ||
199 | |||
200 | /* Read a 128-bit CSR forming part of a table */ | ||
201 | static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value, | ||
202 | unsigned int reg, unsigned int index) | ||
203 | { | ||
204 | efx_reado(efx, value, reg + index * sizeof(efx_oword_t)); | ||
205 | } | ||
206 | |||
207 | /* Write a 32-bit CSR forming part of a table, or 32-bit SRAM */ | ||
208 | static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value, | ||
209 | unsigned int reg, unsigned int index) | ||
210 | { | ||
211 | efx_writed(efx, value, reg + index * sizeof(efx_oword_t)); | ||
212 | } | ||
213 | |||
214 | /* Read a 32-bit CSR forming part of a table, or 32-bit SRAM */ | ||
215 | static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value, | ||
216 | unsigned int reg, unsigned int index) | ||
217 | { | ||
218 | efx_readd(efx, value, reg + index * sizeof(efx_dword_t)); | ||
219 | } | ||
220 | |||
221 | /* Page-mapped register block size */ | ||
222 | #define EFX_PAGE_BLOCK_SIZE 0x2000 | ||
223 | |||
224 | /* Calculate offset to page-mapped register block */ | ||
225 | #define EFX_PAGED_REG(page, reg) \ | ||
226 | ((page) * EFX_PAGE_BLOCK_SIZE + (reg)) | ||
227 | |||
228 | /* Write the whole of RX_DESC_UPD or TX_DESC_UPD */ | ||
229 | static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value, | ||
230 | unsigned int reg, unsigned int page) | ||
231 | { | ||
232 | reg = EFX_PAGED_REG(page, reg); | ||
233 | |||
234 | netif_vdbg(efx, hw, efx->net_dev, | ||
235 | "writing register %x with " EFX_OWORD_FMT "\n", reg, | ||
236 | EFX_OWORD_VAL(*value)); | ||
237 | |||
238 | #ifdef EFX_USE_QWORD_IO | ||
239 | _efx_writeq(efx, value->u64[0], reg + 0); | ||
240 | _efx_writeq(efx, value->u64[1], reg + 8); | ||
241 | #else | ||
242 | _efx_writed(efx, value->u32[0], reg + 0); | ||
243 | _efx_writed(efx, value->u32[1], reg + 4); | ||
244 | _efx_writed(efx, value->u32[2], reg + 8); | ||
245 | _efx_writed(efx, value->u32[3], reg + 12); | ||
246 | #endif | ||
247 | } | ||
248 | #define efx_writeo_page(efx, value, reg, page) \ | ||
249 | _efx_writeo_page(efx, value, \ | ||
250 | reg + \ | ||
251 | BUILD_BUG_ON_ZERO((reg) != 0x830 && (reg) != 0xa10), \ | ||
252 | page) | ||
253 | |||
254 | /* Write a page-mapped 32-bit CSR (EVQ_RPTR or the high bits of | ||
255 | * RX_DESC_UPD or TX_DESC_UPD) | ||
256 | */ | ||
257 | static inline void _efx_writed_page(struct efx_nic *efx, efx_dword_t *value, | ||
258 | unsigned int reg, unsigned int page) | ||
259 | { | ||
260 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | ||
261 | } | ||
262 | #define efx_writed_page(efx, value, reg, page) \ | ||
263 | _efx_writed_page(efx, value, \ | ||
264 | reg + \ | ||
265 | BUILD_BUG_ON_ZERO((reg) != 0x400 && (reg) != 0x83c \ | ||
266 | && (reg) != 0xa1c), \ | ||
267 | page) | ||
268 | |||
269 | /* Write TIMER_COMMAND. This is a page-mapped 32-bit CSR, but a bug | ||
270 | * in the BIU means that writes to TIMER_COMMAND[0] invalidate the | ||
271 | * collector register. | ||
272 | */ | ||
273 | static inline void _efx_writed_page_locked(struct efx_nic *efx, | ||
274 | efx_dword_t *value, | ||
275 | unsigned int reg, | ||
276 | unsigned int page) | ||
277 | { | ||
278 | unsigned long flags __attribute__ ((unused)); | ||
279 | |||
280 | if (page == 0) { | ||
281 | spin_lock_irqsave(&efx->biu_lock, flags); | ||
282 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | ||
283 | spin_unlock_irqrestore(&efx->biu_lock, flags); | ||
284 | } else { | ||
285 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | ||
286 | } | ||
287 | } | ||
288 | #define efx_writed_page_locked(efx, value, reg, page) \ | ||
289 | _efx_writed_page_locked(efx, value, \ | ||
290 | reg + BUILD_BUG_ON_ZERO((reg) != 0x420), \ | ||
291 | page) | ||
292 | |||
293 | #endif /* EFX_IO_H */ | ||