License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[sfrench/cifs-2.6.git] / arch / parisc / lib / io.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * arch/parisc/lib/io.c
4  *
5  * Copyright (c) Matthew Wilcox 2001 for Hewlett-Packard
6  * Copyright (c) Randolph Chung 2001 <tausq@debian.org>
7  *
8  * IO accessing functions which shouldn't be inlined because they're too big
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <asm/io.h>
14
15 /* Copies a block of memory to a device in an efficient manner.
16  * Assumes the device can cope with 32-bit transfers.  If it can't,
17  * don't use this function.
18  */
19 void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
20 {
21         if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
22                 goto bytecopy;
23         while ((unsigned long)dst & 3) {
24                 writeb(*(char *)src, dst++);
25                 src++;
26                 count--;
27         }
28         while (count > 3) {
29                 __raw_writel(*(u32 *)src, dst);
30                 src += 4;
31                 dst += 4;
32                 count -= 4;
33         }
34  bytecopy:
35         while (count--) {
36                 writeb(*(char *)src, dst++);
37                 src++;
38         }
39 }
40
41 /*
42 ** Copies a block of memory from a device in an efficient manner.
43 ** Assumes the device can cope with 32-bit transfers.  If it can't,
44 ** don't use this function.
45 **
46 ** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
47 **      27341/64    = 427 cyc per int
48 **      61311/128   = 478 cyc per short
49 **      122637/256  = 479 cyc per byte
50 ** Ergo bus latencies dominant (not transfer size).
51 **      Minimize total number of transfers at cost of CPU cycles.
52 **      TODO: only look at src alignment and adjust the stores to dest.
53 */
54 void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
55 {
56         /* first compare alignment of src/dst */ 
57         if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
58                 goto bytecopy;
59
60         if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
61                 goto shortcopy;
62
63         /* Then check for misaligned start address */
64         if ((unsigned long)src & 1) {
65                 *(u8 *)dst = readb(src);
66                 src++;
67                 dst++;
68                 count--;
69                 if (count < 2) goto bytecopy;
70         }
71
72         if ((unsigned long)src & 2) {
73                 *(u16 *)dst = __raw_readw(src);
74                 src += 2;
75                 dst += 2;
76                 count -= 2;
77         }
78
79         while (count > 3) {
80                 *(u32 *)dst = __raw_readl(src);
81                 dst += 4;
82                 src += 4;
83                 count -= 4;
84         }
85
86  shortcopy:
87         while (count > 1) {
88                 *(u16 *)dst = __raw_readw(src);
89                 src += 2;
90                 dst += 2;
91                 count -= 2;
92         }
93
94  bytecopy:
95         while (count--) {
96                 *(char *)dst = readb(src);
97                 src++;
98                 dst++;
99         }
100 }
101
102 /* Sets a block of memory on a device to a given value.
103  * Assumes the device can cope with 32-bit transfers.  If it can't,
104  * don't use this function.
105  */
106 void memset_io(volatile void __iomem *addr, unsigned char val, int count)
107 {
108         u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
109         while ((unsigned long)addr & 3) {
110                 writeb(val, addr++);
111                 count--;
112         }
113         while (count > 3) {
114                 __raw_writel(val32, addr);
115                 addr += 4;
116                 count -= 4;
117         }
118         while (count--) {
119                 writeb(val, addr++);
120         }
121 }
122
123 /*
124  * Read COUNT 8-bit bytes from port PORT into memory starting at
125  * SRC.
126  */
127 void insb (unsigned long port, void *dst, unsigned long count)
128 {
129         unsigned char *p;
130
131         p = (unsigned char *)dst;
132
133         while (((unsigned long)p) & 0x3) {
134                 if (!count)
135                         return;
136                 count--;
137                 *p = inb(port);
138                 p++;
139         }
140
141         while (count >= 4) {
142                 unsigned int w;
143                 count -= 4;
144                 w = inb(port) << 24;
145                 w |= inb(port) << 16;
146                 w |= inb(port) << 8;
147                 w |= inb(port);
148                 *(unsigned int *) p = w;
149                 p += 4;
150         }
151
152         while (count) {
153                 --count;
154                 *p = inb(port);
155                 p++;
156         }
157 }
158
159
160 /*
161  * Read COUNT 16-bit words from port PORT into memory starting at
162  * SRC.  SRC must be at least short aligned.  This is used by the
163  * IDE driver to read disk sectors.  Performance is important, but
164  * the interfaces seems to be slow: just using the inlined version
165  * of the inw() breaks things.
166  */
167 void insw (unsigned long port, void *dst, unsigned long count)
168 {
169         unsigned int l = 0, l2;
170         unsigned char *p;
171
172         p = (unsigned char *)dst;
173         
174         if (!count)
175                 return;
176         
177         switch (((unsigned long)p) & 0x3)
178         {
179          case 0x00:                     /* Buffer 32-bit aligned */
180                 while (count>=2) {
181                         
182                         count -= 2;
183                         l = cpu_to_le16(inw(port)) << 16;
184                         l |= cpu_to_le16(inw(port));
185                         *(unsigned int *)p = l;
186                         p += 4;
187                 }
188                 if (count) {
189                         *(unsigned short *)p = cpu_to_le16(inw(port));
190                 }
191                 break;
192         
193          case 0x02:                     /* Buffer 16-bit aligned */
194                 *(unsigned short *)p = cpu_to_le16(inw(port));
195                 p += 2;
196                 count--;
197                 while (count>=2) {
198                         
199                         count -= 2;
200                         l = cpu_to_le16(inw(port)) << 16;
201                         l |= cpu_to_le16(inw(port));
202                         *(unsigned int *)p = l;
203                         p += 4;
204                 }
205                 if (count) {
206                         *(unsigned short *)p = cpu_to_le16(inw(port));
207                 }
208                 break;
209                 
210          case 0x01:                     /* Buffer 8-bit aligned */
211          case 0x03:
212                 /* I don't bother with 32bit transfers
213                  * in this case, 16bit will have to do -- DE */
214                 --count;
215                 
216                 l = cpu_to_le16(inw(port));
217                 *p = l >> 8;
218                 p++;
219                 while (count--)
220                 {
221                         l2 = cpu_to_le16(inw(port));
222                         *(unsigned short *)p = (l & 0xff) << 8 | (l2 >> 8);
223                         p += 2;
224                         l = l2;
225                 }
226                 *p = l & 0xff;
227                 break;
228         }
229 }
230
231
232
233 /*
234  * Read COUNT 32-bit words from port PORT into memory starting at
235  * SRC. Now works with any alignment in SRC. Performance is important,
236  * but the interfaces seems to be slow: just using the inlined version
237  * of the inl() breaks things.
238  */
239 void insl (unsigned long port, void *dst, unsigned long count)
240 {
241         unsigned int l = 0, l2;
242         unsigned char *p;
243
244         p = (unsigned char *)dst;
245         
246         if (!count)
247                 return;
248         
249         switch (((unsigned long) dst) & 0x3)
250         {
251          case 0x00:                     /* Buffer 32-bit aligned */
252                 while (count--)
253                 {
254                         *(unsigned int *)p = cpu_to_le32(inl(port));
255                         p += 4;
256                 }
257                 break;
258         
259          case 0x02:                     /* Buffer 16-bit aligned */
260                 --count;
261                 
262                 l = cpu_to_le32(inl(port));
263                 *(unsigned short *)p = l >> 16;
264                 p += 2;
265                 
266                 while (count--)
267                 {
268                         l2 = cpu_to_le32(inl(port));
269                         *(unsigned int *)p = (l & 0xffff) << 16 | (l2 >> 16);
270                         p += 4;
271                         l = l2;
272                 }
273                 *(unsigned short *)p = l & 0xffff;
274                 break;
275          case 0x01:                     /* Buffer 8-bit aligned */
276                 --count;
277                 
278                 l = cpu_to_le32(inl(port));
279                 *(unsigned char *)p = l >> 24;
280                 p++;
281                 *(unsigned short *)p = (l >> 8) & 0xffff;
282                 p += 2;
283                 while (count--)
284                 {
285                         l2 = cpu_to_le32(inl(port));
286                         *(unsigned int *)p = (l & 0xff) << 24 | (l2 >> 8);
287                         p += 4;
288                         l = l2;
289                 }
290                 *p = l & 0xff;
291                 break;
292          case 0x03:                     /* Buffer 8-bit aligned */
293                 --count;
294                 
295                 l = cpu_to_le32(inl(port));
296                 *p = l >> 24;
297                 p++;
298                 while (count--)
299                 {
300                         l2 = cpu_to_le32(inl(port));
301                         *(unsigned int *)p = (l & 0xffffff) << 8 | l2 >> 24;
302                         p += 4;
303                         l = l2;
304                 }
305                 *(unsigned short *)p = (l >> 8) & 0xffff;
306                 p += 2;
307                 *p = l & 0xff;
308                 break;
309         }
310 }
311
312
313 /*
314  * Like insb but in the opposite direction.
315  * Don't worry as much about doing aligned memory transfers:
316  * doing byte reads the "slow" way isn't nearly as slow as
317  * doing byte writes the slow way (no r-m-w cycle).
318  */
319 void outsb(unsigned long port, const void * src, unsigned long count)
320 {
321         const unsigned char *p;
322
323         p = (const unsigned char *)src;
324         while (count) {
325                 count--;
326                 outb(*p, port);
327                 p++;
328         }
329 }
330
331 /*
332  * Like insw but in the opposite direction.  This is used by the IDE
333  * driver to write disk sectors.  Performance is important, but the
334  * interfaces seems to be slow: just using the inlined version of the
335  * outw() breaks things.
336  */
337 void outsw (unsigned long port, const void *src, unsigned long count)
338 {
339         unsigned int l = 0, l2;
340         const unsigned char *p;
341
342         p = (const unsigned char *)src;
343         
344         if (!count)
345                 return;
346         
347         switch (((unsigned long)p) & 0x3)
348         {
349          case 0x00:                     /* Buffer 32-bit aligned */
350                 while (count>=2) {
351                         count -= 2;
352                         l = *(unsigned int *)p;
353                         p += 4;
354                         outw(le16_to_cpu(l >> 16), port);
355                         outw(le16_to_cpu(l & 0xffff), port);
356                 }
357                 if (count) {
358                         outw(le16_to_cpu(*(unsigned short*)p), port);
359                 }
360                 break;
361         
362          case 0x02:                     /* Buffer 16-bit aligned */
363                 
364                 outw(le16_to_cpu(*(unsigned short*)p), port);
365                 p += 2;
366                 count--;
367                 
368                 while (count>=2) {
369                         count -= 2;
370                         l = *(unsigned int *)p;
371                         p += 4;
372                         outw(le16_to_cpu(l >> 16), port);
373                         outw(le16_to_cpu(l & 0xffff), port);
374                 }
375                 if (count) {
376                         outw(le16_to_cpu(*(unsigned short *)p), port);
377                 }
378                 break;
379                 
380          case 0x01:                     /* Buffer 8-bit aligned */      
381                 /* I don't bother with 32bit transfers
382                  * in this case, 16bit will have to do -- DE */
383                 
384                 l  = *p << 8;
385                 p++;
386                 count--;
387                 while (count)
388                 {
389                         count--;
390                         l2 = *(unsigned short *)p;
391                         p += 2;
392                         outw(le16_to_cpu(l | l2 >> 8), port);
393                         l = l2 << 8;
394                 }
395                 l2 = *(unsigned char *)p;
396                 outw (le16_to_cpu(l | l2>>8), port);
397                 break;
398         
399         }
400 }
401
402
403 /*
404  * Like insl but in the opposite direction.  This is used by the IDE
405  * driver to write disk sectors.  Works with any alignment in SRC.
406  *  Performance is important, but the interfaces seems to be slow:
407  * just using the inlined version of the outl() breaks things.
408  */
409 void outsl (unsigned long port, const void *src, unsigned long count)
410 {
411         unsigned int l = 0, l2;
412         const unsigned char *p;
413
414         p = (const unsigned char *)src;
415         
416         if (!count)
417                 return;
418         
419         switch (((unsigned long)p) & 0x3)
420         {
421          case 0x00:                     /* Buffer 32-bit aligned */
422                 while (count--)
423                 {
424                         outl(le32_to_cpu(*(unsigned int *)p), port);
425                         p += 4;
426                 }
427                 break;
428         
429          case 0x02:                     /* Buffer 16-bit aligned */
430                 --count;
431                 
432                 l = *(unsigned short *)p;
433                 p += 2;
434                 
435                 while (count--)
436                 {
437                         l2 = *(unsigned int *)p;
438                         p += 4;
439                         outl (le32_to_cpu(l << 16 | l2 >> 16), port);
440                         l = l2;
441                 }
442                 l2 = *(unsigned short *)p;
443                 outl (le32_to_cpu(l << 16 | l2), port);
444                 break;
445          case 0x01:                     /* Buffer 8-bit aligned */
446                 --count;
447
448                 l = *p << 24;
449                 p++;
450                 l |= *(unsigned short *)p << 8;
451                 p += 2;
452
453                 while (count--)
454                 {
455                         l2 = *(unsigned int *)p;
456                         p += 4;
457                         outl (le32_to_cpu(l | l2 >> 24), port);
458                         l = l2 << 8;
459                 }
460                 l2 = *p;
461                 outl (le32_to_cpu(l | l2), port);
462                 break;
463          case 0x03:                     /* Buffer 8-bit aligned */
464                 --count;
465                 
466                 l = *p << 24;
467                 p++;
468
469                 while (count--)
470                 {
471                         l2 = *(unsigned int *)p;
472                         p += 4;
473                         outl (le32_to_cpu(l | l2 >> 8), port);
474                         l = l2 << 24;
475                 }
476                 l2 = *(unsigned short *)p << 16;
477                 p += 2;
478                 l2 |= *p;
479                 outl (le32_to_cpu(l | l2), port);
480                 break;
481         }
482 }
483
484 EXPORT_SYMBOL(insb);
485 EXPORT_SYMBOL(insw);
486 EXPORT_SYMBOL(insl);
487 EXPORT_SYMBOL(outsb);
488 EXPORT_SYMBOL(outsw);
489 EXPORT_SYMBOL(outsl);