GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / sparc / lib / PeeCeeI.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * PeeCeeI.c: The emerging standard...
4  *
5  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6  */
7
8 #include <linux/module.h>
9
10 #include <asm/io.h>
11 #include <asm/byteorder.h>
12
13 void outsb(unsigned long __addr, const void *src, unsigned long count)
14 {
15         void __iomem *addr = (void __iomem *) __addr;
16         const u8 *p = src;
17
18         while (count--)
19                 __raw_writeb(*p++, addr);
20 }
21 EXPORT_SYMBOL(outsb);
22
23 void outsw(unsigned long __addr, const void *src, unsigned long count)
24 {
25         void __iomem *addr = (void __iomem *) __addr;
26
27         while (count--) {
28                 __raw_writew(*(u16 *)src, addr);
29                 src += sizeof(u16);
30         }
31 }
32 EXPORT_SYMBOL(outsw);
33
34 void outsl(unsigned long __addr, const void *src, unsigned long count)
35 {
36         void __iomem *addr = (void __iomem *) __addr;
37         u32 l, l2;
38
39         if (!count)
40                 return;
41
42         switch (((unsigned long)src) & 0x3) {
43         case 0x0:
44                 /* src is naturally aligned */
45                 while (count--) {
46                         __raw_writel(*(u32 *)src, addr);
47                         src += sizeof(u32);
48                 }
49                 break;
50         case 0x2:
51                 /* 2-byte alignment */
52                 while (count--) {
53                         l = (*(u16 *)src) << 16;
54                         l |= *(u16 *)(src + sizeof(u16));
55                         __raw_writel(l, addr);
56                         src += sizeof(u32);
57                 }
58                 break;
59         case 0x1:
60                 /* Hold three bytes in l each time, grab a byte from l2 */
61                 l = (*(u8 *)src) << 24;
62                 l |= (*(u16 *)(src + sizeof(u8))) << 8;
63                 src += sizeof(u8) + sizeof(u16);
64                 while (count--) {
65                         l2 = *(u32 *)src;
66                         l |= (l2 >> 24);
67                         __raw_writel(l, addr);
68                         l = l2 << 8;
69                         src += sizeof(u32);
70                 }
71                 break;
72         case 0x3:
73                 /* Hold a byte in l each time, grab 3 bytes from l2 */
74                 l = (*(u8 *)src) << 24;
75                 src += sizeof(u8);
76                 while (count--) {
77                         l2 = *(u32 *)src;
78                         l |= (l2 >> 8);
79                         __raw_writel(l, addr);
80                         l = l2 << 24;
81                         src += sizeof(u32);
82                 }
83                 break;
84         }
85 }
86 EXPORT_SYMBOL(outsl);
87
88 void insb(unsigned long __addr, void *dst, unsigned long count)
89 {
90         void __iomem *addr = (void __iomem *) __addr;
91
92         if (count) {
93                 u32 *pi;
94                 u8 *pb = dst;
95
96                 while ((((unsigned long)pb) & 0x3) && count--)
97                         *pb++ = __raw_readb(addr);
98                 pi = (u32 *)pb;
99                 while (count >= 4) {
100                         u32 w;
101
102                         w  = (__raw_readb(addr) << 24);
103                         w |= (__raw_readb(addr) << 16);
104                         w |= (__raw_readb(addr) << 8);
105                         w |= (__raw_readb(addr) << 0);
106                         *pi++ = w;
107                         count -= 4;
108                 }
109                 pb = (u8 *)pi;
110                 while (count--)
111                         *pb++ = __raw_readb(addr);
112         }
113 }
114 EXPORT_SYMBOL(insb);
115
116 void insw(unsigned long __addr, void *dst, unsigned long count)
117 {
118         void __iomem *addr = (void __iomem *) __addr;
119
120         if (count) {
121                 u16 *ps = dst;
122                 u32 *pi;
123
124                 if (((unsigned long)ps) & 0x2) {
125                         *ps++ = __raw_readw(addr);
126                         count--;
127                 }
128                 pi = (u32 *)ps;
129                 while (count >= 2) {
130                         u32 w;
131
132                         w  = __raw_readw(addr) << 16;
133                         w |= __raw_readw(addr) << 0;
134                         *pi++ = w;
135                         count -= 2;
136                 }
137                 ps = (u16 *)pi;
138                 if (count)
139                         *ps = __raw_readw(addr);
140         }
141 }
142 EXPORT_SYMBOL(insw);
143
144 void insl(unsigned long __addr, void *dst, unsigned long count)
145 {
146         void __iomem *addr = (void __iomem *) __addr;
147
148         if (count) {
149                 if ((((unsigned long)dst) & 0x3) == 0) {
150                         u32 *pi = dst;
151                         while (count--)
152                                 *pi++ = __raw_readl(addr);
153                 } else {
154                         u32 l = 0, l2, *pi;
155                         u16 *ps;
156                         u8 *pb;
157
158                         switch (((unsigned long)dst) & 3) {
159                         case 0x2:
160                                 ps = dst;
161                                 count -= 1;
162                                 l = __raw_readl(addr);
163                                 *ps++ = l;
164                                 pi = (u32 *)ps;
165                                 while (count--) {
166                                         l2 = __raw_readl(addr);
167                                         *pi++ = (l << 16) | (l2 >> 16);
168                                         l = l2;
169                                 }
170                                 ps = (u16 *)pi;
171                                 *ps = l;
172                                 break;
173
174                         case 0x1:
175                                 pb = dst;
176                                 count -= 1;
177                                 l = __raw_readl(addr);
178                                 *pb++ = l >> 24;
179                                 ps = (u16 *)pb;
180                                 *ps++ = ((l >> 8) & 0xffff);
181                                 pi = (u32 *)ps;
182                                 while (count--) {
183                                         l2 = __raw_readl(addr);
184                                         *pi++ = (l << 24) | (l2 >> 8);
185                                         l = l2;
186                                 }
187                                 pb = (u8 *)pi;
188                                 *pb = l;
189                                 break;
190
191                         case 0x3:
192                                 pb = (u8 *)dst;
193                                 count -= 1;
194                                 l = __raw_readl(addr);
195                                 *pb++ = l >> 24;
196                                 pi = (u32 *)pb;
197                                 while (count--) {
198                                         l2 = __raw_readl(addr);
199                                         *pi++ = (l << 8) | (l2 >> 24);
200                                         l = l2;
201                                 }
202                                 ps = (u16 *)pi;
203                                 *ps++ = ((l >> 8) & 0xffff);
204                                 pb = (u8 *)ps;
205                                 *pb = l;
206                                 break;
207                         }
208                 }
209         }
210 }
211 EXPORT_SYMBOL(insl);
212