1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de> |
4 | */ |
5 | |
6 | #include <linux/linkage.h> |
7 | #include <asm/assembler.h> |
8 | |
9 | /* |
10 | * r8 = bit 0-15: tx offset, bit 16-31: tx buffer size |
11 | * r9 = bit 0-15: rx offset, bit 16-31: rx buffer size |
12 | */ |
13 | |
14 | #define SSI_STX0 0x00 |
15 | #define SSI_SRX0 0x08 |
16 | #define SSI_SISR 0x14 |
17 | #define SSI_SIER 0x18 |
18 | #define SSI_SACNT 0x38 |
19 | |
20 | #define SSI_SACNT_AC97EN (1 << 0) |
21 | |
22 | #define SSI_SIER_TFE0_EN (1 << 0) |
23 | #define SSI_SISR_TFE0 (1 << 0) |
24 | #define SSI_SISR_RFF0 (1 << 2) |
25 | #define SSI_SIER_RFF0_EN (1 << 2) |
26 | |
27 | .text |
28 | .global imx_ssi_fiq_start |
29 | .global imx_ssi_fiq_end |
30 | .global imx_ssi_fiq_base |
31 | .global imx_ssi_fiq_rx_buffer |
32 | .global imx_ssi_fiq_tx_buffer |
33 | |
34 | /* |
35 | * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol |
36 | * using ENDPROC(). imx_ssi_fiq_start and imx_ssi_fiq_end are used to |
37 | * mark the function body so that it can be copied to the FIQ vector in |
38 | * the vectors page. imx_ssi_fiq_start should only be called as the result |
39 | * of an FIQ: calling it directly will not work. |
40 | */ |
41 | imx_ssi_fiq_start: |
42 | ldr r12, .L_imx_ssi_fiq_base |
43 | |
44 | /* TX */ |
45 | ldr r13, .L_imx_ssi_fiq_tx_buffer |
46 | |
47 | /* shall we send? */ |
48 | ldr r11, [r12, #SSI_SIER] |
49 | tst r11, #SSI_SIER_TFE0_EN |
50 | beq 1f |
51 | |
52 | /* TX FIFO empty? */ |
53 | ldr r11, [r12, #SSI_SISR] |
54 | tst r11, #SSI_SISR_TFE0 |
55 | beq 1f |
56 | |
57 | mov r10, #0x10000 |
58 | sub r10, #1 |
59 | and r10, r10, r8 /* r10: current buffer offset */ |
60 | |
61 | add r13, r13, r10 |
62 | |
63 | ldrh r11, [r13] |
64 | strh r11, [r12, #SSI_STX0] |
65 | |
66 | ldrh r11, [r13, #2] |
67 | strh r11, [r12, #SSI_STX0] |
68 | |
69 | ldrh r11, [r13, #4] |
70 | strh r11, [r12, #SSI_STX0] |
71 | |
72 | ldrh r11, [r13, #6] |
73 | strh r11, [r12, #SSI_STX0] |
74 | |
75 | add r10, #8 |
76 | lsr r11, r8, #16 /* r11: buffer size */ |
77 | cmp r10, r11 |
78 | lslgt r8, r11, #16 |
79 | addle r8, #8 |
80 | 1: |
81 | /* RX */ |
82 | |
83 | /* shall we receive? */ |
84 | ldr r11, [r12, #SSI_SIER] |
85 | tst r11, #SSI_SIER_RFF0_EN |
86 | beq 1f |
87 | |
88 | /* RX FIFO full? */ |
89 | ldr r11, [r12, #SSI_SISR] |
90 | tst r11, #SSI_SISR_RFF0 |
91 | beq 1f |
92 | |
93 | ldr r13, .L_imx_ssi_fiq_rx_buffer |
94 | |
95 | mov r10, #0x10000 |
96 | sub r10, #1 |
97 | and r10, r10, r9 /* r10: current buffer offset */ |
98 | |
99 | add r13, r13, r10 |
100 | |
101 | ldr r11, [r12, #SSI_SACNT] |
102 | tst r11, #SSI_SACNT_AC97EN |
103 | |
104 | ldr r11, [r12, #SSI_SRX0] |
105 | strh r11, [r13] |
106 | |
107 | ldr r11, [r12, #SSI_SRX0] |
108 | strh r11, [r13, #2] |
109 | |
110 | /* dummy read to skip slot 12 */ |
111 | ldrne r11, [r12, #SSI_SRX0] |
112 | |
113 | ldr r11, [r12, #SSI_SRX0] |
114 | strh r11, [r13, #4] |
115 | |
116 | ldr r11, [r12, #SSI_SRX0] |
117 | strh r11, [r13, #6] |
118 | |
119 | /* dummy read to skip slot 12 */ |
120 | ldrne r11, [r12, #SSI_SRX0] |
121 | |
122 | add r10, #8 |
123 | lsr r11, r9, #16 /* r11: buffer size */ |
124 | cmp r10, r11 |
125 | lslgt r9, r11, #16 |
126 | addle r9, #8 |
127 | |
128 | 1: |
129 | @ return from FIQ |
130 | subs pc, lr, #4 |
131 | |
132 | .align |
133 | .L_imx_ssi_fiq_base: |
134 | imx_ssi_fiq_base: |
135 | .word 0x0 |
136 | .L_imx_ssi_fiq_rx_buffer: |
137 | imx_ssi_fiq_rx_buffer: |
138 | .word 0x0 |
139 | .L_imx_ssi_fiq_tx_buffer: |
140 | imx_ssi_fiq_tx_buffer: |
141 | .word 0x0 |
142 | .L_imx_ssi_fiq_end: |
143 | imx_ssi_fiq_end: |
144 | |
145 | |