/* * Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/linkage.h> #include <asm/assembler.h> /* * r8 = bit 0-15: tx offset, bit 16-31: tx buffer size * r9 = bit 0-15: rx offset, bit 16-31: rx buffer size */ #define SSI_STX0 0x00 #define SSI_SRX0 0x08 #define SSI_SISR 0x14 #define SSI_SIER 0x18 #define SSI_SACNT 0x38 #define SSI_SACNT_AC97EN (1 << 0) #define SSI_SIER_TFE0_EN (1 << 0) #define SSI_SISR_TFE0 (1 << 0) #define SSI_SISR_RFF0 (1 << 2) #define SSI_SIER_RFF0_EN (1 << 2) .text .global imx_ssi_fiq_start .global imx_ssi_fiq_end .global imx_ssi_fiq_base .global imx_ssi_fiq_rx_buffer .global imx_ssi_fiq_tx_buffer /* * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol * using ENDPROC(). imx_ssi_fiq_start and imx_ssi_fiq_end are used to * mark the function body so that it can be copied to the FIQ vector in * the vectors page. imx_ssi_fiq_start should only be called as the result * of an FIQ: calling it directly will not work. */ imx_ssi_fiq_start: ldr r12, .L_imx_ssi_fiq_base /* TX */ ldr r13, .L_imx_ssi_fiq_tx_buffer /* shall we send? */ ldr r11, [r12, #SSI_SIER] tst r11, #SSI_SIER_TFE0_EN beq 1f /* TX FIFO empty? */ ldr r11, [r12, #SSI_SISR] tst r11, #SSI_SISR_TFE0 beq 1f mov r10, #0x10000 sub r10, #1 and r10, r10, r8 /* r10: current buffer offset */ add r13, r13, r10 ldrh r11, [r13] strh r11, [r12, #SSI_STX0] ldrh r11, [r13, #2] strh r11, [r12, #SSI_STX0] ldrh r11, [r13, #4] strh r11, [r12, #SSI_STX0] ldrh r11, [r13, #6] strh r11, [r12, #SSI_STX0] add r10, #8 lsr r11, r8, #16 /* r11: buffer size */ cmp r10, r11 lslgt r8, r11, #16 addle r8, #8 1: /* RX */ /* shall we receive? */ ldr r11, [r12, #SSI_SIER] tst r11, #SSI_SIER_RFF0_EN beq 1f /* RX FIFO full? */ ldr r11, [r12, #SSI_SISR] tst r11, #SSI_SISR_RFF0 beq 1f ldr r13, .L_imx_ssi_fiq_rx_buffer mov r10, #0x10000 sub r10, #1 and r10, r10, r9 /* r10: current buffer offset */ add r13, r13, r10 ldr r11, [r12, #SSI_SACNT] tst r11, #SSI_SACNT_AC97EN ldr r11, [r12, #SSI_SRX0] strh r11, [r13] ldr r11, [r12, #SSI_SRX0] strh r11, [r13, #2] /* dummy read to skip slot 12 */ ldrne r11, [r12, #SSI_SRX0] ldr r11, [r12, #SSI_SRX0] strh r11, [r13, #4] ldr r11, [r12, #SSI_SRX0] strh r11, [r13, #6] /* dummy read to skip slot 12 */ ldrne r11, [r12, #SSI_SRX0] add r10, #8 lsr r11, r9, #16 /* r11: buffer size */ cmp r10, r11 lslgt r9, r11, #16 addle r9, #8 1: @ return from FIQ subs pc, lr, #4 .align .L_imx_ssi_fiq_base: imx_ssi_fiq_base: .word 0x0 .L_imx_ssi_fiq_rx_buffer: imx_ssi_fiq_rx_buffer: .word 0x0 .L_imx_ssi_fiq_tx_buffer: imx_ssi_fiq_tx_buffer: .word 0x0 .L_imx_ssi_fiq_end: imx_ssi_fiq_end: