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