1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 *  linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO
4 */
5#include <linux/linkage.h>
6
7#include <asm/assembler.h>
8#include <mach/hardware.h>
9
10#if defined(__APCS_32__)
11#define LOADREGS(t,r,l...)	ldm##t	r, l
12#elif defined(__APCS_26__)
13#define LOADREGS(t,r,l...)	ldm##t	r, l##^
14#endif
15
16@ Purpose: transfer a block of data from the acorn scsi card to memory
17@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
18@ Returns: nothing
19
20		.align
21ENTRY(__acornscsi_in)
22		stmfd	sp!, {r4 - r7, lr}
23		bic	r0, r0, #3
24		mov	lr, #0xff
25		orr	lr, lr, #0xff00
26acornscsi_in16lp:
27		subs	r2, r2, #16
28		bmi	acornscsi_in8
29		ldmia	r0!, {r3, r4, r5, r6}
30		and	r3, r3, lr
31		orr	r3, r3, r4, lsl #16
32		and 	r4, r5, lr
33		orr	r4, r4, r6, lsl #16
34		ldmia	r0!, {r5, r6, r7, ip}
35		and	r5, r5, lr
36		orr	r5, r5, r6, lsl #16
37		and	r6, r7, lr
38		orr	r6, r6, ip, lsl #16
39		stmia	r1!, {r3 - r6}
40		bne	acornscsi_in16lp
41		LOADREGS(fd, sp!, {r4 - r7, pc})
42
43acornscsi_in8:	adds	r2, r2, #8
44		bmi	acornscsi_in4
45		ldmia	r0!, {r3, r4, r5, r6}
46		and	r3, r3, lr
47		orr	r3, r3, r4, lsl #16
48		and	r4, r5, lr
49		orr	r4, r4, r6, lsl #16
50		stmia	r1!, {r3 - r4}
51		LOADREGS(eqfd, sp!, {r4 - r7, pc})
52		sub	r2, r2, #8
53
54acornscsi_in4:	adds	r2, r2, #4
55		bmi	acornscsi_in2
56		ldmia	r0!, {r3, r4}
57		and	r3, r3, lr
58		orr	r3, r3, r4, lsl #16
59		str	r3, [r1], #4
60		LOADREGS(eqfd, sp!, {r4 - r7, pc})
61		sub	r2, r2, #4
62
63acornscsi_in2:	adds	r2, r2, #2
64		ldr	r3, [r0], #4
65		and	r3, r3, lr
66		strb	r3, [r1], #1
67		mov	r3, r3, lsr #8
68		strplb	r3, [r1], #1
69		LOADREGS(fd, sp!, {r4 - r7, pc})
70
71@ Purpose: transfer a block of data from memory to the acorn scsi card
72@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
73@ Returns: nothing
74
75ENTRY(__acornscsi_out)
76		stmfd	sp!, {r4 - r6, lr}
77		bic	r0, r0, #3
78acornscsi_out16lp:
79		subs	r2, r2, #16
80		bmi	acornscsi_out8
81		ldmia	r1!, {r4, r6, ip, lr}
82		mov	r3, r4, lsl #16
83		orr	r3, r3, r3, lsr #16
84		mov	r4, r4, lsr #16
85		orr	r4, r4, r4, lsl #16
86		mov	r5, r6, lsl #16
87		orr	r5, r5, r5, lsr #16
88		mov	r6, r6, lsr #16
89		orr	r6, r6, r6, lsl #16
90		stmia	r0!, {r3, r4, r5, r6}
91		mov	r3, ip, lsl #16
92		orr	r3, r3, r3, lsr #16
93		mov	r4, ip, lsr #16
94		orr	r4, r4, r4, lsl #16
95		mov	ip, lr, lsl #16
96		orr	ip, ip, ip, lsr #16
97		mov	lr, lr, lsr #16
98		orr	lr, lr, lr, lsl #16
99		stmia	r0!, {r3, r4, ip, lr}
100		bne	acornscsi_out16lp
101		LOADREGS(fd, sp!, {r4 - r6, pc})
102
103acornscsi_out8:	adds	r2, r2, #8
104		bmi	acornscsi_out4
105		ldmia	r1!, {r4, r6}
106		mov	r3, r4, lsl #16
107		orr	r3, r3, r3, lsr #16
108		mov	r4, r4, lsr #16
109		orr	r4, r4, r4, lsl #16
110		mov	r5, r6, lsl #16
111		orr	r5, r5, r5, lsr #16
112		mov	r6, r6, lsr #16
113		orr	r6, r6, r6, lsl #16
114		stmia	r0!, {r3, r4, r5, r6}
115		LOADREGS(eqfd, sp!, {r4 - r6, pc})
116
117		sub	r2, r2, #8
118acornscsi_out4:	adds	r2, r2, #4
119		bmi	acornscsi_out2
120		ldr	r4, [r1], #4
121		mov	r3, r4, lsl #16
122		orr	r3, r3, r3, lsr #16
123		mov	r4, r4, lsr #16
124		orr	r4, r4, r4, lsl #16
125		stmia	r0!, {r3, r4}
126		LOADREGS(eqfd, sp!, {r4 - r6, pc})
127
128		sub	r2, r2, #4
129acornscsi_out2:	adds	r2, r2, #2
130		ldr	r3, [r1], #2
131		strb	r3, [r0], #1
132		mov	r3, r3, lsr #8
133		strplb	r3, [r0], #1
134		LOADREGS(fd, sp!, {r4 - r6, pc})
135
136