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 */ 41imx_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 801: 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 1281: 129 @ return from FIQ 130 subs pc, lr, #4 131 132 .align 133.L_imx_ssi_fiq_base: 134imx_ssi_fiq_base: 135 .word 0x0 136.L_imx_ssi_fiq_rx_buffer: 137imx_ssi_fiq_rx_buffer: 138 .word 0x0 139.L_imx_ssi_fiq_tx_buffer: 140imx_ssi_fiq_tx_buffer: 141 .word 0x0 142.L_imx_ssi_fiq_end: 143imx_ssi_fiq_end: 144 145