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